Merge branches 'acpi-ec' and 'acpi-platform'
* acpi-ec: ACPI / EC: Cleanup coding style. ACPI / EC: Refine event/query debugging messages. ACPI / EC: Add detailed command/query debugging information. ACPI / EC: Enhance the logs to apply to QR_EC transactions. ACPI / EC: Add CPU ID to debugging messages. * acpi-platform: ACPI / platform: provide default DMA mask
This commit is contained in:
commit
286180d8d3
|
@ -16,6 +16,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
@ -102,6 +103,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
|
|||
pdevinfo.res = resources;
|
||||
pdevinfo.num_res = count;
|
||||
pdevinfo.acpi_node.companion = adev;
|
||||
pdevinfo.dma_mask = DMA_BIT_MASK(32);
|
||||
pdev = platform_device_register_full(&pdevinfo);
|
||||
if (IS_ERR(pdev))
|
||||
dev_err(&adev->dev, "platform device creation failed: %ld\n",
|
||||
|
|
|
@ -128,12 +128,13 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
|
|||
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Transaction Management
|
||||
-------------------------------------------------------------------------- */
|
||||
* Transaction Management
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
||||
{
|
||||
u8 x = inb(ec->command_addr);
|
||||
|
||||
pr_debug("EC_SC(R) = 0x%2.2x "
|
||||
"SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
|
||||
x,
|
||||
|
@ -148,6 +149,7 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
|||
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
|
||||
{
|
||||
u8 x = inb(ec->data_addr);
|
||||
|
||||
pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
|
||||
return x;
|
||||
}
|
||||
|
@ -164,10 +166,32 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
|
|||
outb(data, ec->data_addr);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *acpi_ec_cmd_string(u8 cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case 0x80:
|
||||
return "RD_EC";
|
||||
case 0x81:
|
||||
return "WR_EC";
|
||||
case 0x82:
|
||||
return "BE_EC";
|
||||
case 0x83:
|
||||
return "BD_EC";
|
||||
case 0x84:
|
||||
return "QR_EC";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
#else
|
||||
#define acpi_ec_cmd_string(cmd) "UNDEF"
|
||||
#endif
|
||||
|
||||
static int ec_transaction_completed(struct acpi_ec *ec)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
|
||||
ret = 1;
|
||||
|
@ -181,7 +205,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
u8 status;
|
||||
bool wakeup = false;
|
||||
|
||||
pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK");
|
||||
pr_debug("===== %s (%d) =====\n",
|
||||
in_interrupt() ? "IRQ" : "TASK", smp_processor_id());
|
||||
status = acpi_ec_read_status(ec);
|
||||
t = ec->curr;
|
||||
if (!t)
|
||||
|
@ -198,7 +223,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
if (t->rlen == t->ri) {
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
if (t->command == ACPI_EC_COMMAND_QUERY)
|
||||
pr_debug("hardware QR_EC completion\n");
|
||||
pr_debug("***** Command(%s) hardware completion *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
wakeup = true;
|
||||
}
|
||||
} else
|
||||
|
@ -221,7 +247,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
t->flags |= ACPI_EC_COMMAND_POLL;
|
||||
t->rdata[t->ri++] = 0x00;
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
pr_debug("software QR_EC completion\n");
|
||||
pr_debug("***** Command(%s) software completion *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
wakeup = true;
|
||||
} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
acpi_ec_write_cmd(ec, t->command);
|
||||
|
@ -264,6 +291,7 @@ static int ec_poll(struct acpi_ec *ec)
|
|||
{
|
||||
unsigned long flags;
|
||||
int repeat = 5; /* number of command restarts */
|
||||
|
||||
while (repeat--) {
|
||||
unsigned long delay = jiffies +
|
||||
msecs_to_jiffies(ec_delay);
|
||||
|
@ -296,18 +324,25 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
|||
{
|
||||
unsigned long tmp;
|
||||
int ret = 0;
|
||||
|
||||
if (EC_FLAGS_MSI)
|
||||
udelay(ACPI_EC_MSI_UDELAY);
|
||||
/* start transaction */
|
||||
spin_lock_irqsave(&ec->lock, tmp);
|
||||
/* following two actions should be kept atomic */
|
||||
ec->curr = t;
|
||||
pr_debug("***** Command(%s) started *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
start_transaction(ec);
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
ret = ec_poll(ec);
|
||||
spin_lock_irqsave(&ec->lock, tmp);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
pr_debug("***** Event stopped *****\n");
|
||||
}
|
||||
pr_debug("***** Command(%s) stopped *****\n",
|
||||
acpi_ec_cmd_string(t->command));
|
||||
ec->curr = NULL;
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
return ret;
|
||||
|
@ -317,6 +352,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
{
|
||||
int status;
|
||||
u32 glk;
|
||||
|
||||
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
|
||||
return -EINVAL;
|
||||
if (t->rdata)
|
||||
|
@ -333,8 +369,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
goto unlock;
|
||||
}
|
||||
}
|
||||
pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
|
||||
t->command, t->wdata ? t->wdata[0] : 0);
|
||||
/* disable GPE during transaction if storm is detected */
|
||||
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
|
||||
/* It has to be disabled, so that it doesn't trigger. */
|
||||
|
@ -355,7 +389,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|||
t->irq_count);
|
||||
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
|
||||
}
|
||||
pr_debug("transaction end\n");
|
||||
if (ec->global_lock)
|
||||
acpi_release_global_lock(glk);
|
||||
unlock:
|
||||
|
@ -383,7 +416,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
|
|||
acpi_ec_transaction(ec, &t) : 0;
|
||||
}
|
||||
|
||||
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
|
||||
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
|
@ -419,10 +452,9 @@ int ec_read(u8 addr, u8 *val)
|
|||
if (!err) {
|
||||
*val = temp_data;
|
||||
return 0;
|
||||
} else
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_read);
|
||||
|
||||
int ec_write(u8 addr, u8 val)
|
||||
|
@ -436,22 +468,21 @@ int ec_write(u8 addr, u8 val)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_write);
|
||||
|
||||
int ec_transaction(u8 command,
|
||||
const u8 * wdata, unsigned wdata_len,
|
||||
u8 * rdata, unsigned rdata_len)
|
||||
const u8 *wdata, unsigned wdata_len,
|
||||
u8 *rdata, unsigned rdata_len)
|
||||
{
|
||||
struct transaction t = {.command = command,
|
||||
.wdata = wdata, .rdata = rdata,
|
||||
.wlen = wdata_len, .rlen = rdata_len};
|
||||
|
||||
if (!first_ec)
|
||||
return -ENODEV;
|
||||
|
||||
return acpi_ec_transaction(first_ec, &t);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_transaction);
|
||||
|
||||
/* Get the handle to the EC device */
|
||||
|
@ -461,7 +492,6 @@ acpi_handle ec_get_handle(void)
|
|||
return NULL;
|
||||
return first_ec->handle;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ec_get_handle);
|
||||
|
||||
/*
|
||||
|
@ -525,13 +555,14 @@ void acpi_ec_unblock_transactions_early(void)
|
|||
clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
|
||||
}
|
||||
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
|
||||
static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data)
|
||||
{
|
||||
int result;
|
||||
u8 d;
|
||||
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
||||
.wdata = NULL, .rdata = &d,
|
||||
.wlen = 0, .rlen = 1};
|
||||
|
||||
if (!ec || !data)
|
||||
return -EINVAL;
|
||||
/*
|
||||
|
@ -557,6 +588,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|||
{
|
||||
struct acpi_ec_query_handler *handler =
|
||||
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
|
||||
|
||||
if (!handler)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -569,12 +601,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|||
mutex_unlock(&ec->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
|
||||
|
||||
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
||||
{
|
||||
struct acpi_ec_query_handler *handler, *tmp;
|
||||
|
||||
mutex_lock(&ec->mutex);
|
||||
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
|
||||
if (query_bit == handler->query_bit) {
|
||||
|
@ -584,20 +616,20 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|||
}
|
||||
mutex_unlock(&ec->mutex);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
||||
|
||||
static void acpi_ec_run(void *cxt)
|
||||
{
|
||||
struct acpi_ec_query_handler *handler = cxt;
|
||||
|
||||
if (!handler)
|
||||
return;
|
||||
pr_debug("start query execution\n");
|
||||
pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
|
||||
if (handler->func)
|
||||
handler->func(handler->data);
|
||||
else if (handler->handle)
|
||||
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
|
||||
pr_debug("stop query execution\n");
|
||||
pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit);
|
||||
kfree(handler);
|
||||
}
|
||||
|
||||
|
@ -620,8 +652,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
|
|||
if (!copy)
|
||||
return -ENOMEM;
|
||||
memcpy(copy, handler, sizeof(*copy));
|
||||
pr_debug("push query execution (0x%2x) on queue\n",
|
||||
value);
|
||||
pr_debug("##### Query(0x%02x) scheduled #####\n",
|
||||
handler->query_bit);
|
||||
return acpi_os_execute((copy->func) ?
|
||||
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
|
||||
acpi_ec_run, copy);
|
||||
|
@ -633,6 +665,7 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
|
|||
static void acpi_ec_gpe_query(void *ec_cxt)
|
||||
{
|
||||
struct acpi_ec *ec = ec_cxt;
|
||||
|
||||
if (!ec)
|
||||
return;
|
||||
mutex_lock(&ec->mutex);
|
||||
|
@ -644,7 +677,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
|
|||
{
|
||||
if (state & ACPI_EC_FLAG_SCI) {
|
||||
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
|
||||
pr_debug("push gpe query to the queue\n");
|
||||
pr_debug("***** Event started *****\n");
|
||||
return acpi_os_execute(OSL_NOTIFY_HANDLER,
|
||||
acpi_ec_gpe_query, ec);
|
||||
}
|
||||
|
@ -667,8 +700,8 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
|
|||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Address Space Management
|
||||
-------------------------------------------------------------------------- */
|
||||
* Address Space Management
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static acpi_status
|
||||
acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
|
@ -699,27 +732,26 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
|||
switch (result) {
|
||||
case -EINVAL:
|
||||
return AE_BAD_PARAMETER;
|
||||
break;
|
||||
case -ENODEV:
|
||||
return AE_NOT_FOUND;
|
||||
break;
|
||||
case -ETIME:
|
||||
return AE_TIME;
|
||||
break;
|
||||
default:
|
||||
return AE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Driver Interface
|
||||
-------------------------------------------------------------------------- */
|
||||
* Driver Interface
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static acpi_status
|
||||
ec_parse_io_ports(struct acpi_resource *resource, void *context);
|
||||
|
||||
static struct acpi_ec *make_acpi_ec(void)
|
||||
{
|
||||
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
||||
|
||||
if (!ec)
|
||||
return NULL;
|
||||
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
|
||||
|
@ -742,9 +774,8 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
|
|||
|
||||
status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
|
||||
|
||||
if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1) {
|
||||
if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1)
|
||||
acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
|
||||
}
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
@ -753,7 +784,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|||
{
|
||||
acpi_status status;
|
||||
unsigned long long tmp = 0;
|
||||
|
||||
struct acpi_ec *ec = context;
|
||||
|
||||
/* clear addr values, ec_parse_io_ports depend on it */
|
||||
|
@ -781,6 +811,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|||
static int ec_install_handlers(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
|
||||
return 0;
|
||||
status = acpi_install_gpe_handler(NULL, ec->gpe,
|
||||
|
@ -1078,7 +1109,8 @@ int __init acpi_ec_ecdt_probe(void)
|
|||
boot_ec->data_addr = ecdt_ptr->data.address;
|
||||
boot_ec->gpe = ecdt_ptr->gpe;
|
||||
boot_ec->handle = ACPI_ROOT_OBJECT;
|
||||
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
|
||||
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
|
||||
&boot_ec->handle);
|
||||
/* Don't trust ECDT, which comes from ASUSTek */
|
||||
if (!EC_FLAGS_VALIDATE_ECDT)
|
||||
goto install;
|
||||
|
@ -1162,6 +1194,5 @@ static void __exit acpi_ec_exit(void)
|
|||
{
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_ec_driver);
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
|
Loading…
Reference in New Issue