aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@intel.com>2007-11-13 20:10:09 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:34:51 -0500
commitf0fbd5b9ba893b965b2892c1971e3433092b98c7 (patch)
tree8f2684012950c354d1fcb0dd08e78c0ce5fb6ff6
parent00274921a052d3232d9f00856387fb269ac0af11 (diff)
USB: Prepare serial core for autosuspend.
Claim the interface for a USB to serial converter when the tty is open, and release the interface when the tty is closed. If a driver doesn't provide a resume function, use the generic resume instead. Make sure the generic resume function does not submit the URBs if we're coming back from autosuspend. On autoresume, we know that the open function will be called next, which will attempt to submit the URBs. If we submit them in the resume function, the open will fail. This works for: - autosuspend - suspending with the tty open or closed - hibernate with the tty closed A hibernate (or a suspend that causes the USB subsystem to lose power) has issues. If you have the tty open when you hibernate, a new tty will be created when the device re-enumerates during resume. Signed-off-by: Sarah Sharp <sarah.a.sharp@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/serial/generic.c8
-rw-r--r--drivers/usb/serial/usb-serial.c12
2 files changed, 18 insertions, 2 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index d41531139c55..97fa3c428435 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -175,6 +175,14 @@ int usb_serial_generic_resume(struct usb_serial *serial)
175 struct usb_serial_port *port; 175 struct usb_serial_port *port;
176 int i, c = 0, r; 176 int i, c = 0, r;
177 177
178#ifdef CONFIG_PM
179 /*
180 * If this is an autoresume, don't submit URBs.
181 * They will be submitted in the open function instead.
182 */
183 if (serial->dev->auto_pm)
184 return 0;
185#endif
178 for (i = 0; i < serial->num_ports; i++) { 186 for (i = 0; i < serial->num_ports; i++) {
179 port = serial->port[i]; 187 port = serial->port[i];
180 if (port->open_count && port->read_urb) { 188 if (port->open_count && port->read_urb) {
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 5c33e2471be8..28315b05c9cc 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -225,16 +225,21 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
225 goto bailout_mutex_unlock; 225 goto bailout_mutex_unlock;
226 } 226 }
227 227
228 retval = usb_autopm_get_interface(serial->interface);
229 if (retval)
230 goto bailout_module_put;
228 /* only call the device specific open if this 231 /* only call the device specific open if this
229 * is the first time the port is opened */ 232 * is the first time the port is opened */
230 retval = serial->type->open(port, filp); 233 retval = serial->type->open(port, filp);
231 if (retval) 234 if (retval)
232 goto bailout_module_put; 235 goto bailout_interface_put;
233 } 236 }
234 237
235 mutex_unlock(&port->mutex); 238 mutex_unlock(&port->mutex);
236 return 0; 239 return 0;
237 240
241bailout_interface_put:
242 usb_autopm_put_interface(serial->interface);
238bailout_module_put: 243bailout_module_put:
239 module_put(serial->type->driver.owner); 244 module_put(serial->type->driver.owner);
240bailout_mutex_unlock: 245bailout_mutex_unlock:
@@ -277,8 +282,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
277 } 282 }
278 } 283 }
279 284
280 if (port->open_count == 0) 285 if (port->open_count == 0) {
286 usb_autopm_put_interface(port->serial->interface);
281 module_put(port->serial->type->driver.owner); 287 module_put(port->serial->type->driver.owner);
288 }
282 289
283 mutex_unlock(&port->mutex); 290 mutex_unlock(&port->mutex);
284 usb_serial_put(port->serial); 291 usb_serial_put(port->serial);
@@ -1255,6 +1262,7 @@ static void fixup_generic(struct usb_serial_driver *device)
1255 set_to_generic_if_null(device, read_bulk_callback); 1262 set_to_generic_if_null(device, read_bulk_callback);
1256 set_to_generic_if_null(device, write_bulk_callback); 1263 set_to_generic_if_null(device, write_bulk_callback);
1257 set_to_generic_if_null(device, shutdown); 1264 set_to_generic_if_null(device, shutdown);
1265 set_to_generic_if_null(device, resume);
1258} 1266}
1259 1267
1260int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ 1268int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */