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,
if (rc)
return rc;
val = apei_exec_ctx_get_output(&ctx);
if (val != EINJ_STATUS_SUCCESS)
if (val == EINJ_STATUS_FAIL)
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);
if (rc)
return rc;
......@@ -584,6 +590,12 @@ static const char * const einj_error_type_string[] = {
"0x00000200\tPlatform Correctable\n",
"0x00000400\tPlatform Uncorrectable non-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)
......
......@@ -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,
void *data)
{
struct acpi_ec_query_handler *handler =
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
struct acpi_ec_query_handler *handler;
if (!handle && !func)
return -EINVAL;
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
if (!handler)
return -ENOMEM;
......@@ -1097,6 +1100,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
kref_init(&handler->kref);
list_add(&handler->node, &ec->list);
mutex_unlock(&ec->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
......@@ -1109,9 +1113,16 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec *ec,
mutex_lock(&ec->mutex);
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_add(&handler->node, &free_list);
}
}
mutex_unlock(&ec->mutex);
......@@ -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)
{
acpi_ec_remove_query_handlers(ec, false, query_bit);
flush_workqueue(ec_query_wq);
}
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,
enum dev_prop_type proptype, void *val)
{
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);
if (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;
default:
if (val)
*(u64 *)val = obj->integer.value;
break;
}
if (!val)
return 1;
} else if (proptype == DEV_PROP_STRING) {
else if (proptype == DEV_PROP_STRING)
ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
if (ret)
return ret;
if (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)
*(char **)val = obj->string.pointer;
return 1;
} else {
ret = -EINVAL;
default:
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) \
......
......@@ -473,23 +473,32 @@ static const struct device_attribute alarm_attr = {
-------------------------------------------------------------------------- */
static int acpi_battery_read(struct acpi_battery *battery)
{
int result = 0, saved_present = battery->present;
int result, saved_present = battery->present;
u16 state;
if (battery->sbs->manager_present) {
result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
if (!result)
battery->present = state & (1 << battery->id);
state &= 0x0fff;
if (result)
return result;
battery->present = state & (1 << battery->id);
if (!battery->present)
return 0;
/* Masking necessary for Smart Battery Selectors */
state = 0x0fff;
state |= 1 << (battery->id + 12);
acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
} else if (battery->id == 0)
battery->present = 1;
if (result || !battery->present)
return result;
} else {
if (battery->id == 0) {
battery->present = 1;
} else {
if (!battery->present)
return 0;
}
}
if (saved_present != battery->present) {
battery->update_time = 0;
......
......@@ -419,10 +419,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
* the next higher trip point
*/
tz->trips.active[i-1].temperature =
(tz->trips.active[i-2].temperature <
celsius_to_deci_kelvin(act) ?
tz->trips.active[i-2].temperature :
celsius_to_deci_kelvin(act));
min_t(unsigned long,
tz->trips.active[i-2].temperature,
celsius_to_deci_kelvin(act));
break;
} 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