aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2016-09-07 04:50:08 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-09 20:33:49 -0400
commit72c77b7ea9ce781f4987840984a462e4456ba98e (patch)
tree5aa84ab38f1d66459b8c96223ed8b1d694e449af
parentd30283057ecdf8c543ae757ae34db3d7fd2d7732 (diff)
ACPI / EC: Cleanup first_ec/boot_ec code
In order to support full ECDT (driving the ECDT EC after probing the namespace EC), we need to change our EC device alloc/free algorithm, ensure not to free old boot EC before qualifying new boot EC. This patch achieves this by cleaning up first_ec/boot_ec logic: 1. first_ec: used to perform transactions, so it is assigned in new acpi_ec_setup() function. 2. boot_ec: used to track early EC device, so it is assigned in new acpi_config_boot_ec() function which explictly tells the driver to save the EC device as early EC device. Link: https://bugzilla.kernel.org/show_bug.cgi?id=115021 Reported-and-tested-by: Luya Tshimbalanga <luya@fedoraproject.org> Tested-by: Jonh Henderson <jw.hendy@gmail.com> Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/ec.c96
1 files changed, 63 insertions, 33 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 1925589ecf66..9eab651a4502 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -184,6 +184,7 @@ static void acpi_ec_event_processor(struct work_struct *work);
184 184
185struct acpi_ec *boot_ec, *first_ec; 185struct acpi_ec *boot_ec, *first_ec;
186EXPORT_SYMBOL(first_ec); 186EXPORT_SYMBOL(first_ec);
187static bool boot_ec_is_ecdt = false;
187static struct workqueue_struct *ec_query_wq; 188static struct workqueue_struct *ec_query_wq;
188 189
189static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ 190static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
@@ -1304,7 +1305,16 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
1304static acpi_status 1305static acpi_status
1305ec_parse_io_ports(struct acpi_resource *resource, void *context); 1306ec_parse_io_ports(struct acpi_resource *resource, void *context);
1306 1307
1307static struct acpi_ec *make_acpi_ec(void) 1308static void acpi_ec_free(struct acpi_ec *ec)
1309{
1310 if (first_ec == ec)
1311 first_ec = NULL;
1312 if (boot_ec == ec)
1313 boot_ec = NULL;
1314 kfree(ec);
1315}
1316
1317static struct acpi_ec *acpi_ec_alloc(void)
1308{ 1318{
1309 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); 1319 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
1310 1320
@@ -1365,6 +1375,11 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
1365 return AE_CTRL_TERMINATE; 1375 return AE_CTRL_TERMINATE;
1366} 1376}
1367 1377
1378/*
1379 * Note: This function returns an error code only when the address space
1380 * handler is not installed, which means "not able to handle
1381 * transactions".
1382 */
1368static int ec_install_handlers(struct acpi_ec *ec) 1383static int ec_install_handlers(struct acpi_ec *ec)
1369{ 1384{
1370 acpi_status status; 1385 acpi_status status;
@@ -1440,21 +1455,49 @@ static void ec_remove_handlers(struct acpi_ec *ec)
1440 } 1455 }
1441} 1456}
1442 1457
1443static struct acpi_ec *acpi_ec_alloc(void) 1458static int acpi_ec_setup(struct acpi_ec *ec)
1444{ 1459{
1445 struct acpi_ec *ec; 1460 int ret;
1446 1461
1447 /* Check for boot EC */ 1462 ret = ec_install_handlers(ec);
1448 if (boot_ec) { 1463 if (ret)
1449 ec = boot_ec; 1464 return ret;
1450 boot_ec = NULL; 1465
1451 ec_remove_handlers(ec); 1466 /* First EC capable of handling transactions */
1452 if (first_ec == ec) 1467 if (!first_ec) {
1453 first_ec = NULL; 1468 first_ec = ec;
1454 } else { 1469 acpi_handle_info(first_ec->handle, "Used as first EC\n");
1455 ec = make_acpi_ec();
1456 } 1470 }
1457 return ec; 1471
1472 acpi_handle_info(ec->handle,
1473 "GPE=0x%lx, EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n",
1474 ec->gpe, ec->command_addr, ec->data_addr);
1475 return ret;
1476}
1477
1478static int acpi_config_boot_ec(struct acpi_ec *ec, bool is_ecdt)
1479{
1480 int ret;
1481
1482 if (boot_ec)
1483 ec_remove_handlers(boot_ec);
1484
1485 /* Unset old boot EC */
1486 if (boot_ec != ec)
1487 acpi_ec_free(boot_ec);
1488
1489 ret = acpi_ec_setup(ec);
1490 if (ret)
1491 return ret;
1492
1493 /* Set new boot EC */
1494 if (!boot_ec) {
1495 boot_ec = ec;
1496 boot_ec_is_ecdt = is_ecdt;
1497 acpi_handle_info(boot_ec->handle, "Used as boot %s EC\n",
1498 is_ecdt ? "ECDT" : "DSDT");
1499 }
1500 return ret;
1458} 1501}
1459 1502
1460static int acpi_ec_add(struct acpi_device *device) 1503static int acpi_ec_add(struct acpi_device *device)
@@ -1470,7 +1513,7 @@ static int acpi_ec_add(struct acpi_device *device)
1470 return -ENOMEM; 1513 return -ENOMEM;
1471 if (ec_parse_device(device->handle, 0, ec, NULL) != 1514 if (ec_parse_device(device->handle, 0, ec, NULL) !=
1472 AE_CTRL_TERMINATE) { 1515 AE_CTRL_TERMINATE) {
1473 kfree(ec); 1516 acpi_ec_free(ec);
1474 return -EINVAL; 1517 return -EINVAL;
1475 } 1518 }
1476 1519
@@ -1478,8 +1521,6 @@ static int acpi_ec_add(struct acpi_device *device)
1478 acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, 1521 acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
1479 acpi_ec_register_query_methods, NULL, ec, NULL); 1522 acpi_ec_register_query_methods, NULL, ec, NULL);
1480 1523
1481 if (!first_ec)
1482 first_ec = ec;
1483 device->driver_data = ec; 1524 device->driver_data = ec;
1484 1525
1485 ret = !!request_region(ec->data_addr, 1, "EC data"); 1526 ret = !!request_region(ec->data_addr, 1, "EC data");
@@ -1487,10 +1528,7 @@ static int acpi_ec_add(struct acpi_device *device)
1487 ret = !!request_region(ec->command_addr, 1, "EC cmd"); 1528 ret = !!request_region(ec->command_addr, 1, "EC cmd");
1488 WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); 1529 WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
1489 1530
1490 pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 1531 ret = acpi_config_boot_ec(ec, false);
1491 ec->gpe, ec->command_addr, ec->data_addr);
1492
1493 ret = ec_install_handlers(ec);
1494 1532
1495 /* Reprobe devices depending on the EC */ 1533 /* Reprobe devices depending on the EC */
1496 acpi_walk_dep_device_list(ec->handle); 1534 acpi_walk_dep_device_list(ec->handle);
@@ -1513,9 +1551,7 @@ static int acpi_ec_remove(struct acpi_device *device)
1513 release_region(ec->data_addr, 1); 1551 release_region(ec->data_addr, 1);
1514 release_region(ec->command_addr, 1); 1552 release_region(ec->command_addr, 1);
1515 device->driver_data = NULL; 1553 device->driver_data = NULL;
1516 if (ec == first_ec) 1554 acpi_ec_free(ec);
1517 first_ec = NULL;
1518 kfree(ec);
1519 return 0; 1555 return 0;
1520} 1556}
1521 1557
@@ -1567,13 +1603,10 @@ int __init acpi_ec_dsdt_probe(void)
1567 ret = -ENODEV; 1603 ret = -ENODEV;
1568 goto error; 1604 goto error;
1569 } 1605 }
1570 ret = ec_install_handlers(ec); 1606 ret = acpi_config_boot_ec(ec, false);
1571
1572error: 1607error:
1573 if (ret) 1608 if (ret)
1574 kfree(ec); 1609 acpi_ec_free(ec);
1575 else
1576 first_ec = boot_ec = ec;
1577 return ret; 1610 return ret;
1578} 1611}
1579 1612
@@ -1671,7 +1704,6 @@ int __init acpi_ec_ecdt_probe(void)
1671 goto error; 1704 goto error;
1672 } 1705 }
1673 1706
1674 pr_info("EC description table is found, configuring boot EC\n");
1675 if (EC_FLAGS_CORRECT_ECDT) { 1707 if (EC_FLAGS_CORRECT_ECDT) {
1676 ec->command_addr = ecdt_ptr->data.address; 1708 ec->command_addr = ecdt_ptr->data.address;
1677 ec->data_addr = ecdt_ptr->control.address; 1709 ec->data_addr = ecdt_ptr->control.address;
@@ -1681,12 +1713,10 @@ int __init acpi_ec_ecdt_probe(void)
1681 } 1713 }
1682 ec->gpe = ecdt_ptr->gpe; 1714 ec->gpe = ecdt_ptr->gpe;
1683 ec->handle = ACPI_ROOT_OBJECT; 1715 ec->handle = ACPI_ROOT_OBJECT;
1684 ret = ec_install_handlers(ec); 1716 ret = acpi_config_boot_ec(ec, true);
1685error: 1717error:
1686 if (ret) 1718 if (ret)
1687 kfree(ec); 1719 acpi_ec_free(ec);
1688 else
1689 first_ec = boot_ec = ec;
1690 return ret; 1720 return ret;
1691} 1721}
1692 1722