summaryrefslogtreecommitdiff
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-29 09:04:39 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-29 09:04:39 -0700
commitb472b8e22f9f9bc88dc73017d61609684289fb13 (patch)
treecbb2ec0c2fd2cf6d9f4d2e323e97aa757bd93c59 /drivers/usb/serial
parentd124a60dbbe7c12f3871e2c7fc71f98a821ee9a8 (diff)
parent8f0d8163b50e01f398b14bcd4dc039ac5ab18d64 (diff)
downloadlinux-b472b8e22f9f9bc88dc73017d61609684289fb13.tar.gz
linux-b472b8e22f9f9bc88dc73017d61609684289fb13.tar.bz2
linux-b472b8e22f9f9bc88dc73017d61609684289fb13.zip
Merge 3.7-rc3 into usb-next.
This pulls in all of the USB changes in 3.7-rc3 into usb-next and resolves the merge issue with: drivers/usb/misc/ezusb.c Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/ch341.c23
-rw-r--r--drivers/usb/serial/digi_acceleport.c117
-rw-r--r--drivers/usb/serial/ipw.c7
-rw-r--r--drivers/usb/serial/keyspan.c181
-rw-r--r--drivers/usb/serial/keyspan.h8
-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.c23
-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/usb-wwan.h2
-rw-r--r--drivers/usb/serial/usb_wwan.c124
-rw-r--r--drivers/usb/serial/whiteheat.c60
18 files changed, 744 insertions, 830 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index e9c7046ae355..d255f66e708e 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -242,13 +242,11 @@ out: kfree(buffer);
return r;
}
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
{
struct ch341_private *priv;
int r;
- /* private data */
priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
- r = ch341_configure(serial->dev, priv);
+ r = ch341_configure(port->serial->dev, priv);
if (r < 0)
goto error;
- usb_set_serial_port_data(serial->port[0], priv);
+ usb_set_serial_port_data(port, priv);
return 0;
error: kfree(priv);
return r;
}
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+ struct ch341_private *priv;
+
+ priv = usb_get_serial_port_data(port);
+ kfree(priv);
+
+ return 0;
+}
+
static int ch341_carrier_raised(struct usb_serial_port *port)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
- struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+ struct ch341_private *priv = usb_get_serial_port_data(port);
int r;
priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
.tiocmget = ch341_tiocmget,
.tiocmset = ch341_tiocmset,
.read_int_callback = ch341_read_int_callback,
- .attach = ch341_attach,
+ .port_probe = ch341_port_probe,
+ .port_remove = ch341_port_remove,
.reset_resume = ch341_reset_resume,
};
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index c86f68c6b078..b50fa1c6d885 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/ipw.c b/drivers/usb/serial/ipw.c
index 20a132ec39e2..4264821a3b34 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
return 0;
}
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
{
struct usb_wwan_intf_private *data;
@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
.num_ports = 1,
.open = ipw_open,
.close = ipw_close,
- .probe = ipw_probe,
- .attach = usb_wwan_startup,
+ .attach = ipw_attach,
.release = ipw_release,
+ .port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.dtr_rts = ipw_dtr_rts,
.write = usb_wwan_write,
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 29c943d737d0..7179b0c5f814 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1374,13 +1374,9 @@ static struct callbacks {
data in device_details */
static void keyspan_setup_urbs(struct usb_serial *serial)
{
- int i, j;
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
- struct usb_serial_port *port;
- struct keyspan_port_private *p_priv;
struct callbacks *cback;
- int endp;
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
(serial, d_details->glocont_endpoint, USB_DIR_OUT,
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
cback->glocont_callback);
-
- /* Setup endpoints for each port specific thing */
- for (i = 0; i < d_details->num_ports; i++) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
-
- /* Do indat endpoints first, once for each flip */
- endp = d_details->indat_endpoints[i];
- for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
- p_priv->in_urbs[j] = keyspan_setup_urb
- (serial, endp, USB_DIR_IN, port,
- p_priv->in_buffer[j], 64,
- cback->indat_callback);
- }
- for (; j < 2; ++j)
- p_priv->in_urbs[j] = NULL;
-
- /* outdat endpoints also have flip */
- endp = d_details->outdat_endpoints[i];
- for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
- p_priv->out_urbs[j] = keyspan_setup_urb
- (serial, endp, USB_DIR_OUT, port,
- p_priv->out_buffer[j], 64,
- cback->outdat_callback);
- }
- for (; j < 2; ++j)
- p_priv->out_urbs[j] = NULL;
-
- /* inack endpoint */
- p_priv->inack_urb = keyspan_setup_urb
- (serial, d_details->inack_endpoints[i], USB_DIR_IN,
- port, p_priv->inack_buffer, 1, cback->inack_callback);
-
- /* outcont endpoint */
- p_priv->outcont_urb = keyspan_setup_urb
- (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
- port, p_priv->outcont_buffer, 64,
- cback->outcont_callback);
- }
}
/* usa19 function doesn't require prescaler */
@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
static int keyspan_startup(struct usb_serial *serial)
{
int i, err;
- struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
- struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
s_priv->device_details = d_details;
usb_set_serial_data(serial, s_priv);
- /* Now setup per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- p_priv = kzalloc(sizeof(struct keyspan_port_private),
- GFP_KERNEL);
- if (!p_priv) {
- dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
- return 1;
- }
- p_priv->device_details = d_details;
- usb_set_serial_port_data(port, p_priv);
- }
-
keyspan_setup_urbs(serial);
if (s_priv->instat_urb != NULL) {
@@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)
static void keyspan_disconnect(struct usb_serial *serial)
{
- int i, j;
- struct usb_serial_port *port;
- struct keyspan_serial_private *s_priv;
- struct keyspan_port_private *p_priv;
+ struct keyspan_serial_private *s_priv;
s_priv = usb_get_serial_data(serial);
- /* Stop reading/writing urbs */
stop_urb(s_priv->instat_urb);
stop_urb(s_priv->glocont_urb);
stop_urb(s_priv->indat_urb);
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
- stop_urb(p_priv->inack_urb);
- stop_urb(p_priv->outcont_urb);
- for (j = 0; j < 2; j++) {
- stop_urb(p_priv->in_urbs[j]);
- stop_urb(p_priv->out_urbs[j]);
- }
- }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+ struct keyspan_serial_private *s_priv;
+
+ s_priv = usb_get_serial_data(serial);
- /* Now free them */
usb_free_urb(s_priv->instat_urb);
usb_free_urb(s_priv->indat_urb);
usb_free_urb(s_priv->glocont_urb);
- for (i = 0; i < serial->num_ports; ++i) {
- port = serial->port[i];
- p_priv = usb_get_serial_port_data(port);
- usb_free_urb(p_priv->inack_urb);
- usb_free_urb(p_priv->outcont_urb);
- for (j = 0; j < 2; j++) {
- usb_free_urb(p_priv->in_urbs[j]);
- usb_free_urb(p_priv->out_urbs[j]);
- }
- }
+
+ kfree(s_priv);
}
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
{
- int i;
- struct usb_serial_port *port;
- struct keyspan_serial_private *s_priv;
+ struct usb_serial *serial = port->serial;
+ struct keyspan_port_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const struct keyspan_device_details *d_details;
+ struct callbacks *cback;
+ int endp;
+ int port_num;
+ int i;
s_priv = usb_get_serial_data(serial);
+ d_details = s_priv->device_details;
- kfree(s_priv);
+ p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+ if (!p_priv)
+ return -ENOMEM;
- /* Now free per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- kfree(usb_get_serial_port_data(port));
+ s_priv = usb_get_serial_data(port->serial);
+ p_priv->device_details = d_details;
+
+ /* Setup values for the various callback routines */
+ cback = &keyspan_callbacks[d_details->msg_format];
+
+ port_num = port->number - port->serial->minor;
+
+ /* Do indat endpoints first, once for each flip */
+ endp = d_details->indat_endpoints[port_num];
+ for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+ p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+ USB_DIR_IN, port,
+ p_priv->in_buffer[i], 64,
+ cback->indat_callback);
+ }
+ /* outdat endpoints also have flip */
+ endp = d_details->outdat_endpoints[port_num];
+ for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+ p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+ USB_DIR_OUT, port,
+ p_priv->out_buffer[i], 64,
+ cback->outdat_callback);
+ }
+ /* inack endpoint */
+ p_priv->inack_urb = keyspan_setup_urb(serial,
+ d_details->inack_endpoints[port_num],
+ USB_DIR_IN, port,
+ p_priv->inack_buffer, 1,
+ cback->inack_callback);
+ /* outcont endpoint */
+ p_priv->outcont_urb = keyspan_setup_urb(serial,
+ d_details->outcont_endpoints[port_num],
+ USB_DIR_OUT, port,
+ p_priv->outcont_buffer, 64,
+ cback->outcont_callback);
+
+ usb_set_serial_port_data(port, p_priv);
+
+ return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+ struct keyspan_port_private *p_priv;
+ int i;
+
+ p_priv = usb_get_serial_port_data(port);
+
+ stop_urb(p_priv->inack_urb);
+ stop_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
+ }
+
+ usb_free_urb(p_priv->inack_urb);
+ usb_free_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ usb_free_urb(p_priv->in_urbs[i]);
+ usb_free_urb(p_priv->out_urbs[i]);
}
+
+ kfree(p_priv);
+
+ return 0;
}
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 0a8a40b5711e..0273dda303a4 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_disconnect (struct usb_serial *serial);
static void keyspan_release (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
static int keyspan_write_room (struct tty_struct *tty);
static int keyspan_write (struct tty_struct *tty,
@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_2port_device = {
@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_4port_device = {
@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
+ .port_probe = keyspan_port_probe,
+ .port_remove = keyspan_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index f3947712e137..8a2081004107 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 0b257ddffbdb..6f29c74eb769 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 1bf1ad066666..75267421aad8 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 d6d4eeca8c68..1cf3375ec1af 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;