diff options
author | Alexey Orishko <alexey.orishko@gmail.com> | 2011-05-24 01:26:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-24 13:26:12 -0400 |
commit | 19694ac88d4a73c6f12159d9e53bd636319a69dc (patch) | |
tree | c9dcde3f1d990dc88a366320bbbedc71d5b3b467 /drivers/net/usb | |
parent | eb722d7a2e11b0426a17acaa7336120acbc49406 (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/net/usb')
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 73 |
1 files changed, 25 insertions, 48 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4ab557d0287d..cdd3ae486109 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 | ||
141 | static void cdc_ncm_tx_timeout(unsigned long arg); | 139 | static 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 | ||
622 | error2: | ||
623 | usb_set_intfdata(ctx->control, NULL); | ||
624 | usb_set_intfdata(ctx->data, NULL); | ||
625 | usb_driver_release_interface(driver, ctx->data); | ||
645 | error: | 626 | error: |
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 | ||
652 | static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) | 633 | static 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 | ||