From: Shem Multinymous <multinymous@gmail.com>
To: Robert Love <rlove@rlove.org>
Cc: Jean Delvare <khali@linux-fr.org>,
Greg Kroah-Hartman <gregkh@suse.de>,
Alan Cox <alan@lxorguk.ukuu.org.uk>,
linux-kernel@vger.kernel.org, hdaps-devel@lists.sourceforge.net
Subject: [PATCH 03/12] hdaps: Unify and cache hdaps readouts
Date: Sun, 06 Aug 2006 10:26:48 +0300 [thread overview]
Message-ID: <1154849246822-git-send-email-multinymous@gmail.com> (raw)
In-Reply-To: <11548492171301-git-send-email-multinymous@gmail.com>
The current hdaps driver queries the hardware on (almost) any sysfs
read, reading just the information it needs and discarding the rest
This is inefficient, because every hardware query actually gives all
information. It also means we're losing data, because readouts are
offered by the hardware at a constant rate and each query "eats up"
a readout. It also results in unnecessarily complex code.
This patch moves all hardware value reading+parsing to a single
function, __hdaps_update(). All values are cached, and easily
referenced afterwards. This function is still invoked on every sysfs
read. This will be fixed in a later patch.
Signed-off-by: Shem Multinymous <multinymous@gmail.com>
---
hdaps.c | 152 +++++++++++++++++++++++++++++-----------------------------------
1 file changed, 71 insertions(+), 81 deletions(-)
diff -up a/drivers/hwmon/hdaps.c a/drivers/hwmon/hdaps.c
--- a/drivers/hwmon/hdaps.c
+++ a/drivers/hwmon/hdaps.c
@@ -63,66 +63,66 @@ static struct timer_list hdaps_timer;
static struct platform_device *pdev;
static struct input_dev *hdaps_idev;
static unsigned int hdaps_invert;
+
+/* Latest state readout */
+static int pos_x, pos_y; /* position */
+static int var_x, var_y; /* variance (what is this?) */
+static u8 temp1, temp2; /* temperatures */
static u8 km_activity;
-static int rest_x;
-static int rest_y;
+static int rest_x, rest_y; /* calibrated rest position */
-/*
- * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
- * the given pointer. Returns zero on success or a negative error on failure.
- * Can sleep.
+
+/* __hdaps_update - read current state and update global state variables.
+ * Also prefetches the next read, to reduce udelay busy-waiting.
+ * If fast!=0, do one quick attempt without retries.
+ * Caller must hold controller lock.
*/
-static int hdaps_readb_one(unsigned int port, u8 *val)
+static int __hdaps_update(int fast)
{
- int ret;
+ /* Read data: */
struct thinkpad_ec_row data;
-
- ret = thinkpad_ec_lock();
- if (ret)
- return ret;
- data.mask = (1 << port);
- ret = thinkpad_ec_read_row(&ec_accel_args, &data);
- *val = data.val[port];
- thinkpad_ec_unlock();
- return ret;
-}
-
-/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
-static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
- int *x, int *y)
-{
int ret;
- struct thinkpad_ec_row data;
- data.mask = (3 << port1) | (3 << port2) | (1 << EC_ACCEL_IDX_KMACT);
- ret = thinkpad_ec_read_row(&ec_accel_args, &data);
+ data.mask = (1 << EC_ACCEL_IDX_KMACT) |
+ (3 << EC_ACCEL_IDX_YPOS1) | (3 << EC_ACCEL_IDX_XPOS1) |
+ (3 << EC_ACCEL_IDX_YPOS2) | (3 << EC_ACCEL_IDX_XPOS2) |
+ (1 << EC_ACCEL_IDX_TEMP1) | (1 << EC_ACCEL_IDX_TEMP2);
+ if (fast)
+ ret = thinkpad_ec_try_read_row(&ec_accel_args, &data);
+ else
+ ret = thinkpad_ec_read_row(&ec_accel_args, &data);
+ thinkpad_ec_prefetch_row(&ec_accel_args); /* Prefetch even if error */
if (ret)
return ret;
- *x = *(s16*)(data.val+port1);
- *y = *(s16*)(data.val+port2);
+ /* Parse position data: */
+ pos_x = *(s16*)(data.val+EC_ACCEL_IDX_XPOS1) * (hdaps_invert?-1:1);
+ pos_y = *(s16*)(data.val+EC_ACCEL_IDX_YPOS1) * (hdaps_invert?-1:1);
+
+ /* Parse so-called "variance" data: */
+ var_x = *(s16*)(data.val+EC_ACCEL_IDX_XPOS2) * (hdaps_invert?-1:1);
+ var_y = *(s16*)(data.val+EC_ACCEL_IDX_YPOS2) * (hdaps_invert?-1:1);
+
km_activity = data.val[EC_ACCEL_IDX_KMACT];
- /* if hdaps_invert is set, negate the two values */
- if (hdaps_invert) {
- *x = -*x;
- *y = -*y;
- }
+ temp1 = data.val[EC_ACCEL_IDX_TEMP1];
+ temp2 = data.val[EC_ACCEL_IDX_TEMP2];
return 0;
}
-/*
- * hdaps_read_pair - reads the values from a pair of ports, placing the values
- * in the given pointers. Returns zero on success. Can sleep.
+/* hdaps_update - read current state and update global state variables.
+ * Also prefetches the next read, to reduce udelay busy-waiting.
+ * Retries until timeout if the accelerometer is not in ready status (common).
+ * Does its own locking.
*/
-static int hdaps_read_pair(unsigned int port1, unsigned int port2,
- int *val1, int *val2)
+static int hdaps_update(void)
{
- int ret = thinkpad_ec_lock();
+ int ret;
+ ret = thinkpad_ec_lock();
if (ret)
return ret;
- ret = __hdaps_read_pair(port1, port2, val1, val2);
+ ret = __hdaps_update(0);
thinkpad_ec_unlock();
return ret;
}
@@ -237,34 +237,41 @@ static struct platform_driver hdaps_driv
};
/*
- * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
+ * hdaps_calibrate - Set our "resting" values. Does its own locking.
*/
static void hdaps_calibrate(void)
{
- __hdaps_read_pair(EC_ACCEL_IDX_XPOS1, EC_ACCEL_IDX_YPOS1, &rest_x, &rest_y);
+ hdaps_update();
+ rest_x = pos_x;
+ rest_y = pos_y;
}
+/* Timer handler for updating the input device. Runs in softirq context,
+ * so avoid lenghty or blocking operations.
+ */
static void hdaps_mousedev_poll(unsigned long unused)
{
- int x, y;
+ int ret;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (thinkpad_ec_try_lock()) {
- mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
+ if (thinkpad_ec_try_lock())
+ goto keep_active;
+
+ ret = __hdaps_update(1); /* fast update, we're in softirq context */
+ thinkpad_ec_unlock();
+ /* Any of "successful", "not yet ready" and "not prefetched"? */
+ if (ret!=0 && ret!=-EBUSY && ret!=-ENODATA) {
+ printk(KERN_ERR
+ "hdaps: poll failed, disabling mousedev updates\n");
return;
}
- if (__hdaps_read_pair(EC_ACCEL_IDX_XPOS1, EC_ACCEL_IDX_YPOS1, &x, &y))
- goto out;
-
- input_report_abs(hdaps_idev, ABS_X, x - rest_x);
- input_report_abs(hdaps_idev, ABS_Y, y - rest_y);
+keep_active:
+ /* Even if we failed now, pos_x,y may have been updated earlier: */
+ input_report_abs(hdaps_idev, ABS_X, pos_x - rest_x);
+ input_report_abs(hdaps_idev, ABS_Y, pos_y - rest_y);
input_sync(hdaps_idev);
-
mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
-
-out:
- thinkpad_ec_unlock();
}
@@ -273,51 +280,37 @@ out:
static ssize_t hdaps_position_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret, x, y;
-
- ret = hdaps_read_pair(EC_ACCEL_IDX_XPOS1, EC_ACCEL_IDX_YPOS1, &x, &y);
+ int ret = hdaps_update();
if (ret)
return ret;
-
- return sprintf(buf, "(%d,%d)\n", x, y);
+ return sprintf(buf, "(%d,%d)\n", pos_x, pos_y);
}
static ssize_t hdaps_variance_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- int ret, x, y;
-
- ret = hdaps_read_pair(EC_ACCEL_IDX_XPOS2, EC_ACCEL_IDX_YPOS2, &x, &y);
+ int ret = hdaps_update();
if (ret)
return ret;
-
- return sprintf(buf, "(%d,%d)\n", x, y);
+ return sprintf(buf, "(%d,%d)\n", var_x, var_y);
}
static ssize_t hdaps_temp1_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- u8 temp;
- int ret;
-
- ret = hdaps_readb_one(EC_ACCEL_IDX_TEMP1, &temp);
- if (ret < 0)
+ int ret = hdaps_update();
+ if (ret)
return ret;
-
- return sprintf(buf, "%u\n", temp);
+ return sprintf(buf, "%u\n", temp1);
}
static ssize_t hdaps_temp2_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- u8 temp;
- int ret;
-
- ret = hdaps_readb_one(EC_ACCEL_IDX_TEMP2, &temp);
- if (ret < 0)
+ int ret = hdaps_update();
+ if (ret)
return ret;
-
- return sprintf(buf, "%u\n", temp);
+ return sprintf(buf, "%u\n", temp2);
}
static ssize_t hdaps_keyboard_activity_show(struct device *dev,
@@ -344,10 +337,7 @@ static ssize_t hdaps_calibrate_store(str
struct device_attribute *attr,
const char *buf, size_t count)
{
- if (thinkpad_ec_lock())
- return -EIO;
hdaps_calibrate();
- thinkpad_ec_unlock();
return count;
}
next prev parent reply other threads:[~2006-08-06 7:33 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-08-06 7:26 [PATCH 00/12] ThinkPad embedded controller and hdaps drivers Shem Multinymous
2006-08-06 7:26 ` [PATCH 01/12] thinkpad_ec: New driver for ThinkPad embedded controller access Shem Multinymous
2006-08-06 7:56 ` Andrew Morton
2006-08-06 9:56 ` Shem Multinymous
2006-08-06 10:07 ` Andrew Morton
2006-08-06 10:44 ` Shem Multinymous
2006-08-06 14:55 ` Theodore Tso
2006-08-06 16:40 ` Olaf Hering
2006-08-06 16:55 ` Willy Tarreau
2006-08-06 18:40 ` Andrew Morton
2006-08-06 22:31 ` Shem Multinymous
2006-08-06 22:08 ` Shem Multinymous
2006-08-07 0:56 ` [Hdaps-devel] " Shawn Starr
2006-08-07 3:40 ` Theodore Tso
2006-08-06 18:53 ` Arjan van de Ven
2006-08-06 22:41 ` Shem Multinymous
2006-08-06 22:56 ` Greg KH
2006-08-06 23:13 ` Arjan van de Ven
2006-08-07 13:26 ` Pavel Machek
2006-08-07 19:23 ` Andrew Morton
2006-08-07 23:20 ` Pavel Machek
2006-08-07 13:47 ` Pavel Machek
2006-08-07 13:44 ` Pavel Machek
2006-08-07 15:13 ` Shem Multinymous
2006-08-07 16:27 ` Björn Steinbrink
2006-08-07 16:41 ` Shem Multinymous
2006-08-07 16:54 ` Björn Steinbrink
2006-08-07 23:17 ` Pavel Machek
2006-08-07 23:15 ` Pavel Machek
2006-08-07 23:23 ` Greg KH
2006-08-07 23:25 ` Pavel Machek
2006-08-07 23:29 ` Greg KH
2006-08-07 23:37 ` [PATCH] pr_debug() should not be used in drivers Pavel Machek
2006-08-08 9:44 ` [PATCH 01/12] thinkpad_ec: New driver for ThinkPad embedded controller access Shem Multinymous
2006-08-08 9:23 ` Shem Multinymous
2006-08-08 9:39 ` Pavel Machek
2006-08-07 23:39 ` Randy.Dunlap
2006-08-06 7:26 ` [PATCH 02/12] hdaps: Use thinkpad_ec instead of direct port access Shem Multinymous
2006-08-07 13:55 ` Pavel Machek
2006-08-07 15:40 ` Shem Multinymous
2006-08-07 23:22 ` Pavel Machek
2006-08-06 7:26 ` Shem Multinymous [this message]
2006-08-07 14:02 ` [PATCH 03/12] hdaps: Unify and cache hdaps readouts Pavel Machek
2006-08-07 16:14 ` Shem Multinymous
2006-08-07 23:24 ` Pavel Machek
2006-08-08 9:16 ` Shem Multinymous
2006-08-08 9:21 ` Pavel Machek
2006-08-08 10:06 ` Shem Multinymous
2006-08-08 10:09 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 04/12] hdaps: Correct readout and remove nonsensical attributes Shem Multinymous
2006-08-07 14:07 ` Pavel Machek
2006-08-07 16:30 ` Shem Multinymous
2006-08-07 18:20 ` Björn Steinbrink
2006-08-07 23:30 ` timeout nonsense [was Re: [PATCH 04/12] hdaps: Correct readout and remove nonsensical attributes] Pavel Machek
2006-08-08 12:22 ` [PATCH 04/12] hdaps: Correct readout and remove nonsensical attributes Muli Ben-Yehuda
2006-08-08 12:56 ` Pavel Machek
2006-08-08 13:17 ` Muli Ben-Yehuda
2006-08-08 13:35 ` Shem Multinymous
2006-08-08 13:43 ` Muli Ben-Yehuda
2006-08-08 14:53 ` Shem Multinymous
2006-08-08 15:19 ` Alan Cox
2006-08-08 15:33 ` Shem Multinymous
2006-08-09 3:44 ` Muli Ben-Yehuda
2006-08-09 9:02 ` Shem Multinymous
2006-08-09 9:56 ` Muli Ben-Yehuda
2006-08-07 23:26 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 05/12] hdaps: Remember keyboard and mouse activity Shem Multinymous
2006-08-07 14:11 ` Pavel Machek
2006-08-07 16:19 ` Shem Multinymous
2006-08-06 7:26 ` [PATCH 06/12] hdaps: Limit hardware query rate Shem Multinymous
2006-08-08 12:08 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 07/12] hdaps: delay calibration to first hardware query Shem Multinymous
2006-08-08 12:10 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 08/12] hdaps: Add explicit hardware configuration functions Shem Multinymous
2006-08-08 12:16 ` Pavel Machek
2006-08-08 13:17 ` Shem Multinymous
2006-08-06 7:26 ` [PATCH 09/12] hdaps: Add new sysfs attributes Shem Multinymous
2006-08-08 12:19 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 10/12] hdaps: Power off accelerometer on suspend and unload Shem Multinymous
2006-08-08 12:45 ` Pavel Machek
2006-08-08 13:28 ` Shem Multinymous
2006-08-06 7:26 ` [PATCH 11/12] hdaps: Stop polling timer when suspended Shem Multinymous
2006-08-08 12:46 ` Pavel Machek
2006-08-06 7:26 ` [PATCH 12/12] hdaps: Simplify whitelist Shem Multinymous
2006-08-08 12:47 ` Pavel Machek
-- strict thread matches above, loose matches on Subject: below --
2006-08-10 9:48 [PATCH 00/12] ThinkPad embedded controller and hdaps drivers (version 2) Shem Multinymous
2006-08-10 9:48 ` [PATCH 03/12] hdaps: Unify and cache hdaps readouts Shem Multinymous
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=1154849246822-git-send-email-multinymous@gmail.com \
--to=multinymous@gmail.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=gregkh@suse.de \
--cc=hdaps-devel@lists.sourceforge.net \
--cc=khali@linux-fr.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rlove@rlove.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox