aboutsummaryrefslogtreecommitdiffstats
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 {
119 u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ 119 u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */
120 int key_code; /* last reported key */ 120 int key_code; /* last reported key */
121 121
122 unsigned int shutdown:1;
123
122 int stat_ix; 124 int stat_ix;
123 union { 125 union {
124 struct yld_status s; 126 struct yld_status s;
@@ -424,10 +426,10 @@ send_update:
424static void urb_irq_callback(struct urb *urb) 426static void urb_irq_callback(struct urb *urb)
425{ 427{
426 struct yealink_dev *yld = urb->context; 428 struct yealink_dev *yld = urb->context;
427 int ret; 429 int ret, status = urb->status;
428 430
429 if (urb->status) 431 if (status)
430 err("%s - urb status %d", __FUNCTION__, urb->status); 432 err("%s - urb status %d", __func__, status);
431 433
432 switch (yld->irq_data->cmd) { 434 switch (yld->irq_data->cmd) {
433 case CMD_KEYPRESS: 435 case CMD_KEYPRESS:
@@ -447,33 +449,38 @@ static void urb_irq_callback(struct urb *urb)
447 449
448 yealink_do_idle_tasks(yld); 450 yealink_do_idle_tasks(yld);
449 451
450 ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); 452 if (!yld->shutdown) {
451 if (ret) 453 ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
452 err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); 454 if (ret && ret != -EPERM)
455 err("%s - usb_submit_urb failed %d", __func__, ret);
456 }
453} 457}
454 458
455static void urb_ctl_callback(struct urb *urb) 459static void urb_ctl_callback(struct urb *urb)
456{ 460{
457 struct yealink_dev *yld = urb->context; 461 struct yealink_dev *yld = urb->context;
458 int ret; 462 int ret = 0, status = urb->status;
459 463
460 if (urb->status) 464 if (status)
461 err("%s - urb status %d", __FUNCTION__, urb->status); 465 err("%s - urb status %d", __func__, status);
462 466
463 switch (yld->ctl_data->cmd) { 467 switch (yld->ctl_data->cmd) {
464 case CMD_KEYPRESS: 468 case CMD_KEYPRESS:
465 case CMD_SCANCODE: 469 case CMD_SCANCODE:
466 /* ask for a response */ 470 /* ask for a response */
467 ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC); 471 if (!yld->shutdown)
472 ret = usb_submit_urb(yld->urb_irq, GFP_ATOMIC);
468 break; 473 break;
469 default: 474 default:
470 /* send new command */ 475 /* send new command */
471 yealink_do_idle_tasks(yld); 476 yealink_do_idle_tasks(yld);
472 ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC); 477 if (!yld->shutdown)
478 ret = usb_submit_urb(yld->urb_ctl, GFP_ATOMIC);
479 break;
473 } 480 }
474 481
475 if (ret) 482 if (ret && ret != -EPERM)
476 err("%s - usb_submit_urb failed %d", __FUNCTION__, ret); 483 err("%s - usb_submit_urb failed %d", __func__, ret);
477} 484}
478 485
479/******************************************************************************* 486/*******************************************************************************
@@ -505,7 +512,7 @@ static int input_open(struct input_dev *dev)
505 struct yealink_dev *yld = input_get_drvdata(dev); 512 struct yealink_dev *yld = input_get_drvdata(dev);
506 int i, ret; 513 int i, ret;
507 514
508 dbg("%s", __FUNCTION__); 515 dbg("%s", __func__);
509 516
510 /* force updates to device */ 517 /* force updates to device */
511 for (i = 0; i<sizeof(yld->master); i++) 518 for (i = 0; i<sizeof(yld->master); i++)
@@ -521,7 +528,7 @@ static int input_open(struct input_dev *dev)
521 yld->ctl_data->sum = 0x100-CMD_INIT-10; 528 yld->ctl_data->sum = 0x100-CMD_INIT-10;
522 if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) { 529 if ((ret = usb_submit_urb(yld->urb_ctl, GFP_KERNEL)) != 0) {
523 dbg("%s - usb_submit_urb failed with result %d", 530 dbg("%s - usb_submit_urb failed with result %d",
524 __FUNCTION__, ret); 531 __func__, ret);
525 return ret; 532 return ret;
526 } 533 }
527 return 0; 534 return 0;
@@ -531,8 +538,18 @@ static void input_close(struct input_dev *dev)
531{ 538{
532 struct yealink_dev *yld = input_get_drvdata(dev); 539 struct yealink_dev *yld = input_get_drvdata(dev);
533 540
541 yld->shutdown = 1;
542 /*
543 * Make sure the flag is seen by other CPUs before we start
544 * killing URBs so new URBs won't be submitted
545 */
546 smp_wmb();
547
534 usb_kill_urb(yld->urb_ctl); 548 usb_kill_urb(yld->urb_ctl);
535 usb_kill_urb(yld->urb_irq); 549 usb_kill_urb(yld->urb_irq);
550
551 yld->shutdown = 0;
552 smp_wmb();
536} 553}
537 554
538/******************************************************************************* 555/*******************************************************************************
@@ -809,9 +826,6 @@ static int usb_cleanup(struct yealink_dev *yld, int err)
809 if (yld == NULL) 826 if (yld == NULL)
810 return err; 827 return err;
811 828
812 usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */
813 usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */
814
815 if (yld->idev) { 829 if (yld->idev) {
816 if (err) 830 if (err)
817 input_free_device(yld->idev); 831 input_free_device(yld->idev);