diff options
Diffstat (limited to 'drivers/usb')
30 files changed, 790 insertions, 839 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 64854d76f52..1af04bdeaf0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)  	int			limit = 100;  	spin_lock_irqsave (&hub->tt.lock, flags); -	while (--limit && !list_empty (&hub->tt.clear_list)) { +	while (!list_empty(&hub->tt.clear_list)) {  		struct list_head	*next;  		struct usb_tt_clear	*clear;  		struct usb_device	*hdev = hub->hdev;  		const struct hc_driver	*drv;  		int			status; +		if (!hub->quiescing && --limit < 0) +			break; +  		next = hub->tt.clear_list.next;  		clear = list_entry (next, struct usb_tt_clear, clear_list);  		list_del (&clear->clear_list); @@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)  	if (hub->has_indicators)  		cancel_delayed_work_sync(&hub->leds);  	if (hub->tt.hub) -		cancel_work_sync(&hub->tt.clear_work); +		flush_work(&hub->tt.clear_work);  }  /* caller has locked the hub device */ diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 43ac7482fa9..c009263a47e 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)  #if defined(PLX_PCI_RDK2)  	/* see if PCI int for us by checking irqstat */  	intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); -	if (!intcsr & (1 << NET2272_PCI_IRQ)) +	if (!intcsr & (1 << NET2272_PCI_IRQ)) { +		spin_unlock(&dev->lock);  		return IRQ_NONE; +	}  	/* check dma interrupts */  #endif  	/* Platform/devcice interrupt handler */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee7..39f9e4a9a2d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {  		/*  Pegatron Lucid (Ordissimo AIRIS) */  		.matches = {  			DMI_MATCH(DMI_BOARD_NAME, "M11JB"), -			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), +			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), +		}, +	}, +	{ +		/*  Pegatron Lucid (Ordissimo) */ +		.matches = { +			DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), +			DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),  		},  	},  	{ } diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5a417..5f3a7c74aa8 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,  	int i;  	/* Fields are 32 bits wide, DMA addresses are in bytes */  	int field_size = 32 / 8; -	struct xhci_slot_ctx *slot_ctx;  	dma_addr_t dma = ctx->dma;  	int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,  			dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);  	} -	slot_ctx = xhci_get_slot_ctx(xhci, ctx);  	xhci_dbg_slot_ctx(xhci, ctx);  	xhci_dbg_ep_ctx(xhci, ctx, last_ep);  } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa90ad4d4fd..a686cf4905b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,  		if (portsc & PORT_DEV_REMOVE)  			port_removable |= 1 << (i + 1);  	} -	memset(&desc->u.ss.DeviceRemovable, -			(__force __u16) cpu_to_le16(port_removable), -			sizeof(__u16)); + +	desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);  }  static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, @@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			temp = xhci_readl(xhci, port_array[wIndex]);  			xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp); +			spin_unlock_irqrestore(&xhci->lock, flags);  			temp = usb_acpi_power_manageable(hcd->self.root_hub,  					wIndex);  			if (temp)  				usb_acpi_set_power_state(hcd->self.root_hub,  						wIndex, true); +			spin_lock_irqsave(&xhci->lock, flags);  			break;  		case USB_PORT_FEAT_RESET:  			temp = (temp | PORT_RESET); @@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  			xhci_writel(xhci, temp & ~PORT_POWER,  				port_array[wIndex]); +			spin_unlock_irqrestore(&xhci->lock, flags);  			temp = usb_acpi_power_manageable(hcd->self.root_hub,  					wIndex);  			if (temp)  				usb_acpi_set_power_state(hcd->self.root_hub,  						wIndex, false); +			spin_lock_irqsave(&xhci->lock, flags);  			break;  		default:  			goto error; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c6ebb176dc4..4e1a8946b8d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)  	cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,  			xhci->cmd_ring->dequeue, &cycle_state); +	if (!cur_seg) { +		xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", +				xhci->cmd_ring->dequeue, +				(unsigned long long) +				xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, +					xhci->cmd_ring->dequeue)); +		xhci_debug_ring(xhci, xhci->cmd_ring); +		xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); +		return; +	} +  	/* find the command trb matched by cd from command ring */  	for (cmd_trb = xhci->cmd_ring->dequeue;  			cmd_trb != xhci->cmd_ring->enqueue; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7d462bf2009..c9e419f29b7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	struct xhci_hcd *xhci;  	struct xhci_container_ctx *in_ctx, *out_ctx;  	unsigned int ep_index; -	struct xhci_ep_ctx *ep_ctx;  	struct xhci_slot_ctx *slot_ctx;  	struct xhci_input_control_ctx *ctrl_ctx;  	u32 added_ctxs; @@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,  	out_ctx = virt_dev->out_ctx;  	ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);  	ep_index = xhci_get_endpoint_index(&ep->desc); -	ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);  	/* If this endpoint is already in use, and the upper layers are trying  	 * to add it again without dropping it, reject the addition. @@ -1817,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,  	case COMP_EBADSLT:  		dev_warn(&udev->dev, "WARN: slot not enabled for"  				"evaluate context command.\n"); +		ret = -EINVAL; +		break;  	case COMP_CTX_STATE:  		dev_warn(&udev->dev, "WARN: invalid context state for "  				"evaluate context command.\n"); @@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)  static unsigned long long xhci_service_interval_to_ns(  		struct usb_endpoint_descriptor *desc)  { -	return (1 << (desc->bInterval - 1)) * 125 * 1000; +	return (1ULL << (desc->bInterval - 1)) * 125 * 1000;  }  static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, @@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,  			(xhci_service_interval_to_ns(desc) > timeout_ns))  		timeout_ns = xhci_service_interval_to_ns(desc); -	u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; +	u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;  	if (u2_del_ns > timeout_ns)  		timeout_ns = u2_del_ns; diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 4223d761223..6589268a651 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,  }  EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 444346e1e10..ff5f112053d 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	struct platform_device	*musb;  	struct resource *res;  	struct resource	resources[2]; -	char res_name[10]; +	char res_name[11];  	int ret, musbid;  	/* get memory resource */ -	sprintf(res_name, "musb%d", id); +	snprintf(res_name, sizeof(res_name), "musb%d", id);  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);  	if (!res) {  		dev_err(dev, "%s get mem resource failed\n", res_name); @@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  	resources[0] = *res;  	/* get irq resource */ -	sprintf(res_name, "musb%d-irq", id); +	snprintf(res_name, sizeof(res_name), "musb%d-irq", id);  	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);  	if (!res) {  		dev_err(dev, "%s get irq resource failed\n", res_name); @@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  		of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);  		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); -		sprintf(res_name, "port%d-mode", id); +		snprintf(res_name, sizeof(res_name), "port%d-mode", id);  		of_property_read_u32(np, res_name, (u32 *)&pdata->mode);  		of_property_read_u32(np, "power", (u32 *)&pdata->power);  		config->multipoint = of_property_read_bool(np, "multipoint"); diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 143c4e9e1be..c021b202c0f 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)  	dev_dbg(dev, "  %s %d (%d/ %d)\n",  		fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); +	usbhs_pipe_enable(pipe);  	usbhsf_dma_start(pipe, fifo);  	dma_async_issue_pending(chan);  } diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 9b69a132329..069cd765400 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,  	struct device *dev = usbhs_priv_to_dev(priv);  	unsigned long flags; +	if (unlikely(!uep)) { +		dev_err(dev, "no uep\n"); +		return; +	} +  	/********************  spin lock ********************/  	usbhs_lock(priv, flags); diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index e9c7046ae35..d255f66e708 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -242,13 +242,11 @@ out:	kfree(buffer);  	return r;  } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port)  {  	struct ch341_private *priv;  	int r; -	/* private data */  	priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);  	if (!priv)  		return -ENOMEM; @@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)  	priv->baud_rate = DEFAULT_BAUD_RATE;  	priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; -	r = ch341_configure(serial->dev, priv); +	r = ch341_configure(port->serial->dev, priv);  	if (r < 0)  		goto error; -	usb_set_serial_port_data(serial->port[0], priv); +	usb_set_serial_port_data(port, priv);  	return 0;  error:	kfree(priv);  	return r;  } +static int ch341_port_remove(struct usb_serial_port *port) +{ +	struct ch341_private *priv; + +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +} +  static int ch341_carrier_raised(struct usb_serial_port *port)  {  	struct ch341_private *priv = usb_get_serial_port_data(port); @@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)  static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)  {  	struct usb_serial *serial = port->serial; -	struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); +	struct ch341_private *priv = usb_get_serial_port_data(port);  	int r;  	priv->baud_rate = DEFAULT_BAUD_RATE; @@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {  	.tiocmget          = ch341_tiocmget,  	.tiocmset          = ch341_tiocmset,  	.read_int_callback = ch341_read_int_callback, -	.attach            = ch341_attach, +	.port_probe        = ch341_port_probe, +	.port_remove       = ch341_port_remove,  	.reset_resume      = ch341_reset_resume,  }; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index c86f68c6b07..b50fa1c6d88 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);  static int digi_startup(struct usb_serial *serial);  static void digi_disconnect(struct usb_serial *serial);  static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port);  static void digi_read_bulk_callback(struct urb *urb);  static int digi_read_inb_callback(struct urb *urb);  static int digi_read_oob_callback(struct urb *urb); @@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {  	.attach =			digi_startup,  	.disconnect =			digi_disconnect,  	.release =			digi_release, +	.port_probe =			digi_port_probe, +	.port_remove =			digi_port_remove,  };  static struct usb_serial_driver digi_acceleport_4_device = { @@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {  	.attach =			digi_startup,  	.disconnect =			digi_disconnect,  	.release =			digi_release, +	.port_probe =			digi_port_probe, +	.port_remove =			digi_port_remove,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)  	return ret;  } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num)  { - -	int i;  	struct digi_port *priv; -	struct digi_serial *serial_priv; -	/* allocate the private data structures for all ports */ -	/* number of regular ports + 1 for the out-of-band port */ -	for (i = 0; i < serial->type->num_ports + 1; i++) { -		/* allocate port private structure */ -		priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); -		if (priv == NULL) { -			while (--i >= 0) -				kfree(usb_get_serial_port_data(serial->port[i])); -			return 1;			/* error */ -		} +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; -		/* initialize port private structure */ -		spin_lock_init(&priv->dp_port_lock); -		priv->dp_port_num = i; -		priv->dp_out_buf_len = 0; -		priv->dp_write_urb_in_use = 0; -		priv->dp_modem_signals = 0; -		init_waitqueue_head(&priv->dp_modem_change_wait); -		priv->dp_transmit_idle = 0; -		init_waitqueue_head(&priv->dp_transmit_idle_wait); -		priv->dp_throttled = 0; -		priv->dp_throttle_restart = 0; -		init_waitqueue_head(&priv->dp_flush_wait); -		init_waitqueue_head(&priv->dp_close_wait); -		INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); -		priv->dp_port = serial->port[i]; -		/* initialize write wait queue for this port */ -		init_waitqueue_head(&serial->port[i]->write_wait); +	spin_lock_init(&priv->dp_port_lock); +	priv->dp_port_num = port_num; +	init_waitqueue_head(&priv->dp_modem_change_wait); +	init_waitqueue_head(&priv->dp_transmit_idle_wait); +	init_waitqueue_head(&priv->dp_flush_wait); +	init_waitqueue_head(&priv->dp_close_wait); +	INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); +	priv->dp_port = port; -		usb_set_serial_port_data(serial->port[i], priv); -	} +	init_waitqueue_head(&port->write_wait); -	/* allocate serial private structure */ -	serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); -	if (serial_priv == NULL) { -		for (i = 0; i < serial->type->num_ports + 1; i++) -			kfree(usb_get_serial_port_data(serial->port[i])); -		return 1;			/* error */ -	} +	usb_set_serial_port_data(port, priv); + +	return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ +	struct digi_serial *serial_priv; +	int ret; + +	serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); +	if (!serial_priv) +		return -ENOMEM; -	/* initialize serial private structure */  	spin_lock_init(&serial_priv->ds_serial_lock);  	serial_priv->ds_oob_port_num = serial->type->num_ports;  	serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; -	serial_priv->ds_device_started = 0; + +	ret = digi_port_init(serial_priv->ds_oob_port, +						serial_priv->ds_oob_port_num); +	if (ret) { +		kfree(serial_priv); +		return ret; +	} +  	usb_set_serial_data(serial, serial_priv);  	return 0; @@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)  static void digi_release(struct usb_serial *serial)  { -	int i; +	struct digi_serial *serial_priv; +	struct digi_port *priv; + +	serial_priv = usb_get_serial_data(serial); + +	priv = usb_get_serial_port_data(serial_priv->ds_oob_port); +	kfree(priv); + +	kfree(serial_priv); +} -	/* free the private data structures for all ports */ -	/* number of regular ports + 1 for the out-of-band port */ -	for (i = 0; i < serial->type->num_ports + 1; i++) -		kfree(usb_get_serial_port_data(serial->port[i])); -	kfree(usb_get_serial_data(serial)); +static int digi_port_probe(struct usb_serial_port *port) +{ +	unsigned port_num; + +	port_num = port->number - port->serial->minor; + +	return digi_port_init(port, port_num);  } +static int digi_port_remove(struct usb_serial_port *port) +{ +	struct digi_port *priv; + +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +}  static void digi_read_bulk_callback(struct urb *urb)  { diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 20a132ec39e..4264821a3b3 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)  	return 0;  } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *data; @@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {  	.num_ports =		1,  	.open =			ipw_open,  	.close =		ipw_close, -	.probe =		ipw_probe, -	.attach =		usb_wwan_startup, +	.attach =		ipw_attach,  	.release =		ipw_release, +	.port_probe =		usb_wwan_port_probe,  	.port_remove =		usb_wwan_port_remove,  	.dtr_rts =		ipw_dtr_rts,  	.write =		usb_wwan_write, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d737d..7179b0c5f81 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1374,13 +1374,9 @@ static struct callbacks {  	   data in device_details */  static void keyspan_setup_urbs(struct usb_serial *serial)  { -	int				i, j;  	struct keyspan_serial_private 	*s_priv;  	const struct keyspan_device_details	*d_details; -	struct usb_serial_port		*port; -	struct keyspan_port_private	*p_priv;  	struct callbacks		*cback; -	int				endp;  	s_priv = usb_get_serial_data(serial);  	d_details = s_priv->device_details; @@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)  		(serial, d_details->glocont_endpoint, USB_DIR_OUT,  		 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,  		 cback->glocont_callback); - -	/* Setup endpoints for each port specific thing */ -	for (i = 0; i < d_details->num_ports; i++) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); - -		/* Do indat endpoints first, once for each flip */ -		endp = d_details->indat_endpoints[i]; -		for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { -			p_priv->in_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_IN, port, -				 p_priv->in_buffer[j], 64, -				 cback->indat_callback); -		} -		for (; j < 2; ++j) -			p_priv->in_urbs[j] = NULL; - -		/* outdat endpoints also have flip */ -		endp = d_details->outdat_endpoints[i]; -		for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { -			p_priv->out_urbs[j] = keyspan_setup_urb -				(serial, endp, USB_DIR_OUT, port, -				 p_priv->out_buffer[j], 64, -				 cback->outdat_callback); -		} -		for (; j < 2; ++j) -			p_priv->out_urbs[j] = NULL; - -		/* inack endpoint */ -		p_priv->inack_urb = keyspan_setup_urb -			(serial, d_details->inack_endpoints[i], USB_DIR_IN, -			 port, p_priv->inack_buffer, 1, cback->inack_callback); - -		/* outcont endpoint */ -		p_priv->outcont_urb = keyspan_setup_urb -			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT, -			 port, p_priv->outcont_buffer, 64, -			 cback->outcont_callback); -	}  }  /* usa19 function doesn't require prescaler */ @@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)  static int keyspan_startup(struct usb_serial *serial)  {  	int				i, err; -	struct usb_serial_port		*port;  	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv;  	const struct keyspan_device_details	*d_details;  	for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)  	s_priv->device_details = d_details;  	usb_set_serial_data(serial, s_priv); -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		p_priv = kzalloc(sizeof(struct keyspan_port_private), -								GFP_KERNEL); -		if (!p_priv) { -			dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); -			return 1; -		} -		p_priv->device_details = d_details; -		usb_set_serial_port_data(port, p_priv); -	} -  	keyspan_setup_urbs(serial);  	if (s_priv->instat_urb != NULL) { @@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)  static void keyspan_disconnect(struct usb_serial *serial)  { -	int				i, j; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; -	struct keyspan_port_private	*p_priv; +	struct keyspan_serial_private *s_priv;  	s_priv = usb_get_serial_data(serial); -	/* Stop reading/writing urbs */  	stop_urb(s_priv->instat_urb);  	stop_urb(s_priv->glocont_urb);  	stop_urb(s_priv->indat_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		stop_urb(p_priv->inack_urb); -		stop_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			stop_urb(p_priv->in_urbs[j]); -			stop_urb(p_priv->out_urbs[j]); -		} -	} +} + +static void keyspan_release(struct usb_serial *serial) +{ +	struct keyspan_serial_private *s_priv; + +	s_priv = usb_get_serial_data(serial); -	/* Now free them */  	usb_free_urb(s_priv->instat_urb);  	usb_free_urb(s_priv->indat_urb);  	usb_free_urb(s_priv->glocont_urb); -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		p_priv = usb_get_serial_port_data(port); -		usb_free_urb(p_priv->inack_urb); -		usb_free_urb(p_priv->outcont_urb); -		for (j = 0; j < 2; j++) { -			usb_free_urb(p_priv->in_urbs[j]); -			usb_free_urb(p_priv->out_urbs[j]); -		} -	} + +	kfree(s_priv);  } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port)  { -	int				i; -	struct usb_serial_port		*port; -	struct keyspan_serial_private 	*s_priv; +	struct usb_serial *serial = port->serial; +	struct keyspan_port_private *s_priv; +	struct keyspan_port_private *p_priv; +	const struct keyspan_device_details *d_details; +	struct callbacks *cback; +	int endp; +	int port_num; +	int i;  	s_priv = usb_get_serial_data(serial); +	d_details = s_priv->device_details; -	kfree(s_priv); +	p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); +	if (!p_priv) +		return -ENOMEM; -	/* Now free per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		kfree(usb_get_serial_port_data(port)); +	s_priv = usb_get_serial_data(port->serial); +	p_priv->device_details = d_details; + +	/* Setup values for the various callback routines */ +	cback = &keyspan_callbacks[d_details->msg_format]; + +	port_num = port->number - port->serial->minor; + +	/* Do indat endpoints first, once for each flip */ +	endp = d_details->indat_endpoints[port_num]; +	for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { +		p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_IN, port, +						p_priv->in_buffer[i], 64, +						cback->indat_callback);  	} +	/* outdat endpoints also have flip */ +	endp = d_details->outdat_endpoints[port_num]; +	for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { +		p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, +						USB_DIR_OUT, port, +						p_priv->out_buffer[i], 64, +						cback->outdat_callback); +	} +	/* inack endpoint */ +	p_priv->inack_urb = keyspan_setup_urb(serial, +					d_details->inack_endpoints[port_num], +					USB_DIR_IN, port, +					p_priv->inack_buffer, 1, +					cback->inack_callback); +	/* outcont endpoint */ +	p_priv->outcont_urb = keyspan_setup_urb(serial, +					d_details->outcont_endpoints[port_num], +					USB_DIR_OUT, port, +					p_priv->outcont_buffer, 64, +					 cback->outcont_callback); + +	usb_set_serial_port_data(port, p_priv); + +	return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ +	struct keyspan_port_private *p_priv; +	int i; + +	p_priv = usb_get_serial_port_data(port); + +	stop_urb(p_priv->inack_urb); +	stop_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		stop_urb(p_priv->in_urbs[i]); +		stop_urb(p_priv->out_urbs[i]); +	} + +	usb_free_urb(p_priv->inack_urb); +	usb_free_urb(p_priv->outcont_urb); +	for (i = 0; i < 2; i++) { +		usb_free_urb(p_priv->in_urbs[i]); +		usb_free_urb(p_priv->out_urbs[i]); +	} + +	kfree(p_priv); + +	return 0;  }  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 0a8a40b5711..0273dda303a 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts		(struct usb_serial_port *port, int on);  static int  keyspan_startup		(struct usb_serial *serial);  static void keyspan_disconnect		(struct usb_serial *serial);  static void keyspan_release		(struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port);  static int  keyspan_write_room		(struct tty_struct *tty);  static int  keyspan_write		(struct tty_struct *tty, @@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver keyspan_2port_device = { @@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver keyspan_4port_device = { @@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {  	.attach			= keyspan_startup,  	.disconnect		= keyspan_disconnect,  	.release		= keyspan_release, +	.port_probe		= keyspan_port_probe, +	.port_remove		= keyspan_port_remove,  };  static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index f3947712e13..8a208100410 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -49,7 +49,8 @@   * Function prototypes   */  static int  mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int  mct_u232_port_probe(struct usb_serial_port *port); +static int  mct_u232_port_remove(struct usb_serial_port *remove);  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);  static void mct_u232_close(struct usb_serial_port *port);  static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {  	.tiocmget =	     mct_u232_tiocmget,  	.tiocmset =	     mct_u232_tiocmset,  	.attach =	     mct_u232_startup, -	.release =	     mct_u232_release, +	.port_probe =        mct_u232_port_probe, +	.port_remove =       mct_u232_port_remove,  	.ioctl =             mct_u232_ioctl,  	.get_icount =        mct_u232_get_icount,  }; @@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,  static int mct_u232_startup(struct usb_serial *serial)  { -	struct mct_u232_private *priv;  	struct usb_serial_port *port, *rport; -	priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); -	if (!priv) -		return -ENOMEM; -	spin_lock_init(&priv->lock); -	init_waitqueue_head(&priv->msr_wait); -	usb_set_serial_port_data(serial->port[0], priv); - -	init_waitqueue_head(&serial->port[0]->write_wait); -  	/* Puh, that's dirty */  	port = serial->port[0];  	rport = serial->port[1]; @@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)  	return 0;  } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ +	struct mct_u232_private *priv; + +	priv = kzalloc(sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	spin_lock_init(&priv->lock); +	init_waitqueue_head(&priv->msr_wait); + +	usb_set_serial_port_data(port, priv); -static void mct_u232_release(struct usb_serial *serial) +	return 0; +} + +static int mct_u232_port_remove(struct usb_serial_port *port)  {  	struct mct_u232_private *priv; -	int i; -	for (i = 0; i < serial->num_ports; ++i) { -		/* My special items, the standard routines free my urbs */ -		priv = usb_get_serial_port_data(serial->port[i]); -		kfree(priv); -	} -} /* mct_u232_release */ +	priv = usb_get_serial_port_data(port); +	kfree(priv); + +	return 0; +}  static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)  { @@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)  static void mct_u232_close(struct usb_serial_port *port)  { -	if (port->serial->dev) { -		/* shutdown our urbs */ -		usb_kill_urb(port->write_urb); -		usb_kill_urb(port->read_urb); -		usb_kill_urb(port->interrupt_in_urb); -	} +	/* +	 * Must kill the read urb as it is actually an interrupt urb, which +	 * generic close thus fails to kill. +	 */ +	usb_kill_urb(port->read_urb); +	usb_kill_urb(port->interrupt_in_urb); + +	usb_serial_generic_close(port);  } /* mct_u232_close */ diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257ddffbd..6f29c74eb76 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)  {  	dev_dbg(&port->dev, "%s\n", __func__); -	if (port->serial->dev) { -		/* Shutdown any interrupt in urbs. */ -		if (port->interrupt_in_urb) { -			usb_unlink_urb(port->interrupt_in_urb); -			usb_kill_urb(port->interrupt_in_urb); -		} +	usb_unlink_urb(port->interrupt_in_urb); +	usb_kill_urb(port->interrupt_in_urb); -		/* Send deactivate cmd to device */ +	mutex_lock(&port->serial->disc_mutex); +	if (!port->serial->disconnected)  		metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); -	} +	mutex_unlock(&port->serial->disc_mutex);  }  static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr  	return retval;  } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port)  { -	int i = 0; +	struct metrousb_private *metro_priv; -	dev_dbg(&serial->dev->dev, "%s\n", __func__); +	metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); +	if (!metro_priv) +		return -ENOMEM; -	/* Stop reading and writing on all ports. */ -	for (i = 0; i < serial->num_ports; ++i) { -		/* Close any open urbs. */ -		metrousb_cleanup(serial->port[i]); +	spin_lock_init(&metro_priv->lock); -		/* Free memory. */ -		kfree(usb_get_serial_port_data(serial->port[i])); -		usb_set_serial_port_data(serial->port[i], NULL); +	usb_set_serial_port_data(port, metro_priv); -		dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", -			__func__, serial->port[i]->number); -	} +	return 0;  } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port)  {  	struct metrousb_private *metro_priv; -	struct usb_serial_port *port; -	int i = 0; -	dev_dbg(&serial->dev->dev, "%s\n", __func__); - -	/* Loop through the serial ports setting up the private structures. -	 * Currently we only use one port. */ -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; - -		/* Declare memory. */ -		metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); -		if (!metro_priv) -			return -ENOMEM; - -		/* Initialize memory. */ -		spin_lock_init(&metro_priv->lock); -		usb_set_serial_port_data(port, metro_priv); - -		dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", -			__func__, port->number); -	} +	metro_priv = usb_get_serial_port_data(port); +	kfree(metro_priv);  	return 0;  } @@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {  	.close			= metrousb_cleanup,  	.read_int_callback	= metrousb_read_int_callback,  	.write_int_callback	= metrousb_write_int_callback, -	.attach			= metrousb_startup, -	.release		= metrousb_shutdown, +	.port_probe		= metrousb_port_probe, +	.port_remove		= metrousb_port_remove,  	.throttle		= metrousb_throttle,  	.unthrottle		= metrousb_unthrottle,  	.tiocmget		= metrousb_tiocmget, diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1bf1ad06666..75267421aad 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,  static int mos7720_startup(struct usb_serial *serial)  { -	struct moschip_port *mos7720_port;  	struct usb_device *dev; -	int i;  	char data;  	u16 product;  	int ret_val; @@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)  		serial->port[1]->interrupt_in_buffer = NULL;  	} - -	/* set up serial port private structures */ -	for (i = 0; i < serial->num_ports; ++i) { -		mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); -		if (mos7720_port == NULL) { -			dev_err(&dev->dev, "%s - Out of memory\n", __func__); -			return -ENOMEM; -		} - -		/* Initialize all port interrupt end point to port 0 int -		 * endpoint.  Our device has only one interrupt endpoint -		 * common to all ports */ -		serial->port[i]->interrupt_in_endpointAddress = -				serial->port[0]->interrupt_in_endpointAddress; - -		mos7720_port->port = serial->port[i]; -		usb_set_serial_port_data(serial->port[i], mos7720_port); - -		dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); -		dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); -	} - -  	/* setting configuration feature to one */  	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),  			(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)  static void mos7720_release(struct usb_serial *serial)  { -	int i; -  #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT  	/* close the parallel port */ @@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)  		kref_put(&mos_parport->ref_count, destroy_mos_parport);  	}  #endif -	/* free private structure allocated for serial port */ -	for (i = 0; i < serial->num_ports; ++i) -		kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ +	struct moschip_port *mos7720_port; + +	mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); +	if (!mos7720_port) +		return -ENOMEM; + +	/* Initialize all port interrupt end point to port 0 int endpoint. +	 * Our device has only one interrupt endpoint common to all ports. +	 */ +	port->interrupt_in_endpointAddress = +		port->serial->port[0]->interrupt_in_endpointAddress; +	mos7720_port->port = port; + +	usb_set_serial_port_data(port, mos7720_port); + +	return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ +	struct moschip_port *mos7720_port; + +	mos7720_port = usb_get_serial_port_data(port); +	kfree(mos7720_port); + +	return 0;  }  static struct usb_serial_driver moschip7720_2port_driver = { @@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {  	.probe			= mos77xx_probe,  	.attach			= mos7720_startup,  	.release		= mos7720_release, +	.port_probe		= mos7720_port_probe, +	.port_remove		= mos7720_port_remove,  	.ioctl			= mos7720_ioctl,  	.tiocmget		= mos7720_tiocmget,  	.tiocmset		= mos7720_tiocmset, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eeca8c6..1cf3375ec1a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,12 +218,10 @@ struct moschip_port {  	int port_num;		/*Actual port number in the device(1,2,etc) */  	struct urb *write_urb;	/* write URB for this port */  	struct urb *read_urb;	/* read URB for this port */ -	struct urb *int_urb;  	__u8 shadowLCR;		/* last LCR value received */  	__u8 shadowMCR;		/* last MCR value received */  	char open;  	char open_ports; -	char zombie;  	wait_queue_head_t wait_chase;	/* for handling sleeping while waiting for chase to finish */  	wait_queue_head_t delta_msr_wait;	/* for handling sleeping while waiting for msr change to happen */  	int delta_msr_cond; @@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)  	struct moschip_port *mos7840_port;  	struct device *dev = &urb->dev->dev;  	__u8 regval = 0x0; -	int result = 0;  	int status = urb->status;  	mos7840_port = urb->context; @@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)  		return;  	default:  		dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); -		goto exit; +		return;  	}  	dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); @@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)  		mos7840_handle_new_msr(mos7840_port, regval);  	else if (mos7840_port->MsrLsr == 1)  		mos7840_handle_new_lsr(mos7840_port, regval); - -exit: -	spin_lock(&mos7840_port->pool_lock); -	if (!mos7840_port->zombie) -		result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); -	spin_unlock(&mos7840_port->pool_lock); -	if (result) { -		dev_err(dev, "%s - Error %d submitting interrupt urb\n", -			__func__, result); -	}  }  static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, @@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)  					wreg = MODEM_STATUS_REGISTER;  					break;  				} -				spin_lock(&mos7840_port->pool_lock); -				if (!mos7840_port->zombie) { -					rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); -				} else { -					spin_unlock(&mos7840_port->pool_lock); -					return; -				} -				spin_unlock(&mos7840_port->pool_lock); +				rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);  			}  		}  	} @@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)  	return mos7840_num_ports;  } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port)  { +	struct usb_serial *serial = port->serial;  	struct moschip_port *mos7840_port; -	struct usb_device *dev; -	int i, status; +	int status; +	int pnum;  	__u16 Data; -	dev = serial->dev; -  	/* we set up the pointers to the endpoints in the mos7840_open *  	 * function, as the structures aren't created yet.             */ -	/* set up port private structures */ -	for (i = 0; i < serial->num_ports; ++i) { -		dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); -		mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); -		if (mos7840_port == NULL) { -			dev_err(&dev->dev, "%s - Out of memory\n", __func__); -			status = -ENOMEM; -			i--; /* don't follow NULL pointer cleaning up */ -			goto error; -		} +	pnum = port->number - serial->minor; -		/* Initialize all port interrupt end point to port 0 int -		 * endpoint. Our device has only one interrupt end point -		 * common to all port */ +	dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); +	mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); +	if (mos7840_port == NULL) { +		dev_err(&port->dev, "%s - Out of memory\n", __func__); +		return -ENOMEM; +	} -		mos7840_port->port = serial->port[i]; -		mos7840_set_port_private(serial->port[i], mos7840_port); -		spin_lock_init(&mos7840_port->pool_lock); +	/* Initialize all port interrupt end point to port 0 int +	 * endpoint. Our device has only one interrupt end point +	 * common to all port */ -		/* minor is not initialised until later by -		 * usb-serial.c:get_free_serial() and cannot therefore be used -		 * to index device instances */ -		mos7840_port->port_num = i + 1; -		dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); -		dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); -		dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); -		dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); +	mos7840_port->port = port; +	mos7840_set_port_private(port, mos7840_port); +	spin_lock_init(&mos7840_port->pool_lock); -		if (mos7840_port->port_num == 1) { -			mos7840_port->SpRegOffset = 0x0; -			mos7840_port->ControlRegOffset = 0x1; -			mos7840_port->DcrRegOffset = 0x4; -		} else if ((mos7840_port->port_num == 2) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0x8; -			mos7840_port->ControlRegOffset = 0x9; -			mos7840_port->DcrRegOffset = 0x16; -		} else if ((mos7840_port->port_num == 2) -			   && (serial->num_ports == 2)) { -			mos7840_port->SpRegOffset = 0xa; -			mos7840_port->ControlRegOffset = 0xb; -			mos7840_port->DcrRegOffset = 0x19; -		} else if ((mos7840_port->port_num == 3) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0xa; -			mos7840_port->ControlRegOffset = 0xb; -			mos7840_port->DcrRegOffset = 0x19; -		} else if ((mos7840_port->port_num == 4) -			   && (serial->num_ports == 4)) { -			mos7840_port->SpRegOffset = 0xc; -			mos7840_port->ControlRegOffset = 0xd; -			mos7840_port->DcrRegOffset = 0x1c; -		} -		mos7840_dump_serial_port(serial->port[i], mos7840_port); -		mos7840_set_port_private(serial->port[i], mos7840_port); +	/* minor is not initialised until later by +	 * usb-serial.c:get_free_serial() and cannot therefore be used +	 * to index device instances */ +	mos7840_port->port_num = pnum + 1; +	dev_dbg(&port->dev, "port->number = %d\n", port->number); +	dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); +	dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); +	dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); -		/* enable rx_disable bit in control register */ -		status = mos7840_get_reg_sync(serial->port[i], -				 mos7840_port->ControlRegOffset, &Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); -		Data |= 0x08;	/* setting driver done bit */ -		Data |= 0x04;	/* sp1_bit to have cts change reflect in -				   modem status reg */ +	if (mos7840_port->port_num == 1) { +		mos7840_port->SpRegOffset = 0x0; +		mos7840_port->ControlRegOffset = 0x1; +		mos7840_port->DcrRegOffset = 0x4; +	} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0x8; +		mos7840_port->ControlRegOffset = 0x9; +		mos7840_port->DcrRegOffset = 0x16; +	} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { +		mos7840_port->SpRegOffset = 0xa; +		mos7840_port->ControlRegOffset = 0xb; +		mos7840_port->DcrRegOffset = 0x19; +	} else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0xa; +		mos7840_port->ControlRegOffset = 0xb; +		mos7840_port->DcrRegOffset = 0x19; +	} else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { +		mos7840_port->SpRegOffset = 0xc; +		mos7840_port->ControlRegOffset = 0xd; +		mos7840_port->DcrRegOffset = 0x1c; +	} +	mos7840_dump_serial_port(port, mos7840_port); +	mos7840_set_port_private(port, mos7840_port); -		/* Data |= 0x20; //rx_disable bit */ -		status = mos7840_set_reg_sync(serial->port[i], -					 mos7840_port->ControlRegOffset, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); +	/* enable rx_disable bit in control register */ +	status = mos7840_get_reg_sync(port, +			mos7840_port->ControlRegOffset, &Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); +	Data |= 0x08;	/* setting driver done bit */ +	Data |= 0x04;	/* sp1_bit to have cts change reflect in +			   modem status reg */ -		/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 -		   and 0x24 in DCR3 */ -		Data = 0x01; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 0), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); +	/* Data |= 0x20; //rx_disable bit */ +	status = mos7840_set_reg_sync(port, +			mos7840_port->ControlRegOffset, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); -		Data = 0x05; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 1), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); +	/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 +	   and 0x24 in DCR3 */ +	Data = 0x01; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 0), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); -		Data = 0x24; -		status = mos7840_set_reg_sync(serial->port[i], -			 (__u16) (mos7840_port->DcrRegOffset + 2), Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); +	Data = 0x05; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 1), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); -		/* write values in clkstart0x0 and clkmulti 0x20 */ -		Data = 0x0; -		status = mos7840_set_reg_sync(serial->port[i], -					 CLK_START_VALUE_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); +	Data = 0x24; +	status = mos7840_set_reg_sync(port, +			(__u16) (mos7840_port->DcrRegOffset + 2), Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); -		Data = 0x20; -		status = mos7840_set_reg_sync(serial->port[i], -					CLK_MULTI_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); -			goto error; -		} else -			dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); +	/* write values in clkstart0x0 and clkmulti 0x20 */ +	Data = 0x0; +	status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); -		/* write value 0x0 to scratchpad register */ -		Data = 0x00; -		status = mos7840_set_uart_reg(serial->port[i], -						SCRATCH_PAD_REGISTER, Data); -		if (status < 0) { -			dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); -			break; -		} else -			dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); +	Data = 0x20; +	status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); +		goto error; +	} else +		dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); -		/* Zero Length flag register */ -		if ((mos7840_port->port_num != 1) -		    && (serial->num_ports == 2)) { +	/* write value 0x0 to scratchpad register */ +	Data = 0x00; +	status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); +	if (status < 0) { +		dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); +		goto out; +	} else +		dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); -			Data = 0xff; -			status = mos7840_set_reg_sync(serial->port[i], -				      (__u16) (ZLP_REG1 + -				      ((__u16)mos7840_port->port_num)), Data); -			dev_dbg(&dev->dev, "ZLIP offset %x\n", +	/* Zero Length flag register */ +	if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { +		Data = 0xff; +		status = mos7840_set_reg_sync(port, +				(__u16) (ZLP_REG1 + +					((__u16)mos7840_port->port_num)), Data); +		dev_dbg(&port->dev, "ZLIP offset %x\n",  				(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); -			if (status < 0) { -				dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); -				break; -			} else -				dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); -		} else { -			Data = 0xff; -			status = mos7840_set_reg_sync(serial->port[i], -			      (__u16) (ZLP_REG1 + -			      ((__u16)mos7840_port->port_num) - 0x1), Data); -			dev_dbg(&dev->dev, "ZLIP offset %x\n", +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); +			goto out; +		} else +			dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); +	} else { +		Data = 0xff; +		status = mos7840_set_reg_sync(port, +				(__u16) (ZLP_REG1 + +					((__u16)mos7840_port->port_num) - 0x1), Data); +		dev_dbg(&port->dev, "ZLIP offset %x\n",  				(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); -			if (status < 0) { -				dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); -				break; -			} else -				dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); +			goto out; +		} else +			dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); -		} -		mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); -		mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); -		mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), -								GFP_KERNEL); -		if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || -							!mos7840_port->dr) { -			status = -ENOMEM; -			goto error; -		} +	} +	mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); +	mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); +	mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), +			GFP_KERNEL); +	if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || +			!mos7840_port->dr) { +		status = -ENOMEM; +		goto error; +	} -		mos7840_port->has_led = false; +	mos7840_port->has_led = false; -		/* Initialize LED timers */ -		if (device_type == MOSCHIP_DEVICE_ID_7810) { -			mos7840_port->has_led = true; +	/* Initialize LED timers */ +	if (device_type == MOSCHIP_DEVICE_ID_7810) { +		mos7840_port->has_led = true; -			init_timer(&mos7840_port->led_timer1); -			mos7840_port->led_timer1.function = mos7840_led_off; -			mos7840_port->led_timer1.expires = -					jiffies + msecs_to_jiffies(LED_ON_MS); -			mos7840_port->led_timer1.data = -						(unsigned long)mos7840_port; +		init_timer(&mos7840_port->led_timer1); +		mos7840_port->led_timer1.function = mos7840_led_off; +		mos7840_port->led_timer1.expires = +			jiffies + msecs_to_jiffies(LED_ON_MS); +		mos7840_port->led_timer1.data = (unsigned long)mos7840_port; -			init_timer(&mos7840_port->led_timer2); -			mos7840_port->led_timer2.function = -						mos7840_led_flag_off; -			mos7840_port->led_timer2.expires = -					jiffies + msecs_to_jiffies(LED_OFF_MS); -			mos7840_port->led_timer2.data = -						(unsigned long)mos7840_port; +		init_timer(&mos7840_port->led_timer2); +		mos7840_port->led_timer2.function = mos7840_led_flag_off; +		mos7840_port->led_timer2.expires = +			jiffies + msecs_to_jiffies(LED_OFF_MS); +		mos7840_port->led_timer2.data = (unsigned long)mos7840_port; -			mos7840_port->led_flag = false; +		mos7840_port->led_flag = false; -			/* Turn off LED */ -			mos7840_set_led_sync(serial->port[i], -						MODEM_CONTROL_REGISTER, 0x0300); -		} +		/* Turn off LED */ +		mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);  	} +out: +	if (pnum == serial->num_ports - 1) { +		/* Zero Length flag enable */ +		Data = 0x0f; +		status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); +		if (status < 0) { +			dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); +			goto error; +		} else +			dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); -	/* Zero Length flag enable */ -	Data = 0x0f; -	status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); -	if (status < 0) { -		dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); -		goto error; -	} else -		dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); - -	/* setting configuration feature to one */ -	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), -			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); +		/* setting configuration feature to one */ +		usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), +				0x03, 0x00, 0x01, 0x00, NULL, 0x00, +				MOS_WDR_TIMEOUT); +	}  	return 0;  error: -	for (/* nothing */; i >= 0; i--) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); +	kfree(mos7840_port->dr); +	kfree(mos7840_port->ctrl_buf); +	usb_free_urb(mos7840_port->control_urb); +	kfree(mos7840_port); -		kfree(mos7840_port->dr); -		kfree(mos7840_port->ctrl_buf); -		usb_free_urb(mos7840_port->control_urb); -		kfree(mos7840_port); -		serial->port[i] = NULL; -	}  	return status;  } -/**************************************************************************** - * mos7840_disconnect - *	This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port)  { -	int i; -	unsigned long flags;  	struct moschip_port *mos7840_port; -	/* check for the ports to be closed,close the ports and disconnect */ +	mos7840_port = mos7840_get_port_private(port); -	/* free private structure allocated for serial port  * -	 * stop reads and writes on all ports                */ +	if (mos7840_port->has_led) { +		/* Turn off LED */ +		mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); -	for (i = 0; i < serial->num_ports; ++i) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); -		if (mos7840_port) { -			spin_lock_irqsave(&mos7840_port->pool_lock, flags); -			mos7840_port->zombie = 1; -			spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); -			usb_kill_urb(mos7840_port->control_urb); -		} +		del_timer_sync(&mos7840_port->led_timer1); +		del_timer_sync(&mos7840_port->led_timer2);  	} -} - -/**************************************************************************** - * mos7840_release - *	This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ -	int i; -	struct moschip_port *mos7840_port; - -	/* check for the ports to be closed,close the ports and disconnect */ +	usb_kill_urb(mos7840_port->control_urb); +	usb_free_urb(mos7840_port->control_urb); +	kfree(mos7840_port->ctrl_buf); +	kfree(mos7840_port->dr); +	kfree(mos7840_port); -	/* free private structure allocated for serial port  * -	 * stop reads and writes on all ports                */ - -	for (i = 0; i < serial->num_ports; ++i) { -		mos7840_port = mos7840_get_port_private(serial->port[i]); -		if (mos7840_port) { -			if (mos7840_port->has_led) { -				/* Turn off LED */ -				mos7840_set_led_sync(mos7840_port->port, -						MODEM_CONTROL_REGISTER, 0x0300); - -				del_timer_sync(&mos7840_port->led_timer1); -				del_timer_sync(&mos7840_port->led_timer2); -			} -			kfree(mos7840_port->ctrl_buf); -			kfree(mos7840_port->dr); -			kfree(mos7840_port); -		} -	} +	return 0;  }  static struct usb_serial_driver moschip7840_4port_device = { @@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {  	.tiocmget = mos7840_tiocmget,  	.tiocmset = mos7840_tiocmset,  	.get_icount = mos7840_get_icount, -	.attach = mos7840_startup, -	.disconnect = mos7840_disconnect, -	.release = mos7840_release, +	.port_probe = mos7840_port_probe, +	.port_remove = mos7840_port_remove,  	.read_bulk_callback = mos7840_bulk_in_callback,  	.read_int_callback = mos7840_interrupt_callback,  }; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6def58b7938..9ab73d29577 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,  				const unsigned char *buf, int count);  static int  omninet_write_room(struct tty_struct *tty);  static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port);  static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.description =		"ZyXEL - omni.net lcd plus usb",  	.id_table =		id_table,  	.num_ports =		1, -	.attach =		omninet_attach, +	.port_probe =		omninet_port_probe, +	.port_remove =		omninet_port_remove,  	.open =			omninet_open,  	.close =		omninet_close,  	.write =		omninet_write, @@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {  	.read_bulk_callback =	omninet_read_bulk_callback,  	.write_bulk_callback =	omninet_write_bulk_callback,  	.disconnect =		omninet_disconnect, -	.release =		omninet_release,  };  static struct usb_serial_driver * const serial_drivers[] = { @@ -112,18 +112,26 @@ struct omninet_data {  	__u8	od_outseq;	/* Sequence number for bulk_out URBs */  }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port)  {  	struct omninet_data *od; -	struct usb_serial_port *port = serial->port[0];  	od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); -	if (!od) { -		dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", -			__func__, sizeof(struct omninet_data)); +	if (!od)  		return -ENOMEM; -	} +  	usb_set_serial_port_data(port, od); + +	return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ +	struct omninet_data *od; + +	od = usb_get_serial_port_data(port); +	kfree(od); +  	return 0;  } @@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)  	usb_kill_urb(wport->write_urb);  } - -static void omninet_release(struct usb_serial *serial) -{ -	struct usb_serial_port *port = serial->port[0]; - -	kfree(usb_get_serial_port_data(port)); -} -  module_usb_serial_driver(serial_drivers, id_table);  MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 41b1647306e..6aba731d486 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  {  	struct usb_serial *serial = port->serial;  	int retval; -	u8 buffer[2]; +	u8 *buffer; + +	buffer = kzalloc(1, GFP_KERNEL); +	if (!buffer) +		return -ENOMEM;  	buffer[0] = val;  	/* Send the message to the vendor control endpoint @@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,  				requesttype,  				USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,  				0, 0, buffer, 1, 0); +	kfree(buffer);  	return retval;  } @@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  	if (!dr) {  		dev_err(&port->dev, "out of memory\n");  		count = -ENOMEM; -		goto error; +		goto error_no_dr;  	}  	dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,  	return count;  error: +	kfree(dr); +error_no_dr:  	usb_free_urb(urb);  error_no_urb:  	kfree(buffer); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 54d4148d01d..5dee7d61241 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@  /* Function prototypes */  static int  option_probe(struct usb_serial *serial,  			const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial);  static void option_release(struct usb_serial *serial);  static int option_send_setup(struct usb_serial_port *port);  static void option_instat_callback(struct urb *urb); @@ -1288,8 +1289,9 @@ static struct usb_serial_driver option_1port_device = {  	.tiocmget          = usb_wwan_tiocmget,  	.tiocmset          = usb_wwan_tiocmset,  	.ioctl             = usb_wwan_ioctl, -	.attach            = usb_wwan_startup, +	.attach            = option_attach,  	.release           = option_release, +	.port_probe        = usb_wwan_port_probe,  	.port_remove	   = usb_wwan_port_remove,  	.read_int_callback = option_instat_callback,  #ifdef CONFIG_PM @@ -1335,8 +1337,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,  static int option_probe(struct usb_serial *serial,  			const struct usb_device_id *id)  { -	struct usb_wwan_intf_private *data; -	struct option_private *priv;  	struct usb_interface_descriptor *iface_desc =  				&serial->interface->cur_altsetting->desc;  	struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1374,6 +1374,19 @@ static int option_probe(struct usb_serial *serial,  		iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)  		return -ENODEV; +	/* Store device id so we can use it during attach. */ +	usb_set_serial_data(serial, (void *)id); + +	return 0; +} + +static int option_attach(struct usb_serial *serial) +{ +	struct usb_interface_descriptor *iface_desc; +	const struct usb_device_id *id; +	struct usb_wwan_intf_private *data; +	struct option_private *priv; +  	data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);  	if (!data)  		return -ENOMEM; @@ -1384,6 +1397,10 @@ static int option_probe(struct usb_serial *serial,  		return -ENOMEM;  	} +	/* Retrieve device id stored at probe. */ +	id = usb_get_serial_data(serial); +	iface_desc = &serial->interface->cur_altsetting->desc; +  	priv->bInterfaceNumber = iface_desc->bInterfaceNumber;  	data->private = priv; diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c3ddb65c05f..aa148c21ea4 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);  static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  { -	struct usb_wwan_intf_private *data;  	struct usb_host_interface *intf = serial->interface->cur_altsetting;  	struct device *dev = &serial->dev->dev;  	int retval = -ENODEV; @@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	ifnum = intf->desc.bInterfaceNumber;  	dev_dbg(dev, "This Interface = %d\n", ifnum); -	data = kzalloc(sizeof(struct usb_wwan_intf_private), -					 GFP_KERNEL); -	if (!data) -		return -ENOMEM; - -	spin_lock_init(&data->susp_lock); -  	if (nintf == 1) {  		/* QDL mode */  		/* Gobi 2000 has a single altsetting, older ones have two */ @@ -253,20 +245,28 @@ done:  		}  	} -	/* Set serial->private if not returning error */ -	if (retval == 0) -		usb_set_serial_data(serial, data); -	else -		kfree(data); -  	return retval;  } +static int qc_attach(struct usb_serial *serial) +{ +	struct usb_wwan_intf_private *data; + +	data = kzalloc(sizeof(*data), GFP_KERNEL); +	if (!data) +		return -ENOMEM; + +	spin_lock_init(&data->susp_lock); + +	usb_set_serial_data(serial, data); + +	return 0; +} +  static void qc_release(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); -	/* Free the private data allocated in qcprobe */  	usb_set_serial_data(serial, NULL);  	kfree(priv);  } @@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {  	.write		     = usb_wwan_write,  	.write_room	     = usb_wwan_write_room,  	.chars_in_buffer     = usb_wwan_chars_in_buffer, -	.attach		     = usb_wwan_startup, +	.attach              = qc_attach,  	.release	     = qc_release, +	.port_probe          = usb_wwan_port_probe,  	.port_remove	     = usb_wwan_port_remove,  #ifdef CONFIG_PM  	.suspend	     = usb_wwan_suspend, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc90b3..ffcfc962ab1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);  static void qt2_release(struct usb_serial *serial)  { -	int i; +	struct qt2_serial_private *serial_priv; -	kfree(usb_get_serial_data(serial)); +	serial_priv = usb_get_serial_data(serial); -	for (i = 0; i < serial->num_ports; i++) -		kfree(usb_get_serial_port_data(serial->port[i])); +	usb_free_urb(serial_priv->read_urb); +	kfree(serial_priv);  }  static inline int calc_baud_divisor(int baudrate) @@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)  	port_priv->is_open = false;  	spin_lock_irqsave(&port_priv->urb_lock, flags); -	if (port_priv->write_urb->status == -EINPROGRESS) -		usb_kill_urb(port_priv->write_urb); +	usb_kill_urb(port_priv->write_urb);  	port_priv->urb_in_use = false;  	spin_unlock_irqrestore(&port_priv->urb_lock, flags); +	mutex_lock(&port->serial->disc_mutex); +	if (port->serial->disconnected) { +		mutex_unlock(&port->serial->disc_mutex); +		return; +	} +  	/* flush the port transmit buffer */  	i = usb_control_msg(serial->dev,  			    usb_rcvctrlpipe(serial->dev, 0), @@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)  		dev_err(&port->dev, "%s - close port failed %i\n",  			__func__, i); +	mutex_unlock(&port->serial->disc_mutex);  }  static void qt2_disconnect(struct usb_serial *serial)  {  	struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); -	struct qt2_port_private *port_priv; -	int i; - -	if (serial_priv->read_urb->status == -EINPROGRESS) -		usb_kill_urb(serial_priv->read_urb); - -	usb_free_urb(serial_priv->read_urb); -	for (i = 0; i < serial->num_ports; i++) { -		port_priv = usb_get_serial_port_data(serial->port[i]); - -		if (port_priv->write_urb->status == -EINPROGRESS) -			usb_kill_urb(port_priv->write_urb); -		usb_free_urb(port_priv->write_urb); -	} +	usb_kill_urb(serial_priv->read_urb);  }  static int get_serial_info(struct usb_serial_port *port, @@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)  static int qt2_setup_urbs(struct usb_serial *serial)  { -	struct usb_serial_port *port;  	struct usb_serial_port *port0;  	struct qt2_serial_private *serial_priv; -	struct qt2_port_private *port_priv; -	int pcount, status; +	int status;  	port0 = serial->port[0]; @@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)  			  sizeof(serial_priv->read_buffer),  			  qt2_read_bulk_callback, serial); -	/* setup write_urb for each port */ -	for (pcount = 0; pcount < serial->num_ports; pcount++) { - -		port = serial->port[pcount]; -		port_priv = usb_get_serial_port_data(port); - -		port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); -		if (!port_priv->write_urb) { -			dev_err(&serial->dev->dev, -				"failed to alloc write_urb for port %i\n", -				pcount); -			return -ENOMEM; -		} - -		usb_fill_bulk_urb(port_priv->write_urb, -				  serial->dev, -				  usb_sndbulkpipe(serial->dev, -						  port0-> -						  bulk_out_endpointAddress), -				  port_priv->write_buffer, -				  sizeof(port_priv->write_buffer), -				  qt2_write_bulk_callback, port); -	} -  	status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);  	if (status != 0) {  		dev_err(&serial->dev->dev,  			"%s - submit read urb failed %i\n", __func__, status); +		usb_free_urb(serial_priv->read_urb);  		return status;  	}  	return 0; -  }  static int qt2_attach(struct usb_serial *serial)  {  	struct qt2_serial_private *serial_priv; -	struct qt2_port_private *port_priv; -	int status, pcount; +	int status;  	/* power on unit */  	status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)  	usb_set_serial_data(serial, serial_priv); -	for (pcount = 0; pcount < serial->num_ports; pcount++) { -		port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); -		if (!port_priv) { -			dev_err(&serial->dev->dev, -				"%s- kmalloc(%Zd) failed.\n", __func__, -				sizeof(*port_priv)); -			pcount--; -			status = -ENOMEM; -			goto attach_failed; -		} - -		spin_lock_init(&port_priv->lock); -		spin_lock_init(&port_priv->urb_lock); -		init_waitqueue_head(&port_priv->delta_msr_wait); - -		port_priv->port = serial->port[pcount]; - -		usb_set_serial_port_data(serial->port[pcount], port_priv); -	} -  	status = qt2_setup_urbs(serial);  	if (status != 0)  		goto attach_failed; @@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)  	return 0;  attach_failed: -	for (/* empty */; pcount >= 0; pcount--) { -		port_priv = usb_get_serial_port_data(serial->port[pcount]); -		kfree(port_priv); -	}  	kfree(serial_priv);  	return status;  } +static int qt2_port_probe(struct usb_serial_port *port) +{ +	struct usb_serial *serial = port->serial; +	struct qt2_port_private *port_priv; +	u8 bEndpointAddress; + +	port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); +	if (!port_priv) +		return -ENOMEM; + +	spin_lock_init(&port_priv->lock); +	spin_lock_init(&port_priv->urb_lock); +	init_waitqueue_head(&port_priv->delta_msr_wait); +	port_priv->port = port; + +	port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); +	if (!port_priv->write_urb) { +		kfree(port_priv); +		return -ENOMEM; +	} +	bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; +	usb_fill_bulk_urb(port_priv->write_urb, serial->dev, +				usb_sndbulkpipe(serial->dev, bEndpointAddress), +				port_priv->write_buffer, +				sizeof(port_priv->write_buffer), +				qt2_write_bulk_callback, port); + +	usb_set_serial_port_data(port, port_priv); + +	return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ +	struct qt2_port_private *port_priv; + +	port_priv = usb_get_serial_port_data(port); +	usb_free_urb(port_priv->write_urb); +	kfree(port_priv); + +	return 0; +} +  static int qt2_tiocmget(struct tty_struct *tty)  {  	struct usb_serial_port *port = tty->driver_data; @@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {  	.attach              = qt2_attach,  	.release             = qt2_release,  	.disconnect          = qt2_disconnect, +	.port_probe          = qt2_port_probe, +	.port_remove         = qt2_port_remove,  	.dtr_rts             = qt2_dtr_rts,  	.break_ctl           = qt2_break_ctl,  	.tiocmget            = qt2_tiocmget, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 01d882cf377..270860f6bb2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,  {  	int result = 0;  	struct usb_device *udev; -	struct sierra_intf_private *data;  	u8 ifnum;  	udev = serial->dev; @@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,  		return -ENODEV;  	} -	data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); -	if (!data) -		return -ENOMEM; -	spin_lock_init(&data->susp_lock); -  	return result;  } @@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)  static int sierra_startup(struct usb_serial *serial)  { -	struct usb_serial_port *port; -	struct sierra_port_private *portdata; -	struct sierra_iface_info *himemoryp = NULL; -	int i; -	u8 ifnum; +	struct sierra_intf_private *intfdata; + +	intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); +	if (!intfdata) +		return -ENOMEM; + +	spin_lock_init(&intfdata->susp_lock); + +	usb_set_serial_data(serial, intfdata);  	/* Set Device mode to D0 */  	sierra_set_power_state(serial->dev, 0x0000); @@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)  	if (nmea)  		sierra_vsc_set_nmea(serial->dev, 1); -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); -		if (!portdata) { -			dev_dbg(&port->dev, "%s: kmalloc for " -				"sierra_port_private (%d) failed!\n", -				__func__, i); -			return -ENOMEM; -		} -		spin_lock_init(&portdata->lock); -		init_usb_anchor(&portdata->active); -		init_usb_anchor(&portdata->delayed); -		ifnum = i; -		/* Assume low memory requirements */ -		portdata->num_out_urbs = N_OUT_URB; -		portdata->num_in_urbs  = N_IN_URB; +	return 0; +} -		/* Determine actual memory requirements */ -		if (serial->num_ports == 1) { -			/* Get interface number for composite device */ -			ifnum = sierra_calc_interface(serial); -			himemoryp = -			    (struct sierra_iface_info *)&typeB_interface_list; -			if (is_himemory(ifnum, himemoryp)) { -				portdata->num_out_urbs = N_OUT_URB_HM; -				portdata->num_in_urbs  = N_IN_URB_HM; -			} -		} -		else { -			himemoryp = -			    (struct sierra_iface_info *)&typeA_interface_list; -			if (is_himemory(i, himemoryp)) { -				portdata->num_out_urbs = N_OUT_URB_HM; -				portdata->num_in_urbs  = N_IN_URB_HM; -			} -		} -		dev_dbg(&serial->dev->dev, -			"Memory usage (urbs) interface #%d, in=%d, out=%d\n", -			ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); -		/* Set the port private data pointer */ -		usb_set_serial_port_data(port, portdata); +static void sierra_release(struct usb_serial *serial) +{ +	struct sierra_intf_private *intfdata; + +	intfdata = usb_get_serial_data(serial); +	kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ +	struct usb_serial *serial = port->serial; +	struct sierra_port_private *portdata; +	const struct sierra_iface_info *himemoryp; +	u8 ifnum; + +	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); +	if (!portdata) +		return -ENOMEM; + +	spin_lock_init(&portdata->lock); +	init_usb_anchor(&portdata->active); +	init_usb_anchor(&portdata->delayed); + +	/* Assume low memory requirements */ +	portdata->num_out_urbs = N_OUT_URB; +	portdata->num_in_urbs  = N_IN_URB; + +	/* Determine actual memory requirements */ +	if (serial->num_ports == 1) { +		/* Get interface number for composite device */ +		ifnum = sierra_calc_interface(serial); +		himemoryp = &typeB_interface_list; +	} else { +		/* This is really the usb-serial port number of the interface +		 * rather than the interface number. +		 */ +		ifnum = port->number - serial->minor; +		himemoryp = &typeA_interface_list;  	} +	if (is_himemory(ifnum, himemoryp)) { +		portdata->num_out_urbs = N_OUT_URB_HM; +		portdata->num_in_urbs  = N_IN_URB_HM; +	} + +	dev_dbg(&port->dev, +			"Memory usage (urbs) interface #%d, in=%d, out=%d\n", +			ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + +	usb_set_serial_port_data(port, portdata); +  	return 0;  } -static void sierra_release(struct usb_serial *serial) +static int sierra_port_remove(struct usb_serial_port *port)  { -	int i; -	struct usb_serial_port *port;  	struct sierra_port_private *portdata; -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		if (!port) -			continue; -		portdata = usb_get_serial_port_data(port); -		if (!portdata) -			continue; -		kfree(portdata); -	} +	portdata = usb_get_serial_port_data(port); +	kfree(portdata); + +	return 0;  }  #ifdef CONFIG_PM @@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {  	.tiocmset          = sierra_tiocmset,  	.attach            = sierra_startup,  	.release           = sierra_release, +	.port_probe        = sierra_port_probe, +	.port_remove       = sierra_port_remove,  	.suspend	   = sierra_suspend,  	.resume		   = sierra_resume,  	.read_int_callback = sierra_instat_callback, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2397c..684739b8efd 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,7 @@  extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);  extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);  extern void usb_wwan_close(struct usb_serial_port *port); -extern int usb_wwan_startup(struct usb_serial *serial); +extern int usb_wwan_port_probe(struct usb_serial_port *port);  extern int usb_wwan_port_remove(struct usb_serial_port *port);  extern int usb_wwan_write_room(struct tty_struct *tty);  extern void usb_wwan_set_termios(struct tty_struct *tty, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e42aa398ed3..61a73ad1a18 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port)  EXPORT_SYMBOL(usb_wwan_close);  /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, +				      int endpoint,  				      int dir, void *ctx, char *buf, int len,  				      void (*callback) (struct urb *))  { +	struct usb_serial *serial = port->serial;  	struct urb *urb;  	if (endpoint == -1) @@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,  	return urb;  } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port)  { -	int i, j; -	struct usb_serial_port *port;  	struct usb_wwan_port_private *portdata; +	struct urb *urb; +	u8 *buffer; +	int err; +	int i; -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = usb_get_serial_port_data(port); +	portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); +	if (!portdata) +		return -ENOMEM; -		/* Do indat endpoints first */ -		for (j = 0; j < N_IN_URB; ++j) { -			portdata->in_urbs[j] = usb_wwan_setup_urb(serial, -								  port-> -								  bulk_in_endpointAddress, -								  USB_DIR_IN, -								  port, -								  portdata-> -								  in_buffer[j], -								  IN_BUFLEN, -								  usb_wwan_indat_callback); -		} +	init_usb_anchor(&portdata->delayed); -		/* outdat endpoints */ -		for (j = 0; j < N_OUT_URB; ++j) { -			portdata->out_urbs[j] = usb_wwan_setup_urb(serial, -								   port-> -								   bulk_out_endpointAddress, -								   USB_DIR_OUT, -								   port, -								   portdata-> -								   out_buffer -								   [j], -								   OUT_BUFLEN, -								   usb_wwan_outdat_callback); -		} -	} -} +	for (i = 0; i < N_IN_URB; i++) { +		buffer = (u8 *)__get_free_page(GFP_KERNEL); +		if (!buffer) +			goto bail_out_error; +		portdata->in_buffer[i] = buffer; -int usb_wwan_startup(struct usb_serial *serial) -{ -	int i, j, err; -	struct usb_serial_port *port; -	struct usb_wwan_port_private *portdata; -	u8 *buffer; +		urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, +						USB_DIR_IN, port, +						buffer, IN_BUFLEN, +						usb_wwan_indat_callback); +		portdata->in_urbs[i] = urb; +	} -	/* Now setup per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); -		if (!portdata) { -			dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", -				__func__, i); -			return 1; -		} -		init_usb_anchor(&portdata->delayed); +	for (i = 0; i < N_OUT_URB; i++) { +		if (port->bulk_out_endpointAddress == -1) +			continue; -		for (j = 0; j < N_IN_URB; j++) { -			buffer = (u8 *) __get_free_page(GFP_KERNEL); -			if (!buffer) -				goto bail_out_error; -			portdata->in_buffer[j] = buffer; -		} +		buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); +		if (!buffer) +			goto bail_out_error2; +		portdata->out_buffer[i] = buffer; -		for (j = 0; j < N_OUT_URB; j++) { -			buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); -			if (!buffer) -				goto bail_out_error2; -			portdata->out_buffer[j] = buffer; -		} +		urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, +						USB_DIR_OUT, port, +						buffer, OUT_BUFLEN, +						usb_wwan_outdat_callback); +		portdata->out_urbs[i] = urb; +	} -		usb_set_serial_port_data(port, portdata); +	usb_set_serial_port_data(port, portdata); -		if (!port->interrupt_in_urb) -			continue; +	if (port->interrupt_in_urb) {  		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);  		if (err)  			dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",  				__func__, err);  	} -	usb_wwan_setup_urbs(serial); +  	return 0;  bail_out_error2: -	for (j = 0; j < N_OUT_URB; j++) -		kfree(portdata->out_buffer[j]); +	for (i = 0; i < N_OUT_URB; i++) { +		usb_free_urb(portdata->out_urbs[i]); +		kfree(portdata->out_buffer[i]); +	}  bail_out_error: -	for (j = 0; j < N_IN_URB; j++) -		if (portdata->in_buffer[j]) -			free_page((unsigned long)portdata->in_buffer[j]); +	for (i = 0; i < N_IN_URB; i++) { +		usb_free_urb(portdata->in_urbs[i]); +		free_page((unsigned long)portdata->in_buffer[i]); +	}  	kfree(portdata); -	return 1; + +	return -ENOMEM;  } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe);  int usb_wwan_port_remove(struct usb_serial_port *port)  { diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 346c7efc20b..b9fca3586d7 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);  /* function prototypes for the Connect Tech WhiteHEAT serial converter */  static int  whiteheat_attach(struct usb_serial *serial);  static void whiteheat_release(struct usb_serial *serial); +static int  whiteheat_port_probe(struct usb_serial_port *port); +static int  whiteheat_port_remove(struct usb_serial_port *port);  static int  whiteheat_open(struct tty_struct *tty,  			struct usb_serial_port *port);  static void whiteheat_close(struct usb_serial_port *port); @@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {  	.num_ports =		4,  	.attach =		whiteheat_attach,  	.release =		whiteheat_release, +	.port_probe =		whiteheat_port_probe, +	.port_remove =		whiteheat_port_remove,  	.open =			whiteheat_open,  	.close =		whiteheat_close,  	.ioctl =		whiteheat_ioctl, @@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)  {  	struct usb_serial_port *command_port;  	struct whiteheat_command_private *command_info; -	struct usb_serial_port *port; -	struct whiteheat_private *info;  	struct whiteheat_hw_info *hw_info;  	int pipe;  	int ret;  	int alen;  	__u8 *command;  	__u8 *result; -	int i;  	command_port = serial->port[COMMAND_PORT]; @@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)  		 serial->type->description,  		 hw_info->sw_major_rev, hw_info->sw_minor_rev); -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; - -		info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); -		if (info == NULL) { -			dev_err(&port->dev, -				"%s: Out of memory for port structures\n", -				serial->type->description); -			goto no_private; -		} - -		info->mcr = 0; - -		usb_set_serial_port_data(port, info); -	} -  	command_info = kmalloc(sizeof(struct whiteheat_command_private),  								GFP_KERNEL);  	if (command_info == NULL) { @@ -333,16 +318,10 @@ no_firmware:  		"%s: please contact support@connecttech.com\n",  		serial->type->description);  	kfree(result); +	kfree(command);  	return -ENODEV;  no_command_private: -	for (i = serial->num_ports - 1; i >= 0; i--) { -		port = serial->port[i]; -		info = usb_get_serial_port_data(port); -		kfree(info); -no_private: -		; -	}  	kfree(result);  no_result_buffer:  	kfree(command); @@ -350,21 +329,36 @@ no_command_buffer:  	return -ENOMEM;  } -  static void whiteheat_release(struct usb_serial *serial)  {  	struct usb_serial_port *command_port; -	struct whiteheat_private *info; -	int i;  	/* free up our private data for our command port */  	command_port = serial->port[COMMAND_PORT];  	kfree(usb_get_serial_port_data(command_port)); +} -	for (i = 0; i < serial->num_ports; i++) { -		info = usb_get_serial_port_data(serial->port[i]); -		kfree(info); -	} +static int whiteheat_port_probe(struct usb_serial_port *port) +{ +	struct whiteheat_private *info; + +	info = kzalloc(sizeof(*info), GFP_KERNEL); +	if (!info) +		return -ENOMEM; + +	usb_set_serial_port_data(port, info); + +	return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ +	struct whiteheat_private *info; + +	info = usb_get_serial_port_data(port); +	kfree(info); + +	return 0;  }  static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 779cd954abc..d305a5aa3a5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,  		USB_SC_8070, USB_PR_CB, NULL,  		US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, +		"Casio", +		"EX-N1 DigitalCamera", +		USB_SC_8070, USB_PR_DEVICE, NULL, 0), +  /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/  UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,  		"Samsung",  |