summaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ark3116.c26
-rw-r--r--drivers/usb/serial/belkin_sa.c31
-rw-r--r--drivers/usb/serial/ch341.c23
-rw-r--r--drivers/usb/serial/cp210x.c40
-rw-r--r--drivers/usb/serial/cyberjack.c49
-rw-r--r--drivers/usb/serial/cypress_m8.c75
-rw-r--r--drivers/usb/serial/digi_acceleport.c117
-rw-r--r--drivers/usb/serial/f81232.c43
-rw-r--r--drivers/usb/serial/garmin_gps.c24
-rw-r--r--drivers/usb/serial/io_edgeport.c54
-rw-r--r--drivers/usb/serial/io_tables.h8
-rw-r--r--drivers/usb/serial/io_ti.c91
-rw-r--r--drivers/usb/serial/ipw.c7
-rw-r--r--drivers/usb/serial/iuu_phoenix.c76
-rw-r--r--drivers/usb/serial/keyspan.c180
-rw-r--r--drivers/usb/serial/keyspan.h8
-rw-r--r--drivers/usb/serial/keyspan_pda.c30
-rw-r--r--drivers/usb/serial/kl5kusb105.c68
-rw-r--r--drivers/usb/serial/kobil_sct.c23
-rw-r--r--drivers/usb/serial/mct_u232.c59
-rw-r--r--drivers/usb/serial/metro-usb.c65
-rw-r--r--drivers/usb/serial/mos7720.c62
-rw-r--r--drivers/usb/serial/mos7840.c495
-rw-r--r--drivers/usb/serial/omninet.c36
-rw-r--r--drivers/usb/serial/opticon.c11
-rw-r--r--drivers/usb/serial/option.c116
-rw-r--r--drivers/usb/serial/oti6858.c68
-rw-r--r--drivers/usb/serial/pl2303.c90
-rw-r--r--drivers/usb/serial/qcserial.c33
-rw-r--r--drivers/usb/serial/quatech2.c135
-rw-r--r--drivers/usb/serial/sierra.c133
-rw-r--r--drivers/usb/serial/spcp8x5.c46
-rw-r--r--drivers/usb/serial/ssu100.c34
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c88
-rw-r--r--drivers/usb/serial/usb-wwan.h2
-rw-r--r--drivers/usb/serial/usb_wwan.c130
-rw-r--r--drivers/usb/serial/whiteheat.c60
37 files changed, 1278 insertions, 1358 deletions
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index cf2522c397d..bd50a8a41a0 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -125,9 +125,6 @@ static inline int calc_divisor(int bps)
static int ark3116_attach(struct usb_serial *serial)
{
- struct usb_serial_port *port = serial->port[0];
- struct ark3116_private *priv;
-
/* make sure we have our end-points */
if ((serial->num_bulk_in == 0) ||
(serial->num_bulk_out == 0) ||
@@ -142,8 +139,15 @@ static int ark3116_attach(struct usb_serial *serial)
return -EINVAL;
}
- priv = kzalloc(sizeof(struct ark3116_private),
- GFP_KERNEL);
+ return 0;
+}
+
+static int ark3116_port_probe(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct ark3116_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -198,18 +202,15 @@ static int ark3116_attach(struct usb_serial *serial)
return 0;
}
-static void ark3116_release(struct usb_serial *serial)
+static int ark3116_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct ark3116_private *priv = usb_get_serial_port_data(port);
/* device is closed, so URBs and DMA should be down */
-
- usb_set_serial_port_data(port, NULL);
-
mutex_destroy(&priv->hw_lock);
-
kfree(priv);
+
+ return 0;
}
static void ark3116_init_termios(struct tty_struct *tty)
@@ -723,7 +724,8 @@ static struct usb_serial_driver ark3116_device = {
.id_table = id_table,
.num_ports = 1,
.attach = ark3116_attach,
- .release = ark3116_release,
+ .port_probe = ark3116_port_probe,
+ .port_remove = ark3116_port_remove,
.set_termios = ark3116_set_termios,
.init_termios = ark3116_init_termios,
.ioctl = ark3116_ioctl,
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 99449424193..ea29556f0d7 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -45,8 +45,8 @@
#define DRIVER_DESC "USB Belkin Serial converter driver"
/* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_release(struct usb_serial *serial);
+static int belkin_sa_port_probe(struct usb_serial_port *port);
+static int belkin_sa_port_remove(struct usb_serial_port *port);
static int belkin_sa_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void belkin_sa_close(struct usb_serial_port *port);
@@ -88,8 +88,8 @@ static struct usb_serial_driver belkin_device = {
.break_ctl = belkin_sa_break_ctl,
.tiocmget = belkin_sa_tiocmget,
.tiocmset = belkin_sa_tiocmset,
- .attach = belkin_sa_startup,
- .release = belkin_sa_release,
+ .port_probe = belkin_sa_port_probe,
+ .port_remove = belkin_sa_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -118,17 +118,15 @@ struct belkin_sa_private {
(c), BELKIN_SA_SET_REQUEST_TYPE, \
(v), 0, NULL, 0, WDR_TIMEOUT)
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup(struct usb_serial *serial)
+static int belkin_sa_port_probe(struct usb_serial_port *port)
{
- struct usb_device *dev = serial->dev;
+ struct usb_device *dev = port->serial->dev;
struct belkin_sa_private *priv;
- /* allocate the private data structure */
priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
if (!priv)
- return -1; /* error */
- /* set initial values for control structures */
+ return -ENOMEM;
+
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
@@ -140,18 +138,19 @@ static int belkin_sa_startup(struct usb_serial *serial)
le16_to_cpu(dev->descriptor.bcdDevice),
priv->bad_flow_control);
- init_waitqueue_head(&serial->port[0]->write_wait);
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
return 0;
}
-static void belkin_sa_release(struct usb_serial *serial)
+static int belkin_sa_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct belkin_sa_private *priv;
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static int belkin_sa_open(struct tty_struct *tty,
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/cp210x.c b/drivers/usb/serial/cp210x.c
index 28af5acc336..eb033fc92a1 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -162,7 +162,7 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
-struct cp210x_port_private {
+struct cp210x_serial_private {
__u8 bInterfaceNumber;
};
@@ -276,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
__le32 *buf;
int result, i, length;
@@ -292,7 +292,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
- port_priv->bInterfaceNumber, buf, size,
+ spriv->bInterfaceNumber, buf, size,
USB_CTRL_GET_TIMEOUT);
/* Convert data into an array of integers */
@@ -323,7 +323,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+ struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
__le32 *buf;
int result, i, length;
@@ -345,13 +345,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
- port_priv->bInterfaceNumber, buf, size,
+ spriv->bInterfaceNumber, buf, size,
USB_CTRL_SET_TIMEOUT);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_INTERFACE, data[0],
- port_priv->bInterfaceNumber, NULL, 0,
+ spriv->bInterfaceNumber, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
@@ -845,36 +845,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
static int cp210x_startup(struct usb_serial *serial)
{
- struct cp210x_port_private *port_priv;
- int i;
+ struct usb_host_interface *cur_altsetting;
+ struct cp210x_serial_private *spriv;
/* cp210x buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
- for (i = 0; i < serial->num_ports; i++) {
- port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
- if (!port_priv)
- return -ENOMEM;
+ spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ if (!spriv)
+ return -ENOMEM;
- port_priv->bInterfaceNumber =
- serial->interface->cur_altsetting->desc.bInterfaceNumber;
+ cur_altsetting = serial->interface->cur_altsetting;
+ spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
- usb_set_serial_port_data(serial->port[i], port_priv);
- }
+ usb_set_serial_data(serial, spriv);
return 0;
}
static void cp210x_release(struct usb_serial *serial)
{
- struct cp210x_port_private *port_priv;
- int i;
+ struct cp210x_serial_private *spriv;
- for (i = 0; i < serial->num_ports; i++) {
- port_priv = usb_get_serial_port_data(serial->port[i]);
- kfree(port_priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
+ spriv = usb_get_serial_data(serial);
+ kfree(spriv);
}
module_usb_serial_driver(serial_drivers, id_table);
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 2a7aecc7223..4ee77dcbe69 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -55,9 +55,9 @@
#define CYBERJACK_PRODUCT_ID 0x0100
/* Function prototypes */
-static int cyberjack_startup(struct usb_serial *serial);
static void cyberjack_disconnect(struct usb_serial *serial);
-static void cyberjack_release(struct usb_serial *serial);
+static int cyberjack_port_probe(struct usb_serial_port *port);
+static int cyberjack_port_remove(struct usb_serial_port *port);
static int cyberjack_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void cyberjack_close(struct usb_serial_port *port);
@@ -83,9 +83,9 @@ static struct usb_serial_driver cyberjack_device = {
.description = "Reiner SCT Cyberjack USB card reader",
.id_table = id_table,
.num_ports = 1,
- .attach = cyberjack_startup,
.disconnect = cyberjack_disconnect,
- .release = cyberjack_release,
+ .port_probe = cyberjack_port_probe,
+ .port_remove = cyberjack_port_remove,
.open = cyberjack_open,
.close = cyberjack_close,
.write = cyberjack_write,
@@ -107,56 +107,45 @@ struct cyberjack_private {
short wrsent; /* Data already sent */
};
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup(struct usb_serial *serial)
+static int cyberjack_port_probe(struct usb_serial_port *port)
{
struct cyberjack_private *priv;
- int i;
+ int result;
- /* allocate the private data structure */
priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- /* set initial values */
spin_lock_init(&priv->lock);
priv->rdtodo = 0;
priv->wrfilled = 0;
priv->wrsent = 0;
- usb_set_serial_port_data(serial->port[0], priv);
- init_waitqueue_head(&serial->port[0]->write_wait);
+ usb_set_serial_port_data(port, priv);
- for (i = 0; i < serial->num_ports; ++i) {
- int result;
- result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
- GFP_KERNEL);
- if (result)
- dev_err(&serial->dev->dev,
- "usb_submit_urb(read int) failed\n");
- dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n",
- __func__);
- }
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
return 0;
}
-static void cyberjack_disconnect(struct usb_serial *serial)
+static int cyberjack_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct cyberjack_private *priv;
- for (i = 0; i < serial->num_ports; ++i)
- usb_kill_urb(serial->port[i]->interrupt_in_urb);
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
-static void cyberjack_release(struct usb_serial *serial)
+static void cyberjack_disconnect(struct usb_serial *serial)
{
int i;
- for (i = 0; i < serial->num_ports; ++i) {
- /* My special items, the standard routines free my urbs */
- kfree(usb_get_serial_port_data(serial->port[i]));
- }
+ for (i = 0; i < serial->num_ports; ++i)
+ usb_kill_urb(serial->port[i]->interrupt_in_urb);
}
static int cyberjack_open(struct tty_struct *tty,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 1befce21e17..f0da1279c11 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -123,10 +123,10 @@ struct cypress_private {
};
/* function prototypes for the Cypress USB to serial device */
-static int cypress_earthmate_startup(struct usb_serial *serial);
-static int cypress_hidcom_startup(struct usb_serial *serial);
-static int cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_release(struct usb_serial *serial);
+static int cypress_earthmate_port_probe(struct usb_serial_port *port);
+static int cypress_hidcom_port_probe(struct usb_serial_port *port);
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port);
+static int cypress_port_remove(struct usb_serial_port *port);
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
static void cypress_close(struct usb_serial_port *port);
static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = {
.description = "DeLorme Earthmate USB",
.id_table = id_table_earthmate,
.num_ports = 1,
- .attach = cypress_earthmate_startup,
- .release = cypress_release,
+ .port_probe = cypress_earthmate_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
@@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = {
.description = "HID->COM RS232 Adapter",
.id_table = id_table_cyphidcomrs232,
.num_ports = 1,
- .attach = cypress_hidcom_startup,
- .release = cypress_release,
+ .port_probe = cypress_hidcom_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
@@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.description = "Nokia CA-42 V2 Adapter",
.id_table = id_table_nokiaca42v2,
.num_ports = 1,
- .attach = cypress_ca42v2_startup,
- .release = cypress_release,
+ .port_probe = cypress_ca42v2_port_probe,
+ .port_remove = cypress_port_remove,
.open = cypress_open,
.close = cypress_close,
.dtr_rts = cypress_dtr_rts,
@@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port)
*****************************************************************************/
-static int generic_startup(struct usb_serial *serial)
+static int cypress_generic_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv)
@@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial)
}
-static int cypress_earthmate_startup(struct usb_serial *serial)
+static int cypress_earthmate_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
+ int ret;
- if (generic_startup(serial)) {
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
- return 1;
+ return ret;
}
priv = usb_get_serial_port_data(port);
@@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
}
return 0;
-} /* cypress_earthmate_startup */
-
+}
-static int cypress_hidcom_startup(struct usb_serial *serial)
+static int cypress_hidcom_port_probe(struct usb_serial_port *port)
{
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
+ int ret;
- if (generic_startup(serial)) {
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
- return 1;
+ return ret;
}
priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CYPHIDCOM;
return 0;
-} /* cypress_hidcom_startup */
-
+}
-static int cypress_ca42v2_startup(struct usb_serial *serial)
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
{
struct cypress_private *priv;
- struct usb_serial_port *port = serial->port[0];
+ int ret;
- if (generic_startup(serial)) {
+ ret = cypress_generic_port_probe(port);
+ if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
- return 1;
+ return ret;
}
priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CA42V2;
return 0;
-} /* cypress_ca42v2_startup */
-
+}
-static void cypress_release(struct usb_serial *serial)
+static int cypress_port_remove(struct usb_serial_port *port)
{
struct cypress_private *priv;
- /* all open ports are closed at this point */
- priv = usb_get_serial_port_data(serial->port[0]);
+ priv = usb_get_serial_port_data(port);
- if (priv) {
- kfifo_free(&priv->write_fifo);
- kfree(priv);
- }
-}
+ kfifo_free(&priv->write_fifo);
+ kfree(priv);
+ return 0;
+}
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
{
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);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
+ 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;
- /* 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 */
- }
+ init_waitqueue_head(&port->write_wait);
+
+ 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);
- /* 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));
+ kfree(serial_priv);
}
+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/f81232.c b/drivers/usb/serial/f81232.c
index 244477107e2..6e4eb57d017 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
-static int f81232_startup(struct usb_serial *serial)
+static int f81232_port_probe(struct usb_serial_port *port)
{
struct f81232_private *priv;
- int i;
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- usb_set_serial_port_data(serial->port[i], priv);
- }
- return 0;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
-cleanup:
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+
+ usb_set_serial_port_data(port, priv);
+
+ return 0;
}
-static void f81232_release(struct usb_serial *serial)
+static int f81232_port_remove(struct usb_serial_port *port)
{
- int i;
struct f81232_private *priv;
- for (i = 0; i < serial->num_ports; ++i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- }
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static struct usb_serial_driver f81232_device = {
@@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = {
.tiocmset = f81232_tiocmset,
.process_read_urb = f81232_process_read_urb,
.read_int_callback = f81232_read_int_callback,
- .attach = f81232_startup,
- .release = f81232_release,
+ .port_probe = f81232_port_probe,
+ .port_remove = f81232_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 3ee92648c02..203358d7e7b 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data)
-static int garmin_attach(struct usb_serial *serial)
+static int garmin_port_probe(struct usb_serial_port *port)
{
- int status = 0;
- struct usb_serial_port *port = serial->port[0];
- struct garmin_data *garmin_data_p = NULL;
+ int status;
+ struct garmin_data *garmin_data_p;
garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
if (garmin_data_p == NULL) {
@@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial)
}
-static void garmin_disconnect(struct usb_serial *serial)
+static int garmin_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
usb_kill_urb(port->interrupt_in_urb);
del_timer_sync(&garmin_data_p->timer);
-}
-
-
-static void garmin_release(struct usb_serial *serial)
-{
- struct usb_serial_port *port = serial->port[0];
- struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-
kfree(garmin_data_p);
+ return 0;
}
@@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = {
.close = garmin_close,
.throttle = garmin_throttle,
.unthrottle = garmin_unthrottle,
- .attach = garmin_attach,
- .disconnect = garmin_disconnect,
- .release = garmin_release,
+ .port_probe = garmin_port_probe,
+ .port_remove = garmin_port_remove,
.write = garmin_write,
.write_room = garmin_write_room,
.write_bulk_callback = garmin_write_bulk_callback,
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 8e6faaf3580..5acc0d13864 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -225,6 +225,8 @@ static int edge_get_icount(struct tty_struct *tty,
static int edge_startup(struct usb_serial *serial);
static void edge_disconnect(struct usb_serial *serial);
static void edge_release(struct usb_serial *serial);
+static int edge_port_probe(struct usb_serial_port *port);
+static int edge_port_remove(struct usb_serial_port *port);
#include "io_tables.h" /* all of the devices that this driver supports */
@@ -2875,10 +2877,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
- struct edgeport_port *edge_port;
struct usb_device *dev;
struct device *ddev = &serial->dev->dev;
- int i, j;
+ int i;
int response;
bool interrupt_in_found;
bool bulk_in_found;
@@ -2961,25 +2962,6 @@ static int edge_startup(struct usb_serial *serial)
/* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */
- /* set up our port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
- if (edge_port == NULL) {
- dev_err(ddev, "%s - Out of memory\n", __func__);
- for (j = 0; j < i; ++j) {
- kfree(usb_get_serial_port_data(serial->port[j]));
- usb_set_serial_port_data(serial->port[j],
- NULL);
- }
- usb_set_serial_data(serial, NULL);
- kfree(edge_serial);
- return -ENOMEM;
- }
- spin_lock_init(&edge_port->ep_lock);
- edge_port->port = serial->port[i];
- usb_set_serial_port_data(serial->port[i], edge_port);
- }
-
response = 0;
if (edge_serial->is_epic) {
@@ -3120,14 +3102,36 @@ static void edge_disconnect(struct usb_serial *serial)
static void edge_release(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
- int i;
-
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
kfree(edge_serial);
}
+static int edge_port_probe(struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port;
+
+ edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+ if (!edge_port)
+ return -ENOMEM;
+
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->port = port;
+
+ usb_set_serial_port_data(port, edge_port);
+
+ return 0;
+}
+
+static int edge_port_remove(struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port;
+
+ edge_port = usb_get_serial_port_data(port);
+ kfree(edge_port);
+
+ return 0;
+}
+
module_usb_serial_driver(serial_drivers, id_table_combined);
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index 350afddb55b..1511dd0ad32 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index a2209cd4509..60023c2d2a3 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2532,12 +2532,7 @@ static void edge_break(struct tty_struct *tty, int break_state)
static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
- struct edgeport_port *edge_port;
- struct usb_device *dev;
int status;
- int i;
-
- dev = serial->dev;
/* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2555,40 +2550,7 @@ static int edge_startup(struct usb_serial *serial)
return status;
}
- /* set up our port private structures */
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
- if (edge_port == NULL) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n",
- __func__);
- goto cleanup;
- }
- spin_lock_init(&edge_port->ep_lock);
- if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
- GFP_KERNEL)) {
- dev_err(&serial->dev->dev, "%s - Out of memory\n",
- __func__);
- kfree(edge_port);
- goto cleanup;
- }
- edge_port->port = serial->port[i];
- edge_port->edge_serial = edge_serial;
- usb_set_serial_port_data(serial->port[i], edge_port);
- edge_port->bUartMode = default_uart_mode;
- }
-
return 0;
-
-cleanup:
- for (--i; i >= 0; --i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- kfifo_free(&edge_port->write_fifo);
- kfree(edge_port);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- kfree(edge_serial);
- usb_set_serial_data(serial, NULL);
- return -ENOMEM;
}
static void edge_disconnect(struct usb_serial *serial)
@@ -2597,17 +2559,54 @@ static void edge_disconnect(struct usb_serial *serial)
static void edge_release(struct usb_serial *serial)
{
- int i;
+ kfree(usb_get_serial_data(serial));
+}
+
+static int edge_port_probe(struct usb_serial_port *port)
+{
struct edgeport_port *edge_port;
+ int ret;
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
+ edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+ if (!edge_port)
+ return -ENOMEM;
+
+ ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
+ GFP_KERNEL);
+ if (ret) {
+ kfree(edge_port);
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&edge_port->ep_lock);
+ edge_port->port = port;
+ edge_port->edge_serial = usb_get_serial_data(port->serial);
+ edge_port->bUartMode = default_uart_mode;
+
+ usb_set_serial_port_data(port, edge_port);
+
+ ret = edge_create_sysfs_attrs(port);
+ if (ret) {
kfifo_free(&edge_port->write_fifo);
kfree(edge_port);
+ return ret;
}
- kfree(usb_get_serial_data(serial));
+
+ return 0;
}
+static int edge_port_remove(struct usb_serial_port *port)
+{
+ struct edgeport_port *edge_port;
+
+ edge_port = usb_get_serial_port_data(port);
+
+ edge_remove_sysfs_attrs(port);
+ kfifo_free(&edge_port->write_fifo);
+ kfree(edge_port);
+
+ return 0;
+}
/* Sysfs Attributes */
@@ -2667,8 +2666,8 @@ static struct usb_serial_driver edgeport_1port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
- .port_probe = edge_create_sysfs_attrs,
- .port_remove = edge_remove_sysfs_attrs,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -2698,8 +2697,8 @@ static struct usb_serial_driver edgeport_2port_device = {
.attach = edge_startup,
.disconnect = edge_disconnect,
.release = edge_release,
- .port_probe = edge_create_sysfs_attrs,
- .port_remove = edge_remove_sysfs_attrs,
+ .port_probe = edge_port_probe,
+ .port_remove = edge_port_remove,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
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/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 01da3ea36e8..cd5533e81de 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -53,6 +53,8 @@ static int iuu_cardout;
static bool xmas;
static int vcc_default = 5;
+static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
+static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
static void read_rxcmd_callback(struct urb *urb);
struct iuu_private {
@@ -72,63 +74,55 @@ struct iuu_private {
u32 clk;
};
-
-static void iuu_free_buf(struct iuu_private *priv)
-{
- kfree(priv->buf);
- kfree(priv->writebuf);
-}
-
-static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv)
-{
- priv->buf = kzalloc(256, GFP_KERNEL);
- priv->writebuf = kzalloc(256, GFP_KERNEL);
- if (!priv->buf || !priv->writebuf) {
- iuu_free_buf(priv);
- dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__);
- return -ENOMEM;
- }
- dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__);
- return 0;
-}
-
-static int iuu_startup(struct usb_serial *serial)
+static int iuu_port_probe(struct usb_serial_port *port)
{
struct iuu_private *priv;
+ int ret;
priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
- dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__);
if (!priv)
return -ENOMEM;
- if (iuu_alloc_buf(serial, priv)) {
+
+ priv->buf = kzalloc(256, GFP_KERNEL);
+ if (!priv->buf) {
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ priv->writebuf = kzalloc(256, GFP_KERNEL);
+ if (!priv->writebuf) {
+ kfree(priv->buf);
kfree(priv);
return -ENOMEM;
}
+
priv->vcc = vcc_default;
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->delta_msr_wait);
- usb_set_serial_port_data(serial->port[0], priv);
+
+ usb_set_serial_port_data(port, priv);
+
+ ret = iuu_create_sysfs_attrs(port);
+ if (ret) {
+ kfree(priv->writebuf);
+ kfree(priv->buf);
+ kfree(priv);
+ return ret;
+ }
+
return 0;
}
-/* Release function */
-static void iuu_release(struct usb_serial *serial)
+static int iuu_port_remove(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct iuu_private *priv = usb_get_serial_port_data(port);
- if (!port)
- return;
- if (priv) {
- iuu_free_buf(priv);
- dev_dbg(&port->dev, "%s - I will free all\n", __func__);
- usb_set_serial_port_data(port, NULL);
-
- dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__);
- kfree(priv);
+ iuu_remove_sysfs_attrs(port);
+ kfree(priv->writebuf);
+ kfree(priv->buf);
+ kfree(priv);
- dev_dbg(&port->dev, "%s priv is now kfree\n", __func__);
- }
+ return 0;
}
static int iuu_tiocmset(struct tty_struct *tty,
@@ -1215,8 +1209,6 @@ static struct usb_serial_driver iuu_device = {
.num_ports = 1,
.bulk_in_size = 512,
.bulk_out_size = 512,
- .port_probe = iuu_create_sysfs_attrs,
- .port_remove = iuu_remove_sysfs_attrs,
.open = iuu_open,
.close = iuu_close,
.write = iuu_uart_write,
@@ -1225,8 +1217,8 @@ static struct usb_serial_driver iuu_device = {
.tiocmset = iuu_tiocmset,
.set_termios = iuu_set_termios,
.init_termios = iuu_init_termios,
- .attach = iuu_startup,
- .release = iuu_release,
+ .port_probe = iuu_port_probe,
+ .port_remove = iuu_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 29c943d737d..cff8dd5b462 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,111 @@ 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_serial_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));
+ 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/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index ca43ecb4a2b..bb87e29c4ac 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -713,29 +713,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
#endif
-static int keyspan_pda_startup(struct usb_serial *serial)
+static int keyspan_pda_port_probe(struct usb_serial_port *port)
{
struct keyspan_pda_private *priv;
- /* allocate the private data structures for all ports. Well, for all
- one ports. */
-
priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
if (!priv)
- return 1; /* error */
- usb_set_serial_port_data(serial->port[0], priv);
- init_waitqueue_head(&serial->port[0]->write_wait);
+ return -ENOMEM;
+
INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
- priv->serial = serial;
- priv->port = serial->port[0];
+ priv->serial = port->serial;
+ priv->port = port;
+
+ usb_set_serial_port_data(port, priv);
+
return 0;
}
-static void keyspan_pda_release(struct usb_serial *serial)
+static int keyspan_pda_port_remove(struct usb_serial_port *port)
{
- kfree(usb_get_serial_port_data(serial->port[0]));
+ struct keyspan_pda_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
#ifdef KEYSPAN
@@ -786,8 +790,8 @@ static struct usb_serial_driver keyspan_pda_device = {
.break_ctl = keyspan_pda_break_ctl,
.tiocmget = keyspan_pda_tiocmget,
.tiocmset = keyspan_pda_tiocmset,
- .attach = keyspan_pda_startup,
- .release = keyspan_pda_release,
+ .port_probe = keyspan_pda_port_probe,
+ .port_remove = keyspan_pda_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 3f6d7376c02..1f4517864cd 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -60,8 +60,8 @@
/*
* Function prototypes
*/
-static int klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_release(struct usb_serial *serial);
+static int klsi_105_port_probe(struct usb_serial_port *port);
+static int klsi_105_port_remove(struct usb_serial_port *port);
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
static void klsi_105_close(struct usb_serial_port *port);
static void klsi_105_set_termios(struct tty_struct *tty,
@@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
.tiocmset = klsi_105_tiocmset,
- .attach = klsi_105_startup,
- .release = klsi_105_release,
+ .port_probe = klsi_105_port_probe,
+ .port_remove = klsi_105_port_remove,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.process_read_urb = klsi_105_process_read_urb,
@@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
* Driver's tty interface functions
*/
-static int klsi_105_startup(struct usb_serial *serial)
+static int klsi_105_port_probe(struct usb_serial_port *port)
{
struct klsi_105_private *priv;
- int i;
- /* check if we support the product id (see keyspan.c)
- * FIXME
- */
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- /* allocate the private data structure */
- for (i = 0; i < serial->num_ports; i++) {
- priv = kmalloc(sizeof(struct klsi_105_private),
- GFP_KERNEL);
- if (!priv) {
- dev_dbg(&serial->interface->dev,
- "%s - kmalloc for klsi_105_private failed.\n",
- __func__);
- i--;
- goto err_cleanup;
- }
- /* set initial values for control structures */
- priv->cfg.pktlen = 5;
- priv->cfg.baudrate = kl5kusb105a_sio_b9600;
- priv->cfg.databits = kl5kusb105a_dtb_8;
- priv->cfg.unknown1 = 0;
- priv->cfg.unknown2 = 1;
+ /* set initial values for control structures */
+ priv->cfg.pktlen = 5;
+ priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+ priv->cfg.databits = kl5kusb105a_dtb_8;
+ priv->cfg.unknown1 = 0;
+ priv->cfg.unknown2 = 1;
- priv->line_state = 0;
+ priv->line_state = 0;
- usb_set_serial_port_data(serial->port[i], priv);
+ spin_lock_init(&priv->lock);
- spin_lock_init(&priv->lock);
+ /* priv->termios is left uninitialized until port opening */
- /* priv->termios is left uninitialized until port opening */
- init_waitqueue_head(&serial->port[i]->write_wait);
- }
+ usb_set_serial_port_data(port, priv);
return 0;
-
-err_cleanup:
- for (; i >= 0; i--) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
}
-static void klsi_105_release(struct usb_serial *serial)
+static int klsi_105_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct klsi_105_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ return 0;
}
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 5c4d2fbd4e1..c9ca7a5b12e 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -54,8 +54,8 @@
/* Function prototypes */
-static int kobil_startup(struct usb_serial *serial);
-static void kobil_release(struct usb_serial *serial);
+static int kobil_port_probe(struct usb_serial_port *probe);
+static int kobil_port_remove(struct usb_serial_port *probe);
static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
static void kobil_close(struct usb_serial_port *port);
static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -89,8 +89,8 @@ static struct usb_serial_driver kobil_device = {
.description = "KOBIL USB smart card terminal",
.id_table = id_table,
.num_ports = 1,
- .attach = kobil_startup,
- .release = kobil_release,
+ .port_probe = kobil_port_probe,
+ .port_remove = kobil_port_remove,
.ioctl = kobil_ioctl,
.set_termios = kobil_set_termios,
.init_termios = kobil_init_termios,
@@ -117,9 +117,10 @@ struct kobil_private {
};
-static int kobil_startup(struct usb_serial *serial)
+static int kobil_port_probe(struct usb_serial_port *port)
{
int i;
+ struct usb_serial *serial = port->serial;
struct kobil_private *priv;
struct usb_device *pdev;
struct usb_host_config *actconfig;
@@ -149,7 +150,7 @@ static int kobil_startup(struct usb_serial *serial)
dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
break;
}
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
/* search for the necessary endpoints */
pdev = serial->dev;
@@ -179,12 +180,14 @@ static int kobil_startup(struct usb_serial *serial)
}
-static void kobil_release(struct usb_serial *serial)
+static int kobil_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct kobil_private *priv;
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static void kobil_init_termios(struct tty_struct *tty)
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);
- }
-
- /* Send deactivate cmd to device */
+ usb_unlink_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+
+ 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;
- }
-
- /* Initialize all port interrupt end point to port 0 int
- * endpoint. Our device has only one interrupt end point
- * common to all port */
-
- mos7840_port->port = serial->port[i];
- mos7840_set_port_private(serial->port[i], mos7840_port);
- spin_lock_init(&mos7840_port->pool_lock);
-
- /* 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);
-
- 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);
+ pnum = port->number - 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 */
-
- /* 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);
+ 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;
+ }
- /* 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);
+ /* Initialize all port interrupt end point to port 0 int
+ * endpoint. Our device has only one interrupt end point
+ * common to all port */
+
+ mos7840_port->port = port;
+ mos7840_set_port_private(port, mos7840_port);
+ spin_lock_init(&mos7840_port->pool_lock);
+
+ /* 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);
+
+ 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);
+
+ /* 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 */
- 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);
+ /* 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 = 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);
+ /* 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);
- /* 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 = 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);
- 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);
+ 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);
- /* 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);
+ /* 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);
- /* Zero Length flag register */
- if ((mos7840_port->port_num != 1)
- && (serial->num_ports == 2)) {
+ 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);
- 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",
+ /* 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);
+
+ /* 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 30cff03e9f0..edc64bb6f45 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);
@@ -157,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
+#define NOVATELWIRELESS_PRODUCT_E362 0x9010
#define NOVATELWIRELESS_PRODUCT_G1 0xA001
#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
@@ -192,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181
#define DELL_PRODUCT_5730_MINICARD_VZW 0x8182
+#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */
+
#define KYOCERA_VENDOR_ID 0x0c88
#define KYOCERA_PRODUCT_KPC650 0x17da
#define KYOCERA_PRODUCT_KPC680 0x180a
@@ -282,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
/* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S_X200 0x0000
+#define ALCATEL_PRODUCT_X220_X500D 0x0017
#define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002
@@ -503,11 +509,19 @@ static const struct option_blacklist_info net_intf5_blacklist = {
.reserved = BIT(5),
};
+static const struct option_blacklist_info net_intf6_blacklist = {
+ .reserved = BIT(6),
+};
+
static const struct option_blacklist_info zte_mf626_blacklist = {
.sendsetup = BIT(0) | BIT(1),
.reserved = BIT(4),
};
+static const struct option_blacklist_info zte_1255_blacklist = {
+ .reserved = BIT(3) | BIT(4),
+};
+
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -697,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -719,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -853,13 +870,19 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
@@ -872,7 +895,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf5_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
@@ -880,13 +904,22 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1002,18 +1035,24 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -1058,8 +1097,16 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */
+ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1071,15 +1118,21 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
@@ -1112,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
.driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
},
+ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1244,8 +1298,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
@@ -1291,8 +1346,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;
@@ -1330,6 +1383,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;
@@ -1340,6 +1406,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/oti6858.c b/drivers/usb/serial/oti6858.c
index 933241f03fd..cee9a52ca89 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -137,8 +137,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
static int oti6858_tiocmget(struct tty_struct *tty);
static int oti6858_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear);
-static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_release(struct usb_serial *serial);
+static int oti6858_port_probe(struct usb_serial_port *port);
+static int oti6858_port_remove(struct usb_serial_port *port);
/* device info */
static struct usb_serial_driver oti6858_device = {
@@ -161,8 +161,8 @@ static struct usb_serial_driver oti6858_device = {
.write_bulk_callback = oti6858_write_bulk_callback,
.write_room = oti6858_write_room,
.chars_in_buffer = oti6858_chars_in_buffer,
- .attach = oti6858_startup,
- .release = oti6858_release,
+ .port_probe = oti6858_port_probe,
+ .port_remove = oti6858_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
@@ -331,36 +331,33 @@ static void send_data(struct work_struct *work)
usb_serial_port_softint(port);
}
-static int oti6858_startup(struct usb_serial *serial)
+static int oti6858_port_probe(struct usb_serial_port *port)
{
- struct usb_serial_port *port = serial->port[0];
struct oti6858_private *priv;
- int i;
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
- if (!priv)
- break;
-
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->intr_wait);
-/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
-/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
- priv->port = port;
- INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
- INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
-
- usb_set_serial_port_data(serial->port[i], priv);
- }
- if (i == serial->num_ports)
- return 0;
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->intr_wait);
+ priv->port = port;
+ INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+ INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+ usb_set_serial_port_data(port, priv);
+
+ return 0;
+}
+
+static int oti6858_port_remove(struct usb_serial_port *port)
+{
+ struct oti6858_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -709,15 +706,6 @@ static int oti6858_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
-
-static void oti6858_release(struct usb_serial *serial)
-{
- int i;
-
- for (i = 0; i < serial->num_ports; ++i)
- kfree(usb_get_serial_port_data(serial->port[i]));
-}
-
static void oti6858_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 892ebdc7a36..60024190136 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -133,12 +133,15 @@ enum pl2303_type {
HX, /* HX version of the pl2303 chip */
};
+struct pl2303_serial_private {
+ enum pl2303_type type;
+};
+
struct pl2303_private {
spinlock_t lock;
wait_queue_head_t delta_msr_wait;
u8 line_control;
u8 line_status;
- enum pl2303_type type;
};
static int pl2303_vendor_read(__u16 value, __u16 index,
@@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
static int pl2303_startup(struct usb_serial *serial)
{
- struct pl2303_private *priv;
+ struct pl2303_serial_private *spriv;
enum pl2303_type type = type_0;
unsigned char *buf;
- int i;
+
+ spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+ if (!spriv)
+ return -ENOMEM;
buf = kmalloc(10, GFP_KERNEL);
- if (buf == NULL)
+ if (!buf) {
+ kfree(spriv);
return -ENOMEM;
+ }
if (serial->dev->descriptor.bDeviceClass == 0x02)
type = type_0;
@@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial)
type = type_1;
dev_dbg(&serial->interface->dev, "device type: %d\n", type);
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- priv->type = type;
- usb_set_serial_port_data(serial->port[i], priv);
- }
+ spriv->type = type;
+ usb_set_serial_data(serial, spriv);
pl2303_vendor_read(0x8484, 0, serial, buf);
pl2303_vendor_write(0x0404, 0, serial);
@@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial)
kfree(buf);
return 0;
+}
-cleanup:
- kfree(buf);
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
- return -ENOMEM;
+static void pl2303_release(struct usb_serial *serial)
+{
+ struct pl2303_serial_private *spriv;
+
+ spriv = usb_get_serial_data(serial);
+ kfree(spriv);
+}
+
+static int pl2303_port_probe(struct usb_serial_port *port)
+{
+ struct pl2303_private *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+
+ usb_set_serial_port_data(port, priv);
+
+ return 0;
+}
+
+static int pl2303_port_remove(struct usb_serial_port *port)
+{
+ struct pl2303_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static int set_control_lines(struct usb_device *dev, u8 value)
@@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int cflag;
@@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
}
if (baud > 1228800) {
/* type_0, type_1 only support up to 1228800 baud */
- if (priv->type != HX)
+ if (spriv->type != HX)
baud = 1228800;
else if (baud > 6000000)
baud = 6000000;
@@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
if (cflag & CRTSCTS) {
- if (priv->type == HX)
+ if (spriv->type == HX)
pl2303_vendor_write(0x0, 0x61, serial);
else
pl2303_vendor_write(0x0, 0x41, serial);
@@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
- struct pl2303_private *priv = usb_get_serial_port_data(port);
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
int result;
- if (priv->type != HX) {
+ if (spriv->type != HX) {
usb_clear_halt(serial->dev, port->write_urb->pipe);
usb_clear_halt(serial->dev, port->read_urb->pipe);
} else {
@@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
dev_err(&port->dev, "error sending break = %d\n", result);
}
-static void pl2303_release(struct usb_serial *serial)
-{
- int i;
- struct pl2303_private *priv;
-
- for (i = 0; i < serial->num_ports; ++i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- }
-}
-
static void pl2303_update_line_status(struct usb_serial_port *port,
unsigned char *data,
unsigned int actual_length)
@@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = {
.read_int_callback = pl2303_read_int_callback,
.attach = pl2303_startup,
.release = pl2303_release,
+ .port_probe = pl2303_port_probe,
+ .port_remove = pl2303_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
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;
-
- /* 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);
- }
-
return 0;
}
static void sierra_release(struct usb_serial *serial)
{
- int i;
- struct usb_serial_port *port;
+ 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;
- 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 = 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 int sierra_port_remove(struct usb_serial_port *port)
+{
+ struct sierra_port_private *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/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 9716efe9295..769c137f897 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -157,13 +157,10 @@ struct spcp8x5_private {
u8 line_status;
};
-/* desc : when device plug in,this function would be called.
- * thanks to usb_serial subsystem,then do almost every things for us. And what
- * we should do just alloc the buffer */
-static int spcp8x5_startup(struct usb_serial *serial)
+static int spcp8x5_port_probe(struct usb_serial_port *port)
{
+ struct usb_serial *serial = port->serial;
struct spcp8x5_private *priv;
- int i;
enum spcp8x5_type type = SPCP825_007_TYPE;
u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
@@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial)
type = SPCP825_PHILIP_TYPE;
dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
- for (i = 0; i < serial->num_ports; ++i) {
- priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
- if (!priv)
- goto cleanup;
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- spin_lock_init(&priv->lock);
- init_waitqueue_head(&priv->delta_msr_wait);
- priv->type = type;
- usb_set_serial_port_data(serial->port[i] , priv);
- }
+ spin_lock_init(&priv->lock);
+ init_waitqueue_head(&priv->delta_msr_wait);
+ priv->type = type;
+
+ usb_set_serial_port_data(port , priv);
return 0;
-cleanup:
- for (--i; i >= 0; --i) {
- priv = usb_get_serial_port_data(serial->port[i]);
- kfree(priv);
- usb_set_serial_port_data(serial->port[i] , NULL);
- }
- return -ENOMEM;
}
-/* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_release(struct usb_serial *serial)
+static int spcp8x5_port_remove(struct usb_serial_port *port)
{
- int i;
+ struct spcp8x5_private *priv;
- for (i = 0; i < serial->num_ports; i++)
- kfree(usb_get_serial_port_data(serial->port[i]));
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
/* set the modem control line of the device.
@@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = {
.ioctl = spcp8x5_ioctl,
.tiocmget = spcp8x5_tiocmget,
.tiocmset = spcp8x5_tiocmset,
- .attach = spcp8x5_startup,
- .release = spcp8x5_release,
+ .port_probe = spcp8x5_port_probe,
+ .port_remove = spcp8x5_port_remove,
.process_read_urb = spcp8x5_process_read_urb,
};
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 015810b3785..868d1e6852e 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -67,13 +67,6 @@ struct ssu100_port_private {
struct async_icount icount;
};
-static void ssu100_release(struct usb_serial *serial)
-{
- struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
-
- kfree(priv);
-}
-
static inline int ssu100_control_msg(struct usb_device *dev,
u8 request, u16 data, u16 index)
{
@@ -442,21 +435,33 @@ static int ssu100_ioctl(struct tty_struct *tty,
static int ssu100_attach(struct usb_serial *serial)
{
+ return ssu100_initdevice(serial->dev);
+}
+
+static int ssu100_port_probe(struct usb_serial_port *port)
+{
struct ssu100_port_private *priv;
- struct usb_serial_port *port = *serial->port;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
- sizeof(*priv));
+ if (!priv)
return -ENOMEM;
- }
spin_lock_init(&priv->status_lock);
init_waitqueue_head(&priv->delta_msr_wait);
+
usb_set_serial_port_data(port, priv);
- return ssu100_initdevice(serial->dev);
+ return 0;
+}
+
+static int ssu100_port_remove(struct usb_serial_port *port)
+{
+ struct ssu100_port_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
}
static int ssu100_tiocmget(struct tty_struct *tty)
@@ -647,7 +652,8 @@ static struct usb_serial_driver ssu100_device = {
.open = ssu100_open,
.close = ssu100_close,
.attach = ssu100_attach,
- .release = ssu100_release,
+ .port_probe = ssu100_port_probe,
+ .port_remove = ssu100_port_remove,
.dtr_rts = ssu100_dtr_rts,
.process_read_urb = ssu100_process_read_urb,
.tiocmget = ssu100_tiocmget,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 6f49392cda5..f2530d2ef3c 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -97,6 +97,8 @@ struct ti_device {
static int ti_startup(struct usb_serial *serial);
static void ti_release(struct usb_serial *serial);
+static int ti_port_probe(struct usb_serial_port *port);
+static int ti_port_remove(struct usb_serial_port *port);
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
static void ti_close(struct usb_serial_port *port);
static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = {
.num_ports = 1,
.attach = ti_startup,
.release = ti_release,
+ .port_probe = ti_port_probe,
+ .port_remove = ti_port_remove,
.open = ti_open,
.close = ti_close,
.write = ti_write,
@@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = {
.num_ports = 2,
.attach = ti_startup,
.release = ti_release,
+ .port_probe = ti_port_probe,
+ .port_remove = ti_port_remove,
.open = ti_open,
.close = ti_close,
.write = ti_write,
@@ -347,11 +353,8 @@ module_exit(ti_exit);
static int ti_startup(struct usb_serial *serial)
{
struct ti_device *tdev;
- struct ti_port *tport;
struct usb_device *dev = serial->dev;
int status;
- int i;
-
dev_dbg(&dev->dev,
"%s - product 0x%4X, num configurations %d, configuration value %d",
@@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial)
goto free_tdev;
}
- /* set up port structures */
- for (i = 0; i < serial->num_ports; ++i) {
- tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
- if (tport == NULL) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- status = -ENOMEM;
- goto free_tports;
- }
- spin_lock_init(&tport->tp_lock);
- tport->tp_uart_base_addr = (i == 0 ?
- TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
- tport->tp_closing_wait = closing_wait;
- init_waitqueue_head(&tport->tp_msr_wait);
- init_waitqueue_head(&tport->tp_write_wait);
- if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
- GFP_KERNEL)) {
- dev_err(&dev->dev, "%s - out of memory\n", __func__);
- kfree(tport);
- status = -ENOMEM;
- goto free_tports;
- }
- tport->tp_port = serial->port[i];
- tport->tp_tdev = tdev;
- usb_set_serial_port_data(serial->port[i], tport);
- tport->tp_uart_mode = 0; /* default is RS232 */
- }
-
return 0;
-free_tports:
- for (--i; i >= 0; --i) {
- tport = usb_get_serial_port_data(serial->port[i]);
- kfifo_free(&tport->write_fifo);
- kfree(tport);
- usb_set_serial_port_data(serial->port[i], NULL);
- }
free_tdev:
kfree(tdev);
usb_set_serial_data(serial, NULL);
@@ -444,21 +413,50 @@ free_tdev:
static void ti_release(struct usb_serial *serial)
{
- int i;
struct ti_device *tdev = usb_get_serial_data(serial);
+
+ kfree(tdev);
+}
+
+static int ti_port_probe(struct usb_serial_port *port)
+{
struct ti_port *tport;
- for (i = 0; i < serial->num_ports; ++i) {
- tport = usb_get_serial_port_data(serial->port[i]);
- if (tport) {
- kfifo_free(&tport->write_fifo);
- kfree(tport);
- }
+ tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+ if (!tport)
+ return -ENOMEM;
+
+ spin_lock_init(&tport->tp_lock);
+ if (port == port->serial->port[0])
+ tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
+ else
+ tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
+ tport->tp_closing_wait = closing_wait;
+ init_waitqueue_head(&tport->tp_msr_wait);
+ init_waitqueue_head(&tport->tp_write_wait);
+ if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
+ kfree(tport);
+ return -ENOMEM;
}
+ tport->tp_port = port;
+ tport->tp_tdev = usb_get_serial_data(port->serial);
+ tport->tp_uart_mode = 0; /* default is RS232 */
- kfree(tdev);
+ usb_set_serial_port_data(port, tport);
+
+ return 0;
}
+static int ti_port_remove(struct usb_serial_port *port)
+{
+ struct ti_port *tport;
+
+ tport = usb_get_serial_port_data(port);
+ kfifo_free(&tport->write_fifo);
+ kfree(tport);
+
+ return 0;
+}
static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
{
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..a3e9c095f0d 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -447,15 +447,14 @@ 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)
- return NULL; /* endpoint not needed */
-
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (urb == NULL) {
dev_dbg(&serial->interface->dev,
@@ -472,101 +471,78 @@ 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++) {
+ if (!port->bulk_in_size)
+ break;
-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;
+ buffer = (u8 *)__get_free_page(GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error;
+ portdata->in_buffer[i] = buffer;
- /* 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);
+ 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;
+ }
- 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;
- }
+ for (i = 0; i < N_OUT_URB; i++) {
+ if (!port->bulk_out_size)
+ break;
- 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;
- }
+ buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+ if (!buffer)
+ goto bail_out_error2;
+ portdata->out_buffer[i] = buffer;
- usb_set_serial_port_data(port, portdata);
+ 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;
+ }
- if (!port->interrupt_in_urb)
- continue;
+ usb_set_serial_port_data(port, portdata);
+
+ 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)