* Re: [PATCH v3] if xen_platform_pci=0 is set don't blow up.
From: Bjorn Helgaas @ 2013-12-17 1:00 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: Jens Axboe, Stefano Stabellini, ian.campbell, xen-devel,
linux-kernel@vger.kernel.org, boris.ostrovsky, David Vrabel,
leosilva, ashley, Peter Hüwe, mail, tpmdd, Dmitry Torokhov,
plagnioj, tomi.valkeinen, tpmdd-devel,
linux-input@vger.kernel.org, netdev, linux-pci@vger.kernel.org,
linux-fbdev
In-Reply-To: <1387206250-13963-1-git-send-email-konrad.wilk@oracle.com>
On Mon, Dec 16, 2013 at 8:04 AM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> wrote:
> The first patch:
> [PATCH v3 1/2] xen/pvhvm: If xen_platform_pci=0 is set don't blow up
>
> I would like to commit to stable as it is fixing an eggregious bug -
> where we blow up if the guest config has: "xen_platform_pci=0" setup.
> This bug has been in existence for years and it is time to stamp it out.
>
> The second patch is a cleanup - not a stable candidate.
>
> It touches all of the Xen frontend drivers and adds the logic of:
> "if user disabled us, don't init" - with variations. As you can
> specify exactly which ones you want to init and which ones
> not (Linux runtime parameter 'xen_emul_unplug'). But for the majority
> of drivers - it is just an on/off switch.
>
> Since it touches a lot of maintainers I figured I would send it
> to Linus on Wednesday or Thursday.
>
> Thank you!
>
> arch/x86/xen/platform-pci-unplug.c | 79 ++++++++++++++++++++++++++++--
> drivers/block/xen-blkfront.c | 4 +-
> drivers/char/tpm/xen-tpmfront.c | 4 ++
> drivers/input/misc/xen-kbdfront.c | 4 ++
> drivers/net/xen-netfront.c | 2 +-
> drivers/pci/xen-pcifront.c | 4 ++
> drivers/video/xen-fbfront.c | 4 ++
> drivers/xen/xenbus/xenbus_probe_frontend.c | 2 +-
> include/xen/platform_pci.h | 25 +++++++++-
> 9 files changed, 119 insertions(+), 9 deletions(-)
If you want it:
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
for the PCI parts.
>
> Konrad Rzeszutek Wilk (2):
> xen/pvhvm: If xen_platform_pci=0 is set don't blow up (v3).
> xen/pvhvm: Remove the xen_platform_pci int.
>
^ permalink raw reply
* [PATCH] input: Port rotary_encoder to of_property_read_bool
From: Ben Gamari @ 2013-12-17 0:10 UTC (permalink / raw)
To: linux-input; +Cc: Ben Gamari
---
drivers/input/misc/rotary_encoder.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index f920ba7..52049db 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -175,12 +175,9 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic
pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
- pdata->relative_axis = !!of_get_property(np,
- "rotary-encoder,relative-axis", NULL);
- pdata->rollover = !!of_get_property(np,
- "rotary-encoder,rollover", NULL);
- pdata->half_period = !!of_get_property(np,
- "rotary-encoder,half-period", NULL);
+ pdata->relative_axis = of_property_read_bool(np, "rotary-encoder,relative-axis");
+ pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover");
+ pdata->half_period = of_property_read_bool(np, "rotary-encoder,half-period");
return pdata;
}
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCH] input: egalax: Send touch end event when is about to suspend
From: Felipe Ferreri Tonello @ 2013-12-16 23:45 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, linux-input, Andy Shevchenko, Sachin Kamat,
Heiko Abraham
In-Reply-To: <20131215104053.GC20197@core.coreip.homeip.net>
Hi Dmitry,
On 12/15/2013 02:40 AM, Dmitry Torokhov wrote:
> Hi Felipe,
>
> On Tue, Dec 10, 2013 at 04:03:16PM -0800, Felipe F. Tonello wrote:
>> From: "Felipe F. Tonello" <eu@felipetonello.com>
>>
>> This is useful to report for users of this device that don't know anything
>> about the suspension of the device. So users will receive a touch end event
>> when the device is about to suspend, making it more user friendly.
>>
>> One example of users is the X Server with the evdev input driver. This patch
>> make sure that the X server will propagate a touch end event to its windows.
>>
>
> Hmm, I would argue we need to do this in input core, similarly to what
> we do for the keys, so that all drivers would benefit from the change.
>
> Thanks.
I agree with you. I didn't do in this case because previous patches that
I had to change core functionality were declined due the fact it's hard
to maintain backwards compatibility.
Do you recommend me something in this case?
Thanks for your answer.
Felipe
>
>> Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
>> ---
>> drivers/input/touchscreen/egalax_ts.c | 18 +++++++++++++++++-
>> 1 file changed, 17 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
>> index 054d225..1f21f0d 100644
>> --- a/drivers/input/touchscreen/egalax_ts.c
>> +++ b/drivers/input/touchscreen/egalax_ts.c
>> @@ -63,6 +63,7 @@
>> struct egalax_ts {
>> struct i2c_client *client;
>> struct input_dev *input_dev;
>> + bool ids_in_use[MAX_SUPPORT_POINTS];
>> };
>>
>> static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
>> @@ -117,6 +118,8 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
>> input_mt_report_pointer_emulation(input_dev, true);
>> input_sync(input_dev);
>>
>> + ts->ids_in_use[id] = down;
>> +
>> return IRQ_HANDLED;
>> }
>>
>> @@ -247,9 +250,22 @@ static int egalax_ts_suspend(struct device *dev)
>> 0x3, 0x6, 0xa, 0x3, 0x36, 0x3f, 0x2, 0, 0, 0
>> };
>> struct i2c_client *client = to_i2c_client(dev);
>> - int ret;
>> + struct egalax_ts *ts = i2c_get_clientdata(client);
>> + int ret, id;
>>
>> ret = i2c_master_send(client, suspend_cmd, MAX_I2C_DATA_LEN);
>> +
>> + /* We send a touch end event (for the ids in use) if the egalax module is
>> + about to be turned off. */
>> + for (id = 0; id < MAX_SUPPORT_POINTS; ++id) {
>> + if (ts->ids_in_use[id]) {
>> + input_mt_slot(ts->input_dev, id);
>> + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
>> + input_mt_report_pointer_emulation(ts->input_dev, true);
>> + input_sync(ts->input_dev);
>> + }
>> + }
>> +
>> return ret > 0 ? 0 : ret;
>> }
>>
>> --
>> 1.8.3.1
>>
>
^ permalink raw reply
* Re: [PATCH] Input: pmic8xxx-pwrkey - switch to using managed resources
From: Stephen Boyd @ 2013-12-16 20:36 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Lars-Peter Clausen, Sachin Kamat, linux-kernel
In-Reply-To: <20131215120723.GA375@core.coreip.homeip.net>
On 12/15, Dmitry Torokhov wrote:
> This simplifies error handling and device removal paths.
>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
Thanks. Like I said on the other mail, I forgot to send this
patch along. This looks almost identical to what I had so I'm
happy.
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH 1/7] Input: pmic8xxx-pwrkey - Pass input device directly to interrupt
From: Stephen Boyd @ 2013-12-16 19:59 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-input
In-Reply-To: <20131215112103.GA14818@core.coreip.homeip.net>
On 12/15, Dmitry Torokhov wrote:
> Hi Stephen,
>
> On Tue, Dec 10, 2013 at 03:43:10PM -0800, Stephen Boyd wrote:
> > Instead of passing the pointer to the container structure just
> > pass the input device here. This saves a dereference in the fast
> > path.
> >
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> > drivers/input/misc/pmic8xxx-pwrkey.c | 22 ++++++++--------------
> > 1 file changed, 8 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
> > index ce3c426..233b216 100644
> > --- a/drivers/input/misc/pmic8xxx-pwrkey.c
> > +++ b/drivers/input/misc/pmic8xxx-pwrkey.c
> > @@ -32,26 +32,21 @@
> > * @key_press_irq: key press irq number
> > */
> > struct pmic8xxx_pwrkey {
> > - struct input_dev *pwr;
>
> This causes compile errors as you need pwrkey->pwr in remove() to
> unregister input device. I'll fix it up.
>
Ah sorry. I forgot to send the patch before this that converts it
to devm.
> > err = devm_request_irq(&pdev->dev, key_press_irq, pwrkey_press_irq,
> > - IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey);
> > + IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwr);
As you can see here because this driver isn't currently using
devm_request_irq().
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply
* Re: [PATCH 6/7] Input: pmic8xxx-keypad - Migrate to devm_* APIs
From: Dmitry Torokhov @ 2013-12-16 15:37 UTC (permalink / raw)
To: Stephen Boyd; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-input
In-Reply-To: <1386718996-3733-7-git-send-email-sboyd@codeaurora.org>
On Tue, Dec 10, 2013 at 03:43:15PM -0800, Stephen Boyd wrote:
> Simplify the error paths and reduce the lines of code in this
> driver by using the devm_* APIs.
>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
> drivers/input/keyboard/pmic8xxx-keypad.c | 62 +++++++++-----------------------
> 1 file changed, 17 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
> index 2c9f19a..4e6bfbf 100644
> --- a/drivers/input/keyboard/pmic8xxx-keypad.c
> +++ b/drivers/input/keyboard/pmic8xxx-keypad.c
> @@ -586,7 +586,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - kp = kzalloc(sizeof(*kp), GFP_KERNEL);
> + kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
> if (!kp)
> return -ENOMEM;
>
> @@ -595,32 +595,27 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> kp->pdata = pdata;
> kp->dev = &pdev->dev;
>
> - kp->input = input_allocate_device();
> + kp->input = devm_input_allocate_device(&pdev->dev);
> if (!kp->input) {
> dev_err(&pdev->dev, "unable to allocate input device\n");
> - rc = -ENOMEM;
> - goto err_alloc_device;
> + return -ENOMEM;
> }
>
> kp->key_sense_irq = platform_get_irq(pdev, 0);
> if (kp->key_sense_irq < 0) {
> dev_err(&pdev->dev, "unable to get keypad sense irq\n");
> - rc = -ENXIO;
> - goto err_get_irq;
> + return kp->key_sense_irq;
> }
>
> kp->key_stuck_irq = platform_get_irq(pdev, 1);
> if (kp->key_stuck_irq < 0) {
> dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
> - rc = -ENXIO;
> - goto err_get_irq;
> + return kp->key_stuck_irq;
> }
>
> kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
> kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";
>
> - kp->input->dev.parent = &pdev->dev;
> -
> kp->input->id.bustype = BUS_I2C;
> kp->input->id.version = 0x0001;
> kp->input->id.product = 0x0001;
> @@ -634,7 +629,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> kp->keycodes, kp->input);
> if (rc) {
> dev_err(&pdev->dev, "failed to build keymap\n");
> - goto err_get_irq;
> + return rc;
> }
>
> if (pdata->rep)
> @@ -650,7 +645,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> rc = pmic8xxx_kpd_init(kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "unable to initialize keypad controller\n");
> - goto err_get_irq;
> + return rc;
> }
>
> rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
> @@ -667,24 +662,26 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> goto err_gpio_config;
> }
>
> - rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
> - IRQF_TRIGGER_RISING, "pmic-keypad", kp);
> + rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq,
> + pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad",
> + kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to request keypad sense irq\n");
> - goto err_get_irq;
> + return rc;
> }
>
> - rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
> - IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
> + rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq,
> + pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING,
> + "pmic-keypad-stuck", kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
> - goto err_req_stuck_irq;
> + return rc;
> }
>
> rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
> - goto err_pmic_reg_read;
> + return rc;
> }
>
> kp->ctrl_reg = ctrl_val;
> @@ -692,36 +689,12 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> rc = input_register_device(kp->input);
> if (rc < 0) {
> dev_err(&pdev->dev, "unable to register keypad input device\n");
> - goto err_pmic_reg_read;
> + return rc;
> }
>
> device_init_wakeup(&pdev->dev, pdata->wakeup);
>
> return 0;
> -
> -err_pmic_reg_read:
> - free_irq(kp->key_stuck_irq, kp);
> -err_req_stuck_irq:
> - free_irq(kp->key_sense_irq, kp);
> -err_gpio_config:
> -err_get_irq:
> - input_free_device(kp->input);
> -err_alloc_device:
> - kfree(kp);
> - return rc;
> -}
> -
> -static int pmic8xxx_kp_remove(struct platform_device *pdev)
> -{
> - struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
> -
> - device_init_wakeup(&pdev->dev, 0);
Why are we removing restoring wakeup capable state?
> - free_irq(kp->key_stuck_irq, kp);
> - free_irq(kp->key_sense_irq, kp);
> - input_unregister_device(kp->input);
> - kfree(kp);
> -
> - return 0;
> }
>
> #ifdef CONFIG_PM_SLEEP
> @@ -771,7 +744,6 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
>
> static struct platform_driver pmic8xxx_kp_driver = {
> .probe = pmic8xxx_kp_probe,
> - .remove = pmic8xxx_kp_remove,
> .driver = {
> .name = PM8XXX_KEYPAD_DEV_NAME,
> .owner = THIS_MODULE,
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
>
--
Dmitry
^ permalink raw reply
* [PATCH] Input: add short note about ABS_MISC+<n> axes
From: David Herrmann @ 2013-12-16 15:23 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, Dmitry Torokhov, Benjamin Tissoires, David Herrmann
We must not reassign those axes or we will break backwards-compat. Add a
small note for that so we don't accidentally some day reuse these.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
include/uapi/linux/input.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index a372627..da1125e 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -816,6 +816,10 @@ struct input_keymap_entry {
#define ABS_MISC 0x28
+/* ABS_MISC+x is used by HID to assign to unknown axes. Note that they used to
+ * flow over into the MT definitions. For backwards-compatibility, we must
+ * not reassign [0x29-0x2e] */
+
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
--
1.8.5.1
^ permalink raw reply related
* Re: [PATCH] Input: fix typos in Documentation/input/gamepad.txt
From: Antonio Ospite @ 2013-12-16 15:10 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input, linux-kernel, Dmitry Torokhov, Jiri Kosina
In-Reply-To: <CANq1E4TUC-Gfu0nkjLOs0BEkxh37pWpqQodK88TW9o96ej5OiQ@mail.gmail.com>
On Mon, 16 Dec 2013 14:03:43 +0100
David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
CCing linux-input which I forgot.
> On Mon, Dec 16, 2013 at 1:34 PM, Antonio Ospite
> <ospite@studenti.unina.it> wrote:
> > Fix some typos and while at it also use "PS" as the name for the central
> > "HOME" button on Sony controllers, this is how Sony itself calls it.
>
> Thanks, looks good. Any news regarding the absolute DPad?
>
I plan on sending a patch to add the individual axes this week.
Any news regarding the ABS_* fixes? :)
Will they make it for 3.14?
I do have an ugly hack to evtest but without the mechanism for
checking the ABS protocol version it's not backward compatible.
> Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
>
> Thanks
> David
>
> > Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
> > ---
> > Documentation/input/gamepad.txt | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt
> > index 4be7f21..63c0256 100644
> > --- a/Documentation/input/gamepad.txt
> > +++ b/Documentation/input/gamepad.txt
> > @@ -71,7 +71,7 @@ features that you need, first. How each feature is mapped is described below.
> > Legacy drivers often don't comply to these rules. As we cannot change them
> > for backwards-compatibility reasons, you need to provide fixup mappings in
> > user-space yourself. Some of them might also provide module-options that
> > -change the mappings so you can adivce users to set these.
> > +change the mappings so you can advice users to set these.
> >
> > All new gamepads are supposed to comply with this mapping. Please report any
> > bugs, if they don't.
> > @@ -156,10 +156,10 @@ Menu-Pad:
> > BTN_START
> > Many pads also have a third button which is branded or has a special symbol
> > and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo
> > - "HOME" button, the XBox "X"-button or Sony "P" button.
> > + "HOME" button, the XBox "X"-button or Sony "PS" button.
> >
> > Rumble:
> > - Rumble is adverticed as FF_RUMBLE.
> > + Rumble is advertised as FF_RUMBLE.
> >
> > Motion-tracking:
> > Motion-tracking is defined in ./Documentation/input/motion-tracking.txt and
> > --
> > 1.8.5.1
> >
>
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* [PATCH v3 2/2] xen/pvhvm: Remove the xen_platform_pci int.
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
Cc: Konrad Rzeszutek Wilk
In-Reply-To: <1387206250-13963-1-git-send-email-konrad.wilk@oracle.com>
Since we have xen_has_pv_devices,xen_has_pv_disk_devices,
xen_has_pv_nic_devices, and xen_has_pv_and_legacy_disk_devices
to figure out the different 'unplug' behaviors - lets
use those instead of this single int.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
arch/x86/xen/platform-pci-unplug.c | 5 ++---
include/xen/platform_pci.h | 2 --
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index ab84ac1..a826171 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -30,10 +30,9 @@
#define XEN_PLATFORM_ERR_PROTOCOL -2
#define XEN_PLATFORM_ERR_BLACKLIST -3
-/* store the value of xen_emul_unplug after the unplug is done */
-int xen_platform_pci_unplug;
-EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
#ifdef CONFIG_XEN_PVHVM
+/* store the value of xen_emul_unplug after the unplug is done */
+static int xen_platform_pci_unplug;
static int xen_emul_unplug;
static int check_platform_magic(void)
diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
index b49eeab..5c52b55 100644
--- a/include/xen/platform_pci.h
+++ b/include/xen/platform_pci.h
@@ -46,8 +46,6 @@ static inline int xen_must_unplug_disks(void) {
#endif
}
-extern int xen_platform_pci_unplug;
-
#if defined(CONFIG_XEN_PVHVM)
extern bool xen_has_pv_devices(void);
extern bool xen_has_pv_disk_devices(void);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3] if xen_platform_pci=0 is set don't blow up.
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
The first patch:
[PATCH v3 1/2] xen/pvhvm: If xen_platform_pci=0 is set don't blow up
I would like to commit to stable as it is fixing an eggregious bug -
where we blow up if the guest config has: "xen_platform_pci=0" setup.
This bug has been in existence for years and it is time to stamp it out.
The second patch is a cleanup - not a stable candidate.
It touches all of the Xen frontend drivers and adds the logic of:
"if user disabled us, don't init" - with variations. As you can
specify exactly which ones you want to init and which ones
not (Linux runtime parameter 'xen_emul_unplug'). But for the majority
of drivers - it is just an on/off switch.
Since it touches a lot of maintainers I figured I would send it
to Linus on Wednesday or Thursday.
Thank you!
arch/x86/xen/platform-pci-unplug.c | 79 ++++++++++++++++++++++++++++--
drivers/block/xen-blkfront.c | 4 +-
drivers/char/tpm/xen-tpmfront.c | 4 ++
drivers/input/misc/xen-kbdfront.c | 4 ++
drivers/net/xen-netfront.c | 2 +-
drivers/pci/xen-pcifront.c | 4 ++
drivers/video/xen-fbfront.c | 4 ++
drivers/xen/xenbus/xenbus_probe_frontend.c | 2 +-
include/xen/platform_pci.h | 25 +++++++++-
9 files changed, 119 insertions(+), 9 deletions(-)
Konrad Rzeszutek Wilk (2):
xen/pvhvm: If xen_platform_pci=0 is set don't blow up (v3).
xen/pvhvm: Remove the xen_platform_pci int.
^ permalink raw reply
* [PATCH v3 1/2] xen/pvhvm: If xen_platform_pci=0 is set don't blow up (v3).
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
Cc: Konrad Rzeszutek Wilk
In-Reply-To: <1387206250-13963-1-git-send-email-konrad.wilk@oracle.com>
The user has the option of disabling the platform driver:
00:02.0 Unassigned class [ff80]: XenSource, Inc. Xen Platform Device (rev 01)
which is used to unplug the emulated drivers (IDE, Realtek 8169, etc)
and allow the PV drivers to take over. If the user wishes
to disable that they can set:
xen_platform_pci=0
(in the guest config file)
or
xen_emul_unplug=never
(on the Linux command line)
except it does not work properly. The PV drivers still try to
load and since the Xen platform driver is not run - and it
has not initialized the grant tables, most of the PV drivers
stumble upon:
input: Xen Virtual Keyboard as /devices/virtual/input/input5
input: Xen Virtual Pointer as /devices/virtual/input/input6M
------------[ cut here ]------------
kernel BUG at /home/konrad/ssd/konrad/linux/drivers/xen/grant-table.c:1206!
invalid opcode: 0000 [#1] SMP
Modules linked in: xen_kbdfront(+) xenfs xen_privcmd
CPU: 6 PID: 1389 Comm: modprobe Not tainted 3.13.0-rc1upstream-00021-ga6c892b-dirty #1
Hardware name: Xen HVM domU, BIOS 4.4-unstable 11/26/2013
RIP: 0010:[<ffffffff813ddc40>] [<ffffffff813ddc40>] get_free_entries+0x2e0/0x300
Call Trace:
[<ffffffff8150d9a3>] ? evdev_connect+0x1e3/0x240
[<ffffffff813ddd0e>] gnttab_grant_foreign_access+0x2e/0x70
[<ffffffffa0010081>] xenkbd_connect_backend+0x41/0x290 [xen_kbdfront]
[<ffffffffa0010a12>] xenkbd_probe+0x2f2/0x324 [xen_kbdfront]
[<ffffffff813e5757>] xenbus_dev_probe+0x77/0x130
[<ffffffff813e7217>] xenbus_frontend_dev_probe+0x47/0x50
[<ffffffff8145e9a9>] driver_probe_device+0x89/0x230
[<ffffffff8145ebeb>] __driver_attach+0x9b/0xa0
[<ffffffff8145eb50>] ? driver_probe_device+0x230/0x230
[<ffffffff8145eb50>] ? driver_probe_device+0x230/0x230
[<ffffffff8145cf1c>] bus_for_each_dev+0x8c/0xb0
[<ffffffff8145e7d9>] driver_attach+0x19/0x20
[<ffffffff8145e260>] bus_add_driver+0x1a0/0x220
[<ffffffff8145f1ff>] driver_register+0x5f/0xf0
[<ffffffff813e55c5>] xenbus_register_driver_common+0x15/0x20
[<ffffffff813e76b3>] xenbus_register_frontend+0x23/0x40
[<ffffffffa0015000>] ? 0xffffffffa0014fff
[<ffffffffa001502b>] xenkbd_init+0x2b/0x1000 [xen_kbdfront]
[<ffffffff81002049>] do_one_initcall+0x49/0x170
.. snip..
which is hardly nice. This patch fixes this by having each
PV driver check for:
- if running in PV, then it is fine to execute (as that is their
native environment).
- if running in HVM, check if user wanted 'xen_emul_unplug=never',
in which case bail out and don't load any PV drivers.
- if running in HVM, and if PCI device 5853:0001 (xen_platform_pci)
does not exist, then bail out and not load PV drivers.
- (v2) if running in HVM, and if the user wanted 'xen_emul_unplug=disks',
then bail out for all PV devices _except_ the block one.
Ditto for the network one ('nics').
- (v2) if running in HVM, and if the user wanted 'xen_emul_unplug=unnecessary'
then load block PV driver, and also setup the legacy IDE paths.
In (v3) make it actually load PV drivers.
Reported-by: Sander Eikelenboom <linux@eikelenboom.it
Reported-by: Anthony PERARD <anthony.perard@citrix.com>
Reported-by: Fabio Fantoni <fabio.fantoni@m2r.biz>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[v2: Add extra logic to handle the myrid ways 'xen_emul_unplug'
can be used per Ian and Stefano suggestion]
[v3: Make the unnecessary case work properly]
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
arch/x86/xen/platform-pci-unplug.c | 74 ++++++++++++++++++++++++++++++
drivers/block/xen-blkfront.c | 4 +-
drivers/char/tpm/xen-tpmfront.c | 4 ++
drivers/input/misc/xen-kbdfront.c | 4 ++
drivers/net/xen-netfront.c | 2 +-
drivers/pci/xen-pcifront.c | 4 ++
drivers/video/xen-fbfront.c | 4 ++
drivers/xen/xenbus/xenbus_probe_frontend.c | 2 +-
include/xen/platform_pci.h | 23 ++++++++++
9 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index 0a78524..ab84ac1 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -69,6 +69,80 @@ static int check_platform_magic(void)
return 0;
}
+bool xen_has_pv_devices()
+{
+ if (!xen_domain())
+ return false;
+
+ /* PV domains always have them. */
+ if (xen_pv_domain())
+ return true;
+
+ /* And user has xen_platform_pci=0 set in guest config as
+ * driver did not modify the value. */
+ if (xen_platform_pci_unplug == 0)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_NEVER)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_ALL)
+ return true;
+
+ /* This is an odd one - we are going to run legacy
+ * and PV drivers at the same time. */
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ /* And the caller has to follow with xen_pv_{disk,nic}_devices
+ * to be certain which driver can load. */
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_devices);
+
+static bool __xen_has_pv_device(int state)
+{
+ /* HVM domains might or might not */
+ if (xen_hvm_domain() && (xen_platform_pci_unplug & state))
+ return true;
+
+ return xen_has_pv_devices();
+}
+
+bool xen_has_pv_nic_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_NICS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_nic_devices);
+
+bool xen_has_pv_disk_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_IDE_DISKS |
+ XEN_UNPLUG_AUX_IDE_DISKS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_disk_devices);
+
+/*
+ * This one is odd - it determines whether you want to run PV _and_
+ * legacy (IDE) drivers together. This combination is only possible
+ * under HVM.
+ */
+bool xen_has_pv_and_legacy_disk_devices(void)
+{
+ if (!xen_domain())
+ return false;
+
+ /* N.B. This is only ever used in HVM mode */
+ if (xen_pv_domain())
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_and_legacy_disk_devices);
+
void xen_unplug_emulated_devices(void)
{
int r;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a4660bb..ed88b3c 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1278,7 +1278,7 @@ static int blkfront_probe(struct xenbus_device *dev,
char *type;
int len;
/* no unplug has been done: do not hook devices != xen vbds */
- if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY) {
+ if (xen_has_pv_and_legacy_disk_devices()) {
int major;
if (!VDEV_IS_EXTENDED(vdevice))
@@ -2022,7 +2022,7 @@ static int __init xlblk_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_disk_devices())
return -ENODEV;
if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 06189e5..9c2cbd1 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -16,6 +16,7 @@
#include <xen/xenbus.h>
#include <xen/page.h>
#include "tpm.h"
+#include <xen/platform_pci.h>
struct tpm_private {
struct tpm_chip *chip;
@@ -422,6 +423,9 @@ static int __init xen_tpmfront_init(void)
if (!xen_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&tpmfront_driver);
}
module_init(xen_tpmfront_init);
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index e21c181..fbfdc10 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -29,6 +29,7 @@
#include <xen/interface/io/fbif.h>
#include <xen/interface/io/kbdif.h>
#include <xen/xenbus.h>
+#include <xen/platform_pci.h>
struct xenkbd_info {
struct input_dev *kbd;
@@ -380,6 +381,9 @@ static int __init xenkbd_init(void)
if (xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&xenkbd_driver);
}
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 36808bf..eea2392 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -2106,7 +2106,7 @@ static int __init netif_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_nic_devices())
return -ENODEV;
pr_info("Initialising Xen virtual ethernet driver\n");
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index f7197a7..eae7cd9 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -20,6 +20,7 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/time.h>
+#include <xen/platform_pci.h>
#include <asm/xen/swiotlb-xen.h>
#define INVALID_GRANT_REF (0)
@@ -1138,6 +1139,9 @@ static int __init pcifront_init(void)
if (!xen_pv_domain() || xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
pci_frontend_registrar(1 /* enable */);
return xenbus_register_frontend(&xenpci_driver);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index cd005c2..4b2d3ab 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -35,6 +35,7 @@
#include <xen/interface/io/fbif.h>
#include <xen/interface/io/protocols.h>
#include <xen/xenbus.h>
+#include <xen/platform_pci.h>
struct xenfb_info {
unsigned char *fb;
@@ -699,6 +700,9 @@ static int __init xenfb_init(void)
if (xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&xenfb_driver);
}
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 34b20bf..6244f9c 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -496,7 +496,7 @@ subsys_initcall(xenbus_probe_frontend_init);
#ifndef MODULE
static int __init boot_wait_for_devices(void)
{
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_devices())
return -ENODEV;
ready_to_wait_for_devices = 1;
diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
index 438c256..b49eeab 100644
--- a/include/xen/platform_pci.h
+++ b/include/xen/platform_pci.h
@@ -48,4 +48,27 @@ static inline int xen_must_unplug_disks(void) {
extern int xen_platform_pci_unplug;
+#if defined(CONFIG_XEN_PVHVM)
+extern bool xen_has_pv_devices(void);
+extern bool xen_has_pv_disk_devices(void);
+extern bool xen_has_pv_nic_devices(void);
+extern bool xen_has_pv_and_legacy_disk_devices(void);
+#else
+static inline bool xen_has_pv_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_disk_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_nic_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_and_legacy_disk_devices(void)
+{
+ return false;
+}
+#endif
#endif /* _XEN_PLATFORM_PCI_H */
--
1.8.3.1
^ permalink raw reply related
* Re: Recent change to hid-core.c
From: Jiri Kosina @ 2013-12-16 14:56 UTC (permalink / raw)
To: Mark Lord; +Cc: linux-input
In-Reply-To: <52AF13A4.8030900@pobox.com>
On Mon, 16 Dec 2013, Mark Lord wrote:
> >> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
> >> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
> >> included an unexpected change to the return code handing for ->raw_event() calls.
> ,,
> >> Was this intentional? Doesn't that have side-effects for some drivers?
> ..
> > this was intentional -- please see commit b1a1442a23 and discussion here:
> > https://lkml.org/lkml/2013/3/21/591
> ..
>
> Thanks Jiri.
> In that case you'll be wanting this patch (unmangled copy attached) as well
> to clean up a tiny bit of leftover logic in there.
>
> * * * * * * SNIP * * * * * *
>
> Recent updates to raw_event handling resulted in some leftover "dead" logic
> in hid-core.c::hid_input_report(). Nuke it.
>
> Signed-off-by: Mark Lord <mlord@pobox.com>
>
> --- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
> +++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
> @@ -1418,10 +1418,8 @@
>
> if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
> ret = hdrv->raw_event(hid, report, data, size);
> - if (ret < 0) {
> - ret = ret < 0 ? ret : 0;
> + if (ret < 0)
> goto unlock;
> - }
Please see commit 556483e2a ("HID: remove self-assignment from
hid_input_report") in Linus' tree.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: Recent change to hid-core.c
From: Mark Lord @ 2013-12-16 14:52 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input
In-Reply-To: <alpine.LNX.2.00.1312161418110.12882@pobox.suse.cz>
[-- Attachment #1: Type: text/plain, Size: 1298 bytes --]
On 13-12-16 08:24 AM, Jiri Kosina wrote:
> On Sun, 15 Dec 2013, Mark Lord wrote:
>
>> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
>> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
>> included an unexpected change to the return code handing for ->raw_event() calls.
,,
>> Was this intentional? Doesn't that have side-effects for some drivers?
..
> this was intentional -- please see commit b1a1442a23 and discussion here:
> https://lkml.org/lkml/2013/3/21/591
..
Thanks Jiri.
In that case you'll be wanting this patch (unmangled copy attached) as well
to clean up a tiny bit of leftover logic in there.
* * * * * * SNIP * * * * * *
Recent updates to raw_event handling resulted in some leftover "dead" logic
in hid-core.c::hid_input_report(). Nuke it.
Signed-off-by: Mark Lord <mlord@pobox.com>
--- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
+++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
@@ -1418,10 +1418,8 @@
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
ret = hdrv->raw_event(hid, report, data, size);
- if (ret < 0) {
- ret = ret < 0 ? ret : 0;
+ if (ret < 0)
goto unlock;
- }
}
ret = hid_report_raw_event(hid, type, data, size, interrupt);
[-- Attachment #2: hid_core_remove_leftover_logic.patch --]
[-- Type: text/x-patch, Size: 599 bytes --]
Recent updates to raw_event handling resulted in some leftover "dead" logic
in hid-core.c::hid_input_report(). Nuke it.
Signed-off-by: Mark Lord <mlord@pobox.com>
--- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
+++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
@@ -1418,10 +1418,8 @@
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
ret = hdrv->raw_event(hid, report, data, size);
- if (ret < 0) {
- ret = ret < 0 ? ret : 0;
+ if (ret < 0)
goto unlock;
- }
}
ret = hid_report_raw_event(hid, type, data, size, interrupt);
^ permalink raw reply
* Re: Recent change to hid-core.c
From: Jiri Kosina @ 2013-12-16 13:24 UTC (permalink / raw)
To: Mark Lord; +Cc: linux-input
In-Reply-To: <52AD3D74.90905@pobox.com>
On Sun, 15 Dec 2013, Mark Lord wrote:
> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
> included an unexpected change to the return code handing for ->raw_event() calls.
>
> A HID driver's raw_event() method previously could return these values:
> 0 --> keep processing.
> 1 --> no further processing required.
> <0 --> error.
>
> Now, "1" and "0" are both treated as "keep processing",
> so a lower level HID driver has to return a negative error code
> to achieve the "no further processing required" state.
>
> Was this intentional? Doesn't that have side-effects for some drivers?
Hi Mark,
this was intentional -- please see commit b1a1442a23 and discussion here:
https://lkml.org/lkml/2013/3/21/591
If you have any other concerns, please let me know.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [v3.11][Regression] HID: hyperv: convert alloc+memcpy to memdup
From: Jiri Kosina @ 2013-12-16 13:01 UTC (permalink / raw)
To: Joseph Salisbury
Cc: Dan Carpenter, thomas, list, Haiyang Zhang, LKML, open,
HID CORE LAYER, devel
In-Reply-To: <52459942.3020600@canonical.com>
On Fri, 27 Sep 2013, Joseph Salisbury wrote:
> >> commit b1a1442a23776756b254b69786848a94d92445ba
> >> Author: Jiri Kosina <jkosina@suse.cz>
> >> Date: Mon Jun 3 11:27:48 2013 +0200
> >>
> >> HID: core: fix reporting of raw events
> >>
> >> Reverting this commit in v3.12-rc2 prevents the system from locking up,
> >> which happens when connecting a bluetooth trackpad.
> >>
> >> Jiri, do you think we should revert this patch, or is there some further
> >> debugging/data collecting you would like to do?
> > Hi Joseph,
> >
> > in this mail:
> >
> > Message-ID: <5241992E.3090805@canonical.com>
> > Date: Tue, 24 Sep 2013 09:52:46 -0400
> >
> > you said that reverting this commit doesn't prevent the lockups, so I am
> > rather confused ... ?
> >
> > Thanks,
> >
> The testing was invalid. Reverting commit b1a1442 does resolve the bug
> and stop the lockups.
Okay, I finally got some sense of this, sorry for the delay.
Could you please test with the patch below, instead of reverting
b1a1442a23? Thanks a lot.
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 253fe23..81eacd3 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1334,7 +1334,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
csize--;
}
- rsize = ((report->size - 1) >> 3) + 1;
+ rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
if (rsize > HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE;
--
Jiri Kosina
SUSE Labs
^ permalink raw reply related
* [PATCH] Input: add i2c/smbus driver for elan touchpad
From: Duson Lin @ 2013-12-16 12:26 UTC (permalink / raw)
To: linux-kernel, linux-input, dmitry.torokhov
Cc: bleung, agnescheng, phoenix, Duson Lin
This driver adds support for elan i2c/smbus touchpad found on some laptops PC
Signed-off-by: Duson Lin <dusonlin@emc.com.tw>
---
drivers/input/mouse/Kconfig | 10 +
drivers/input/mouse/Makefile | 1 +
drivers/input/mouse/elan_i2c.c | 908 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 919 insertions(+)
create mode 100644 drivers/input/mouse/elan_i2c.c
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index effa9c5..095eccc 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -215,6 +215,16 @@ config MOUSE_CYAPA
To compile this driver as a module, choose M here: the module will be
called cyapa.
+config MOUSE_ELAN_I2C
+ tristate "ELAN I2C Touchpad support"
+ depends on I2C
+ help
+ This driver adds support for Elan I2C Trackpads.
+ Say Y here if you have a ELAN I2C Touchpad.
+
+ To compile this driver as a module, choose M here: the module will be
+ called elan_i2c.
+
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
depends on ISA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c25efdb..24a12a6 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
+obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
diff --git a/drivers/input/mouse/elan_i2c.c b/drivers/input/mouse/elan_i2c.c
new file mode 100644
index 0000000..a5a11bb
--- /dev/null
+++ b/drivers/input/mouse/elan_i2c.c
@@ -0,0 +1,908 @@
+/*
+ * Elan I2C/SMBus Touchpad driver
+ *
+ * Copyright (c) 2013 ELAN Microelectronics Corp.
+ *
+ * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
+ * Version: 1.4.6
+ *
+ * Based on cyapa driver:
+ * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
+ * copyright (c) 2011-2012 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Trademarks are the property of their respective owners.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/jiffies.h>
+
+#define DRIVER_NAME "elan_i2c"
+#define ELAN_DRIVER_VERSION "1.4.6"
+#define ETP_PRESSURE_OFFSET 25
+#define ETP_MAX_PRESSURE 255
+#define ETP_FWIDTH_REDUCE 90
+#define ETP_FINGER_WIDTH 15
+
+#define ELAN_ADAPTER_FUNC_NONE 0
+#define ELAN_ADAPTER_FUNC_I2C 1
+#define ELAN_ADAPTER_FUNC_SMBUS 2
+#define ELAN_ADAPTER_FUNC_BOTH 3
+
+/* Length of Elan touchpad information */
+#define ETP_INF_LENGTH 2
+#define ETP_MAX_FINGERS 5
+#define ETP_FINGER_DATA_LEN 5
+#define ETP_REPORT_ID 0x5D
+#define ETP_MAX_REPORT_LEN 34
+#define ETP_ENABLE_ABS 0x0001
+#define ETP_ENABLE_CALIBRATE 0x0002
+#define ETP_DISABLE_CALIBRATE 0x0000
+
+/* Elan smbus command */
+#define ETP_SMBUS_IAP_CMD 0x00
+#define ETP_SMBUS_ENABLE_TP 0x20
+#define ETP_SMBUS_SLEEP_CMD 0x21
+#define ETP_SMBUS_IAP_PASSWORD_WRITE 0x29
+#define ETP_SMBUS_IAP_PASSWORD_READ 0x80
+#define ETP_SMBUS_WRITE_FW_BLOCK 0x2A
+#define ETP_SMBUS_IAP_RESET_CMD 0x2B
+#define ETP_SMBUS_RANGE_CMD 0xA0
+#define ETP_SMBUS_FW_VERSION_CMD 0xA1
+#define ETP_SMBUS_XY_TRACENUM_CMD 0xA2
+#define ETP_SMBUS_SM_VERSION_CMD 0xA3
+#define ETP_SMBUS_UNIQUEID_CMD 0xA3
+#define ETP_SMBUS_RESOLUTION_CMD 0xA4
+#define ETP_SMBUS_HELLOPACKET_CMD 0xA7
+#define ETP_SMBUS_PACKET_QUERY 0xA8
+#define ETP_SMBUS_IAP_VERSION_CMD 0xAC
+#define ETP_SMBUS_IAP_CTRL_CMD 0xAD
+#define ETP_SMBUS_IAP_CHECKSUM_CMD 0xAE
+#define ETP_SMBUS_FW_CHECKSUM_CMD 0xAF
+#define ETP_SMBUS_MAX_BASELINE_CMD 0xC3
+#define ETP_SMBUS_MIN_BASELINE_CMD 0xC4
+#define ETP_SMBUS_CALIBRATE_QUERY 0xC5
+#define ETP_SMBUS_REPORT_LEN 32
+#define ETP_SMBUS_FINGER_DATA_OFFSET 2
+#define ETP_SMBUS_HELLOPACKET_LEN 5
+#define ETP_SMBUS_IAP_PASSWORD 0x1234
+#define ETP_SMBUS_IAP_MODE_ON (1<<6)
+
+/* Elan i2c command */
+#define ETP_I2C_RESET 0x0100
+#define ETP_I2C_WAKE_UP 0x0800
+#define ETP_I2C_SLEEP 0x0801
+#define ETP_I2C_DESC_CMD 0x0001
+#define ETP_I2C_REPORT_DESC_CMD 0x0002
+#define ETP_I2C_STAND_CMD 0x0005
+#define ETP_I2C_UNIQUEID_CMD 0x0101
+#define ETP_I2C_FW_VERSION_CMD 0x0102
+#define ETP_I2C_SM_VERSION_CMD 0x0103
+#define ETP_I2C_XY_TRACENUM_CMD 0x0105
+#define ETP_I2C_MAX_X_AXIS_CMD 0x0106
+#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107
+#define ETP_I2C_RESOLUTION_CMD 0x0108
+#define ETP_I2C_IAP_VERSION_CMD 0x0110
+#define ETP_I2C_SET_CMD 0x0300
+#define ETP_I2C_MAX_BASELINE_CMD 0x0306
+#define ETP_I2C_MIN_BASELINE_CMD 0x0307
+#define ETP_I2C_FW_CHECKSUM_CMD 0x030F
+#define ETP_I2C_IAP_CTRL_CMD 0x0310
+#define ETP_I2C_IAP_CMD 0x0311
+#define ETP_I2C_IAP_RESET_CMD 0x0314
+#define ETP_I2C_IAP_CHECKSUM_CMD 0x0315
+#define ETP_I2C_CALIBRATE_CMD 0x0316
+#define ETP_I2C_REPORT_LEN 34
+#define ETP_I2C_FINGER_DATA_OFFSET 4
+#define ETP_I2C_REPORT_ID_OFFSET 2
+#define ETP_I2C_DESC_LENGTH 30
+#define ETP_I2C_REPORT_DESC_LENGTH 158
+#define ETP_I2C_IAP_PASSWORD 0x1EA5
+#define ETP_I2C_IAP_RESET 0xF0F0
+#define ETP_I2C_MAIN_MODE_ON (1<<9)
+#define ETP_I2C_IAP_REG_L 0x01
+#define ETP_I2C_IAP_REG_H 0x06
+
+/* The main device structure */
+struct elan_tp_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ unsigned int max_x;
+ unsigned int max_y;
+ unsigned int width_x;
+ unsigned int width_y;
+ unsigned int irq;
+ u16 unique_id;
+ u16 fw_version;
+ u16 sm_version;
+ u16 iap_version;
+ bool smbus;
+};
+
+/*
+ *******************************************************************
+ * Elan smbus interface
+ *******************************************************************
+ */
+static int elan_smbus_initialize(struct i2c_client *client)
+{
+ u8 check[ETP_SMBUS_HELLOPACKET_LEN] = {0x55, 0x55, 0x55, 0x55, 0x55};
+ u8 values[ETP_SMBUS_HELLOPACKET_LEN] = {0, 0, 0, 0, 0};
+ int ret;
+
+ /* Get hello packet */
+ ret = i2c_smbus_read_block_data(client,
+ ETP_SMBUS_HELLOPACKET_CMD, values);
+ if (ret != ETP_SMBUS_HELLOPACKET_LEN) {
+ dev_err(&client->dev, "hello packet length fail\n");
+ return -1;
+ }
+
+ /* compare hello packet */
+ if (memcmp(values, check, ETP_SMBUS_HELLOPACKET_LEN)) {
+ dev_err(&client->dev, "hello packet fail [%x %x %x %x %x]\n",
+ values[0], values[1], values[2], values[3], values[4]);
+ return -1;
+ }
+
+ /* enable tp */
+ ret = i2c_smbus_write_byte(client, ETP_SMBUS_ENABLE_TP);
+ return ret;
+}
+
+static int elan_smbus_enable_absolute_mode(struct i2c_client *client)
+{
+ u8 cmd[4] = {0x00, 0x07, 0x00, ETP_ENABLE_ABS};
+
+ return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD, 4, cmd);
+}
+
+/*
+ ******************************************************************
+ * Elan i2c interface
+ ******************************************************************
+ */
+static int elan_i2c_read_block(struct i2c_client *client,
+ u16 reg, u8 *val, u16 len)
+{
+ struct i2c_msg msgs[2];
+ u8 buf[2];
+ int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags & I2C_M_TEN;
+ msgs[0].len = 2;
+ msgs[0].buf = buf;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags & I2C_M_TEN;
+ msgs[1].flags |= I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = val;
+
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ return ret != 2 ? -EIO : 0;
+}
+
+static int elan_i2c_read_cmd(struct i2c_client *client, u16 reg, u8 *val)
+{
+ int retval;
+
+ retval = elan_i2c_read_block(client, reg, val, ETP_INF_LENGTH);
+ if (retval < 0) {
+ dev_err(&client->dev, "reading cmd (0x%04x) fail.\n", reg);
+ return retval;
+ }
+ return 0;
+}
+
+static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd)
+{
+ struct i2c_msg msg;
+ u8 buf[4];
+ int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+ buf[2] = cmd & 0xff;
+ buf[3] = (cmd >> 8) & 0xff;
+
+ msg.addr = client->addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = 4;
+ msg.buf = buf;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ return ret != 1 ? -EIO : 0;
+}
+
+static int elan_i2c_reset(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_RESET);
+}
+
+static int elan_i2c_wake_up(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_WAKE_UP);
+}
+
+static int elan_i2c_sleep(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_SLEEP);
+}
+
+static int elan_i2c_enable_absolute_mode(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_SET_CMD,
+ ETP_ENABLE_ABS);
+}
+
+static int elan_i2c_get_desc(struct i2c_client *client, u8 *val)
+{
+ return elan_i2c_read_block(client, ETP_I2C_DESC_CMD, val,
+ ETP_I2C_DESC_LENGTH);
+}
+
+static int elan_i2c_get_report_desc(struct i2c_client *client, u8 *val)
+{
+ return elan_i2c_read_block(client, ETP_I2C_REPORT_DESC_CMD,
+ val, ETP_I2C_REPORT_DESC_LENGTH);
+}
+
+static int elan_i2c_initialize(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ int rc;
+ u8 val[256];
+
+ rc = elan_i2c_reset(client);
+ if (rc < 0) {
+ dev_err(dev, "device reset failed.\n");
+ return -1;
+ }
+
+ /* wait for get reset return flag */
+ msleep(100);
+ /* get reset return flag 0000 */
+ rc = i2c_master_recv(client, val, ETP_INF_LENGTH);
+ if (rc < 0) {
+ dev_err(dev, "get device reset return value failed.\n");
+ return -1;
+ }
+
+ rc = elan_i2c_get_desc(client, val);
+ if (rc < 0) {
+ dev_err(dev, "cannot get device descriptor.\n");
+ return -1;
+ }
+
+ rc = elan_i2c_get_report_desc(client, val);
+ if (rc < 0) {
+ dev_err(dev, "fetching report descriptor failed.\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************
+ * General functions
+ ******************************************************************
+ */
+/*
+ * (value from firmware) * 10 + 790 = dpi
+ * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
+ */
+static unsigned int elan_convert_res(char val)
+{
+ int res;
+ if (val & 0x80) {
+ val = ~val + 1;
+ res = (790 - val * 10) * 10 / 254;
+ } else
+ res = (val * 10 + 790) * 10 / 254;
+ return res;
+}
+
+static int elan_get_iap_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_IAP_VERSION_CMD, val);
+ ret = val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_IAP_VERSION_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_max(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RANGE_CMD, val);
+ ret = (0x0f & val[0]) << 8 | val[1];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_MAX_X_AXIS_CMD, val);
+ ret = (0x0f & val[1]) << 8 | val[0];
+ }
+ return ret;
+}
+
+static int elan_get_y_max(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RANGE_CMD, val);
+ ret = (0xf0 & val[0]) << 4 | val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_MAX_Y_AXIS_CMD, val);
+ ret = (0x0f & val[1]) << 8 | val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_tracenum(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_XY_TRACENUM_CMD, val);
+ ret = (val[1] - 1);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_XY_TRACENUM_CMD, val);
+ ret = (val[0] - 1);
+ }
+ return ret;
+}
+
+static int elan_get_y_tracenum(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_XY_TRACENUM_CMD, val);
+ ret = (val[2] - 1);
+ } else {
+ ret = elan_i2c_read_cmd(data->client,
+ ETP_I2C_XY_TRACENUM_CMD, val);
+ ret = (val[1] - 1);
+ }
+ return ret;
+}
+
+static int elan_get_fw_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_FW_VERSION_CMD, val);
+ ret = val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_FW_VERSION_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_sm_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus)
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_SM_VERSION_CMD, val);
+ else
+ elan_i2c_read_block(data->client,
+ ETP_I2C_SM_VERSION_CMD, val, 1);
+ ret = val[0];
+ return ret;
+}
+
+static int elan_get_unique_id(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_UNIQUEID_CMD, val);
+ ret = val[1];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_UNIQUEID_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_resolution(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[1] & 0x0F);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[0]);
+ }
+ return ret;
+}
+
+static int elan_get_y_resolution(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RESOLUTION_CMD, val);
+ ret = elan_convert_res((val[1] & 0xF0) >> 4);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[1]);
+ }
+ return ret;
+}
+
+static int elan_initialize(struct elan_tp_data *data)
+{
+ int ret;
+ if (data->smbus) {
+ ret = elan_smbus_initialize(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "device initialize failed.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_smbus_enable_absolute_mode(data->client);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "cannot switch to absolute mode.\n");
+ } else {
+ ret = elan_i2c_initialize(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "device initialize failed.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_i2c_enable_absolute_mode(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "cannot switch to absolute mode.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_i2c_wake_up(data->client);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "device wake up failed.\n");
+ }
+err_initialize:
+ return ret;
+}
+
+
+/*
+ ******************************************************************
+ * Elan isr functions
+ ******************************************************************
+ */
+static int elan_check_packet(struct elan_tp_data *data, u8 *packet)
+{
+ u8 rid;
+
+ if (data->smbus)
+ rid = packet[0];
+ else
+ rid = packet[ETP_I2C_REPORT_ID_OFFSET];
+
+ /* check report id */
+ if (rid != ETP_REPORT_ID) {
+ dev_err(&data->client->dev, "report id [%x] fail.\n", rid);
+ return -1;
+ }
+ return 0;
+}
+
+static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
+{
+ struct input_dev *input = data->input;
+ u8 *finger_data;
+ bool finger_on;
+ int pos_x, pos_y;
+ int pressure, mk_x, mk_y;
+ int i, area_x, area_y, major, minor, new_pressure;
+ int finger_count = 0;
+ int btn_click;
+ u8 tp_info;
+
+ if (data->smbus) {
+ finger_data = &packet[ETP_SMBUS_FINGER_DATA_OFFSET];
+ tp_info = packet[1];
+ } else {
+ finger_data = &packet[ETP_I2C_FINGER_DATA_OFFSET];
+ tp_info = packet[3];
+ }
+
+ btn_click = (tp_info & 0x01);
+ for (i = 0; i < ETP_MAX_FINGERS; i++) {
+ finger_on = (tp_info >> (3 + i)) & 0x01;
+
+ /* analyze touched finger raw data*/
+ if (finger_on) {
+ pos_x = ((finger_data[0] & 0xf0) << 4) |
+ finger_data[1];
+ pos_y = ((finger_data[0] & 0x0f) << 8) |
+ finger_data[2];
+ pos_y = data->max_y - pos_y;
+ mk_x = (finger_data[3] & 0x0f);
+ mk_y = (finger_data[3] >> 4);
+ pressure = finger_data[4];
+
+ /*
+ * to avoid fat finger be as palm, so reduce the
+ * width x and y per trace
+ */
+ area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
+ area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
+
+ major = max(area_x, area_y);
+ minor = min(area_x, area_y);
+
+ new_pressure = pressure + ETP_PRESSURE_OFFSET;
+ if (new_pressure > ETP_MAX_PRESSURE)
+ new_pressure = ETP_MAX_PRESSURE;
+
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER,
+ true);
+ input_report_abs(input, ABS_MT_POSITION_X, pos_x);
+ input_report_abs(input, ABS_MT_POSITION_Y, pos_y);
+ input_report_abs(input, ABS_MT_PRESSURE, new_pressure);
+ input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
+ input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
+ finger_data += ETP_FINGER_DATA_LEN;
+ finger_count++;
+ } else {
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input,
+ MT_TOOL_FINGER, false);
+ }
+ }
+
+ input_report_key(input, BTN_LEFT, (btn_click == 1));
+ input_mt_report_pointer_emulation(input, true);
+ input_sync(input);
+}
+
+static irqreturn_t elan_isr(int irq, void *dev_id)
+{
+ struct elan_tp_data *data = dev_id;
+ u8 raw[ETP_MAX_REPORT_LEN];
+ int retval;
+ int report_len;
+
+ if (data->smbus) {
+ report_len = ETP_SMBUS_REPORT_LEN;
+ retval = i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_PACKET_QUERY,
+ raw);
+ } else {
+ report_len = ETP_I2C_REPORT_LEN;
+ retval = i2c_master_recv(data->client, raw, report_len);
+ }
+
+ if (retval != report_len) {
+ dev_err(&data->client->dev, "wrong packet len(%d)", retval);
+ goto elan_isr_end;
+ }
+
+ if (elan_check_packet(data, raw) < 0) {
+ dev_err(&data->client->dev, "wrong packet format.");
+ goto elan_isr_end;
+ }
+ elan_report_absolute(data, raw);
+
+elan_isr_end:
+ return IRQ_HANDLED;
+}
+
+/*
+ ******************************************************************
+ * Elan initial functions
+ ******************************************************************
+ */
+static int elan_input_dev_create(struct elan_tp_data *data)
+{
+ struct i2c_client *client = data->client;
+ struct input_dev *input;
+ unsigned int x_res, y_res;
+ int ret, max_width, min_width;
+
+ data->input = input = input_allocate_device();
+ if (!input)
+ return -ENOMEM;
+ input->name = "Elan Touchpad";
+ input->id.bustype = BUS_I2C;
+ input->dev.parent = &data->client->dev;
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+ __set_bit(BTN_LEFT, input->keybit);
+
+ data->unique_id = elan_get_unique_id(data);
+ data->fw_version = elan_get_fw_version(data);
+ data->sm_version = elan_get_sm_version(data);
+ data->iap_version = elan_get_iap_version(data);
+ data->max_x = elan_get_x_max(data);
+ data->max_y = elan_get_y_max(data);
+ data->width_x = data->max_x / elan_get_x_tracenum(data);
+ data->width_y = data->max_y / elan_get_y_tracenum(data);
+ x_res = elan_get_x_resolution(data);
+ y_res = elan_get_y_resolution(data);
+ max_width = max(data->width_x, data->width_y);
+ min_width = min(data->width_x, data->width_y);
+
+ dev_dbg(&client->dev,
+ "Elan Touchpad Information:\n"
+ " Module unique ID: 0x%04x\n"
+ " Firmware Version: 0x%04x\n"
+ " Sample Version: 0x%04x\n"
+ " IAP Version: 0x%04x\n"
+ " Max ABS X,Y: %d,%d\n"
+ " Width X,Y: %d,%d\n"
+ " Resolution X,Y: %d,%d (dots/mm)\n",
+ data->unique_id,
+ data->fw_version,
+ data->sm_version,
+ data->iap_version,
+ data->max_x, data->max_y,
+ data->width_x, data->width_y,
+ (char)x_res, (char)y_res);
+
+ input_set_abs_params(input, ABS_X, 0, data->max_x, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, data->max_y, 0, 0);
+ input_abs_set_res(input, ABS_X, x_res);
+ input_abs_set_res(input, ABS_Y, y_res);
+ input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0);
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0);
+
+ /* handle pointer emulation and unused slots in core */
+ ret = input_mt_init_slots(input, ETP_MAX_FINGERS,
+ INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
+ if (ret) {
+ dev_err(&client->dev, "allocate MT slots failed, %d\n", ret);
+ goto err_free_device;
+ }
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, data->max_y, 0, 0);
+ input_abs_set_res(input, ABS_MT_POSITION_X, x_res);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, y_res);
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0,
+ ETP_MAX_PRESSURE, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
+ ETP_FINGER_WIDTH * max_width, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
+ ETP_FINGER_WIDTH * min_width, 0, 0);
+
+ /* Register the device in input subsystem */
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(&client->dev, "input_dev register failed, %d\n", ret);
+ goto err_free_device;
+ }
+
+ return 0;
+
+err_free_device:
+ input_free_device(input);
+ return ret;
+}
+
+static u8 elan_check_adapter_functionality(struct i2c_client *client)
+{
+ u8 ret = ELAN_ADAPTER_FUNC_NONE;
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ ret |= ELAN_ADAPTER_FUNC_I2C;
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ ret |= ELAN_ADAPTER_FUNC_SMBUS;
+ return ret;
+}
+
+static int elan_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct elan_tp_data *data;
+ int ret;
+ u8 adapter_func;
+ union i2c_smbus_data dummy;
+ struct device *dev = &client->dev;
+
+ adapter_func = elan_check_adapter_functionality(client);
+ if (adapter_func == ELAN_ADAPTER_FUNC_NONE) {
+ dev_err(dev, "not a supported I2C/SMBus adapter\n");
+ return -EIO;
+ }
+
+ /* Make sure there is something at this address */
+ if (i2c_smbus_xfer(client->adapter, client->addr, 0,
+ I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0)
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct elan_tp_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* check protocol type */
+ if (adapter_func == ELAN_ADAPTER_FUNC_SMBUS)
+ data->smbus = true;
+ else
+ data->smbus = false;
+ data->client = client;
+ data->irq = client->irq;
+
+ ret = request_threaded_irq(client->irq, NULL, elan_isr,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->name, data);
+ if (ret < 0) {
+ dev_err(&client->dev, "cannot register irq=%d\n",
+ client->irq);
+ goto err_irq;
+ }
+
+ /* initial elan touch pad */
+ ret = elan_initialize(data);
+ if (ret < 0)
+ goto err_init;
+
+ /* create input device */
+ ret = elan_input_dev_create(data);
+ if (ret < 0)
+ goto err_input_dev;
+
+ device_init_wakeup(&client->dev, 1);
+ i2c_set_clientdata(client, data);
+ return 0;
+
+err_input_dev:
+err_init:
+ free_irq(data->irq, data);
+err_irq:
+ kfree(data);
+ dev_err(&client->dev, "Elan Trackpad probe fail!\n");
+ return ret;
+}
+
+static int elan_remove(struct i2c_client *client)
+{
+ struct elan_tp_data *data = i2c_get_clientdata(client);
+ free_irq(data->irq, data);
+ input_free_device(data->input);
+ input_unregister_device(data->input);
+ kfree(data);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int elan_suspend(struct device *dev)
+{
+ int ret = 0;
+ struct elan_tp_data *data = dev_get_drvdata(dev);
+
+ disable_irq(data->irq);
+ if (data->smbus)
+ ret = i2c_smbus_write_byte(data->client,
+ ETP_SMBUS_SLEEP_CMD);
+ else
+ ret = elan_i2c_sleep(data->client);
+
+ if (ret < 0)
+ dev_err(dev, "suspend mode failed, %d\n", ret);
+
+ return ret;
+}
+
+static int elan_resume(struct device *dev)
+{
+ int ret = 0;
+ struct elan_tp_data *data = dev_get_drvdata(dev);
+
+ ret = elan_initialize(data);
+ if (ret < 0)
+ dev_err(dev, "resume active power failed, %d\n", ret);
+
+ enable_irq(data->irq);
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
+
+static const struct i2c_device_id elan_id[] = {
+ { DRIVER_NAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, elan_id);
+
+static struct i2c_driver elan_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &elan_pm_ops,
+ },
+ .probe = elan_probe,
+ .remove = elan_remove,
+ .id_table = elan_id,
+};
+
+
+static int __init elan_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&elan_driver);
+ if (ret)
+ pr_err("elan driver register FAILED.\n");
+
+ return ret;
+}
+
+static void __exit elan_exit(void)
+{
+ i2c_del_driver(&elan_driver);
+}
+
+module_init(elan_init);
+module_exit(elan_exit);
+
+MODULE_AUTHOR("Duson Lin <dusonlin@emc.com.tw>");
+MODULE_DESCRIPTION("Elan I2C/SMBus Touchpad driver");
+MODULE_LICENSE("GPL");
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Antonio Ospite @ 2013-12-16 10:06 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
In-Reply-To: <20131216095140.GA15405@core.coreip.homeip.net>
On Mon, 16 Dec 2013 01:51:41 -0800
Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> Hi Antonio,
>
> On Mon, Dec 16, 2013 at 09:57:15AM +0100, Antonio Ospite wrote:
> > @@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
> > replace the read above with something like
> >
> > struct js_event mybuffer[0xff];
> > - int i = read (fd, mybuffer, sizeof(struct mybuffer));
> > + int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
> >
>
> This is wrong, as ARRAY_SIZE(mybuffer) would be 0xff and not the size of
> buffer in bytes. I'll fix it up.
>
> Thanks.
You're right of course, thank you.
Ciao,
Antonio
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* Re: [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Dmitry Torokhov @ 2013-12-16 9:51 UTC (permalink / raw)
To: Antonio Ospite; +Cc: linux-input
In-Reply-To: <1387184235-20169-3-git-send-email-ospite@studenti.unina.it>
Hi Antonio,
On Mon, Dec 16, 2013 at 09:57:15AM +0100, Antonio Ospite wrote:
> @@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
> replace the read above with something like
>
> struct js_event mybuffer[0xff];
> - int i = read (fd, mybuffer, sizeof(struct mybuffer));
> + int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
>
This is wrong, as ARRAY_SIZE(mybuffer) would be 0xff and not the size of
buffer in bytes. I'll fix it up.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH 1/2] Input: joystick - refer to /dev/input/js0 in documentation
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
In-Reply-To: <1387184235-20169-1-git-send-email-ospite@studenti.unina.it>
Nowadays the joystick device nodes are created under /dev/input, reflect
this in the documentation in order to make copy and paste easier for
users.
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
Documentation/input/joystick-api.txt | 2 +-
Documentation/input/joystick.txt | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/input/joystick-api.txt b/Documentation/input/joystick-api.txt
index c507330..f95f648 100644
--- a/Documentation/input/joystick-api.txt
+++ b/Documentation/input/joystick-api.txt
@@ -16,7 +16,7 @@ joystick.
By default, the device is opened in blocking mode.
- int fd = open ("/dev/js0", O_RDONLY);
+ int fd = open ("/dev/input/js0", O_RDONLY);
2. Event Reading
diff --git a/Documentation/input/joystick.txt b/Documentation/input/joystick.txt
index 304262b..8d027dc 100644
--- a/Documentation/input/joystick.txt
+++ b/Documentation/input/joystick.txt
@@ -116,7 +116,7 @@ your needs:
For testing the joystick driver functionality, there is the jstest
program in the utilities package. You run it by typing:
- jstest /dev/js0
+ jstest /dev/input/js0
And it should show a line with the joystick values, which update as you
move the stick, and press its buttons. The axes should all be zero when the
@@ -136,7 +136,7 @@ joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program
- jscal -c /dev/js0
+ jscal -c /dev/input/js0
included in the joystick package to set better correction coefficients than
what the driver would choose itself.
@@ -145,7 +145,7 @@ what the driver would choose itself.
calibration using the jstest command, and if you do, you then can save the
correction coefficients into a file
- jscal -p /dev/js0 > /etc/joystick.cal
+ jscal -p /dev/input/js0 > /etc/joystick.cal
And add a line to your rc script executing that file
@@ -556,7 +556,7 @@ interface, and "old" for the "0.x" interface. You run it by typing:
5. FAQ
~~~~~~
-Q: Running 'jstest /dev/js0' results in "File not found" error. What's the
+Q: Running 'jstest /dev/input/js0' results in "File not found" error. What's the
cause?
A: The device files don't exist. Create them (see section 2.2).
--
1.8.5.1
^ permalink raw reply related
* [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
In-Reply-To: <1387184235-20169-1-git-send-email-ospite@studenti.unina.it>
Use the preferred style sizeof(VARIABLE) instead of sizeof(TYPE) in the
joystick API documentation, Documentation/CodingStyle states that this
is the preferred style for allocations but using it elsewhere is good
too.
Also fix some errors like "sizeof(struct mybuffer)" which didn't mean
anything.
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
Documentation/input/joystick-api.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/input/joystick-api.txt b/Documentation/input/joystick-api.txt
index f95f648..47e60a5 100644
--- a/Documentation/input/joystick-api.txt
+++ b/Documentation/input/joystick-api.txt
@@ -23,7 +23,7 @@ By default, the device is opened in blocking mode.
~~~~~~~~~~~~~~~~
struct js_event e;
- read (fd, &e, sizeof(struct js_event));
+ read (fd, &e, sizeof(e));
where js_event is defined as
@@ -34,8 +34,8 @@ where js_event is defined as
__u8 number; /* axis/button number */
};
-If the read is successful, it will return sizeof(struct js_event), unless
-you wanted to read more than one event per read as described in section 3.1.
+If the read is successful, it will return sizeof(e), unless you wanted to read
+more than one event per read as described in section 3.1.
2.1 js_event.type
@@ -144,7 +144,7 @@ all events on the queue (that is, until you get a -1).
For example,
while (1) {
- while (read (fd, &e, sizeof(struct js_event)) > 0) {
+ while (read (fd, &e, sizeof(e)) > 0) {
process_event (e);
}
/* EAGAIN is returned when the queue is empty */
@@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
replace the read above with something like
struct js_event mybuffer[0xff];
- int i = read (fd, mybuffer, sizeof(struct mybuffer));
+ int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
In this case, read would return -1 if the queue was empty, or some
other value in which the number of events read would be i /
--
1.8.5.1
^ permalink raw reply related
* [PATCH 0/2] Input: joystick - documentation fixes
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
Hi,
here are a couple of fixes for the joystick API documentation.
Ciao,
Antonio
Antonio Ospite (2):
Input: joystick - refer to /dev/input/js0 in documentation
Input: joystick - use sizeof(VARIABLE) in documentation
Documentation/input/joystick-api.txt | 12 ++++++------
Documentation/input/joystick.txt | 8 ++++----
2 files changed, 10 insertions(+), 10 deletions(-)
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* Re: [PATCH] drivers/input/misc: new PC speaker sounds, clicks and notes
From: Dmitry Torokhov @ 2013-12-16 5:21 UTC (permalink / raw)
To: Karl Dahlke; +Cc: linux-input, linux-kernel
In-Reply-To: <20131109072257.eklhad@comcast.net>
Hi Karl,
On Mon, Dec 09, 2013 at 07:22:57AM -0500, Karl Dahlke wrote:
> From: Karl Dahlke <eklhad@gmail.com>
>
> The speaker driver can play a tone at a specified frequency,
> or the standard control G bell,
> which is a special case of TONE at 1000 hz 0.1 seconds.
> This patch adds kd_mkpulse() to generate a soft click.
> This is introduced to support accessibility modules and adapters in the future.
> With this in place, a module can easily provide soft clicks,
> i.e. audible feedback, whenever a key is depressed,
> or when that keystroke is echoed on screen, whichever you prefer.
> (Many people find the latter more valuable.)
> This allows a blind user, for example, to have ongoing feedback while typing,
> even if he is, at the same time, listening to text that is already on screen.
> This is faster and more convenient than having characters echoed verbally.
> And it works all the time, even if speech or braille is not working
> for whatever reason. And there are many reasons those adapters could fail.
> Misconfigured sound card, bad serial connection,
> software synth not loading, etc.
> Thus these forms of audio feedback are very important.
>
> This should not be confused with the click function in certain specialized
> keyboards such as lkkbd.c.
> That function does a serio write to the client to activate clicks locally.
> In contrast, this function generates a one-time pulse at the pc speaker,
> or through a similar driver, so that modules can click whenever they want,
> e.g. when a key is echoed back to you by a running application,
> perhaps a thousand miles away over ssh, so you know all is well.
> A module may want to click, or issue a series of clicks, for many reasons.
I do not think it is a good idea to add SND_PULSE as it can be easily
implemented by SND_TONE with the additional benefit that parameters of
the click can be adjusted. Also, if clicking is done elsewhere, it would
work with other speaker drivers besides pcspkr.
>
> Another function introduced by this patch is kd_mknotes,
> which plays a series of tones in the background.
> You could do this yourself with kd_mksound and timers,
> but why should everyone reinvent the wheel?
> It is better to write the function once, properly, in the kernel,
> and let modules use it thereafter.
Can it be put into a library instead? Especially given David's work on
trying to push the VT code out of the kernel. Also, what if you want
clicks to go through sound card and not the speaker interface?
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH V2] Input: define KEY_WWAN for Wireless WAN
From: Dmitry Torokhov @ 2013-12-16 5:02 UTC (permalink / raw)
To: Jiri Kosina; +Cc: Rafał Miłecki, linux-input, Hauke Mehrtens
In-Reply-To: <alpine.LNX.2.00.1312102036250.1413@pobox.suse.cz>
On Tue, Dec 10, 2013 at 08:36:41PM +0100, Jiri Kosina wrote:
> On Tue, 10 Dec 2013, Rafał Miłecki wrote:
>
> > Some devices with support for mobile networks may have buttons for
> > enabling/disabling such connection. An example can be Linksys router
> > 54G3G.
> > We already have KEY_BLUETOOTH, KEY_WLAN and KEY_UWB so it makes sense
> > to add KEY_WWAN as well.
> > As we already have KEY_WIMAX, use it's value for KEY_WWAN and make it an
> > alias.
> >
> > Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> > ---
> > V2: Re-use 246 value for WWAN and make WIMAX an aliast to WWAN
> > ---
> > include/uapi/linux/input.h | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> > index a372627..7c69941 100644
> > --- a/include/uapi/linux/input.h
> > +++ b/include/uapi/linux/input.h
> > @@ -464,7 +464,8 @@ struct input_keymap_entry {
> > #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
> > #define KEY_DISPLAY_OFF 245 /* display device to off state */
> >
> > -#define KEY_WIMAX 246
> > +#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
> > +#define KEY_WIMAX KEY_WWAN
> > #define KEY_RFKILL 247 /* Key that controls all radios */
> >
> > #define KEY_MICMUTE 248 /* Mute / unmute the microphone */
>
> Adding Dmitry to CC
Applied, thank you.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* T440s Synaptics clickpad: lost sync / KBC bad data
From: J. Domburg @ 2013-12-15 14:37 UTC (permalink / raw)
To: linux-input
Hello everyone,
I hope I'm at the right address here with my problems. If not, please do
point me in the correct direction.
I have a Lenovo Thinkpad T440s with a Synaptics clickpad and an IBM
trackpoint in it:
input: PS/2 Synaptics TouchPad as /devices/platform/i8042/serio1/input/input120
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1, caps: 0xd001a3/0x940300/0x127c00, board id: 2668, fw id: 1293989
psmouse serio1: synaptics: serio: Synaptics pass-through port at isa0060/serio1/input0
input: SynPS/2 Synaptics TouchPad as /devices/platform/i8042/serio1/input/input123
psmouse serio34: alps: Unknown ALPS touchpad: E7=10 00 64, EC=10 00 64
psmouse serio34: trackpoint: IBM TrackPoint firmware: 0x0e,
buttons: 3/3 input: TPPS/2 IBM TrackPoint as /devices/platform/i8042/serio1/serio34/input/input124
The problem is that the trackpoint behaves incredibly erratic, sometimes
working correctly for minutes at a time, sometimes just jumping around and
many times just hanging. I need to remove and re-insert the psmouse module
to solve that. Alongside this behaviour, my kernel log also is getting
spammed with messages like:
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 - driver resynced.
and
psmouse serio1: bad data from KBC - timeout
What I've tried:
- Tried the kernel options i8042.nomux=1 and i8042.reset=1
- Disable acpi by passing acpi=off to the kernel
- Disabled CPU frequency scaling
- Trying other protocols, e.g. by doing modprobe psmouse proto=imps or
proto=bare
- Switching from vanilla 3.12 kernel to both the latest&greatest kernel
from Linus' Git and an antique 3.1.0 kernel
- Turning on i8042.debug. To my untrained eye, it looks like bytes of PS/2
data are just disappearing when the 'lost sync' messages kick in. I can
give an example of that if needed.
Strangely, the symptoms have been getting worse in the 10 days I've had
this machine: from the first few days with no trouble to today with the
mouse crapping out almost once every ten seconds or so. I would say it's a
DOA and claim my warranty, if not frustratingly the machine works
perfectly fine in Windows 8, with no touchpad trouble at all.
I'm willing to try things on this machine, run patches or take any hint in
what I can change to get this working; if it helps I can even poke an
oscilloscope at the PS2 lines. Not having a working touchpad or
touchpoint is getting a bit frustrating...
Cheers,
Jeroen
^ permalink raw reply
* Re: [RFC] Add ff-memless-next driver
From: Michal Malý @ 2013-12-15 13:07 UTC (permalink / raw)
To: Joe Perches
Cc: dmitry.torokhov, linux-kernel, linux-input, elias.vds,
anssi.hannula
In-Reply-To: <1387073042.2276.21.camel@joe-AO722>
On Saturday 14 of December 2013 18:04:02 Joe Perches wrote:
> On Sun, 2013-12-15 at 01:19 +0100, Michal Malý wrote:
> > diff --git a/drivers/input/ff-memless-next.c
> > b/drivers/input/ff-memless-next.c
> []
>
> > +static inline s32 mlnx_clamp_level(const s32 level)
> > +{
> > + return (level > 0x7fff) ? 0x7fff : ((level < -0x7fff) ? -0x7fff :
> > level);
>
> clamp(level, -0x7fff, 0x7fff);
> []
>
> > +static inline int mlnx_is_conditional(const struct ff_effect *effect)
> > +{
> > + return (effect->type == FF_DAMPER) || (effect->type == FF_FRICTION) ||
> > (effect->type == FF_INERTIA) || (effect->type == FF_SPRING); +}
>
> Maybe try to run your patch through scripts/checkpatch.pl
>
> bool?
> 80 char line max? (true for the file, not just here)
> switch?
> switch (effect->type) {
> case FF_DAMPER:
> case FF_FRICTION:
> case FF_INERTIA:
> case FF_SPRING:
> return true;
> }
> return false;
Okay, thanks for the input. I found a problem regarding effect updating in the code anyway. I'll submit a corrected version of the patch once I'm sure it's fixed.
Michal
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox