Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19694ac8 authored by Alexey Orishko's avatar Alexey Orishko Committed by David S. Miller
Browse files

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: default avatarAlexey Orishko <alexey.orishko@stericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb722d7a
Loading
Loading
Loading
Loading
+25 −48
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc.h>

#define	DRIVER_VERSION				"06-May-2011"
#define	DRIVER_VERSION				"24-May-2011"

/* CDC NCM subclass 3.2.1 */
#define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
@@ -134,8 +134,6 @@ struct cdc_ncm_ctx {
	u16 tx_ndp_modulus;
	u16 tx_seq;
	u16 connected;
	u8 data_claimed;
	u8 control_claimed;
};

static void cdc_ncm_tx_timeout(unsigned long arg);
@@ -460,17 +458,6 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)

	del_timer_sync(&ctx->tx_timer);

	if (ctx->data_claimed) {
		usb_set_intfdata(ctx->data, NULL);
		usb_driver_release_interface(driver_of(ctx->intf), ctx->data);
	}

	if (ctx->control_claimed) {
		usb_set_intfdata(ctx->control, NULL);
		usb_driver_release_interface(driver_of(ctx->intf),
								ctx->control);
	}

	if (ctx->tx_rem_skb != NULL) {
		dev_kfree_skb_any(ctx->tx_rem_skb);
		ctx->tx_rem_skb = NULL;
@@ -495,7 +482,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)

	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
	if (ctx == NULL)
		goto error;
		return -ENODEV;

	memset(ctx, 0, sizeof(*ctx));

@@ -568,46 +555,36 @@ advance:

	/* check if we got everything */
	if ((ctx->control == NULL) || (ctx->data == NULL) ||
	    (ctx->ether_desc == NULL))
	    (ctx->ether_desc == NULL) || (ctx->control != intf))
		goto error;

	/* claim interfaces, if any */
	if (ctx->data != intf) {
	temp = usb_driver_claim_interface(driver, ctx->data, dev);
	if (temp)
		goto error;
		ctx->data_claimed = 1;
	}

	if (ctx->control != intf) {
		temp = usb_driver_claim_interface(driver, ctx->control, dev);
		if (temp)
			goto error;
		ctx->control_claimed = 1;
	}

	iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;

	/* reset data interface */
	temp = usb_set_interface(dev->udev, iface_no, 0);
	if (temp)
		goto error;
		goto error2;

	/* initialize data interface */
	if (cdc_ncm_setup(ctx))
		goto error;
		goto error2;

	/* configure data interface */
	temp = usb_set_interface(dev->udev, iface_no, 1);
	if (temp)
		goto error;
		goto error2;

	cdc_ncm_find_endpoints(ctx, ctx->data);
	cdc_ncm_find_endpoints(ctx, ctx->control);

	if ((ctx->in_ep == NULL) || (ctx->out_ep == NULL) ||
	    (ctx->status_ep == NULL))
		goto error;
		goto error2;

	dev->net->ethtool_ops = &cdc_ncm_ethtool_ops;

@@ -617,7 +594,7 @@ advance:

	temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
	if (temp)
		goto error;
		goto error2;

	dev_info(&dev->udev->dev, "MAC-Address: "
				"0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
@@ -642,38 +619,38 @@ advance:
	ctx->tx_speed = ctx->rx_speed = 0;
	return 0;

error2:
	usb_set_intfdata(ctx->control, NULL);
	usb_set_intfdata(ctx->data, NULL);
	usb_driver_release_interface(driver, ctx->data);
error:
	cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
	dev->data[0] = 0;
	dev_info(&dev->udev->dev, "Descriptor failure\n");
	dev_info(&dev->udev->dev, "bind() failure\n");
	return -ENODEV;
}

static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
{
	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
	struct usb_driver *driver;
	struct usb_driver *driver = driver_of(intf);

	if (ctx == NULL)
		return;		/* no setup */

	driver = driver_of(intf);

	/* disconnect master --> disconnect slave */
	if (intf == ctx->control && ctx->data) {
		usb_set_intfdata(ctx->data, NULL);
	usb_set_intfdata(ctx->control, NULL);
	usb_set_intfdata(ctx->intf, NULL);

	/* release interfaces, if any */
	if (ctx->data_claimed) {
		usb_driver_release_interface(driver, ctx->data);
		ctx->data_claimed = 0;
	}
		ctx->data = NULL;

	if (ctx->control_claimed) {
	} else if (intf == ctx->data && ctx->control) {
		usb_set_intfdata(ctx->control, NULL);
		usb_driver_release_interface(driver, ctx->control);
		ctx->control_claimed = 0;
		ctx->control = NULL;
	}

	usb_set_intfdata(ctx->intf, NULL);
	cdc_ncm_free(ctx);
}