Commit 762caf0b authored by Len Brown's avatar Len Brown
Browse files

Merge branch 'ec' into release



Conflicts:
	drivers/acpi/ec.c

Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parents 3b87bb64 f25752e6
Loading
Loading
Loading
Loading
+50 −100
Original line number Diff line number Diff line
@@ -67,15 +67,13 @@ enum ec_command {
#define ACPI_EC_DELAY		500	/* Wait 500ms max. during EC ops */
#define ACPI_EC_UDELAY_GLK	1000	/* Wait 1ms max. to get global lock */
#define ACPI_EC_CDELAY		10	/* Wait 10us before polling EC */
#define ACPI_EC_MSI_UDELAY	550	/* Wait 550us for MSI EC */

#define ACPI_EC_STORM_THRESHOLD 8	/* number of false interrupts
					   per one transaction */

enum {
	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
	EC_FLAGS_GPE_MODE,		/* Expect GPE to be sent
					 * for status change */
	EC_FLAGS_NO_GPE,		/* Don't use GPE mode */
	EC_FLAGS_GPE_STORM,		/* GPE storm detected */
	EC_FLAGS_HANDLERS_INSTALLED	/* Handlers for GPE and
					 * OpReg are installed */
@@ -169,7 +167,7 @@ static void start_transaction(struct acpi_ec *ec)
	acpi_ec_write_cmd(ec, ec->curr->command);
}

static void gpe_transaction(struct acpi_ec *ec, u8 status)
static void advance_transaction(struct acpi_ec *ec, u8 status)
{
	unsigned long flags;
	spin_lock_irqsave(&ec->curr_lock, flags);
@@ -200,29 +198,6 @@ unlock:
	spin_unlock_irqrestore(&ec->curr_lock, flags);
}

static int acpi_ec_wait(struct acpi_ec *ec)
{
	if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
			       msecs_to_jiffies(ACPI_EC_DELAY)))
		return 0;
	/* try restart command if we get any false interrupts */
	if (ec->curr->irq_count &&
	    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
		pr_debug(PREFIX "controller reset, restart transaction\n");
		start_transaction(ec);
		if (wait_event_timeout(ec->wait, ec_transaction_done(ec),
					msecs_to_jiffies(ACPI_EC_DELAY)))
			return 0;
	}
	/* missing GPEs, switch back to poll mode */
	if (printk_ratelimit())
		pr_info(PREFIX "missing confirmations, "
				"switch off interrupt mode.\n");
	set_bit(EC_FLAGS_NO_GPE, &ec->flags);
	clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
	return 1;
}

static void acpi_ec_gpe_query(void *ec_cxt);

static int ec_check_sci(struct acpi_ec *ec, u8 state)
@@ -235,43 +210,51 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
	return 0;
}

static void ec_delay(void)
{
	/* EC in MSI notebooks don't tolerate delays other than 550 usec */
	if (EC_FLAGS_MSI)
		udelay(ACPI_EC_DELAY);
	else
		/* Use shortest sleep available */
		msleep(1);
}

static int ec_poll(struct acpi_ec *ec)
{
	unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
	udelay(ACPI_EC_CDELAY);
	while (time_before(jiffies, delay)) {
		gpe_transaction(ec, acpi_ec_read_status(ec));
		ec_delay();
	unsigned long flags;
	int repeat = 2; /* number of command restarts */
	while (repeat--) {
		unsigned long delay = jiffies +
			msecs_to_jiffies(ACPI_EC_DELAY);
		do {
			/* don't sleep with disabled interrupts */
			if (EC_FLAGS_MSI || irqs_disabled()) {
				udelay(ACPI_EC_MSI_UDELAY);
				if (ec_transaction_done(ec))
					return 0;
			} else {
				if (wait_event_timeout(ec->wait,
						ec_transaction_done(ec),
						msecs_to_jiffies(1)))
					return 0;
			}
			advance_transaction(ec, acpi_ec_read_status(ec));
		} while (time_before(jiffies, delay));
		if (!ec->curr->irq_count ||
		    (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
			break;
		/* try restart command if we get any false interrupts */
		pr_debug(PREFIX "controller reset, restart transaction\n");
		spin_lock_irqsave(&ec->curr_lock, flags);
		start_transaction(ec);
		spin_unlock_irqrestore(&ec->curr_lock, flags);
	}
	return -ETIME;
}

static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
					struct transaction *t,
					int force_poll)
					struct transaction *t)
{
	unsigned long tmp;
	int ret = 0;
	pr_debug(PREFIX "transaction start\n");
	/* disable GPE during transaction if storm is detected */
	if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
		clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
		acpi_disable_gpe(NULL, ec->gpe);
	}
	if (EC_FLAGS_MSI)
		udelay(ACPI_EC_DELAY);
		udelay(ACPI_EC_MSI_UDELAY);
	/* start transaction */
	spin_lock_irqsave(&ec->curr_lock, tmp);
	/* following two actions should be kept atomic */
@@ -280,10 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
	if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
		clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
	spin_unlock_irqrestore(&ec->curr_lock, tmp);
	/* if we selected poll mode or failed in GPE-mode do a poll loop */
	if (force_poll ||
	    !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ||
	    acpi_ec_wait(ec))
	ret = ec_poll(ec);
	pr_debug(PREFIX "transaction end\n");
	spin_lock_irqsave(&ec->curr_lock, tmp);
@@ -294,8 +273,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
		ec_check_sci(ec, acpi_ec_read_status(ec));
		/* it is safe to enable GPE outside of transaction */
		acpi_enable_gpe(NULL, ec->gpe);
	} else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
		   t->irq_count > ACPI_EC_STORM_THRESHOLD) {
	} else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
		pr_info(PREFIX "GPE storm detected, "
			"transactions will use polling mode\n");
		set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
@@ -313,16 +291,14 @@ static int ec_wait_ibf0(struct acpi_ec *ec)
{
	unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
	/* interrupt wait manually if GPE mode is not active */
	unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ?
		msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1);
	while (time_before(jiffies, delay))
		if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout))
		if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
					msecs_to_jiffies(1)))
			return 0;
	return -ETIME;
}

static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
			       int force_poll)
static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
{
	int status;
	u32 glk;
@@ -344,7 +320,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t,
		status = -ETIME;
		goto end;
	}
	status = acpi_ec_transaction_unlocked(ec, t, force_poll);
	status = acpi_ec_transaction_unlocked(ec, t);
end:
	if (ec->global_lock)
		acpi_release_global_lock(glk);
@@ -353,10 +329,6 @@ unlock:
	return status;
}

/*
 * Note: samsung nv5000 doesn't work with ec burst mode.
 * http://bugzilla.kernel.org/show_bug.cgi?id=4980
 */
static int acpi_ec_burst_enable(struct acpi_ec *ec)
{
	u8 d;
@@ -364,7 +336,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
				.wdata = NULL, .rdata = &d,
				.wlen = 0, .rlen = 1};

	return acpi_ec_transaction(ec, &t, 0);
	return acpi_ec_transaction(ec, &t);
}

static int acpi_ec_burst_disable(struct acpi_ec *ec)
@@ -374,7 +346,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
				.wlen = 0, .rlen = 0};

	return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
				acpi_ec_transaction(ec, &t, 0) : 0;
				acpi_ec_transaction(ec, &t) : 0;
}

static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@@ -385,7 +357,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
				.wdata = &address, .rdata = &d,
				.wlen = 1, .rlen = 1};

	result = acpi_ec_transaction(ec, &t, 0);
	result = acpi_ec_transaction(ec, &t);
	*data = d;
	return result;
}
@@ -397,7 +369,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
				.wdata = wdata, .rdata = NULL,
				.wlen = 2, .rlen = 0};

	return acpi_ec_transaction(ec, &t, 0);
	return acpi_ec_transaction(ec, &t);
}

/*
@@ -465,7 +437,7 @@ int ec_transaction(u8 command,
	if (!first_ec)
		return -ENODEV;

	return acpi_ec_transaction(first_ec, &t, force_poll);
	return acpi_ec_transaction(first_ec, &t);
}

EXPORT_SYMBOL(ec_transaction);
@@ -486,7 +458,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
	 * bit to be cleared (and thus clearing the interrupt source).
	 */

	result = acpi_ec_transaction(ec, &t, 0);
	result = acpi_ec_transaction(ec, &t);
	if (result)
		return result;

@@ -569,28 +541,10 @@ static u32 acpi_ec_gpe_handler(void *data)
	pr_debug(PREFIX "~~~> interrupt\n");
	status = acpi_ec_read_status(ec);

	if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) {
		gpe_transaction(ec, status);
		if (ec_transaction_done(ec) &&
		    (status & ACPI_EC_FLAG_IBF) == 0)
	advance_transaction(ec, status);
	if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0)
		wake_up(&ec->wait);
	}

	ec_check_sci(ec, status);
	if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) &&
	    !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) {
		/* this is non-query, must be confirmation */
		if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
			if (printk_ratelimit())
				pr_info(PREFIX "non-query interrupt received,"
					" switching to interrupt mode\n");
		} else {
			/* hush, STORM switches the mode every transaction */
			pr_debug(PREFIX "non-query interrupt received,"
				" switching to interrupt mode\n");
		}
		set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
	}
	return ACPI_INTERRUPT_HANDLED;
}

@@ -616,6 +570,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
	if (bits != 8 && acpi_strict)
		return AE_BAD_PARAMETER;

	if (EC_FLAGS_MSI)
		acpi_ec_burst_enable(ec);

	if (function == ACPI_READ) {
@@ -637,6 +592,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
		}
	}

	if (EC_FLAGS_MSI)
		acpi_ec_burst_disable(ec);

	switch (result) {
@@ -871,8 +827,6 @@ static int acpi_ec_add(struct acpi_device *device)
	acpi_ec_add_fs(device);
	pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
			  ec->gpe, ec->command_addr, ec->data_addr);
	pr_info(PREFIX "driver started in %s mode\n",
		(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");

	ret = ec_install_handlers(ec);

@@ -1025,8 +979,6 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state)
{
	struct acpi_ec *ec = acpi_driver_data(device);
	/* Stop using GPE */
	set_bit(EC_FLAGS_NO_GPE, &ec->flags);
	clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
	acpi_disable_gpe(NULL, ec->gpe);
	return 0;
}
@@ -1035,8 +987,6 @@ static int acpi_ec_resume(struct acpi_device *device)
{
	struct acpi_ec *ec = acpi_driver_data(device);
	/* Enable use of GPE back */
	clear_bit(EC_FLAGS_NO_GPE, &ec->flags);
	set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
	acpi_enable_gpe(NULL, ec->gpe);
	return 0;
}