Skip to content

Commit 4ed63b3

Browse files
committed
Merge branches 'acpi-ec', 'acpi-sysfs', 'acpi-utils' and 'acpi-soc'
Merge an ACPI EC driver update, ACPI sysfs interface updates, an ACPI library function update, and an ACPI APD driver update for 6.12-rc1: - Do not release locks during operation region accesses in the ACPI EC driver (Rafael Wysocki). - Fix up the _STR handling in the ACPI device object sysfs interface, make it represent the device object attributes as an attribute group and make it rely on driver core functionality for sysfs attrubute management (Thomas Weißschuh). - Extend error messages printed to the kernel log when acpi_evaluate_dsm() fails to include revision and function number (David Wang). - Add a new AMDI0015 platform device ID to the ACPi APD driver for AMD SoCs (Shyam Sundar S K). * acpi-ec: ACPI: EC: Do not release locks during operation region accesses * acpi-sysfs: ACPI: sysfs: remove return value of acpi_device_setup_files() ACPI: sysfs: manage sysfs attributes through device core ACPI: sysfs: manage attributes as attribute_group ACPI: sysfs: evaluate _STR on each sysfs access ACPI: sysfs: validate return type of _STR method * acpi-utils: ACPI: utils: Add rev/func to message when acpi_evaluate_dsm() fails * acpi-soc: ACPI: APD: Add AMDI0015 as platform device
5 parents 45de405 + f0121bf + bb664e5 + eeef915 + 8eea417 commit 4ed63b3

File tree

7 files changed

+146
-124
lines changed

7 files changed

+146
-124
lines changed

drivers/acpi/acpi_apd.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ static const struct apd_device_desc wt_i2c_desc = {
118118
.fixed_clk_rate = 150000000,
119119
};
120120

121+
static const struct apd_device_desc wt_i3c_desc = {
122+
.setup = acpi_apd_setup,
123+
.fixed_clk_rate = 125000000,
124+
};
125+
121126
static struct property_entry uart_properties[] = {
122127
PROPERTY_ENTRY_U32("reg-io-width", 4),
123128
PROPERTY_ENTRY_U32("reg-shift", 2),
@@ -231,6 +236,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
231236
{ "AMD0030", },
232237
{ "AMD0040", APD_ADDR(fch_misc_desc)},
233238
{ "AMDI0010", APD_ADDR(wt_i2c_desc) },
239+
{ "AMDI0015", APD_ADDR(wt_i3c_desc) },
234240
{ "AMDI0019", APD_ADDR(wt_i2c_desc) },
235241
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
236242
{ "AMDI0022", APD_ADDR(cz_uart_desc) },

drivers/acpi/device_sysfs.c

Lines changed: 85 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -439,23 +439,33 @@ static ssize_t description_show(struct device *dev,
439439
char *buf)
440440
{
441441
struct acpi_device *acpi_dev = to_acpi_device(dev);
442+
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
443+
union acpi_object *str_obj;
444+
acpi_status status;
442445
int result;
443446

444-
if (acpi_dev->pnp.str_obj == NULL)
445-
return 0;
447+
status = acpi_evaluate_object_typed(acpi_dev->handle, "_STR",
448+
NULL, &buffer,
449+
ACPI_TYPE_BUFFER);
450+
if (ACPI_FAILURE(status))
451+
return -EIO;
452+
453+
str_obj = buffer.pointer;
446454

447455
/*
448456
* The _STR object contains a Unicode identifier for a device.
449457
* We need to convert to utf-8 so it can be displayed.
450458
*/
451459
result = utf16s_to_utf8s(
452-
(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
453-
acpi_dev->pnp.str_obj->buffer.length,
460+
(wchar_t *)str_obj->buffer.pointer,
461+
str_obj->buffer.length,
454462
UTF16_LITTLE_ENDIAN, buf,
455463
PAGE_SIZE - 1);
456464

457465
buf[result++] = '\n';
458466

467+
kfree(str_obj);
468+
459469
return result;
460470
}
461471
static DEVICE_ATTR_RO(description);
@@ -507,96 +517,97 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr,
507517
}
508518
static DEVICE_ATTR_RO(status);
509519

510-
/**
511-
* acpi_device_setup_files - Create sysfs attributes of an ACPI device.
512-
* @dev: ACPI device object.
513-
*/
514-
int acpi_device_setup_files(struct acpi_device *dev)
515-
{
516-
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
517-
acpi_status status;
518-
int result = 0;
520+
static struct attribute *acpi_attrs[] = {
521+
&dev_attr_path.attr,
522+
&dev_attr_hid.attr,
523+
&dev_attr_modalias.attr,
524+
&dev_attr_description.attr,
525+
&dev_attr_adr.attr,
526+
&dev_attr_uid.attr,
527+
&dev_attr_sun.attr,
528+
&dev_attr_hrv.attr,
529+
&dev_attr_status.attr,
530+
&dev_attr_eject.attr,
531+
&dev_attr_power_state.attr,
532+
&dev_attr_real_power_state.attr,
533+
NULL
534+
};
519535

536+
static bool acpi_show_attr(struct acpi_device *dev, const struct device_attribute *attr)
537+
{
520538
/*
521539
* Devices gotten from FADT don't have a "path" attribute
522540
*/
523-
if (dev->handle) {
524-
result = device_create_file(&dev->dev, &dev_attr_path);
525-
if (result)
526-
goto end;
527-
}
541+
if (attr == &dev_attr_path)
542+
return dev->handle;
528543

529-
if (!list_empty(&dev->pnp.ids)) {
530-
result = device_create_file(&dev->dev, &dev_attr_hid);
531-
if (result)
532-
goto end;
544+
if (attr == &dev_attr_hid || attr == &dev_attr_modalias)
545+
return !list_empty(&dev->pnp.ids);
533546

534-
result = device_create_file(&dev->dev, &dev_attr_modalias);
535-
if (result)
536-
goto end;
537-
}
547+
if (attr == &dev_attr_description)
548+
return acpi_has_method(dev->handle, "_STR");
538549

539-
/*
540-
* If device has _STR, 'description' file is created
541-
*/
542-
if (acpi_has_method(dev->handle, "_STR")) {
543-
status = acpi_evaluate_object(dev->handle, "_STR",
544-
NULL, &buffer);
545-
if (ACPI_FAILURE(status))
546-
buffer.pointer = NULL;
547-
dev->pnp.str_obj = buffer.pointer;
548-
result = device_create_file(&dev->dev, &dev_attr_description);
549-
if (result)
550-
goto end;
551-
}
550+
if (attr == &dev_attr_adr)
551+
return dev->pnp.type.bus_address;
552552

553-
if (dev->pnp.type.bus_address)
554-
result = device_create_file(&dev->dev, &dev_attr_adr);
555-
if (acpi_device_uid(dev))
556-
result = device_create_file(&dev->dev, &dev_attr_uid);
553+
if (attr == &dev_attr_uid)
554+
return acpi_device_uid(dev);
557555

558-
if (acpi_has_method(dev->handle, "_SUN")) {
559-
result = device_create_file(&dev->dev, &dev_attr_sun);
560-
if (result)
561-
goto end;
562-
}
556+
if (attr == &dev_attr_sun)
557+
return acpi_has_method(dev->handle, "_SUN");
563558

564-
if (acpi_has_method(dev->handle, "_HRV")) {
565-
result = device_create_file(&dev->dev, &dev_attr_hrv);
566-
if (result)
567-
goto end;
568-
}
559+
if (attr == &dev_attr_hrv)
560+
return acpi_has_method(dev->handle, "_HRV");
569561

570-
if (acpi_has_method(dev->handle, "_STA")) {
571-
result = device_create_file(&dev->dev, &dev_attr_status);
572-
if (result)
573-
goto end;
574-
}
562+
if (attr == &dev_attr_status)
563+
return acpi_has_method(dev->handle, "_STA");
575564

576565
/*
577566
* If device has _EJ0, 'eject' file is created that is used to trigger
578567
* hot-removal function from userland.
579568
*/
580-
if (acpi_has_method(dev->handle, "_EJ0")) {
581-
result = device_create_file(&dev->dev, &dev_attr_eject);
582-
if (result)
583-
return result;
584-
}
569+
if (attr == &dev_attr_eject)
570+
return acpi_has_method(dev->handle, "_EJ0");
585571

586-
if (dev->flags.power_manageable) {
587-
result = device_create_file(&dev->dev, &dev_attr_power_state);
588-
if (result)
589-
return result;
572+
if (attr == &dev_attr_power_state)
573+
return dev->flags.power_manageable;
590574

591-
if (dev->power.flags.power_resources)
592-
result = device_create_file(&dev->dev,
593-
&dev_attr_real_power_state);
594-
}
575+
if (attr == &dev_attr_real_power_state)
576+
return dev->flags.power_manageable && dev->power.flags.power_resources;
595577

596-
acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
578+
dev_warn_once(&dev->dev, "Unexpected attribute: %s\n", attr->attr.name);
579+
return false;
580+
}
597581

598-
end:
599-
return result;
582+
static umode_t acpi_attr_is_visible(struct kobject *kobj,
583+
struct attribute *attr,
584+
int attrno)
585+
{
586+
struct acpi_device *dev = to_acpi_device(kobj_to_dev(kobj));
587+
588+
if (acpi_show_attr(dev, container_of(attr, struct device_attribute, attr)))
589+
return attr->mode;
590+
else
591+
return 0;
592+
}
593+
594+
static const struct attribute_group acpi_group = {
595+
.attrs = acpi_attrs,
596+
.is_visible = acpi_attr_is_visible,
597+
};
598+
599+
const struct attribute_group *acpi_groups[] = {
600+
&acpi_group,
601+
NULL
602+
};
603+
604+
/**
605+
* acpi_device_setup_files - Create sysfs attributes of an ACPI device.
606+
* @dev: ACPI device object.
607+
*/
608+
void acpi_device_setup_files(struct acpi_device *dev)
609+
{
610+
acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
600611
}
601612

602613
/**
@@ -606,41 +617,4 @@ int acpi_device_setup_files(struct acpi_device *dev)
606617
void acpi_device_remove_files(struct acpi_device *dev)
607618
{
608619
acpi_hide_nondev_subnodes(&dev->data);
609-
610-
if (dev->flags.power_manageable) {
611-
device_remove_file(&dev->dev, &dev_attr_power_state);
612-
if (dev->power.flags.power_resources)
613-
device_remove_file(&dev->dev,
614-
&dev_attr_real_power_state);
615-
}
616-
617-
/*
618-
* If device has _STR, remove 'description' file
619-
*/
620-
if (acpi_has_method(dev->handle, "_STR")) {
621-
kfree(dev->pnp.str_obj);
622-
device_remove_file(&dev->dev, &dev_attr_description);
623-
}
624-
/*
625-
* If device has _EJ0, remove 'eject' file.
626-
*/
627-
if (acpi_has_method(dev->handle, "_EJ0"))
628-
device_remove_file(&dev->dev, &dev_attr_eject);
629-
630-
if (acpi_has_method(dev->handle, "_SUN"))
631-
device_remove_file(&dev->dev, &dev_attr_sun);
632-
633-
if (acpi_has_method(dev->handle, "_HRV"))
634-
device_remove_file(&dev->dev, &dev_attr_hrv);
635-
636-
if (acpi_device_uid(dev))
637-
device_remove_file(&dev->dev, &dev_attr_uid);
638-
if (dev->pnp.type.bus_address)
639-
device_remove_file(&dev->dev, &dev_attr_adr);
640-
device_remove_file(&dev->dev, &dev_attr_modalias);
641-
device_remove_file(&dev->dev, &dev_attr_hid);
642-
if (acpi_has_method(dev->handle, "_STA"))
643-
device_remove_file(&dev->dev, &dev_attr_status);
644-
if (dev->handle)
645-
device_remove_file(&dev->dev, &dev_attr_path);
646620
}

drivers/acpi/ec.c

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
783783
unsigned long tmp;
784784
int ret = 0;
785785

786+
if (t->rdata)
787+
memset(t->rdata, 0, t->rlen);
788+
786789
/* start transaction */
787790
spin_lock_irqsave(&ec->lock, tmp);
788791
/* Enable GPE for command processing (IBF=0/OBF=1) */
@@ -819,8 +822,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
819822

820823
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
821824
return -EINVAL;
822-
if (t->rdata)
823-
memset(t->rdata, 0, t->rlen);
824825

825826
mutex_lock(&ec->mutex);
826827
if (ec->global_lock) {
@@ -847,7 +848,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
847848
.wdata = NULL, .rdata = &d,
848849
.wlen = 0, .rlen = 1};
849850

850-
return acpi_ec_transaction(ec, &t);
851+
return acpi_ec_transaction_unlocked(ec, &t);
851852
}
852853

853854
static int acpi_ec_burst_disable(struct acpi_ec *ec)
@@ -857,7 +858,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
857858
.wlen = 0, .rlen = 0};
858859

859860
return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
860-
acpi_ec_transaction(ec, &t) : 0;
861+
acpi_ec_transaction_unlocked(ec, &t) : 0;
861862
}
862863

863864
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
@@ -873,6 +874,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
873874
return result;
874875
}
875876

877+
static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data)
878+
{
879+
int result;
880+
u8 d;
881+
struct transaction t = {.command = ACPI_EC_COMMAND_READ,
882+
.wdata = &address, .rdata = &d,
883+
.wlen = 1, .rlen = 1};
884+
885+
result = acpi_ec_transaction_unlocked(ec, &t);
886+
*data = d;
887+
return result;
888+
}
889+
876890
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
877891
{
878892
u8 wdata[2] = { address, data };
@@ -883,6 +897,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
883897
return acpi_ec_transaction(ec, &t);
884898
}
885899

900+
static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data)
901+
{
902+
u8 wdata[2] = { address, data };
903+
struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
904+
.wdata = wdata, .rdata = NULL,
905+
.wlen = 2, .rlen = 0};
906+
907+
return acpi_ec_transaction_unlocked(ec, &t);
908+
}
909+
886910
int ec_read(u8 addr, u8 *val)
887911
{
888912
int err;
@@ -1323,27 +1347,46 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
13231347
struct acpi_ec *ec = handler_context;
13241348
int result = 0, i, bytes = bits / 8;
13251349
u8 *value = (u8 *)value64;
1350+
u32 glk;
13261351

13271352
if ((address > 0xFF) || !value || !handler_context)
13281353
return AE_BAD_PARAMETER;
13291354

13301355
if (function != ACPI_READ && function != ACPI_WRITE)
13311356
return AE_BAD_PARAMETER;
13321357

1358+
mutex_lock(&ec->mutex);
1359+
1360+
if (ec->global_lock) {
1361+
acpi_status status;
1362+
1363+
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
1364+
if (ACPI_FAILURE(status)) {
1365+
result = -ENODEV;
1366+
goto unlock;
1367+
}
1368+
}
1369+
13331370
if (ec->busy_polling || bits > 8)
13341371
acpi_ec_burst_enable(ec);
13351372

13361373
for (i = 0; i < bytes; ++i, ++address, ++value) {
13371374
result = (function == ACPI_READ) ?
1338-
acpi_ec_read(ec, address, value) :
1339-
acpi_ec_write(ec, address, *value);
1375+
acpi_ec_read_unlocked(ec, address, value) :
1376+
acpi_ec_write_unlocked(ec, address, *value);
13401377
if (result < 0)
13411378
break;
13421379
}
13431380

13441381
if (ec->busy_polling || bits > 8)
13451382
acpi_ec_burst_disable(ec);
13461383

1384+
if (ec->global_lock)
1385+
acpi_release_global_lock(glk);
1386+
1387+
unlock:
1388+
mutex_unlock(&ec->mutex);
1389+
13471390
switch (result) {
13481391
case -EINVAL:
13491392
return AE_BAD_PARAMETER;

0 commit comments

Comments
 (0)