X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Finput%2Fmisc%2Fyealink.c;h=11b5c7e84ed139ad9af9fe21fccc04927edd2a31;hb=6c5121b78ba5c70a9990e2af6cb4d6bbffe0d4d8;hp=46279ef2b649b7f523006eeffa1bfd14e0173f77;hpb=2843483d2eb02ad104edbe8b2429fb6a39d25063;p=linux-2.6-omap-h63xx.git diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 46279ef2b64..11b5c7e84ed 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -52,8 +52,8 @@ #include #include #include +#include -#include "map_to_7segment.h" #include "yealink.h" #define DRIVER_VERSION "yld-20051230" @@ -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; imaster); 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);