Commit 0f318baa authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-apei', 'acpi-properties', 'acpi-sbs' and 'acpi-thermal'

Merge ACPI APEI changes, ACPI device properties handling update, ACPI
SBS driver fixes and ACPI thermal driver cleanup for 6.4-rc1:

 - Make the APEI error injection code warn on invalid arguments when
   explicitly indicated by platform (Shuai Xue).

 - Add CXL error types to the error injection code in APEI (Tony Luck).

 - Refactor acpi_data_prop_read_single() (Andy Shevchenko).

 - Fix two issues in the ACPI SBS driver (Armin Wolf).

 - Replace ternary operator with min_t() in the generic ACPI thermal
   zone driver (Jiangshan Yi).

* acpi-apei:
  ACPI: APEI: EINJ: warn on invalid argument when explicitly indicated by platform
  ACPI: APEI: EINJ: Add CXL error types

* acpi-properties:
  ACPI: property: Refactor acpi_data_prop_read_single()

* acpi-sbs:
  ACPI: SBS: Fix handling of Smart Battery Selectors
  ACPI: EC: Fix oops when removing custom query handlers
  ACPI: EC: Limit explicit removal of query handlers to custom query handlers

* acpi-thermal:
  ACPI: thermal: Replace ternary operator with min_t()
...@@ -489,9 +489,15 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, ...@@ -489,9 +489,15 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
if (rc) if (rc)
return rc; return rc;
val = apei_exec_ctx_get_output(&ctx); val = apei_exec_ctx_get_output(&ctx);
if (val != EINJ_STATUS_SUCCESS) if (val == EINJ_STATUS_FAIL)
return -EBUSY; return -EBUSY;
else if (val == EINJ_STATUS_INVAL)
return -EINVAL;
/*
* The error is injected into the platform successfully, then it needs
* to trigger the error.
*/
rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE); rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE);
if (rc) if (rc)
return rc; return rc;
...@@ -584,6 +590,12 @@ static const char * const einj_error_type_string[] = { ...@@ -584,6 +590,12 @@ static const char * const einj_error_type_string[] = {
"0x00000200\tPlatform Correctable\n", "0x00000200\tPlatform Correctable\n",
"0x00000400\tPlatform Uncorrectable non-fatal\n", "0x00000400\tPlatform Uncorrectable non-fatal\n",
"0x00000800\tPlatform Uncorrectable fatal\n", "0x00000800\tPlatform Uncorrectable fatal\n",
"0x00001000\tCXL.cache Protocol Correctable\n",
"0x00002000\tCXL.cache Protocol Uncorrectable non-fatal\n",
"0x00004000\tCXL.cache Protocol Uncorrectable fatal\n",
"0x00008000\tCXL.mem Protocol Correctable\n",
"0x00010000\tCXL.mem Protocol Uncorrectable non-fatal\n",
"0x00020000\tCXL.mem Protocol Uncorrectable fatal\n",
}; };
static int available_error_type_show(struct seq_file *m, void *v) static int available_error_type_show(struct seq_file *m, void *v)
......
...@@ -1083,9 +1083,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, ...@@ -1083,9 +1083,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
acpi_handle handle, acpi_ec_query_func func, acpi_handle handle, acpi_ec_query_func func,
void *data) void *data)
{ {
struct acpi_ec_query_handler *handler = struct acpi_ec_query_handler *handler;
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
if (!handle && !func)
return -EINVAL;
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
if (!handler) if (!handler)
return -ENOMEM; return -ENOMEM;
...@@ -1097,6 +1100,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, ...@@ -1097,6 +1100,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
kref_init(&handler->kref); kref_init(&handler->kref);
list_add(&handler->node, &ec->list); list_add(&handler->node, &ec->list);
mutex_unlock(&ec->mutex); mutex_unlock(&ec->mutex);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
...@@ -1109,9 +1113,16 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec, ...@@ -1109,9 +1113,16 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec,
mutex_lock(&ec->mutex); mutex_lock(&ec->mutex);
list_for_each_entry_safe(handler, tmp, &ec->list, node) { list_for_each_entry_safe(handler, tmp, &ec->list, node) {
if (remove_all || query_bit == handler->query_bit) { /*
* When remove_all is false, only remove custom query handlers
* which have handler->func set. This is done to preserve query
* handlers discovered thru ACPI, as they should continue handling
* EC queries.
*/
if (remove_all || (handler->func && handler->query_bit == query_bit)) {
list_del_init(&handler->node); list_del_init(&handler->node);
list_add(&handler->node, &free_list); list_add(&handler->node, &free_list);
} }
} }
mutex_unlock(&ec->mutex); mutex_unlock(&ec->mutex);
...@@ -1122,6 +1133,7 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec, ...@@ -1122,6 +1133,7 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec,
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
{ {
acpi_ec_remove_query_handlers(ec, false, query_bit); acpi_ec_remove_query_handlers(ec, false, query_bit);
flush_workqueue(ec_query_wq);
} }
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
......
...@@ -971,60 +971,48 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data, ...@@ -971,60 +971,48 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data,
enum dev_prop_type proptype, void *val) enum dev_prop_type proptype, void *val)
{ {
const union acpi_object *obj; const union acpi_object *obj;
int ret; int ret = 0;
if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64)
ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj); ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
if (ret) else if (proptype == DEV_PROP_STRING)
return ret;
switch (proptype) {
case DEV_PROP_U8:
if (obj->integer.value > U8_MAX)
return -EOVERFLOW;
if (val)
*(u8 *)val = obj->integer.value;
break;
case DEV_PROP_U16:
if (obj->integer.value > U16_MAX)
return -EOVERFLOW;
if (val)
*(u16 *)val = obj->integer.value;
break;
case DEV_PROP_U32:
if (obj->integer.value > U32_MAX)
return -EOVERFLOW;
if (val)
*(u32 *)val = obj->integer.value;
break;
default:
if (val)
*(u64 *)val = obj->integer.value;
break;
}
if (!val)
return 1;
} else if (proptype == DEV_PROP_STRING) {
ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj); ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
if (ret) if (ret)
return ret; return ret;
switch (proptype) {
case DEV_PROP_U8:
if (obj->integer.value > U8_MAX)
return -EOVERFLOW;
if (val)
*(u8 *)val = obj->integer.value;
break;
case DEV_PROP_U16:
if (obj->integer.value > U16_MAX)
return -EOVERFLOW;
if (val)
*(u16 *)val = obj->integer.value;
break;
case DEV_PROP_U32:
if (obj->integer.value > U32_MAX)
return -EOVERFLOW;
if (val)
*(u32 *)val = obj->integer.value;
break;
case DEV_PROP_U64:
if (val)
*(u64 *)val = obj->integer.value;
break;
case DEV_PROP_STRING:
if (val) if (val)
*(char **)val = obj->string.pointer; *(char **)val = obj->string.pointer;
return 1; return 1;
} else { default:
ret = -EINVAL; return -EINVAL;
} }
return ret;
/* When no storage provided return number of available values */
return val ? 0 : 1;
} }
#define acpi_copy_property_array_uint(items, val, nval) \ #define acpi_copy_property_array_uint(items, val, nval) \
......
...@@ -473,23 +473,32 @@ static const struct device_attribute alarm_attr = { ...@@ -473,23 +473,32 @@ static const struct device_attribute alarm_attr = {
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
static int acpi_battery_read(struct acpi_battery *battery) static int acpi_battery_read(struct acpi_battery *battery)
{ {
int result = 0, saved_present = battery->present; int result, saved_present = battery->present;
u16 state; u16 state;
if (battery->sbs->manager_present) { if (battery->sbs->manager_present) {
result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
ACPI_SBS_MANAGER, 0x01, (u8 *)&state); ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
if (!result) if (result)
battery->present = state & (1 << battery->id); return result;
state &= 0x0fff;
battery->present = state & (1 << battery->id);
if (!battery->present)
return 0;
/* Masking necessary for Smart Battery Selectors */
state = 0x0fff;
state |= 1 << (battery->id + 12); state |= 1 << (battery->id + 12);
acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
} else if (battery->id == 0) } else {
battery->present = 1; if (battery->id == 0) {
battery->present = 1;
if (result || !battery->present) } else {
return result; if (!battery->present)
return 0;
}
}
if (saved_present != battery->present) { if (saved_present != battery->present) {
battery->update_time = 0; battery->update_time = 0;
......
...@@ -419,10 +419,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ...@@ -419,10 +419,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
* the next higher trip point * the next higher trip point
*/ */
tz->trips.active[i-1].temperature = tz->trips.active[i-1].temperature =
(tz->trips.active[i-2].temperature < min_t(unsigned long,
celsius_to_deci_kelvin(act) ? tz->trips.active[i-2].temperature,
tz->trips.active[i-2].temperature : celsius_to_deci_kelvin(act));
celsius_to_deci_kelvin(act));
break; break;
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment