Hi, this is very basic suspend/resume for the option driver. It compiles, otherwise it is untested. Regards Oliver --- commit 3b9d9d1f45d59f7109ffa5a4c5407c1c4cac5207 Author: Oliver Neukum <oneukum@xxxxxxx> Date: Wed Jan 14 19:12:29 2009 +0100 very basic suspend/resume for the option driver diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 30ae72e..2c91e3d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); +static int option_suspend(struct usb_interface *intf, pm_message_t message); +static int option_resume(struct usb_interface *intf); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -487,6 +489,8 @@ static struct usb_driver option_driver = { .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = option_suspend, + .resume = option_resume, .id_table = option_ids, .no_dynamic_id = 1, }; @@ -1068,14 +1072,12 @@ bail_out_error: return 1; } -static void option_shutdown(struct usb_serial *serial) +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct option_port_private *portdata; - dbg("%s", __func__); - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1084,7 +1086,18 @@ static void option_shutdown(struct usb_serial *serial) usb_kill_urb(portdata->in_urbs[j]); for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); - } + } +} + +static void option_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; + + dbg("%s", __func__); + + stop_read_write_urbs(serial); /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { @@ -1115,6 +1128,62 @@ static void option_shutdown(struct usb_serial *serial) } } +static int option_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_serial_port *port; + struct usb_serial *serial = usb_get_intfdata(intf); + int i; + + stop_read_write_urbs(serial); + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + usb_kill_urb(port->interrupt_in_urb); + } + return 0; +} + +static int option_resume(struct usb_interface *intf) +{ + int err, i, j; + struct usb_serial_port *port; + struct urb *urb; + struct option_port_private *portdata; + struct usb_serial *serial = usb_get_intfdata(intf); + + /* get the interrupt URBs resubmitted unconditionally */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); + if (err < 0) + return err; + } + + for (i = 0; i < serial->num_ports; i++) { + /* walk all ports */ + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); + + /* skip closed ports */ + if (!port->port.count) { + mutex_unlock(&port->mutex); + continue; + } + + for (j = 0; j < N_IN_URB; j++) { + urb = portdata->in_urbs[j]; + err = usb_submit_urb(urb, GFP_NOIO); + if (err < 0) { + mutex_unlock(&port->mutex); + return err; + } + } + mutex_unlock(&port->mutex); + } + return 0; +} + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html