Commit dcdcf63e authored by Marcel Holtmann's avatar Marcel Holtmann Committed by David S. Miller

[Bluetooth] Add suspend/resume support to the HCI USB driver

This patch implements the suspend/resume methods for the HCI USB
driver by killing all outstanding URBs on suspend, and re-issuing
them on resume.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 2b86ad21
...@@ -1045,10 +1045,81 @@ static void hci_usb_disconnect(struct usb_interface *intf) ...@@ -1045,10 +1045,81 @@ static void hci_usb_disconnect(struct usb_interface *intf)
hci_free_dev(hdev); 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);
struct list_head killed;
unsigned long flags;
int i;
if (!husb || intf == husb->isoc_iface)
return 0;
hci_suspend_dev(husb->hdev);
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);
unsigned long flags;
int i, err = 0;
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;
}
hci_resume_dev(husb->hdev);
return 0;
}
static struct usb_driver hci_usb_driver = { static struct usb_driver hci_usb_driver = {
.name = "hci_usb", .name = "hci_usb",
.probe = hci_usb_probe, .probe = hci_usb_probe,
.disconnect = hci_usb_disconnect, .disconnect = hci_usb_disconnect,
.suspend = hci_usb_suspend,
.resume = hci_usb_resume,
.id_table = bluetooth_ids, .id_table = bluetooth_ids,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment