diff options
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/core/hcd.c | 2 | ||||
| -rw-r--r-- | drivers/usb/gadget/f_phonet.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-s5p.c | 1 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-hub.c | 17 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 90 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 28 | ||||
| -rw-r--r-- | drivers/usb/musb/blackfin.c | 1 | ||||
| -rw-r--r-- | drivers/usb/musb/cppi_dma.c | 26 | ||||
| -rw-r--r-- | drivers/usb/musb/musb_core.h | 12 | ||||
| -rw-r--r-- | drivers/usb/musb/musb_gadget.c | 4 | ||||
| -rw-r--r-- | drivers/usb/musb/musb_regs.h | 6 | ||||
| -rw-r--r-- | drivers/usb/musb/tusb6010.c | 1 | ||||
| -rw-r--r-- | drivers/usb/musb/tusb6010_omap.c | 1 | ||||
| -rw-r--r-- | drivers/usb/musb/ux500_dma.c | 38 | ||||
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 20 | ||||
| -rw-r--r-- | drivers/usb/serial/option.c | 104 | 
17 files changed, 283 insertions, 76 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8669ba3fe79..73cbbd85219 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1775,6 +1775,8 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev,  		struct usb_interface *iface = usb_ifnum_to_if(udev,  				cur_alt->desc.bInterfaceNumber); +		if (!iface) +			return -EINVAL;  		if (iface->resetting_device) {  			/*  			 * The USB core just reset the device, so the xHCI host diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 8f8d3f6cd89..8f3eab1af88 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -434,6 +434,7 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)  			    config_ep_by_speed(gadget, f, fp->out_ep)) {  				fp->in_ep->desc = NULL;  				fp->out_ep->desc = NULL; +				spin_unlock(&port->lock);  				return -EINVAL;  			}  			usb_ep_enable(fp->out_ep); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index e051b30c184..4c32cb19b40 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -343,7 +343,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  	u32			temp;  	u32			power_okay;  	int			i; -	u8			resume_needed = 0; +	unsigned long		resume_needed = 0;  	if (time_before (jiffies, ehci->next_statechange))  		msleep(5); @@ -416,7 +416,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  		if (test_bit(i, &ehci->bus_suspended) &&  				(temp & PORT_SUSPEND)) {  			temp |= PORT_RESUME; -			resume_needed = 1; +			set_bit(i, &resume_needed);  		}  		ehci_writel(ehci, temp, &ehci->regs->port_status [i]);  	} @@ -431,8 +431,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  	i = HCS_N_PORTS (ehci->hcs_params);  	while (i--) {  		temp = ehci_readl(ehci, &ehci->regs->port_status [i]); -		if (test_bit(i, &ehci->bus_suspended) && -				(temp & PORT_SUSPEND)) { +		if (test_bit(i, &resume_needed)) {  			temp &= ~(PORT_RWC_BITS | PORT_RESUME);  			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);  			ehci_vdbg (ehci, "resumed port %d\n", i + 1); diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index b3958b3d316..9e77f1c8bdb 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -86,6 +86,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev)  		goto fail_hcd;  	} +	s5p_ehci->hcd = hcd;  	s5p_ehci->clk = clk_get(&pdev->dev, "usbhost");  	if (IS_ERR(s5p_ehci->clk)) { diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0be788cc2fd..1e96d1f1fe6 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -463,11 +463,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  					&& (temp & PORT_POWER))  				status |= USB_PORT_STAT_SUSPEND;  		} -		if ((temp & PORT_PLS_MASK) == XDEV_RESUME) { +		if ((temp & PORT_PLS_MASK) == XDEV_RESUME && +				!DEV_SUPERSPEED(temp)) {  			if ((temp & PORT_RESET) || !(temp & PORT_PE))  				goto error; -			if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies, -						bus_state->resume_done[wIndex])) { +			if (time_after_eq(jiffies, +					bus_state->resume_done[wIndex])) {  				xhci_dbg(xhci, "Resume USB2 port %d\n",  					wIndex + 1);  				bus_state->resume_done[wIndex] = 0; @@ -487,6 +488,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  				xhci_ring_device(xhci, slot_id);  				bus_state->port_c_suspend |= 1 << wIndex;  				bus_state->suspended_ports &= ~(1 << wIndex); +			} else { +				/* +				 * The resume has been signaling for less than +				 * 20ms. Report the port status as SUSPEND, +				 * let the usbcore check port status again +				 * and clear resume signaling later. +				 */ +				status |= USB_PORT_STAT_SUSPEND;  			}  		}  		if ((temp & PORT_PLS_MASK) == XDEV_U0 @@ -664,7 +673,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			xhci_dbg(xhci, "PORTSC %04x\n", temp);  			if (temp & PORT_RESET)  				goto error; -			if (temp & XDEV_U3) { +			if ((temp & PORT_PLS_MASK) == XDEV_U3) {  				if ((temp & PORT_PE) == 0)  					goto error; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 7113d16e2d3..54139a2f06c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -514,8 +514,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,  			(unsigned long long) addr);  } +/* flip_cycle means flip the cycle bit of all but the first and last TRB. + * (The last TRB actually points to the ring enqueue pointer, which is not part + * of this TD.)  This is used to remove partially enqueued isoc TDs from a ring. + */  static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, -		struct xhci_td *cur_td) +		struct xhci_td *cur_td, bool flip_cycle)  {  	struct xhci_segment *cur_seg;  	union xhci_trb *cur_trb; @@ -528,6 +532,12 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,  			 * leave the pointers intact.  			 */  			cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN); +			/* Flip the cycle bit (link TRBs can't be the first +			 * or last TRB). +			 */ +			if (flip_cycle) +				cur_trb->generic.field[3] ^= +					cpu_to_le32(TRB_CYCLE);  			xhci_dbg(xhci, "Cancel (unchain) link TRB\n");  			xhci_dbg(xhci, "Address = %p (0x%llx dma); "  					"in seg %p (0x%llx dma)\n", @@ -541,6 +551,11 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,  			cur_trb->generic.field[2] = 0;  			/* Preserve only the cycle bit of this TRB */  			cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE); +			/* Flip the cycle bit except on the first or last TRB */ +			if (flip_cycle && cur_trb != cur_td->first_trb && +					cur_trb != cur_td->last_trb) +				cur_trb->generic.field[3] ^= +					cpu_to_le32(TRB_CYCLE);  			cur_trb->generic.field[3] |= cpu_to_le32(  				TRB_TYPE(TRB_TR_NOOP));  			xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) " @@ -719,14 +734,14 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,  					cur_td->urb->stream_id,  					cur_td, &deq_state);  		else -			td_to_noop(xhci, ep_ring, cur_td); +			td_to_noop(xhci, ep_ring, cur_td, false);  remove_finished_td:  		/*  		 * The event handler won't see a completion for this TD anymore,  		 * so remove it from the endpoint ring's TD list.  Keep it in  		 * the cancelled TD list for URB completion later.  		 */ -		list_del(&cur_td->td_list); +		list_del_init(&cur_td->td_list);  	}  	last_unlinked_td = cur_td;  	xhci_stop_watchdog_timer_in_irq(xhci, ep); @@ -754,7 +769,7 @@ remove_finished_td:  	do {  		cur_td = list_entry(ep->cancelled_td_list.next,  				struct xhci_td, cancelled_td_list); -		list_del(&cur_td->cancelled_td_list); +		list_del_init(&cur_td->cancelled_td_list);  		/* Clean up the cancelled URB */  		/* Doesn't matter what we pass for status, since the core will @@ -862,9 +877,9 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)  				cur_td = list_first_entry(&ring->td_list,  						struct xhci_td,  						td_list); -				list_del(&cur_td->td_list); +				list_del_init(&cur_td->td_list);  				if (!list_empty(&cur_td->cancelled_td_list)) -					list_del(&cur_td->cancelled_td_list); +					list_del_init(&cur_td->cancelled_td_list);  				xhci_giveback_urb_in_irq(xhci, cur_td,  						-ESHUTDOWN, "killed");  			} @@ -873,7 +888,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)  						&temp_ep->cancelled_td_list,  						struct xhci_td,  						cancelled_td_list); -				list_del(&cur_td->cancelled_td_list); +				list_del_init(&cur_td->cancelled_td_list);  				xhci_giveback_urb_in_irq(xhci, cur_td,  						-ESHUTDOWN, "killed");  			} @@ -1565,10 +1580,10 @@ td_cleanup:  			else  				*status = 0;  		} -		list_del(&td->td_list); +		list_del_init(&td->td_list);  		/* Was this TD slated to be cancelled but completed anyway? */  		if (!list_empty(&td->cancelled_td_list)) -			list_del(&td->cancelled_td_list); +			list_del_init(&td->cancelled_td_list);  		urb_priv->td_cnt++;  		/* Giveback the urb when all the tds are completed */ @@ -2500,11 +2515,8 @@ static int prepare_transfer(struct xhci_hcd *xhci,  	if (td_index == 0) {  		ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb); -		if (unlikely(ret)) { -			xhci_urb_free_priv(xhci, urb_priv); -			urb->hcpriv = NULL; +		if (unlikely(ret))  			return ret; -		}  	}  	td->urb = urb; @@ -2672,6 +2684,10 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,  {  	int packets_transferred; +	/* One TRB with a zero-length data packet. */ +	if (running_total == 0 && trb_buff_len == 0) +		return 0; +  	/* All the TRB queueing functions don't count the current TRB in  	 * running_total.  	 */ @@ -3113,20 +3129,15 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci,  		struct urb *urb, int i)  {  	int num_trbs = 0; -	u64 addr, td_len, running_total; +	u64 addr, td_len;  	addr = (u64) (urb->transfer_dma + urb->iso_frame_desc[i].offset);  	td_len = urb->iso_frame_desc[i].length; -	running_total = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1)); -	running_total &= TRB_MAX_BUFF_SIZE - 1; -	if (running_total != 0) -		num_trbs++; - -	while (running_total < td_len) { +	num_trbs = DIV_ROUND_UP(td_len + (addr & (TRB_MAX_BUFF_SIZE - 1)), +			TRB_MAX_BUFF_SIZE); +	if (num_trbs == 0)  		num_trbs++; -		running_total += TRB_MAX_BUFF_SIZE; -	}  	return num_trbs;  } @@ -3226,6 +3237,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	start_trb = &ep_ring->enqueue->generic;  	start_cycle = ep_ring->cycle_state; +	urb_priv = urb->hcpriv;  	/* Queue the first TRB, even if it's zero-length */  	for (i = 0; i < num_tds; i++) {  		unsigned int total_packet_count; @@ -3237,9 +3249,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		addr = start_addr + urb->iso_frame_desc[i].offset;  		td_len = urb->iso_frame_desc[i].length;  		td_remain_len = td_len; -		/* FIXME: Ignoring zero-length packets, can those happen? */  		total_packet_count = roundup(td_len,  				le16_to_cpu(urb->ep->desc.wMaxPacketSize)); +		/* A zero-length transfer still involves at least one packet. */ +		if (total_packet_count == 0) +			total_packet_count++;  		burst_count = xhci_get_burst_count(xhci, urb->dev, urb,  				total_packet_count);  		residue = xhci_get_last_burst_packet_count(xhci, @@ -3249,12 +3263,13 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  		ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,  				urb->stream_id, trbs_per_td, urb, i, mem_flags); -		if (ret < 0) -			return ret; +		if (ret < 0) { +			if (i == 0) +				return ret; +			goto cleanup; +		} -		urb_priv = urb->hcpriv;  		td = urb_priv->td[i]; -  		for (j = 0; j < trbs_per_td; j++) {  			u32 remainder = 0;  			field = TRB_TBC(burst_count) | TRB_TLBPC(residue); @@ -3344,6 +3359,27 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,  	giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,  			start_cycle, start_trb);  	return 0; +cleanup: +	/* Clean up a partially enqueued isoc transfer. */ + +	for (i--; i >= 0; i--) +		list_del_init(&urb_priv->td[i]->td_list); + +	/* Use the first TD as a temporary variable to turn the TDs we've queued +	 * into No-ops with a software-owned cycle bit. That way the hardware +	 * won't accidentally start executing bogus TDs when we partially +	 * overwrite them.  td->first_trb and td->start_seg are already set. +	 */ +	urb_priv->td[0]->last_trb = ep_ring->enqueue; +	/* Every TRB except the first & last will have its cycle bit flipped. */ +	td_to_noop(xhci, ep_ring, urb_priv->td[0], true); + +	/* Reset the ring enqueue back to the first TRB and its cycle bit. */ +	ep_ring->enqueue = urb_priv->td[0]->first_trb; +	ep_ring->enq_seg = urb_priv->td[0]->start_seg; +	ep_ring->cycle_state = start_cycle; +	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); +	return ret;  }  /* diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1c4432d8fc1..3a0f695138f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1085,8 +1085,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)  		if (urb->dev->speed == USB_SPEED_FULL) {  			ret = xhci_check_maxpacket(xhci, slot_id,  					ep_index, urb); -			if (ret < 0) +			if (ret < 0) { +				xhci_urb_free_priv(xhci, urb_priv); +				urb->hcpriv = NULL;  				return ret; +			}  		}  		/* We have a spinlock and interrupts disabled, so we must pass @@ -1097,6 +1100,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)  			goto dying;  		ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,  				slot_id, ep_index); +		if (ret) +			goto free_priv;  		spin_unlock_irqrestore(&xhci->lock, flags);  	} else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {  		spin_lock_irqsave(&xhci->lock, flags); @@ -1117,6 +1122,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)  			ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,  					slot_id, ep_index);  		} +		if (ret) +			goto free_priv;  		spin_unlock_irqrestore(&xhci->lock, flags);  	} else if (usb_endpoint_xfer_int(&urb->ep->desc)) {  		spin_lock_irqsave(&xhci->lock, flags); @@ -1124,6 +1131,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)  			goto dying;  		ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,  				slot_id, ep_index); +		if (ret) +			goto free_priv;  		spin_unlock_irqrestore(&xhci->lock, flags);  	} else {  		spin_lock_irqsave(&xhci->lock, flags); @@ -1131,18 +1140,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)  			goto dying;  		ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb,  				slot_id, ep_index); +		if (ret) +			goto free_priv;  		spin_unlock_irqrestore(&xhci->lock, flags);  	}  exit:  	return ret;  dying: -	xhci_urb_free_priv(xhci, urb_priv); -	urb->hcpriv = NULL;  	xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "  			"non-responsive xHCI host.\n",  			urb->ep->desc.bEndpointAddress, urb); +	ret = -ESHUTDOWN; +free_priv: +	xhci_urb_free_priv(xhci, urb_priv); +	urb->hcpriv = NULL;  	spin_unlock_irqrestore(&xhci->lock, flags); -	return -ESHUTDOWN; +	return ret;  }  /* Get the right ring for the given URB. @@ -1239,6 +1252,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  	if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {  		xhci_dbg(xhci, "HW died, freeing TD.\n");  		urb_priv = urb->hcpriv; +		for (i = urb_priv->td_cnt; i < urb_priv->length; i++) { +			td = urb_priv->td[i]; +			if (!list_empty(&td->td_list)) +				list_del_init(&td->td_list); +			if (!list_empty(&td->cancelled_td_list)) +				list_del_init(&td->cancelled_td_list); +		}  		usb_hcd_unlink_urb_from_ep(hcd, urb);  		spin_unlock_irqrestore(&xhci->lock, flags); diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index ae8c3961774..5e7cfba5b07 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -17,6 +17,7 @@  #include <linux/io.h>  #include <linux/platform_device.h>  #include <linux/dma-mapping.h> +#include <linux/prefetch.h>  #include <asm/cacheflush.h> diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 149f3f310a0..318fb4e8a88 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -226,8 +226,10 @@ static int cppi_controller_stop(struct dma_controller *c)  	struct cppi		*controller;  	void __iomem		*tibase;  	int			i; +	struct musb		*musb;  	controller = container_of(c, struct cppi, controller); +	musb = controller->musb;  	tibase = controller->tibase;  	/* DISABLE INDIVIDUAL CHANNEL Interrupts */ @@ -289,9 +291,11 @@ cppi_channel_allocate(struct dma_controller *c,  	u8			index;  	struct cppi_channel	*cppi_ch;  	void __iomem		*tibase; +	struct musb		*musb;  	controller = container_of(c, struct cppi, controller);  	tibase = controller->tibase; +	musb = controller->musb;  	/* ep0 doesn't use DMA; remember cppi indices are 0..N-1 */  	index = ep->epnum - 1; @@ -339,7 +343,8 @@ static void cppi_channel_release(struct dma_channel *channel)  	c = container_of(channel, struct cppi_channel, channel);  	tibase = c->controller->tibase;  	if (!c->hw_ep) -		dev_dbg(musb->controller, "releasing idle DMA channel %p\n", c); +		dev_dbg(c->controller->musb->controller, +			"releasing idle DMA channel %p\n", c);  	else if (!c->transmit)  		core_rxirq_enable(tibase, c->index + 1); @@ -357,10 +362,11 @@ cppi_dump_rx(int level, struct cppi_channel *c, const char *tag)  	musb_ep_select(base, c->index + 1); -	DBG(level, "RX DMA%d%s: %d left, csr %04x, " -			"%08x H%08x S%08x C%08x, " -			"B%08x L%08x %08x .. %08x" -			"\n", +	dev_dbg(c->controller->musb->controller, +		"RX DMA%d%s: %d left, csr %04x, " +		"%08x H%08x S%08x C%08x, " +		"B%08x L%08x %08x .. %08x" +		"\n",  		c->index, tag,  		musb_readl(c->controller->tibase,  			DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index), @@ -387,10 +393,11 @@ cppi_dump_tx(int level, struct cppi_channel *c, const char *tag)  	musb_ep_select(base, c->index + 1); -	DBG(level, "TX DMA%d%s: csr %04x, " -			"H%08x S%08x C%08x %08x, " -			"F%08x L%08x .. %08x" -			"\n", +	dev_dbg(c->controller->musb->controller, +		"TX DMA%d%s: csr %04x, " +		"H%08x S%08x C%08x %08x, " +		"F%08x L%08x .. %08x" +		"\n",  		c->index, tag,  		musb_readw(c->hw_ep->regs, MUSB_TXCSR), @@ -1022,6 +1029,7 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)  	int				i;  	dma_addr_t			safe2ack;  	void __iomem			*regs = rx->hw_ep->regs; +	struct musb			*musb = cppi->musb;  	cppi_dump_rx(6, rx, "/K"); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 668eeef601a..b3c065ab9db 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -172,7 +172,8 @@ enum musb_g_ep0_state {  #endif  /* TUSB mapping: "flat" plus ep0 special cases */ -#if	defined(CONFIG_USB_MUSB_TUSB6010) +#if defined(CONFIG_USB_MUSB_TUSB6010) || \ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  #define musb_ep_select(_mbase, _epnum) \  	musb_writeb((_mbase), MUSB_INDEX, (_epnum))  #define	MUSB_EP_OFFSET			MUSB_TUSB_OFFSET @@ -241,7 +242,8 @@ struct musb_hw_ep {  	void __iomem		*fifo;  	void __iomem		*regs; -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) || \ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  	void __iomem		*conf;  #endif @@ -258,7 +260,8 @@ struct musb_hw_ep {  	struct dma_channel	*tx_channel;  	struct dma_channel	*rx_channel; -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) || \ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  	/* TUSB has "asynchronous" and "synchronous" dma modes */  	dma_addr_t		fifo_async;  	dma_addr_t		fifo_sync; @@ -356,7 +359,8 @@ struct musb {  	void __iomem		*ctrl_base;  	void __iomem		*mregs; -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) || \ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  	dma_addr_t		async;  	dma_addr_t		sync;  	void __iomem		*sync_va; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 8c41a2e6ea7..e81820370d6 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1856,6 +1856,7 @@ int __init musb_gadget_setup(struct musb *musb)  	return 0;  err: +	musb->g.dev.parent = NULL;  	device_unregister(&musb->g.dev);  	return status;  } @@ -1863,7 +1864,8 @@ err:  void musb_gadget_cleanup(struct musb *musb)  {  	usb_del_gadget_udc(&musb->g); -	device_unregister(&musb->g.dev); +	if (musb->g.dev.parent) +		device_unregister(&musb->g.dev);  }  /* diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 82410703dcd..03f2655af29 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -234,7 +234,8 @@  #define MUSB_TESTMODE		0x0F	/* 8 bit */  /* Get offset for a given FIFO from musb->mregs */ -#ifdef	CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) ||	\ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  #define MUSB_FIFO_OFFSET(epnum)	(0x200 + ((epnum) * 0x20))  #else  #define MUSB_FIFO_OFFSET(epnum)	(0x20 + ((epnum) * 4)) @@ -295,7 +296,8 @@  #define MUSB_FLAT_OFFSET(_epnum, _offset)	\  	(0x100 + (0x10*(_epnum)) + (_offset)) -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) ||	\ +	defined(CONFIG_USB_MUSB_TUSB6010_MODULE)  /* TUSB6010 EP0 configuration register is special */  #define MUSB_TUSB_OFFSET(_epnum, _offset)	\  	(0x10 + _offset) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 9eec41fbf3a..ec1480191f7 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -18,6 +18,7 @@  #include <linux/kernel.h>  #include <linux/errno.h>  #include <linux/init.h> +#include <linux/prefetch.h>  #include <linux/usb.h>  #include <linux/irq.h>  #include <linux/platform_device.h> diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 07c8a73dfe4..b67b4bc596c 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -20,6 +20,7 @@  #include <plat/mux.h>  #include "musb_core.h" +#include "tusb6010.h"  #define to_chdat(c)		((struct tusb_omap_dma_ch *)(c)->private_data) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index cecace41183..ef4333f4bbe 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -65,7 +65,8 @@ static void ux500_tx_work(struct work_struct *data)  	struct musb *musb = hw_ep->musb;  	unsigned long flags; -	DBG(4, "DMA tx transfer done on hw_ep=%d\n", hw_ep->epnum); +	dev_dbg(musb->controller, "DMA tx transfer done on hw_ep=%d\n", +		hw_ep->epnum);  	spin_lock_irqsave(&musb->lock, flags);  	ux500_channel->channel.actual_len = ux500_channel->cur_len; @@ -84,7 +85,8 @@ static void ux500_rx_work(struct work_struct *data)  	struct musb *musb = hw_ep->musb;  	unsigned long flags; -	DBG(4, "DMA rx transfer done on hw_ep=%d\n", hw_ep->epnum); +	dev_dbg(musb->controller, "DMA rx transfer done on hw_ep=%d\n", +		hw_ep->epnum);  	spin_lock_irqsave(&musb->lock, flags);  	ux500_channel->channel.actual_len = ux500_channel->cur_len; @@ -116,9 +118,11 @@ static bool ux500_configure_channel(struct dma_channel *channel,  	enum dma_slave_buswidth addr_width;  	dma_addr_t usb_fifo_addr = (MUSB_FIFO_OFFSET(hw_ep->epnum) +  					ux500_channel->controller->phy_base); +	struct musb *musb = ux500_channel->controller->private_data; -	DBG(4, "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n", -			packet_sz, mode, dma_addr, len, ux500_channel->is_tx); +	dev_dbg(musb->controller, +		"packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n", +		packet_sz, mode, dma_addr, len, ux500_channel->is_tx);  	ux500_channel->cur_len = len; @@ -133,15 +137,13 @@ static bool ux500_configure_channel(struct dma_channel *channel,  					DMA_SLAVE_BUSWIDTH_4_BYTES;  	slave_conf.direction = direction; -	if (direction == DMA_FROM_DEVICE) { -		slave_conf.src_addr = usb_fifo_addr; -		slave_conf.src_addr_width = addr_width; -		slave_conf.src_maxburst = 16; -	} else { -		slave_conf.dst_addr = usb_fifo_addr; -		slave_conf.dst_addr_width = addr_width; -		slave_conf.dst_maxburst = 16; -	} +	slave_conf.src_addr = usb_fifo_addr; +	slave_conf.src_addr_width = addr_width; +	slave_conf.src_maxburst = 16; +	slave_conf.dst_addr = usb_fifo_addr; +	slave_conf.dst_addr_width = addr_width; +	slave_conf.dst_maxburst = 16; +  	dma_chan->device->device_control(dma_chan, DMA_SLAVE_CONFIG,  					     (unsigned long) &slave_conf); @@ -166,6 +168,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,  	struct ux500_dma_controller *controller = container_of(c,  			struct ux500_dma_controller, controller);  	struct ux500_dma_channel *ux500_channel = NULL; +	struct musb *musb = controller->private_data;  	u8 ch_num = hw_ep->epnum - 1;  	u32 max_ch; @@ -192,7 +195,7 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,  	ux500_channel->hw_ep = hw_ep;  	ux500_channel->is_allocated = 1; -	DBG(7, "hw_ep=%d, is_tx=0x%x, channel=%d\n", +	dev_dbg(musb->controller, "hw_ep=%d, is_tx=0x%x, channel=%d\n",  		hw_ep->epnum, is_tx, ch_num);  	return &(ux500_channel->channel); @@ -201,8 +204,9 @@ static struct dma_channel *ux500_dma_channel_allocate(struct dma_controller *c,  static void ux500_dma_channel_release(struct dma_channel *channel)  {  	struct ux500_dma_channel *ux500_channel = channel->private_data; +	struct musb *musb = ux500_channel->controller->private_data; -	DBG(7, "channel=%d\n", ux500_channel->ch_num); +	dev_dbg(musb->controller, "channel=%d\n", ux500_channel->ch_num);  	if (ux500_channel->is_allocated) {  		ux500_channel->is_allocated = 0; @@ -252,8 +256,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel)  	void __iomem *epio = musb->endpoints[ux500_channel->hw_ep->epnum].regs;  	u16 csr; -	DBG(4, "channel=%d, is_tx=%d\n", ux500_channel->ch_num, -						ux500_channel->is_tx); +	dev_dbg(musb->controller, "channel=%d, is_tx=%d\n", +		ux500_channel->ch_num, ux500_channel->is_tx);  	if (channel->status == MUSB_DMA_STATUS_BUSY) {  		if (ux500_channel->is_tx) { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 78a2cf9551c..5fc13e71791 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -101,6 +101,7 @@ static int   ftdi_jtag_probe(struct usb_serial *serial);  static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);  static int   ftdi_NDI_device_setup(struct usb_serial *serial);  static int   ftdi_stmclite_probe(struct usb_serial *serial); +static int   ftdi_8u2232c_probe(struct usb_serial *serial);  static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);  static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv); @@ -128,6 +129,10 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {  	.probe	= ftdi_stmclite_probe,  }; +static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { +	.probe	= ftdi_8u2232c_probe, +}; +  /*   * The 8U232AM has the same API as the sio except for:   * - it can support MUCH higher baudrates; up to: @@ -178,7 +183,8 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_232RL_PID) }, -	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) , +		.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },  	{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, @@ -1737,6 +1743,18 @@ static int ftdi_jtag_probe(struct usb_serial *serial)  	return 0;  } +static int ftdi_8u2232c_probe(struct usb_serial *serial) +{ +	struct usb_device *udev = serial->dev; + +	dbg("%s", __func__); + +	if (strcmp(udev->manufacturer, "CALAO Systems") == 0) +		return ftdi_jtag_probe(serial); + +	return 0; +} +  /*   * First and second port on STMCLiteadaptors is reserved for JTAG interface   * and the forth port for pio diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 81565619891..fe22e90bc87 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -148,6 +148,8 @@ static void option_instat_callback(struct urb *urb);  #define HUAWEI_PRODUCT_K4505			0x1464  #define HUAWEI_PRODUCT_K3765			0x1465  #define HUAWEI_PRODUCT_E14AC			0x14AC +#define HUAWEI_PRODUCT_K3806			0x14AE +#define HUAWEI_PRODUCT_K4605			0x14C6  #define HUAWEI_PRODUCT_K3770			0x14C9  #define HUAWEI_PRODUCT_K3771			0x14CA  #define HUAWEI_PRODUCT_K4510			0x14CB @@ -416,6 +418,56 @@ static void option_instat_callback(struct urb *urb);  #define SAMSUNG_VENDOR_ID                       0x04e8  #define SAMSUNG_PRODUCT_GT_B3730                0x6889 +/* YUGA products  www.yuga-info.com*/ +#define YUGA_VENDOR_ID				0x257A +#define YUGA_PRODUCT_CEM600			0x1601 +#define YUGA_PRODUCT_CEM610			0x1602 +#define YUGA_PRODUCT_CEM500			0x1603 +#define YUGA_PRODUCT_CEM510			0x1604 +#define YUGA_PRODUCT_CEM800			0x1605 +#define YUGA_PRODUCT_CEM900			0x1606 + +#define YUGA_PRODUCT_CEU818			0x1607 +#define YUGA_PRODUCT_CEU816			0x1608 +#define YUGA_PRODUCT_CEU828			0x1609 +#define YUGA_PRODUCT_CEU826			0x160A +#define YUGA_PRODUCT_CEU518			0x160B +#define YUGA_PRODUCT_CEU516			0x160C +#define YUGA_PRODUCT_CEU528			0x160D +#define YUGA_PRODUCT_CEU526			0x160F + +#define YUGA_PRODUCT_CWM600			0x2601 +#define YUGA_PRODUCT_CWM610			0x2602 +#define YUGA_PRODUCT_CWM500			0x2603 +#define YUGA_PRODUCT_CWM510			0x2604 +#define YUGA_PRODUCT_CWM800			0x2605 +#define YUGA_PRODUCT_CWM900			0x2606 + +#define YUGA_PRODUCT_CWU718			0x2607 +#define YUGA_PRODUCT_CWU716			0x2608 +#define YUGA_PRODUCT_CWU728			0x2609 +#define YUGA_PRODUCT_CWU726			0x260A +#define YUGA_PRODUCT_CWU518			0x260B +#define YUGA_PRODUCT_CWU516			0x260C +#define YUGA_PRODUCT_CWU528			0x260D +#define YUGA_PRODUCT_CWU526			0x260F + +#define YUGA_PRODUCT_CLM600			0x2601 +#define YUGA_PRODUCT_CLM610			0x2602 +#define YUGA_PRODUCT_CLM500			0x2603 +#define YUGA_PRODUCT_CLM510			0x2604 +#define YUGA_PRODUCT_CLM800			0x2605 +#define YUGA_PRODUCT_CLM900			0x2606 + +#define YUGA_PRODUCT_CLU718			0x2607 +#define YUGA_PRODUCT_CLU716			0x2608 +#define YUGA_PRODUCT_CLU728			0x2609 +#define YUGA_PRODUCT_CLU726			0x260A +#define YUGA_PRODUCT_CLU518			0x260B +#define YUGA_PRODUCT_CLU516			0x260C +#define YUGA_PRODUCT_CLU528			0x260D +#define YUGA_PRODUCT_CLU526			0x260F +  /* some devices interfaces need special handling due to a number of reasons */  enum option_blacklist_reason {  		OPTION_BLACKLIST_NONE = 0, @@ -551,6 +603,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, @@ -1005,6 +1059,48 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */  	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */  	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM500) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM510) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM800) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM900) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU818) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU816) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU828) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU826) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU518) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU516) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU528) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU526) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM600) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM610) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM500) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM510) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM800) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWM900) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU718) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU716) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU728) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU726) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU518) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU516) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU528) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU526) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM600) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM610) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM500) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM510) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM800) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLM900) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU718) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU716) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU728) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU726) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU518) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, +	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },  	{ } /* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, option_ids); @@ -1134,11 +1230,13 @@ static int option_probe(struct usb_serial *serial,  		serial->interface->cur_altsetting->desc.bInterfaceClass != 0xff)  		return -ENODEV; -	/* Don't bind network interfaces on Huawei K3765 & K4505 */ +	/* Don't bind network interfaces on Huawei K3765, K4505 & K4605 */  	if (serial->dev->descriptor.idVendor == HUAWEI_VENDOR_ID &&  		(serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K3765 || -			serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505) && -		serial->interface->cur_altsetting->desc.bInterfaceNumber == 1) +			serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4505 || +			serial->dev->descriptor.idProduct == HUAWEI_PRODUCT_K4605) && +		(serial->interface->cur_altsetting->desc.bInterfaceNumber == 1 || +			serial->interface->cur_altsetting->desc.bInterfaceNumber == 2))  		return -ENODEV;  	/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */  |