diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c index 1c9de07e73c..e6f20492cf5 100644 --- a/drivers/usb/misc/mdm_data_bridge.c +++ b/drivers/usb/misc/mdm_data_bridge.c @@ -109,6 +109,25 @@ static unsigned int get_timestamp(void); static void dbg_timestamp(char *, struct sk_buff *); static int submit_rx_urb(struct data_bridge *dev, struct urb *urb, gfp_t flags); +static void* interface[MAX_BRIDGE_DEVICES]; + +static inline int get_chid(struct usb_interface *iface) +{ + int i; + for (i = 0; i < MAX_BRIDGE_DEVICES; i++) { + if (interface[i] == iface) + return i; + } + + return -1; +} + +static inline void set_chid(struct usb_interface *iface, int chid) +{ + if (chid >= 0 && chid < MAX_BRIDGE_DEVICES) { + interface[chid] = iface; + } +} static inline bool rx_halted(struct data_bridge *dev) { @@ -962,6 +981,8 @@ bridge_probe(struct usb_interface *iface, const struct usb_device_id *id) goto free_data_bridge; } + set_chid(iface, ch_id); + ch_id++; return 0; @@ -983,17 +1004,26 @@ static void bridge_disconnect(struct usb_interface *intf) struct list_head *head; struct urb *rx_urb; unsigned long flags; + int chid; if (!dev) { err("%s: data device not found\n", __func__); return; } - ch_id--; - ctrl_bridge_disconnect(ch_id); + ch_id--; /* leave it for now */ + + chid = get_chid(intf); + + if (chid < 0) { + err("%s: invalid interface\n", __func__); + return; + } + + ctrl_bridge_disconnect(chid); platform_device_unregister(dev->pdev); usb_set_intfdata(intf, NULL); - __dev[ch_id] = NULL; + __dev[chid] = NULL; cancel_work_sync(&dev->process_rx_w); cancel_work_sync(&dev->kevent); @@ -1010,6 +1040,8 @@ static void bridge_disconnect(struct usb_interface *intf) usb_put_dev(dev->udev); kfree(dev); + + set_chid(NULL, chid); } /*bit position represents interface number*/