Lines 112-117
enum {
Link Here
|
112 |
EC_FLAGS_STOPPED, /* Driver is stopped */ |
112 |
EC_FLAGS_STOPPED, /* Driver is stopped */ |
113 |
EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the |
113 |
EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the |
114 |
* current command processing */ |
114 |
* current command processing */ |
|
|
115 |
EC_FLAGS_QUERY_HANDLER_INSTALLED, |
116 |
/* _Qxx handlers installed */ |
115 |
}; |
117 |
}; |
116 |
|
118 |
|
117 |
#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ |
119 |
#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ |
Lines 1228-1233
acpi_ec_space_handler(u32 function, acpi
Link Here
|
1228 |
static acpi_status |
1230 |
static acpi_status |
1229 |
ec_parse_io_ports(struct acpi_resource *resource, void *context); |
1231 |
ec_parse_io_ports(struct acpi_resource *resource, void *context); |
1230 |
|
1232 |
|
|
|
1233 |
static void free_acpi_ec(struct acpi_ec *ec) |
1234 |
{ |
1235 |
if (first_ec == ec) |
1236 |
first_ec = NULL; |
1237 |
if (boot_ec == ec) |
1238 |
boot_ec = NULL; |
1239 |
kfree(ec); |
1240 |
} |
1241 |
|
1231 |
static struct acpi_ec *make_acpi_ec(void) |
1242 |
static struct acpi_ec *make_acpi_ec(void) |
1232 |
{ |
1243 |
{ |
1233 |
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); |
1244 |
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); |
Lines 1290-1296
ec_parse_device(acpi_handle handle, u32
Link Here
|
1290 |
return AE_CTRL_TERMINATE; |
1301 |
return AE_CTRL_TERMINATE; |
1291 |
} |
1302 |
} |
1292 |
|
1303 |
|
1293 |
static int ec_install_handlers(struct acpi_ec *ec) |
1304 |
static int ec_install_handlers(struct acpi_ec *ec, bool handle_events) |
1294 |
{ |
1305 |
{ |
1295 |
acpi_status status; |
1306 |
acpi_status status; |
1296 |
|
1307 |
|
Lines 1319-1324
static int ec_install_handlers(struct ac
Link Here
|
1319 |
set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); |
1330 |
set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags); |
1320 |
} |
1331 |
} |
1321 |
|
1332 |
|
|
|
1333 |
if (!handle_events) |
1334 |
return 0; |
1335 |
|
1322 |
if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { |
1336 |
if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) { |
1323 |
status = acpi_install_gpe_raw_handler(NULL, ec->gpe, |
1337 |
status = acpi_install_gpe_raw_handler(NULL, ec->gpe, |
1324 |
ACPI_GPE_EDGE_TRIGGERED, |
1338 |
ACPI_GPE_EDGE_TRIGGERED, |
Lines 1331-1337
static int ec_install_handlers(struct ac
Link Here
|
1331 |
acpi_ec_enable_gpe(ec, true); |
1345 |
acpi_ec_enable_gpe(ec, true); |
1332 |
} |
1346 |
} |
1333 |
} |
1347 |
} |
|
|
1348 |
if (!test_bit(EC_FLAGS_QUERY_HANDLER_INSTALLED, &ec->flags)) { |
1349 |
/* Find and register all query methods */ |
1350 |
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, |
1351 |
acpi_ec_register_query_methods, |
1352 |
NULL, ec, NULL); |
1353 |
set_bit(EC_FLAGS_QUERY_HANDLER_INSTALLED, &ec->flags); |
1354 |
} |
1334 |
|
1355 |
|
|
|
1356 |
/* EC is fully operational, allow queries */ |
1357 |
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
1335 |
return 0; |
1358 |
return 0; |
1336 |
} |
1359 |
} |
1337 |
|
1360 |
|
Lines 1365-1385
static void ec_remove_handlers(struct ac
Link Here
|
1365 |
} |
1388 |
} |
1366 |
} |
1389 |
} |
1367 |
|
1390 |
|
1368 |
static struct acpi_ec *acpi_ec_alloc(void) |
1391 |
static int acpi_set_boot_ec(struct acpi_ec *ec, bool refresh_globals, |
|
|
1392 |
bool handle_events) |
1369 |
{ |
1393 |
{ |
1370 |
struct acpi_ec *ec; |
1394 |
int ret; |
1371 |
|
1395 |
|
1372 |
/* Check for boot EC */ |
1396 |
/* Release old boot EC */ |
1373 |
if (boot_ec) { |
1397 |
if (refresh_globals) { |
1374 |
ec = boot_ec; |
1398 |
if (boot_ec) { |
1375 |
boot_ec = NULL; |
1399 |
ec_remove_handlers(boot_ec); |
1376 |
ec_remove_handlers(ec); |
1400 |
free_acpi_ec(boot_ec); |
1377 |
if (first_ec == ec) |
1401 |
} |
1378 |
first_ec = NULL; |
|
|
1379 |
} else { |
1380 |
ec = make_acpi_ec(); |
1381 |
} |
1402 |
} |
1382 |
return ec; |
1403 |
|
|
|
1404 |
/* Switch boot EC to use new EC */ |
1405 |
ret = ec_install_handlers(ec, handle_events); |
1406 |
if (!ret) { |
1407 |
if (refresh_globals) { |
1408 |
boot_ec = ec; |
1409 |
if (!first_ec) |
1410 |
first_ec = ec; |
1411 |
} |
1412 |
acpi_handle_info(ec->handle, "used as boot EC to handle %s\n", |
1413 |
handle_events ? |
1414 |
"events and transactions" : "transactions"); |
1415 |
acpi_handle_info(ec->handle, |
1416 |
"GPE=0x%lx, I/O: CMD/SC=0x%lx, DATA=0x%lx\n", |
1417 |
ec->gpe, ec->command_addr, ec->data_addr); |
1418 |
} |
1419 |
return ret; |
1383 |
} |
1420 |
} |
1384 |
|
1421 |
|
1385 |
static int acpi_ec_add(struct acpi_device *device) |
1422 |
static int acpi_ec_add(struct acpi_device *device) |
Lines 1390-1410
static int acpi_ec_add(struct acpi_devic
Link Here
|
1390 |
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
1427 |
strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); |
1391 |
strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
1428 |
strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
1392 |
|
1429 |
|
1393 |
ec = acpi_ec_alloc(); |
1430 |
ec = make_acpi_ec(); |
1394 |
if (!ec) |
1431 |
if (!ec) |
1395 |
return -ENOMEM; |
1432 |
return -ENOMEM; |
1396 |
if (ec_parse_device(device->handle, 0, ec, NULL) != |
1433 |
if (ec_parse_device(device->handle, 0, ec, NULL) != |
1397 |
AE_CTRL_TERMINATE) { |
1434 |
AE_CTRL_TERMINATE) { |
1398 |
kfree(ec); |
1435 |
free_acpi_ec(ec); |
1399 |
return -EINVAL; |
1436 |
return -EINVAL; |
1400 |
} |
1437 |
} |
1401 |
|
1438 |
|
1402 |
/* Find and register all query methods */ |
|
|
1403 |
acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, |
1404 |
acpi_ec_register_query_methods, NULL, ec, NULL); |
1405 |
|
1406 |
if (!first_ec) |
1407 |
first_ec = ec; |
1408 |
device->driver_data = ec; |
1439 |
device->driver_data = ec; |
1409 |
|
1440 |
|
1410 |
ret = !!request_region(ec->data_addr, 1, "EC data"); |
1441 |
ret = !!request_region(ec->data_addr, 1, "EC data"); |
Lines 1412-1428
static int acpi_ec_add(struct acpi_devic
Link Here
|
1412 |
ret = !!request_region(ec->command_addr, 1, "EC cmd"); |
1443 |
ret = !!request_region(ec->command_addr, 1, "EC cmd"); |
1413 |
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); |
1444 |
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); |
1414 |
|
1445 |
|
1415 |
pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", |
1446 |
ret = acpi_set_boot_ec(ec, true, true); |
1416 |
ec->gpe, ec->command_addr, ec->data_addr); |
|
|
1417 |
|
1418 |
ret = ec_install_handlers(ec); |
1419 |
|
1447 |
|
1420 |
/* Reprobe devices depending on the EC */ |
1448 |
/* Reprobe devices depending on the EC */ |
1421 |
acpi_walk_dep_device_list(ec->handle); |
1449 |
acpi_walk_dep_device_list(ec->handle); |
1422 |
|
1450 |
|
1423 |
/* EC is fully operational, allow queries */ |
|
|
1424 |
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
1425 |
|
1426 |
/* Clear stale _Q events if hardware might require that */ |
1451 |
/* Clear stale _Q events if hardware might require that */ |
1427 |
if (EC_FLAGS_CLEAR_ON_RESUME) |
1452 |
if (EC_FLAGS_CLEAR_ON_RESUME) |
1428 |
acpi_ec_clear(ec); |
1453 |
acpi_ec_clear(ec); |
Lines 1442-1450
static int acpi_ec_remove(struct acpi_de
Link Here
|
1442 |
release_region(ec->data_addr, 1); |
1467 |
release_region(ec->data_addr, 1); |
1443 |
release_region(ec->command_addr, 1); |
1468 |
release_region(ec->command_addr, 1); |
1444 |
device->driver_data = NULL; |
1469 |
device->driver_data = NULL; |
1445 |
if (ec == first_ec) |
1470 |
free_acpi_ec(ec); |
1446 |
first_ec = NULL; |
|
|
1447 |
kfree(ec); |
1448 |
return 0; |
1471 |
return 0; |
1449 |
} |
1472 |
} |
1450 |
|
1473 |
|
Lines 1476-1488
static const struct acpi_device_id ec_de
Link Here
|
1476 |
{"", 0}, |
1499 |
{"", 0}, |
1477 |
}; |
1500 |
}; |
1478 |
|
1501 |
|
|
|
1502 |
static int __init acpi_ec_ecdt_start(void) |
1503 |
{ |
1504 |
struct acpi_table_ecdt *ecdt_ptr; |
1505 |
acpi_status status; |
1506 |
acpi_handle handle; |
1507 |
int ret = 0; |
1508 |
|
1509 |
if (!boot_ec) |
1510 |
return -ENODEV; |
1511 |
|
1512 |
status = acpi_get_table(ACPI_SIG_ECDT, 1, |
1513 |
(struct acpi_table_header **)&ecdt_ptr); |
1514 |
if (ACPI_FAILURE(status)) { |
1515 |
ret = -ENODEV; |
1516 |
goto error; |
1517 |
} |
1518 |
|
1519 |
/* At this point, the namespace is initialized */ |
1520 |
status = acpi_get_handle(NULL, ecdt_ptr->id, &handle); |
1521 |
if (ACPI_FAILURE(status)) { |
1522 |
ret = -EINVAL; |
1523 |
goto error; |
1524 |
} |
1525 |
boot_ec->handle = handle; |
1526 |
ret = acpi_set_boot_ec(boot_ec, false, true); |
1527 |
|
1528 |
error: |
1529 |
if (ret) |
1530 |
acpi_handle_warn(boot_ec->handle, "cannot handle events\n"); |
1531 |
return ret; |
1532 |
} |
1533 |
|
1479 |
int __init acpi_ec_dsdt_probe(void) |
1534 |
int __init acpi_ec_dsdt_probe(void) |
1480 |
{ |
1535 |
{ |
1481 |
acpi_status status; |
1536 |
acpi_status status; |
1482 |
struct acpi_ec *ec; |
1537 |
struct acpi_ec *ec; |
1483 |
int ret; |
1538 |
int ret; |
1484 |
|
1539 |
|
1485 |
ec = acpi_ec_alloc(); |
1540 |
ec = make_acpi_ec(); |
1486 |
if (!ec) |
1541 |
if (!ec) |
1487 |
return -ENOMEM; |
1542 |
return -ENOMEM; |
1488 |
/* |
1543 |
/* |
Lines 1496-1508
int __init acpi_ec_dsdt_probe(void)
Link Here
|
1496 |
ret = -ENODEV; |
1551 |
ret = -ENODEV; |
1497 |
goto error; |
1552 |
goto error; |
1498 |
} |
1553 |
} |
1499 |
ret = ec_install_handlers(ec); |
1554 |
ret = acpi_set_boot_ec(ec, true, true); |
1500 |
|
|
|
1501 |
error: |
1555 |
error: |
1502 |
if (ret) |
1556 |
if (ret) { |
1503 |
kfree(ec); |
1557 |
free_acpi_ec(ec); |
1504 |
else |
1558 |
ret = acpi_ec_ecdt_start(); |
1505 |
first_ec = boot_ec = ec; |
1559 |
} |
1506 |
return ret; |
1560 |
return ret; |
1507 |
} |
1561 |
} |
1508 |
|
1562 |
|
Lines 1577-1583
int __init acpi_ec_ecdt_probe(void)
Link Here
|
1577 |
struct acpi_table_ecdt *ecdt_ptr; |
1631 |
struct acpi_table_ecdt *ecdt_ptr; |
1578 |
struct acpi_ec *ec; |
1632 |
struct acpi_ec *ec; |
1579 |
|
1633 |
|
1580 |
ec = acpi_ec_alloc(); |
1634 |
ec = make_acpi_ec(); |
1581 |
if (!ec) |
1635 |
if (!ec) |
1582 |
return -ENOMEM; |
1636 |
return -ENOMEM; |
1583 |
/* |
1637 |
/* |
Lines 1600-1606
int __init acpi_ec_ecdt_probe(void)
Link Here
|
1600 |
goto error; |
1654 |
goto error; |
1601 |
} |
1655 |
} |
1602 |
|
1656 |
|
1603 |
pr_info("EC description table is found, configuring boot EC\n"); |
|
|
1604 |
if (EC_FLAGS_CORRECT_ECDT) { |
1657 |
if (EC_FLAGS_CORRECT_ECDT) { |
1605 |
ec->command_addr = ecdt_ptr->data.address; |
1658 |
ec->command_addr = ecdt_ptr->data.address; |
1606 |
ec->data_addr = ecdt_ptr->control.address; |
1659 |
ec->data_addr = ecdt_ptr->control.address; |
Lines 1609-1621
int __init acpi_ec_ecdt_probe(void)
Link Here
|
1609 |
ec->data_addr = ecdt_ptr->data.address; |
1662 |
ec->data_addr = ecdt_ptr->data.address; |
1610 |
} |
1663 |
} |
1611 |
ec->gpe = ecdt_ptr->gpe; |
1664 |
ec->gpe = ecdt_ptr->gpe; |
|
|
1665 |
|
1666 |
/* |
1667 |
* At this point, the namespace is not initialized, so it is not |
1668 |
* possible to find the namespace object, and handle events. |
1669 |
*/ |
1612 |
ec->handle = ACPI_ROOT_OBJECT; |
1670 |
ec->handle = ACPI_ROOT_OBJECT; |
1613 |
ret = ec_install_handlers(ec); |
1671 |
ret = acpi_set_boot_ec(ec, true, false); |
1614 |
error: |
1672 |
error: |
1615 |
if (ret) |
1673 |
if (ret) |
1616 |
kfree(ec); |
1674 |
free_acpi_ec(ec); |
1617 |
else |
|
|
1618 |
first_ec = boot_ec = ec; |
1619 |
return ret; |
1675 |
return ret; |
1620 |
} |
1676 |
} |
1621 |
|
1677 |
|