diff options
| -rw-r--r-- | drivers/bluetooth/hci_usb.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 95afce1cb465..987a3dff8af9 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
| @@ -1045,10 +1045,81 @@ static void hci_usb_disconnect(struct usb_interface *intf) | |||
| 1045 | hci_free_dev(hdev); | 1045 | hci_free_dev(hdev); |
| 1046 | } | 1046 | } |
| 1047 | 1047 | ||
| 1048 | static int hci_usb_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 1049 | { | ||
| 1050 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
| 1051 | struct list_head killed; | ||
| 1052 | unsigned long flags; | ||
| 1053 | int i; | ||
| 1054 | |||
| 1055 | if (!husb || intf == husb->isoc_iface) | ||
| 1056 | return 0; | ||
| 1057 | |||
| 1058 | hci_suspend_dev(husb->hdev); | ||
| 1059 | |||
| 1060 | INIT_LIST_HEAD(&killed); | ||
| 1061 | |||
| 1062 | for (i = 0; i < 4; i++) { | ||
| 1063 | struct _urb_queue *q = &husb->pending_q[i]; | ||
| 1064 | struct _urb *_urb, *_tmp; | ||
| 1065 | |||
| 1066 | while ((_urb = _urb_dequeue(q))) { | ||
| 1067 | /* reset queue since _urb_dequeue sets it to NULL */ | ||
| 1068 | _urb->queue = q; | ||
| 1069 | usb_kill_urb(&_urb->urb); | ||
| 1070 | list_add(&_urb->list, &killed); | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | spin_lock_irqsave(&q->lock, flags); | ||
| 1074 | |||
| 1075 | list_for_each_entry_safe(_urb, _tmp, &killed, list) { | ||
| 1076 | list_move_tail(&_urb->list, &q->head); | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | spin_unlock_irqrestore(&q->lock, flags); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | return 0; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static int hci_usb_resume(struct usb_interface *intf) | ||
| 1086 | { | ||
| 1087 | struct hci_usb *husb = usb_get_intfdata(intf); | ||
| 1088 | unsigned long flags; | ||
| 1089 | int i, err = 0; | ||
| 1090 | |||
| 1091 | if (!husb || intf == husb->isoc_iface) | ||
| 1092 | return 0; | ||
| 1093 | |||
| 1094 | for (i = 0; i < 4; i++) { | ||
| 1095 | struct _urb_queue *q = &husb->pending_q[i]; | ||
| 1096 | struct _urb *_urb; | ||
| 1097 | |||
| 1098 | spin_lock_irqsave(&q->lock, flags); | ||
| 1099 | |||
| 1100 | list_for_each_entry(_urb, &q->head, list) { | ||
| 1101 | err = usb_submit_urb(&_urb->urb, GFP_ATOMIC); | ||
| 1102 | if (err) | ||
| 1103 | break; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | spin_unlock_irqrestore(&q->lock, flags); | ||
| 1107 | |||
| 1108 | if (err) | ||
| 1109 | return -EIO; | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | hci_resume_dev(husb->hdev); | ||
| 1113 | |||
| 1114 | return 0; | ||
| 1115 | } | ||
| 1116 | |||
| 1048 | static struct usb_driver hci_usb_driver = { | 1117 | static struct usb_driver hci_usb_driver = { |
| 1049 | .name = "hci_usb", | 1118 | .name = "hci_usb", |
| 1050 | .probe = hci_usb_probe, | 1119 | .probe = hci_usb_probe, |
| 1051 | .disconnect = hci_usb_disconnect, | 1120 | .disconnect = hci_usb_disconnect, |
| 1121 | .suspend = hci_usb_suspend, | ||
| 1122 | .resume = hci_usb_resume, | ||
| 1052 | .id_table = bluetooth_ids, | 1123 | .id_table = bluetooth_ids, |
| 1053 | }; | 1124 | }; |
| 1054 | 1125 | ||
