Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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",
+69 −38
Original line number Diff line number Diff line
@@ -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:
@@ -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,7 +468,6 @@ int ec_write(u8 addr, u8 val)

	return err;
}

EXPORT_SYMBOL(ec_write);

int ec_transaction(u8 command,
@@ -446,12 +477,12 @@ int ec_transaction(u8 command,
	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);

/*
@@ -532,6 +562,7 @@ static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
	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 */