From: Len Brown <len.brown@intel.com>
To: linux-acpi@vger.kernel.org
Cc: Lennart Poettering <mzxreary@0pointer.de>,
Andrew Morton <akpm@osdl.org>, Len Brown <len.brown@intel.com>
Subject: [PATCH 8/28] ACPI: consolidate functions in acpi ec driver
Date: Sat, 14 Oct 2006 04:05:49 -0400
Date: Tue, 5 Sep 2006 12:12:24 -0400 [thread overview]
Message-ID: <11608131774195-git-send-email-len.brown@intel.com> (raw)
Message-ID: <d7a76e4cb3b4469b1eccb6204c053e3ebcd4c196.1160812999.git.len.brown@intel.com> (raw)
In-Reply-To: <11608131691346-git-send-email-len.brown@intel.com>
In-Reply-To: <288f3ad406460f03642a41bb945826891a7b866f.1160812999.git.len.brown@intel.com>
From: Lennart Poettering <mzxreary@0pointer.de>
Unify the following functions:
acpi_ec_poll_read()
acpi_ec_poll_write()
acpi_ec_poll_query()
acpi_ec_intr_read()
acpi_ec_intr_write()
acpi_ec_intr_query()
into:
acpi_ec_poll_transaction()
acpi_ec_intr_transaction()
These new functions take as arguments an ACPI EC command, a few bytes
to write to the EC data register and a buffer for a few bytes to read
from the EC data register. The old _read(), _write(), _query() are
just special cases of these functions.
Then unified the code in acpi_ec_poll_transaction() and
acpi_ec_intr_transaction() a little more. Both functions are now just
wrappers around the new acpi_ec_transaction_unlocked() function. The
latter contains the EC access logic, the two original
function now just do their special way of locking and call the the
new function for the actual work.
This saves a lot of very similar code. The primary reason for doing
this, however, is that my driver for MSI 270 laptops needs to issue
some non-standard EC commands in a safe way. Due to this I added a new
exported function similar to ec_write()/ec_write() which is called
ec_transaction() and is essentially just a wrapper around
acpi_ec_{poll,intr}_transaction().
Signed-off-by: Lennart Poettering <mzxreary@0pointer.de>
Acked-by: Luming Yu <luming.yu@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/ec.c | 325 +++++++++++++++-----------------------------------
include/linux/acpi.h | 3 +
2 files changed, 98 insertions(+), 230 deletions(-)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e5d7963..a0dcbad 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -122,12 +122,12 @@ union acpi_ec {
static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event);
static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event);
-static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data);
-static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data);
-static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data);
-static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data);
+static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len);
+static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len);
static void acpi_ec_gpe_poll_query(void *ec_cxt);
static void acpi_ec_gpe_intr_query(void *ec_cxt);
static u32 acpi_ec_gpe_poll_handler(void *data);
@@ -302,110 +302,95 @@ end:
}
#endif /* ACPI_FUTURE_USAGE */
-static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_transaction(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len)
{
if (acpi_ec_poll_mode)
- return acpi_ec_poll_read(ec, address, data);
+ return acpi_ec_poll_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
else
- return acpi_ec_intr_read(ec, address, data);
+ return acpi_ec_intr_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
+}
+static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
+{
+ int result;
+ u8 d;
+ result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, &address, 1, &d, 1);
+ *data = d;
+ return result;
}
static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
{
- if (acpi_ec_poll_mode)
- return acpi_ec_poll_write(ec, address, data);
- else
- return acpi_ec_intr_write(ec, address, data);
+ u8 wdata[2] = { address, data };
+ return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, wdata, 2, NULL, 0);
}
-static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data)
+
+static int acpi_ec_transaction_unlocked(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len)
{
- acpi_status status = AE_OK;
- int result = 0;
- u32 glk = 0;
+ int result;
+ acpi_hw_low_level_write(8, command, &ec->common.command_addr);
- if (!ec || !data)
- return -EINVAL;
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ return result;
- *data = 0;
+ for (; wdata_len > 0; wdata_len --) {
- if (ec->common.global_lock) {
- status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
- if (ACPI_FAILURE(status))
- return -ENODEV;
- }
+ acpi_hw_low_level_write(8, *(wdata++), &ec->common.data_addr);
- if (down_interruptible(&ec->poll.sem)) {
- result = -ERESTARTSYS;
- goto end_nosem;
- }
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
- &ec->common.command_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (result)
- goto end;
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
+ if (result)
+ return result;
+ }
- acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (result)
- goto end;
- acpi_hw_low_level_read(8, data, &ec->common.data_addr);
+ for (; rdata_len > 0; rdata_len --) {
+ u32 d;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
+ result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
+ if (result)
+ return result;
- end:
- up(&ec->poll.sem);
-end_nosem:
- if (ec->common.global_lock)
- acpi_release_global_lock(glk);
+ acpi_hw_low_level_read(8, &d, &ec->common.data_addr);
+ *(rdata++) = (u8) d;
+ }
- return result;
+ return 0;
}
-static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data)
+static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len)
{
- int result = 0;
acpi_status status = AE_OK;
+ int result;
u32 glk = 0;
-
- if (!ec)
+ if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
return -EINVAL;
+ if (rdata)
+ memset(rdata, 0, rdata_len);
+
if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status))
return -ENODEV;
- }
+ }
if (down_interruptible(&ec->poll.sem)) {
result = -ERESTARTSYS;
goto end_nosem;
}
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
- &ec->common.command_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (result)
- goto end;
- acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (result)
- goto end;
-
- acpi_hw_low_level_write(8, data, &ec->common.data_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (result)
- goto end;
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
-
- end:
+ result = acpi_ec_transaction_unlocked(ec, command,
+ wdata, wdata_len,
+ rdata, rdata_len);
up(&ec->poll.sem);
+
end_nosem:
if (ec->common.global_lock)
acpi_release_global_lock(glk);
@@ -413,16 +398,18 @@ end_nosem:
return result;
}
-static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data)
+static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len)
{
- int status = 0;
+ int status;
u32 glk;
-
- if (!ec || !data)
+ if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
return -EINVAL;
- *data = 0;
+ if (rdata)
+ memset(rdata, 0, rdata_len);
if (ec->common.global_lock) {
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
@@ -438,72 +425,12 @@ static int acpi_ec_intr_read(union acpi_
printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
goto end;
}
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
- &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status) {
- printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
- }
-
- acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status) {
- printk(KERN_DEBUG PREFIX "read EC, OB not full\n");
- goto end;
- }
- acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n",
- *data, address));
-
- end:
- up(&ec->intr.sem);
-
- if (ec->common.global_lock)
- acpi_release_global_lock(glk);
-
- return status;
-}
-
-static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data)
-{
- int status = 0;
- u32 glk;
-
-
- if (!ec)
- return -EINVAL;
-
- if (ec->common.global_lock) {
- status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
- if (ACPI_FAILURE(status))
- return -ENODEV;
- }
-
- WARN_ON(in_interrupt());
- down(&ec->intr.sem);
-
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status) {
- printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
- }
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
- &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status) {
- printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
- }
-
- acpi_hw_low_level_write(8, address, &ec->common.data_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status) {
- printk(KERN_DEBUG PREFIX "write EC, IB not empty\n");
- }
- acpi_hw_low_level_write(8, data, &ec->common.data_addr);
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
- data, address));
+ status = acpi_ec_transaction_unlocked(ec, command,
+ wdata, wdata_len,
+ rdata, rdata_len);
+end:
up(&ec->intr.sem);
if (ec->common.global_lock)
@@ -554,106 +481,44 @@ int ec_write(u8 addr, u8 val)
EXPORT_SYMBOL(ec_write);
-static int acpi_ec_query(union acpi_ec *ec, u32 * data)
-{
- if (acpi_ec_poll_mode)
- return acpi_ec_poll_query(ec, data);
- else
- return acpi_ec_intr_query(ec, data);
-}
-static int acpi_ec_poll_query(union acpi_ec *ec, u32 * data)
+extern int ec_transaction(u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len)
{
- int result = 0;
- acpi_status status = AE_OK;
- u32 glk = 0;
-
-
- if (!ec || !data)
- return -EINVAL;
-
- *data = 0;
-
- if (ec->common.global_lock) {
- status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
- if (ACPI_FAILURE(status))
- return -ENODEV;
- }
-
- /*
- * Query the EC to find out which _Qxx method we need to evaluate.
- * Note that successful completion of the query causes the ACPI_EC_SCI
- * bit to be cleared (and thus clearing the interrupt source).
- */
- if (down_interruptible(&ec->poll.sem)) {
- result = -ERESTARTSYS;
- goto end_nosem;
- }
-
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
- &ec->common.command_addr);
- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (result)
- goto end;
+ union acpi_ec *ec;
- acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- if (!*data)
- result = -ENODATA;
+ if (!first_ec)
+ return -ENODEV;
- end:
- up(&ec->poll.sem);
-end_nosem:
- if (ec->common.global_lock)
- acpi_release_global_lock(glk);
+ ec = acpi_driver_data(first_ec);
- return result;
+ return acpi_ec_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
}
-static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data)
-{
- int status = 0;
- u32 glk;
+EXPORT_SYMBOL(ec_transaction);
- if (!ec || !data)
- return -EINVAL;
- *data = 0;
+static int acpi_ec_query(union acpi_ec *ec, u32 * data) {
+ int result;
+ u8 d;
- if (ec->common.global_lock) {
- status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
- if (ACPI_FAILURE(status))
- return -ENODEV;
- }
+ if (!ec || !data)
+ return -EINVAL;
- down(&ec->intr.sem);
+ /*
+ * Query the EC to find out which _Qxx method we need to evaluate.
+ * Note that successful completion of the query causes the ACPI_EC_SCI
+ * bit to be cleared (and thus clearing the interrupt source).
+ */
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
- if (status) {
- printk(KERN_DEBUG PREFIX "query EC, IB not empty\n");
- goto end;
- }
- /*
- * Query the EC to find out which _Qxx method we need to evaluate.
- * Note that successful completion of the query causes the ACPI_EC_SCI
- * bit to be cleared (and thus clearing the interrupt source).
- */
- acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
- &ec->common.command_addr);
- status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status) {
- printk(KERN_DEBUG PREFIX "query EC, OB not full\n");
- goto end;
- }
-
- acpi_hw_low_level_read(8, data, &ec->common.data_addr);
- if (!*data)
- status = -ENODATA;
+ result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+ if (result)
+ return result;
- end:
- up(&ec->intr.sem);
+ if (!d)
+ return -ENODATA;
- if (ec->common.global_lock)
- acpi_release_global_lock(glk);
-
- return status;
+ *data = d;
+ return 0;
}
/* --------------------------------------------------------------------------
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 88b5dfd..2b0c955 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -494,6 +494,9 @@ #ifdef CONFIG_ACPI_EC
extern int ec_read(u8 addr, u8 *val);
extern int ec_write(u8 addr, u8 val);
+extern int ec_transaction(u8 command,
+ const u8 *wdata, unsigned wdata_len,
+ u8 *rdata, unsigned rdata_len);
#endif /*CONFIG_ACPI_EC*/
--
1.4.3.rc2.g23bed-dirty
next prev parent reply other threads:[~2006-10-14 8:02 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-10-14 8:05 ACPI patches pushed to linux-2.6.19-rc2 Len Brown
2006-10-14 8:05 ` [PATCH 1/28] ACPI: asus_acpi: W3000 support Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 2/28] ACPI: ibm_acpi: Remove experimental status for brightness and volume Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 3/28] ACPI: ibm_acpi: Update documentation " Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 4/28] ACPI: ibm_acpi: Documentation the wan feature Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 5/28] ACPI: sbs: check for NULL device pointer Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 6/28] ACPI: sbs: fix module_param() initializers Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 7/28] ACPI: Processor native C-states using MWAIT Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` Len Brown [this message]
2006-10-14 8:05 ` [PATCH 8/28] ACPI: consolidate functions in acpi ec driver Len Brown
2006-10-14 8:05 ` [PATCH 14/28] ACPI: EC: export ec_transaction() for msi-laptop driver Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 15/28] MSI S270 Laptop support: backlight, wlan, bluetooth states Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:05 ` [PATCH 18/28] ACPI: ibm_acpi: delete obsolete documentation Len Brown
2006-10-14 8:05 ` Len Brown
2006-10-14 8:06 ` [PATCH 19/28] ACPI: fix potential OOPS in power driver with CONFIG_ACPI_DEBUG Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 20/28] ACPI: acpi_pci_link_set() can allocate with either GFP_ATOMIC or GFP_KERNEL Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 21/28] ACPI: update comments in motherboard.c Len Brown
2006-10-14 8:06 ` Len Brown
2007-01-07 4:56 ` Bjorn Helgaas
2006-10-14 8:06 ` [PATCH 22/28] ACPI: fix section for CPU init functions Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 23/28] ACPI: fix printk format warnings Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 24/28] ACPI: SCI interrupt source override Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 25/28] ACPI: asus_acpi: fix proc files parsing Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 26/28] ACPI: asus_acpi: don't printk on writing garbage to proc files Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 27/28] ACPICA: Fix incorrect handling of PCI Express Root Bridge _HID Len Brown
2006-10-14 8:06 ` Len Brown
2006-10-14 8:06 ` [PATCH 28/28] ACPI: check battery status on resume for un/plug events during sleep Len Brown
2006-10-14 8:06 ` Len Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11608131774195-git-send-email-len.brown@intel.com \
--to=len.brown@intel.com \
--cc=akpm@osdl.org \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=mzxreary@0pointer.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.