|
@@ -878,12 +878,7 @@ 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_intf_private *intfdata;
|
|
|
- struct sierra_port_private *portdata;
|
|
|
- struct sierra_iface_info *himemoryp = NULL;
|
|
|
- int i;
|
|
|
- u8 ifnum;
|
|
|
|
|
|
intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
|
|
|
if (!intfdata)
|
|
@@ -900,77 +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);
|
|
|
- goto err;
|
|
|
- }
|
|
|
- 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)
|
|
|
+{
|
|
|
+ struct sierra_intf_private *intfdata;
|
|
|
+
|
|
|
+ intfdata = usb_get_serial_data(serial);
|
|
|
+ kfree(intfdata);
|
|
|
+}
|
|
|
+
|
|
|
+static int sierra_port_probe(struct usb_serial_port *port)
|
|
|
+{
|
|
|
+ struct usb_serial *serial = port->serial;
|
|
|
+ struct sierra_port_private *portdata;
|
|
|
+ const struct sierra_iface_info *himemoryp;
|
|
|
+ u8 ifnum;
|
|
|
+
|
|
|
+ portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
|
|
|
+ if (!portdata)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ spin_lock_init(&portdata->lock);
|
|
|
+ init_usb_anchor(&portdata->active);
|
|
|
+ init_usb_anchor(&portdata->delayed);
|
|
|
+
|
|
|
+ /* Assume low memory requirements */
|
|
|
+ portdata->num_out_urbs = N_OUT_URB;
|
|
|
+ portdata->num_in_urbs = N_IN_URB;
|
|
|
+
|
|
|
+ /* Determine actual memory requirements */
|
|
|
+ if (serial->num_ports == 1) {
|
|
|
+ /* Get interface number for composite device */
|
|
|
+ ifnum = sierra_calc_interface(serial);
|
|
|
+ himemoryp = &typeB_interface_list;
|
|
|
+ } else {
|
|
|
+ /* This is really the usb-serial port number of the interface
|
|
|
+ * rather than the interface number.
|
|
|
+ */
|
|
|
+ ifnum = port->number - serial->minor;
|
|
|
+ himemoryp = &typeA_interface_list;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
-err:
|
|
|
- for (--i; i >= 0; --i) {
|
|
|
- portdata = usb_get_serial_port_data(serial->port[i]);
|
|
|
- kfree(portdata);
|
|
|
+ if (is_himemory(ifnum, himemoryp)) {
|
|
|
+ portdata->num_out_urbs = N_OUT_URB_HM;
|
|
|
+ portdata->num_in_urbs = N_IN_URB_HM;
|
|
|
}
|
|
|
- kfree(intfdata);
|
|
|
|
|
|
- return -ENOMEM;
|
|
|
+ dev_dbg(&port->dev,
|
|
|
+ "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
|
|
|
+ ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
|
|
|
+
|
|
|
+ usb_set_serial_port_data(port, portdata);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static void sierra_release(struct usb_serial *serial)
|
|
|
+static int sierra_port_remove(struct usb_serial_port *port)
|
|
|
{
|
|
|
- int i;
|
|
|
- struct usb_serial_port *port;
|
|
|
struct sierra_port_private *portdata;
|
|
|
|
|
|
- for (i = 0; i < serial->num_ports; ++i) {
|
|
|
- port = serial->port[i];
|
|
|
- if (!port)
|
|
|
- continue;
|
|
|
- portdata = usb_get_serial_port_data(port);
|
|
|
- if (!portdata)
|
|
|
- continue;
|
|
|
- kfree(portdata);
|
|
|
- }
|
|
|
- kfree(serial->private);
|
|
|
+ portdata = usb_get_serial_port_data(port);
|
|
|
+ kfree(portdata);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
@@ -1074,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,
|