Messages in this thread Patch in this message | | | Subject | Re: [PATCH] hci_usb: implement suspend/resume | From | Johannes Berg <> | Date | Wed, 18 Jan 2006 17:38:43 +0100 |
| |
The attached patch implements suspend/resume for the hci_usb bluetooth driver by simply killing all outstanding urbs on suspend, and re-issuing them on resume.
This allows me to actually use the internal bluetooth "dongle" in my powerbook after suspend-to-ram without taking down all userland programs (sdpd, ...) and the hci device and reloading the module.
Signed-Off-By: Johannes Berg <johannes@sipsolutions.net>
--- linux-2.6.git.orig/drivers/bluetooth/hci_usb.c +++ linux-2.6.git/drivers/bluetooth/hci_usb.c @@ -1043,10 +1043,65 @@ hci_free_dev(hdev); } +static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct hci_usb *husb = usb_get_intfdata(intf); + int i; + unsigned long flags; + struct list_head killed; + + if (!husb || intf == husb->isoc_iface) + return 0; + + INIT_LIST_HEAD(&killed); + + for (i = 0; i < 4; i++) { + struct _urb_queue *q = &husb->pending_q[i]; + struct _urb *_urb, *_tmp; + while ((_urb = _urb_dequeue(q))) { + /* reset queue since _urb_dequeue sets it to NULL */ + _urb->queue = q; + usb_kill_urb(&_urb->urb); + list_add(&_urb->list, &killed); + } + spin_lock_irqsave(&q->lock, flags); + list_for_each_entry_safe(_urb, _tmp, &killed, list) { + list_move_tail(&_urb->list, &q->head); + } + spin_unlock_irqrestore(&q->lock, flags); + } + return 0; +} + +static int hci_usb_resume(struct usb_interface *intf) +{ + struct hci_usb *husb = usb_get_intfdata(intf); + int i, err = 0; + unsigned long flags; + if (!husb || intf == husb->isoc_iface) + return 0; + + for (i = 0; i < 4; i++) { + struct _urb_queue *q = &husb->pending_q[i]; + struct _urb *_urb; + spin_lock_irqsave(&q->lock, flags); + list_for_each_entry(_urb, &q->head, list) { + err = usb_submit_urb(&_urb->urb, GFP_ATOMIC); + if (err) break; + } + spin_unlock_irqrestore(&q->lock, flags); + if (err) + return -EIO; + } + return 0; +} + static struct usb_driver hci_usb_driver = { .name = "hci_usb", .probe = hci_usb_probe, .disconnect = hci_usb_disconnect, + .suspend = hci_usb_suspend, + .resume = hci_usb_resume, .id_table = bluetooth_ids, };
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |