Commit 286180d8 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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
......@@ -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;
}
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 */
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