From 35d6b8ecc95686a31c5da5d696353e5c3fc7c6df Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 3 Jul 2006 10:02:24 +0200 Subject: [PATCH] --- yaml --- r: 31960 b: refs/heads/master c: dcdcf63ef12dc3fbaa17a6d04f16ada8e63bb4d0 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/bluetooth/hci_usb.c | 71 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index eecfd08f2ffb..7c47d428c94e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2b86ad21deec4c47a1f0089298f12e4038c2aa68 +refs/heads/master: dcdcf63ef12dc3fbaa17a6d04f16ada8e63bb4d0 diff --git a/trunk/drivers/bluetooth/hci_usb.c b/trunk/drivers/bluetooth/hci_usb.c index 95afce1cb465..987a3dff8af9 100644 --- a/trunk/drivers/bluetooth/hci_usb.c +++ b/trunk/drivers/bluetooth/hci_usb.c @@ -1045,10 +1045,81 @@ static void hci_usb_disconnect(struct usb_interface *intf) 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 = { .name = "hci_usb", .probe = hci_usb_probe, .disconnect = hci_usb_disconnect, + .suspend = hci_usb_suspend, + .resume = hci_usb_resume, .id_table = bluetooth_ids, };