diff options
Diffstat (limited to 'drivers/usb/serial/qcserial.c')
| -rw-r--r-- | drivers/usb/serial/qcserial.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 8858201eb1d3..54a9dab1f33b 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
| @@ -111,7 +111,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 111 | ifnum = intf->desc.bInterfaceNumber; | 111 | ifnum = intf->desc.bInterfaceNumber; |
| 112 | dbg("This Interface = %d", ifnum); | 112 | dbg("This Interface = %d", ifnum); |
| 113 | 113 | ||
| 114 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), | 114 | data = kzalloc(sizeof(struct usb_wwan_intf_private), |
| 115 | GFP_KERNEL); | 115 | GFP_KERNEL); |
| 116 | if (!data) | 116 | if (!data) |
| 117 | return -ENOMEM; | 117 | return -ENOMEM; |
| @@ -134,8 +134,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 134 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { | 134 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { |
| 135 | dbg("QDL port found"); | 135 | dbg("QDL port found"); |
| 136 | 136 | ||
| 137 | if (serial->interface->num_altsetting == 1) | 137 | if (serial->interface->num_altsetting == 1) { |
| 138 | return 0; | 138 | retval = 0; /* Success */ |
| 139 | break; | ||
| 140 | } | ||
| 139 | 141 | ||
| 140 | retval = usb_set_interface(serial->dev, ifnum, 1); | 142 | retval = usb_set_interface(serial->dev, ifnum, 1); |
| 141 | if (retval < 0) { | 143 | if (retval < 0) { |
| @@ -145,7 +147,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 145 | retval = -ENODEV; | 147 | retval = -ENODEV; |
| 146 | kfree(data); | 148 | kfree(data); |
| 147 | } | 149 | } |
| 148 | return retval; | ||
| 149 | } | 150 | } |
| 150 | break; | 151 | break; |
| 151 | 152 | ||
| @@ -166,6 +167,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 166 | "Could not set interface, error %d\n", | 167 | "Could not set interface, error %d\n", |
| 167 | retval); | 168 | retval); |
| 168 | retval = -ENODEV; | 169 | retval = -ENODEV; |
| 170 | kfree(data); | ||
| 169 | } | 171 | } |
| 170 | } else if (ifnum == 2) { | 172 | } else if (ifnum == 2) { |
| 171 | dbg("Modem port found"); | 173 | dbg("Modem port found"); |
| @@ -177,7 +179,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 177 | retval = -ENODEV; | 179 | retval = -ENODEV; |
| 178 | kfree(data); | 180 | kfree(data); |
| 179 | } | 181 | } |
| 180 | return retval; | ||
| 181 | } else if (ifnum==3) { | 182 | } else if (ifnum==3) { |
| 182 | /* | 183 | /* |
| 183 | * NMEA (serial line 9600 8N1) | 184 | * NMEA (serial line 9600 8N1) |
| @@ -191,6 +192,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 191 | "Could not set interface, error %d\n", | 192 | "Could not set interface, error %d\n", |
| 192 | retval); | 193 | retval); |
| 193 | retval = -ENODEV; | 194 | retval = -ENODEV; |
| 195 | kfree(data); | ||
| 194 | } | 196 | } |
| 195 | } | 197 | } |
| 196 | break; | 198 | break; |
| @@ -199,12 +201,27 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
| 199 | dev_err(&serial->dev->dev, | 201 | dev_err(&serial->dev->dev, |
| 200 | "unknown number of interfaces: %d\n", nintf); | 202 | "unknown number of interfaces: %d\n", nintf); |
| 201 | kfree(data); | 203 | kfree(data); |
| 202 | return -ENODEV; | 204 | retval = -ENODEV; |
| 203 | } | 205 | } |
| 204 | 206 | ||
| 207 | /* Set serial->private if not returning -ENODEV */ | ||
| 208 | if (retval != -ENODEV) | ||
| 209 | usb_set_serial_data(serial, data); | ||
| 205 | return retval; | 210 | return retval; |
| 206 | } | 211 | } |
| 207 | 212 | ||
| 213 | static void qc_release(struct usb_serial *serial) | ||
| 214 | { | ||
| 215 | struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); | ||
| 216 | |||
| 217 | dbg("%s", __func__); | ||
| 218 | |||
| 219 | /* Call usb_wwan release & free the private data allocated in qcprobe */ | ||
| 220 | usb_wwan_release(serial); | ||
| 221 | usb_set_serial_data(serial, NULL); | ||
| 222 | kfree(priv); | ||
| 223 | } | ||
| 224 | |||
| 208 | static struct usb_serial_driver qcdevice = { | 225 | static struct usb_serial_driver qcdevice = { |
| 209 | .driver = { | 226 | .driver = { |
| 210 | .owner = THIS_MODULE, | 227 | .owner = THIS_MODULE, |
| @@ -222,7 +239,7 @@ static struct usb_serial_driver qcdevice = { | |||
| 222 | .chars_in_buffer = usb_wwan_chars_in_buffer, | 239 | .chars_in_buffer = usb_wwan_chars_in_buffer, |
| 223 | .attach = usb_wwan_startup, | 240 | .attach = usb_wwan_startup, |
| 224 | .disconnect = usb_wwan_disconnect, | 241 | .disconnect = usb_wwan_disconnect, |
| 225 | .release = usb_wwan_release, | 242 | .release = qc_release, |
| 226 | #ifdef CONFIG_PM | 243 | #ifdef CONFIG_PM |
| 227 | .suspend = usb_wwan_suspend, | 244 | .suspend = usb_wwan_suspend, |
| 228 | .resume = usb_wwan_resume, | 245 | .resume = usb_wwan_resume, |
