summaryrefslogtreecommitdiffstats
path: root/drivers/input/misc/yealink.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/misc/yealink.c')
-rw-r--r--drivers/input/misc/yealink.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c
index 46279ef2b649..facefd3dba29 100644
--- a/drivers/input/misc/yealink.c
+++ b/drivers/input/misc/yealink.c
@@ -119,6 +119,8 @@ struct yealink_dev {
u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
int key_code; /* last reported key */
+ unsigned int shutdown:1;
+
int stat_ix;
union {
struct yld_status s;
@@ -424,10 +426,10 @@ send_update:
static void urb_irq_callback(struct urb *urb)
{
struct yealink_dev *yld = urb->context;
- int ret;
+ int ret, status = urb->status;
- if (urb->status)
- err("%s - urb status %d", __FUNCTION__, urb->status);
+ if (status)
+ err("%s - urb status %d", __func__, status);
switch (yld->irq_data->cmd) {
case CMD_KEYPRESS:
@@ -447,33 +449,38 @@ static void urb_irq_callback(struct urb *urb)
yealink_do_idle_tasks(yld);
- ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
- if (ret)
- err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+ if (!yld->shutdown) {
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (ret && ret != -EPERM)
+ err("%s - usb_submit_urb failed %d", __func__, ret);
+ }
}
static void urb_ctl_callback(struct urb *urb)
{
struct yealink_dev *yld = urb->context;
- int ret;
+ int ret = 0, status = urb->status;
- if (urb->status)
- err("%s - urb status %d", __FUNCTION__, urb->status);
+ if (status)
+ err("%s - urb status %d", __func__, status);
switch (yld->ctl_data->cmd) {
case CMD_KEYPRESS:
case CMD_SCANCODE:
/* ask for a response */
- ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
+ if (!yld->shutdown)
+ ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
break;
default:
/* send new command */
yealink_do_idle_tasks(yld);
- ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ if (!yld->shutdown)
+ ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
+ break;
}
- if (ret)
- err("%s - usb_submit_urb failed %d", __FUNCTION__, ret);
+ if (ret && ret != -EPERM)
+ err("%s - usb_submit_urb failed %d", __func__, ret);
}
/*******************************************************************************
@@ -505,7 +512,7 @@ static int input_open(struct input_dev *dev)
struct yealink_dev *yld = input_get_drvdata(dev);
int i, ret;
- dbg("%s", __FUNCTION__);
+ dbg("%s", __func__);
/* force updates to device */
for (i = 0; i<sizeof(yld->master); i++)
@@ -521,7 +528,7 @@ static int input_open(struct input_dev *dev)
yld->ctl_data->sum = 0x100-CMD_INIT-10;
if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
dbg("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, ret);
+ __func__, ret);
return ret;
}
return 0;
@@ -531,8 +538,18 @@ static void input_close(struct input_dev *dev)
{
struct yealink_dev *yld = input_get_drvdata(dev);
+ yld->shutdown = 1;
+ /*
+ * Make sure the flag is seen by other CPUs before we start
+ * killing URBs so new URBs won't be submitted
+ */
+ smp_wmb();
+
usb_kill_urb(yld->urb_ctl);
usb_kill_urb(yld->urb_irq);
+
+ yld->shutdown = 0;
+ smp_wmb();
}
/*******************************************************************************
@@ -809,9 +826,6 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
if (yld == NULL)
return err;
- usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */
- usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */
-
if (yld->idev) {
if (err)
input_free_device(yld->idev);