aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexey Orishko <alexey.orishko@gmail.com>2011-05-24 01:26:13 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-24 13:26:12 -0400
commit19694ac88d4a73c6f12159d9e53bd636319a69dc (patch)
treec9dcde3f1d990dc88a366320bbbedc71d5b3b467 /drivers
parenteb722d7a2e11b0426a17acaa7336120acbc49406 (diff)
CDC NCM: release interfaces fix in unbind()
Changes: - claim slave/data interface during bind() and release interfaces in unbind() unconditionally - in case of error during bind(), release claimed data interface in the same function - remove obsolited "*_claimed" entries from driver context Signed-off-by: Alexey Orishko <alexey.orishko@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/usb/cdc_ncm.c73
1 files changed, 25 insertions, 48 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 4ab557d0287..cdd3ae48610 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -54,7 +54,7 @@
54#include <linux/usb/usbnet.h> 54#include <linux/usb/usbnet.h>
55#include <linux/usb/cdc.h> 55#include <linux/usb/cdc.h>
56 56
57#define DRIVER_VERSION "06-May-2011" 57#define DRIVER_VERSION "24-May-2011"
58 58
59/* CDC NCM subclass 3.2.1 */ 59/* CDC NCM subclass 3.2.1 */
60#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 60#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10
@@ -134,8 +134,6 @@ struct cdc_ncm_ctx {
134 u16 tx_ndp_modulus; 134 u16 tx_ndp_modulus;
135 u16 tx_seq; 135 u16 tx_seq;
136 u16 connected; 136 u16 connected;
137 u8 data_claimed;
138 u8 control_claimed;
139}; 137};
140 138
141static void cdc_ncm_tx_timeout(unsigned long arg); 139static void cdc_ncm_tx_timeout(unsigned long arg);
@@ -460,17 +458,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
460 458
461 del_timer_sync(&ctx->tx_timer); 459 del_timer_sync(&ctx->tx_timer);
462 460
463 if (ctx->data_claimed) {
464 usb_set_intfdata(ctx->data, NULL);
465 usb_driver_release_interface(driver_of(ctx->intf), ctx->data);
466 }
467
468 if (ctx->control_claimed) {
469 usb_set_intfdata(ctx->control, NULL);
470 usb_driver_release_interface(driver_of(ctx->intf),
471 ctx->control);
472 }
473
474 if (ctx->tx_rem_skb != NULL) { 461 if (ctx->tx_rem_skb != NULL) {
475 dev_kfree_skb_any(ctx->tx_rem_skb); 462 dev_kfree_skb_any(ctx->tx_rem_skb);
476 ctx->tx_rem_skb = NULL; 463 ctx->tx_rem_skb = NULL;
@@ -495,7 +482,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
495 482
496 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 483 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
497 if (ctx == NULL) 484 if (ctx == NULL)
498 goto error; 485 return -ENODEV;
499 486
500 memset(ctx, 0, sizeof(*ctx)); 487 memset(ctx, 0, sizeof(*ctx));
501 488
@@ -568,46 +555,36 @@ advance:
568 555
569 /* check if we got everything */ 556 /* check if we got everything */
570 if ((ctx->control == NULL) || (ctx->data == NULL) || 557 if ((ctx->control == NULL) || (ctx->data == NULL) ||
571 (ctx->ether_desc == NULL)) 558 (ctx->ether_desc == NULL) || (ctx->control != intf))
572 goto error; 559 goto error;
573 560
574 /* claim interfaces, if any */ 561 /* claim interfaces, if any */
575 if (ctx->data != intf) { 562 temp = usb_driver_claim_interface(driver, ctx->data, dev);
576 temp = usb_driver_claim_interface(driver, ctx->data, dev); 563 if (temp)
577 if (temp) 564 goto error;
578 goto error;
579 ctx->data_claimed = 1;
580 }
581
582 if (ctx->control != intf) {
583 temp = usb_driver_claim_interface(driver, ctx->control, dev);
584 if (temp)
585 goto error;
586 ctx->control_claimed = 1;
587 }
588 565
589 iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; 566 iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
590 567
591 /* reset data interface */ 568 /* reset data interface */
592 temp = usb_set_interface(dev->udev, iface_no, 0); 569 temp = usb_set_interface(dev->udev, iface_no, 0);
593 if (temp) 570 if (temp)
594 goto error; 571 goto error2;
595 572
596 /* initialize data interface */ 573 /* initialize data interface */
597 if (cdc_ncm_setup(ctx)) 574 if (cdc_ncm_setup(ctx))
598 goto error; 575 goto error2;
599 576
600 /* configure data interface */ 577 /* configure data interface */
601 temp = usb_set_interface(dev->udev, iface_no, 1); 578 temp = usb_set_interface(dev->udev, iface_no, 1);
602 if (temp) 579 if (temp)
603 goto error; 580 goto error2;
604 581
605 cdc_ncm_find_endpoints(ctx, ctx->data); 582 cdc_ncm_find_endpoints(ctx, ctx->data);
606 cdc_ncm_find_endpoints(ctx, ctx->control); 583 cdc_ncm_find_endpoints(ctx, ctx->control);
607 584
608 if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) || 585 if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) ||
609 (ctx->status_ep == NULL)) 586 (ctx->status_ep == NULL))
610 goto error; 587 goto error2;
611 588
612 dev->net->ethtool_ops = &cdc_ncm_ethtool_ops; 589 dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;
613 590
@@ -617,7 +594,7 @@ advance:
617 594
618 temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress); 595 temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
619 if (temp) 596 if (temp)
620 goto error; 597 goto error2;
621 598
622 dev_info(&dev->udev->dev, "MAC-Address: " 599 dev_info(&dev->udev->dev, "MAC-Address: "
623 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", 600 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
@@ -642,38 +619,38 @@ advance:
642 ctx->tx_speed = ctx->rx_speed = 0; 619 ctx->tx_speed = ctx->rx_speed = 0;
643 return 0; 620 return 0;
644 621
622error2:
623 usb_set_intfdata(ctx->control, NULL);
624 usb_set_intfdata(ctx->data, NULL);
625 usb_driver_release_interface(driver, ctx->data);
645error: 626error:
646 cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); 627 cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
647 dev->data[0] = 0; 628 dev->data[0] = 0;
648 dev_info(&dev->udev->dev, "Descriptor failure\n"); 629 dev_info(&dev->udev->dev, "bind() failure\n");
649 return -ENODEV; 630 return -ENODEV;
650} 631}
651 632
652static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) 633static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
653{ 634{
654 struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; 635 struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
655 struct usb_driver *driver; 636 struct usb_driver *driver = driver_of(intf);
656 637
657 if (ctx == NULL) 638 if (ctx == NULL)
658 return; /* no setup */ 639 return; /* no setup */
659 640
660 driver = driver_of(intf); 641 /* disconnect master --> disconnect slave */
661 642 if (intf == ctx->control && ctx->data) {
662 usb_set_intfdata(ctx->data, NULL); 643 usb_set_intfdata(ctx->data, NULL);
663 usb_set_intfdata(ctx->control, NULL);
664 usb_set_intfdata(ctx->intf, NULL);
665
666 /* release interfaces, if any */
667 if (ctx->data_claimed) {
668 usb_driver_release_interface(driver, ctx->data); 644 usb_driver_release_interface(driver, ctx->data);
669 ctx->data_claimed = 0; 645 ctx->data = NULL;
670 }
671 646
672 if (ctx->control_claimed) { 647 } else if (intf == ctx->data && ctx->control) {
648 usb_set_intfdata(ctx->control, NULL);
673 usb_driver_release_interface(driver, ctx->control); 649 usb_driver_release_interface(driver, ctx->control);
674 ctx->control_claimed = 0; 650 ctx->control = NULL;
675 } 651 }
676 652
653 usb_set_intfdata(ctx->intf, NULL);
677 cdc_ncm_free(ctx); 654 cdc_ncm_free(ctx);
678} 655}
679 656