diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/ath3k.c | 6 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 3 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 56 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 112 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 16 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 3 |
7 files changed, 164 insertions, 34 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 2812b152d6e9..ad591bd240ec 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -81,6 +81,9 @@ static struct usb_device_id ath3k_table[] = { | |||
81 | /* Atheros AR5BBU12 with sflash firmware */ | 81 | /* Atheros AR5BBU12 with sflash firmware */ |
82 | { USB_DEVICE(0x0489, 0xE02C) }, | 82 | { USB_DEVICE(0x0489, 0xE02C) }, |
83 | 83 | ||
84 | /* Atheros AR5BBU22 with sflash firmware */ | ||
85 | { USB_DEVICE(0x0489, 0xE03C) }, | ||
86 | |||
84 | { } /* Terminating entry */ | 87 | { } /* Terminating entry */ |
85 | }; | 88 | }; |
86 | 89 | ||
@@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
99 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 102 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
100 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 103 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
101 | 104 | ||
105 | /* Atheros AR5BBU22 with sflash firmware */ | ||
106 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, | ||
107 | |||
102 | { } /* Terminating entry */ | 108 | { } /* Terminating entry */ |
103 | }; | 109 | }; |
104 | 110 | ||
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 90bda50dc446..94f2d65131c4 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -67,6 +67,7 @@ struct btmrvl_adapter { | |||
67 | u8 wakeup_tries; | 67 | u8 wakeup_tries; |
68 | wait_queue_head_t cmd_wait_q; | 68 | wait_queue_head_t cmd_wait_q; |
69 | u8 cmd_complete; | 69 | u8 cmd_complete; |
70 | bool is_suspended; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | struct btmrvl_private { | 73 | struct btmrvl_private { |
@@ -139,8 +140,10 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); | |||
139 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); | 140 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); |
140 | 141 | ||
141 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); | 142 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); |
143 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); | ||
142 | int btmrvl_enable_ps(struct btmrvl_private *priv); | 144 | int btmrvl_enable_ps(struct btmrvl_private *priv); |
143 | int btmrvl_prepare_command(struct btmrvl_private *priv); | 145 | int btmrvl_prepare_command(struct btmrvl_private *priv); |
146 | int btmrvl_enable_hs(struct btmrvl_private *priv); | ||
144 | 147 | ||
145 | #ifdef CONFIG_DEBUG_FS | 148 | #ifdef CONFIG_DEBUG_FS |
146 | void btmrvl_debugfs_init(struct hci_dev *hdev); | 149 | void btmrvl_debugfs_init(struct hci_dev *hdev); |
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index d1209adc882d..681ca9d18e12 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c | |||
@@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | |||
200 | } | 200 | } |
201 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); | 201 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); |
202 | 202 | ||
203 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) | ||
204 | { | ||
205 | struct sk_buff *skb; | ||
206 | struct btmrvl_cmd *cmd; | ||
207 | |||
208 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
209 | if (!skb) { | ||
210 | BT_ERR("No free skb"); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | |||
214 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
215 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, | ||
216 | BT_CMD_HOST_SLEEP_CONFIG)); | ||
217 | cmd->length = 2; | ||
218 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
219 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
220 | |||
221 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
222 | |||
223 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
224 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
225 | |||
226 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], | ||
227 | cmd->data[1]); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); | ||
232 | |||
203 | int btmrvl_enable_ps(struct btmrvl_private *priv) | 233 | int btmrvl_enable_ps(struct btmrvl_private *priv) |
204 | { | 234 | { |
205 | struct sk_buff *skb; | 235 | struct sk_buff *skb; |
@@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv) | |||
232 | } | 262 | } |
233 | EXPORT_SYMBOL_GPL(btmrvl_enable_ps); | 263 | EXPORT_SYMBOL_GPL(btmrvl_enable_ps); |
234 | 264 | ||
235 | static int btmrvl_enable_hs(struct btmrvl_private *priv) | 265 | int btmrvl_enable_hs(struct btmrvl_private *priv) |
236 | { | 266 | { |
237 | struct sk_buff *skb; | 267 | struct sk_buff *skb; |
238 | struct btmrvl_cmd *cmd; | 268 | struct btmrvl_cmd *cmd; |
@@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv) | |||
268 | 298 | ||
269 | return ret; | 299 | return ret; |
270 | } | 300 | } |
301 | EXPORT_SYMBOL_GPL(btmrvl_enable_hs); | ||
271 | 302 | ||
272 | int btmrvl_prepare_command(struct btmrvl_private *priv) | 303 | int btmrvl_prepare_command(struct btmrvl_private *priv) |
273 | { | 304 | { |
274 | struct sk_buff *skb = NULL; | ||
275 | struct btmrvl_cmd *cmd; | ||
276 | int ret = 0; | 305 | int ret = 0; |
277 | 306 | ||
278 | if (priv->btmrvl_dev.hscfgcmd) { | 307 | if (priv->btmrvl_dev.hscfgcmd) { |
279 | priv->btmrvl_dev.hscfgcmd = 0; | 308 | priv->btmrvl_dev.hscfgcmd = 0; |
280 | 309 | btmrvl_send_hscfg_cmd(priv); | |
281 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
282 | if (skb == NULL) { | ||
283 | BT_ERR("No free skb"); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | |||
287 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
288 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); | ||
289 | cmd->length = 2; | ||
290 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
291 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
292 | |||
293 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
294 | |||
295 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
296 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
297 | |||
298 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", | ||
299 | cmd->data[0], cmd->data[1]); | ||
300 | } | 310 | } |
301 | 311 | ||
302 | if (priv->btmrvl_dev.pscmd) { | 312 | if (priv->btmrvl_dev.pscmd) { |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 27b74b0d547b..a853244e7fd7 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) | |||
339 | 339 | ||
340 | done: | 340 | done: |
341 | kfree(tmphlprbuf); | 341 | kfree(tmphlprbuf); |
342 | if (fw_helper) | 342 | release_firmware(fw_helper); |
343 | release_firmware(fw_helper); | ||
344 | |||
345 | return ret; | 343 | return ret; |
346 | } | 344 | } |
347 | 345 | ||
@@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) | |||
484 | 482 | ||
485 | done: | 483 | done: |
486 | kfree(tmpfwbuf); | 484 | kfree(tmpfwbuf); |
487 | 485 | release_firmware(fw_firmware); | |
488 | if (fw_firmware) | ||
489 | release_firmware(fw_firmware); | ||
490 | |||
491 | return ret; | 486 | return ret; |
492 | } | 487 | } |
493 | 488 | ||
@@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, | |||
1013 | priv->btmrvl_dev.psmode = 1; | 1008 | priv->btmrvl_dev.psmode = 1; |
1014 | btmrvl_enable_ps(priv); | 1009 | btmrvl_enable_ps(priv); |
1015 | 1010 | ||
1011 | priv->btmrvl_dev.gpio_gap = 0xffff; | ||
1012 | btmrvl_send_hscfg_cmd(priv); | ||
1013 | |||
1016 | return 0; | 1014 | return 0; |
1017 | 1015 | ||
1018 | disable_host_int: | 1016 | disable_host_int: |
@@ -1048,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func) | |||
1048 | } | 1046 | } |
1049 | } | 1047 | } |
1050 | 1048 | ||
1049 | static int btmrvl_sdio_suspend(struct device *dev) | ||
1050 | { | ||
1051 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1052 | struct btmrvl_sdio_card *card; | ||
1053 | struct btmrvl_private *priv; | ||
1054 | mmc_pm_flag_t pm_flags; | ||
1055 | struct hci_dev *hcidev; | ||
1056 | |||
1057 | if (func) { | ||
1058 | pm_flags = sdio_get_host_pm_caps(func); | ||
1059 | BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func), | ||
1060 | pm_flags); | ||
1061 | if (!(pm_flags & MMC_PM_KEEP_POWER)) { | ||
1062 | BT_ERR("%s: cannot remain alive while suspended", | ||
1063 | sdio_func_id(func)); | ||
1064 | return -ENOSYS; | ||
1065 | } | ||
1066 | card = sdio_get_drvdata(func); | ||
1067 | if (!card || !card->priv) { | ||
1068 | BT_ERR("card or priv structure is not valid"); | ||
1069 | return 0; | ||
1070 | } | ||
1071 | } else { | ||
1072 | BT_ERR("sdio_func is not specified"); | ||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | priv = card->priv; | ||
1077 | |||
1078 | if (priv->adapter->hs_state != HS_ACTIVATED) { | ||
1079 | if (btmrvl_enable_hs(priv)) { | ||
1080 | BT_ERR("HS not actived, suspend failed!"); | ||
1081 | return -EBUSY; | ||
1082 | } | ||
1083 | } | ||
1084 | hcidev = priv->btmrvl_dev.hcidev; | ||
1085 | BT_DBG("%s: SDIO suspend", hcidev->name); | ||
1086 | hci_suspend_dev(hcidev); | ||
1087 | skb_queue_purge(&priv->adapter->tx_queue); | ||
1088 | |||
1089 | priv->adapter->is_suspended = true; | ||
1090 | |||
1091 | /* We will keep the power when hs enabled successfully */ | ||
1092 | if (priv->adapter->hs_state == HS_ACTIVATED) { | ||
1093 | BT_DBG("suspend with MMC_PM_KEEP_POWER"); | ||
1094 | return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
1095 | } else { | ||
1096 | BT_DBG("suspend without MMC_PM_KEEP_POWER"); | ||
1097 | return 0; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | static int btmrvl_sdio_resume(struct device *dev) | ||
1102 | { | ||
1103 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1104 | struct btmrvl_sdio_card *card; | ||
1105 | struct btmrvl_private *priv; | ||
1106 | mmc_pm_flag_t pm_flags; | ||
1107 | struct hci_dev *hcidev; | ||
1108 | |||
1109 | if (func) { | ||
1110 | pm_flags = sdio_get_host_pm_caps(func); | ||
1111 | BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func), | ||
1112 | pm_flags); | ||
1113 | card = sdio_get_drvdata(func); | ||
1114 | if (!card || !card->priv) { | ||
1115 | BT_ERR("card or priv structure is not valid"); | ||
1116 | return 0; | ||
1117 | } | ||
1118 | } else { | ||
1119 | BT_ERR("sdio_func is not specified"); | ||
1120 | return 0; | ||
1121 | } | ||
1122 | priv = card->priv; | ||
1123 | |||
1124 | if (!priv->adapter->is_suspended) { | ||
1125 | BT_DBG("device already resumed"); | ||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | priv->adapter->is_suspended = false; | ||
1130 | hcidev = priv->btmrvl_dev.hcidev; | ||
1131 | BT_DBG("%s: SDIO resume", hcidev->name); | ||
1132 | hci_resume_dev(hcidev); | ||
1133 | priv->hw_wakeup_firmware(priv); | ||
1134 | priv->adapter->hs_state = HS_DEACTIVATED; | ||
1135 | BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static const struct dev_pm_ops btmrvl_sdio_pm_ops = { | ||
1141 | .suspend = btmrvl_sdio_suspend, | ||
1142 | .resume = btmrvl_sdio_resume, | ||
1143 | }; | ||
1144 | |||
1051 | static struct sdio_driver bt_mrvl_sdio = { | 1145 | static struct sdio_driver bt_mrvl_sdio = { |
1052 | .name = "btmrvl_sdio", | 1146 | .name = "btmrvl_sdio", |
1053 | .id_table = btmrvl_sdio_ids, | 1147 | .id_table = btmrvl_sdio_ids, |
1054 | .probe = btmrvl_sdio_probe, | 1148 | .probe = btmrvl_sdio_probe, |
1055 | .remove = btmrvl_sdio_remove, | 1149 | .remove = btmrvl_sdio_remove, |
1150 | .drv = { | ||
1151 | .owner = THIS_MODULE, | ||
1152 | .pm = &btmrvl_sdio_pm_ops, | ||
1153 | } | ||
1056 | }; | 1154 | }; |
1057 | 1155 | ||
1058 | static int __init btmrvl_sdio_init_module(void) | 1156 | static int __init btmrvl_sdio_init_module(void) |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 461c68bc4dd7..c9463af8e564 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = { | |||
143 | /* Atheros AR5BBU12 with sflash firmware */ | 143 | /* Atheros AR5BBU12 with sflash firmware */ |
144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | 144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, |
145 | 145 | ||
146 | /* Atheros AR5BBU12 with sflash firmware */ | ||
147 | { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, | ||
148 | |||
146 | /* Broadcom BCM2035 */ | 149 | /* Broadcom BCM2035 */ |
147 | { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, | 150 | { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, |
148 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, | 151 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, |
@@ -855,6 +858,7 @@ static void btusb_work(struct work_struct *work) | |||
855 | { | 858 | { |
856 | struct btusb_data *data = container_of(work, struct btusb_data, work); | 859 | struct btusb_data *data = container_of(work, struct btusb_data, work); |
857 | struct hci_dev *hdev = data->hdev; | 860 | struct hci_dev *hdev = data->hdev; |
861 | int new_alts; | ||
858 | int err; | 862 | int err; |
859 | 863 | ||
860 | if (hdev->conn_hash.sco_num > 0) { | 864 | if (hdev->conn_hash.sco_num > 0) { |
@@ -868,11 +872,19 @@ static void btusb_work(struct work_struct *work) | |||
868 | 872 | ||
869 | set_bit(BTUSB_DID_ISO_RESUME, &data->flags); | 873 | set_bit(BTUSB_DID_ISO_RESUME, &data->flags); |
870 | } | 874 | } |
871 | if (data->isoc_altsetting != 2) { | 875 | |
876 | if (hdev->voice_setting & 0x0020) { | ||
877 | static const int alts[3] = { 2, 4, 5 }; | ||
878 | new_alts = alts[hdev->conn_hash.sco_num - 1]; | ||
879 | } else { | ||
880 | new_alts = hdev->conn_hash.sco_num; | ||
881 | } | ||
882 | |||
883 | if (data->isoc_altsetting != new_alts) { | ||
872 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | 884 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
873 | usb_kill_anchored_urbs(&data->isoc_anchor); | 885 | usb_kill_anchored_urbs(&data->isoc_anchor); |
874 | 886 | ||
875 | if (__set_isoc_interface(hdev, 2) < 0) | 887 | if (__set_isoc_interface(hdev, new_alts) < 0) |
876 | return; | 888 | return; |
877 | } | 889 | } |
878 | 890 | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 98a8c05d4f23..e564579a6115 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -388,7 +388,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) | |||
388 | hdev->close = hci_uart_close; | 388 | hdev->close = hci_uart_close; |
389 | hdev->flush = hci_uart_flush; | 389 | hdev->flush = hci_uart_flush; |
390 | hdev->send = hci_uart_send_frame; | 390 | hdev->send = hci_uart_send_frame; |
391 | hdev->parent = hu->tty->dev; | 391 | SET_HCIDEV_DEV(hdev, hu->tty->dev); |
392 | 392 | ||
393 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) | 393 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) |
394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 158bfe507da7..3f72595a6017 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -252,8 +252,9 @@ static int vhci_open(struct inode *inode, struct file *file) | |||
252 | } | 252 | } |
253 | 253 | ||
254 | file->private_data = data; | 254 | file->private_data = data; |
255 | nonseekable_open(inode, file); | ||
255 | 256 | ||
256 | return nonseekable_open(inode, file); | 257 | return 0; |
257 | } | 258 | } |
258 | 259 | ||
259 | static int vhci_release(struct inode *inode, struct file *file) | 260 | static int vhci_release(struct inode *inode, struct file *file) |