diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/Makefile | 2 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 12 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 269 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 15 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.h | 2 | ||||
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 170 |
6 files changed, 319 insertions, 151 deletions
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 4afae20df512..9fe8a875a827 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile | |||
@@ -30,3 +30,5 @@ hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o | |||
30 | hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o | 30 | hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o |
31 | hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o | 31 | hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o |
32 | hci_uart-objs := $(hci_uart-y) | 32 | hci_uart-objs := $(hci_uart-y) |
33 | |||
34 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 27068d149380..f9d183387f45 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/bitops.h> | 23 | #include <linux/bitops.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <net/bluetooth/bluetooth.h> | 25 | #include <net/bluetooth/bluetooth.h> |
26 | #include <linux/ctype.h> | ||
27 | #include <linux/firmware.h> | ||
26 | 28 | ||
27 | #define BTM_HEADER_LEN 4 | 29 | #define BTM_HEADER_LEN 4 |
28 | #define BTM_UPLD_SIZE 2312 | 30 | #define BTM_UPLD_SIZE 2312 |
@@ -41,6 +43,8 @@ struct btmrvl_thread { | |||
41 | struct btmrvl_device { | 43 | struct btmrvl_device { |
42 | void *card; | 44 | void *card; |
43 | struct hci_dev *hcidev; | 45 | struct hci_dev *hcidev; |
46 | struct device *dev; | ||
47 | const char *cal_data; | ||
44 | 48 | ||
45 | u8 dev_type; | 49 | u8 dev_type; |
46 | 50 | ||
@@ -91,6 +95,7 @@ struct btmrvl_private { | |||
91 | #define BT_CMD_HOST_SLEEP_CONFIG 0x59 | 95 | #define BT_CMD_HOST_SLEEP_CONFIG 0x59 |
92 | #define BT_CMD_HOST_SLEEP_ENABLE 0x5A | 96 | #define BT_CMD_HOST_SLEEP_ENABLE 0x5A |
93 | #define BT_CMD_MODULE_CFG_REQ 0x5B | 97 | #define BT_CMD_MODULE_CFG_REQ 0x5B |
98 | #define BT_CMD_LOAD_CONFIG_DATA 0x61 | ||
94 | 99 | ||
95 | /* Sub-commands: Module Bringup/Shutdown Request/Response */ | 100 | /* Sub-commands: Module Bringup/Shutdown Request/Response */ |
96 | #define MODULE_BRINGUP_REQ 0xF1 | 101 | #define MODULE_BRINGUP_REQ 0xF1 |
@@ -116,11 +121,8 @@ struct btmrvl_private { | |||
116 | #define PS_SLEEP 0x01 | 121 | #define PS_SLEEP 0x01 |
117 | #define PS_AWAKE 0x00 | 122 | #define PS_AWAKE 0x00 |
118 | 123 | ||
119 | struct btmrvl_cmd { | 124 | #define BT_CMD_DATA_SIZE 32 |
120 | __le16 ocf_ogf; | 125 | #define BT_CAL_DATA_SIZE 28 |
121 | u8 length; | ||
122 | u8 data[4]; | ||
123 | } __packed; | ||
124 | 126 | ||
125 | struct btmrvl_event { | 127 | struct btmrvl_event { |
126 | u8 ec; /* event counter */ | 128 | u8 ec; /* event counter */ |
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 9a9f51875df5..6e7bd4e4adbb 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c | |||
@@ -57,8 +57,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) | |||
57 | ocf = hci_opcode_ocf(opcode); | 57 | ocf = hci_opcode_ocf(opcode); |
58 | ogf = hci_opcode_ogf(opcode); | 58 | ogf = hci_opcode_ogf(opcode); |
59 | 59 | ||
60 | if (ocf == BT_CMD_MODULE_CFG_REQ && | 60 | if (priv->btmrvl_dev.sendcmdflag) { |
61 | priv->btmrvl_dev.sendcmdflag) { | ||
62 | priv->btmrvl_dev.sendcmdflag = false; | 61 | priv->btmrvl_dev.sendcmdflag = false; |
63 | priv->adapter->cmd_complete = true; | 62 | priv->adapter->cmd_complete = true; |
64 | wake_up_interruptible(&priv->adapter->cmd_wait_q); | 63 | wake_up_interruptible(&priv->adapter->cmd_wait_q); |
@@ -116,7 +115,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) | |||
116 | adapter->hs_state = HS_ACTIVATED; | 115 | adapter->hs_state = HS_ACTIVATED; |
117 | if (adapter->psmode) | 116 | if (adapter->psmode) |
118 | adapter->ps_state = PS_SLEEP; | 117 | adapter->ps_state = PS_SLEEP; |
119 | wake_up_interruptible(&adapter->cmd_wait_q); | ||
120 | BT_DBG("HS ACTIVATED!"); | 118 | BT_DBG("HS ACTIVATED!"); |
121 | } else { | 119 | } else { |
122 | BT_DBG("HS Enable failed"); | 120 | BT_DBG("HS Enable failed"); |
@@ -168,22 +166,24 @@ exit: | |||
168 | } | 166 | } |
169 | EXPORT_SYMBOL_GPL(btmrvl_process_event); | 167 | EXPORT_SYMBOL_GPL(btmrvl_process_event); |
170 | 168 | ||
171 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | 169 | static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, |
170 | const void *param, u8 len) | ||
172 | { | 171 | { |
173 | struct sk_buff *skb; | 172 | struct sk_buff *skb; |
174 | struct btmrvl_cmd *cmd; | 173 | struct hci_command_hdr *hdr; |
175 | int ret = 0; | ||
176 | 174 | ||
177 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | 175 | skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_ATOMIC); |
178 | if (skb == NULL) { | 176 | if (skb == NULL) { |
179 | BT_ERR("No free skb"); | 177 | BT_ERR("No free skb"); |
180 | return -ENOMEM; | 178 | return -ENOMEM; |
181 | } | 179 | } |
182 | 180 | ||
183 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | 181 | hdr = (struct hci_command_hdr *)skb_put(skb, HCI_COMMAND_HDR_SIZE); |
184 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ)); | 182 | hdr->opcode = cpu_to_le16(hci_opcode_pack(OGF, cmd_no)); |
185 | cmd->length = 1; | 183 | hdr->plen = len; |
186 | cmd->data[0] = subcmd; | 184 | |
185 | if (len) | ||
186 | memcpy(skb_put(skb, len), param, len); | ||
187 | 187 | ||
188 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | 188 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; |
189 | 189 | ||
@@ -194,19 +194,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | |||
194 | 194 | ||
195 | priv->adapter->cmd_complete = false; | 195 | priv->adapter->cmd_complete = false; |
196 | 196 | ||
197 | BT_DBG("Queue module cfg Command"); | ||
198 | |||
199 | wake_up_interruptible(&priv->main_thread.wait_q); | 197 | wake_up_interruptible(&priv->main_thread.wait_q); |
200 | 198 | ||
201 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, | 199 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, |
202 | priv->adapter->cmd_complete, | 200 | priv->adapter->cmd_complete, |
203 | msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) { | 201 | msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) |
204 | ret = -ETIMEDOUT; | 202 | return -ETIMEDOUT; |
205 | BT_ERR("module_cfg_cmd(%x): timeout: %d", | ||
206 | subcmd, priv->btmrvl_dev.sendcmdflag); | ||
207 | } | ||
208 | 203 | ||
209 | BT_DBG("module cfg Command done"); | 204 | return 0; |
205 | } | ||
206 | |||
207 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | ||
208 | { | ||
209 | int ret; | ||
210 | |||
211 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1); | ||
212 | if (ret) | ||
213 | BT_ERR("module_cfg_cmd(%x) failed\n", subcmd); | ||
210 | 214 | ||
211 | return ret; | 215 | return ret; |
212 | } | 216 | } |
@@ -214,61 +218,36 @@ EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); | |||
214 | 218 | ||
215 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) | 219 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) |
216 | { | 220 | { |
217 | struct sk_buff *skb; | 221 | int ret; |
218 | struct btmrvl_cmd *cmd; | 222 | u8 param[2]; |
219 | |||
220 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
221 | if (!skb) { | ||
222 | BT_ERR("No free skb"); | ||
223 | return -ENOMEM; | ||
224 | } | ||
225 | |||
226 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
227 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, | ||
228 | BT_CMD_HOST_SLEEP_CONFIG)); | ||
229 | cmd->length = 2; | ||
230 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
231 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
232 | 223 | ||
233 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | 224 | param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; |
225 | param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
234 | 226 | ||
235 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | 227 | BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x", |
236 | skb_queue_head(&priv->adapter->tx_queue, skb); | 228 | param[0], param[1]); |
237 | 229 | ||
238 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], | 230 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2); |
239 | cmd->data[1]); | 231 | if (ret) |
232 | BT_ERR("HSCFG command failed\n"); | ||
240 | 233 | ||
241 | return 0; | 234 | return ret; |
242 | } | 235 | } |
243 | EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); | 236 | EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); |
244 | 237 | ||
245 | int btmrvl_enable_ps(struct btmrvl_private *priv) | 238 | int btmrvl_enable_ps(struct btmrvl_private *priv) |
246 | { | 239 | { |
247 | struct sk_buff *skb; | 240 | int ret; |
248 | struct btmrvl_cmd *cmd; | 241 | u8 param; |
249 | |||
250 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
251 | if (skb == NULL) { | ||
252 | BT_ERR("No free skb"); | ||
253 | return -ENOMEM; | ||
254 | } | ||
255 | |||
256 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
257 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, | ||
258 | BT_CMD_AUTO_SLEEP_MODE)); | ||
259 | cmd->length = 1; | ||
260 | 242 | ||
261 | if (priv->btmrvl_dev.psmode) | 243 | if (priv->btmrvl_dev.psmode) |
262 | cmd->data[0] = BT_PS_ENABLE; | 244 | param = BT_PS_ENABLE; |
263 | else | 245 | else |
264 | cmd->data[0] = BT_PS_DISABLE; | 246 | param = BT_PS_DISABLE; |
265 | |||
266 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
267 | 247 | ||
268 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | 248 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1); |
269 | skb_queue_head(&priv->adapter->tx_queue, skb); | 249 | if (ret) |
270 | 250 | BT_ERR("PSMODE command failed\n"); | |
271 | BT_DBG("Queue PSMODE Command:%d", cmd->data[0]); | ||
272 | 251 | ||
273 | return 0; | 252 | return 0; |
274 | } | 253 | } |
@@ -276,37 +255,11 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps); | |||
276 | 255 | ||
277 | int btmrvl_enable_hs(struct btmrvl_private *priv) | 256 | int btmrvl_enable_hs(struct btmrvl_private *priv) |
278 | { | 257 | { |
279 | struct sk_buff *skb; | 258 | int ret; |
280 | struct btmrvl_cmd *cmd; | ||
281 | int ret = 0; | ||
282 | |||
283 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
284 | if (skb == NULL) { | ||
285 | BT_ERR("No free skb"); | ||
286 | return -ENOMEM; | ||
287 | } | ||
288 | |||
289 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
290 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE)); | ||
291 | cmd->length = 0; | ||
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 hs enable Command"); | ||
299 | |||
300 | wake_up_interruptible(&priv->main_thread.wait_q); | ||
301 | 259 | ||
302 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, | 260 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); |
303 | priv->adapter->hs_state, | 261 | if (ret) |
304 | msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) { | 262 | BT_ERR("Host sleep enable command failed\n"); |
305 | ret = -ETIMEDOUT; | ||
306 | BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state, | ||
307 | priv->adapter->ps_state, | ||
308 | priv->adapter->wakeup_tries); | ||
309 | } | ||
310 | 263 | ||
311 | return ret; | 264 | return ret; |
312 | } | 265 | } |
@@ -480,6 +433,137 @@ static int btmrvl_open(struct hci_dev *hdev) | |||
480 | } | 433 | } |
481 | 434 | ||
482 | /* | 435 | /* |
436 | * This function parses provided calibration data input. It should contain | ||
437 | * hex bytes separated by space or new line character. Here is an example. | ||
438 | * 00 1C 01 37 FF FF FF FF 02 04 7F 01 | ||
439 | * CE BA 00 00 00 2D C6 C0 00 00 00 00 | ||
440 | * 00 F0 00 00 | ||
441 | */ | ||
442 | static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size) | ||
443 | { | ||
444 | const u8 *s = src; | ||
445 | u8 *d = dst; | ||
446 | int ret; | ||
447 | u8 tmp[3]; | ||
448 | |||
449 | tmp[2] = '\0'; | ||
450 | while ((s - src) <= len - 2) { | ||
451 | if (isspace(*s)) { | ||
452 | s++; | ||
453 | continue; | ||
454 | } | ||
455 | |||
456 | if (isxdigit(*s)) { | ||
457 | if ((d - dst) >= dst_size) { | ||
458 | BT_ERR("calibration data file too big!!!"); | ||
459 | return -EINVAL; | ||
460 | } | ||
461 | |||
462 | memcpy(tmp, s, 2); | ||
463 | |||
464 | ret = kstrtou8(tmp, 16, d++); | ||
465 | if (ret < 0) | ||
466 | return ret; | ||
467 | |||
468 | s += 2; | ||
469 | } else { | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | } | ||
473 | if (d == dst) | ||
474 | return -EINVAL; | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static int btmrvl_load_cal_data(struct btmrvl_private *priv, | ||
480 | u8 *config_data) | ||
481 | { | ||
482 | int i, ret; | ||
483 | u8 data[BT_CMD_DATA_SIZE]; | ||
484 | |||
485 | data[0] = 0x00; | ||
486 | data[1] = 0x00; | ||
487 | data[2] = 0x00; | ||
488 | data[3] = BT_CMD_DATA_SIZE - 4; | ||
489 | |||
490 | /* Swap cal-data bytes. Each four bytes are swapped. Considering 4 | ||
491 | * byte SDIO header offset, mapping of input and output bytes will be | ||
492 | * {3, 2, 1, 0} -> {0+4, 1+4, 2+4, 3+4}, | ||
493 | * {7, 6, 5, 4} -> {4+4, 5+4, 6+4, 7+4} */ | ||
494 | for (i = 4; i < BT_CMD_DATA_SIZE; i++) | ||
495 | data[i] = config_data[(i / 4) * 8 - 1 - i]; | ||
496 | |||
497 | print_hex_dump_bytes("Calibration data: ", | ||
498 | DUMP_PREFIX_OFFSET, data, BT_CMD_DATA_SIZE); | ||
499 | |||
500 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data, | ||
501 | BT_CMD_DATA_SIZE); | ||
502 | if (ret) | ||
503 | BT_ERR("Failed to download caibration data\n"); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static int | ||
509 | btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size) | ||
510 | { | ||
511 | u8 cal_data[BT_CAL_DATA_SIZE]; | ||
512 | int ret; | ||
513 | |||
514 | ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data)); | ||
515 | if (ret) | ||
516 | return ret; | ||
517 | |||
518 | ret = btmrvl_load_cal_data(priv, cal_data); | ||
519 | if (ret) { | ||
520 | BT_ERR("Fail to load calibrate data"); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int btmrvl_cal_data_config(struct btmrvl_private *priv) | ||
528 | { | ||
529 | const struct firmware *cfg; | ||
530 | int ret; | ||
531 | const char *cal_data = priv->btmrvl_dev.cal_data; | ||
532 | |||
533 | if (!cal_data) | ||
534 | return 0; | ||
535 | |||
536 | ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev); | ||
537 | if (ret < 0) { | ||
538 | BT_DBG("Failed to get %s file, skipping cal data download", | ||
539 | cal_data); | ||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size); | ||
544 | release_firmware(cfg); | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | static int btmrvl_setup(struct hci_dev *hdev) | ||
549 | { | ||
550 | struct btmrvl_private *priv = hci_get_drvdata(hdev); | ||
551 | |||
552 | btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); | ||
553 | |||
554 | if (btmrvl_cal_data_config(priv)) | ||
555 | BT_ERR("Set cal data failed"); | ||
556 | |||
557 | priv->btmrvl_dev.psmode = 1; | ||
558 | btmrvl_enable_ps(priv); | ||
559 | |||
560 | priv->btmrvl_dev.gpio_gap = 0xffff; | ||
561 | btmrvl_send_hscfg_cmd(priv); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | /* | ||
483 | * This function handles the event generated by firmware, rx data | 567 | * This function handles the event generated by firmware, rx data |
484 | * received from firmware, and tx data sent from kernel. | 568 | * received from firmware, and tx data sent from kernel. |
485 | */ | 569 | */ |
@@ -572,8 +656,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) | |||
572 | hdev->flush = btmrvl_flush; | 656 | hdev->flush = btmrvl_flush; |
573 | hdev->send = btmrvl_send_frame; | 657 | hdev->send = btmrvl_send_frame; |
574 | hdev->ioctl = btmrvl_ioctl; | 658 | hdev->ioctl = btmrvl_ioctl; |
575 | 659 | hdev->setup = btmrvl_setup; | |
576 | btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); | ||
577 | 660 | ||
578 | hdev->dev_type = priv->btmrvl_dev.dev_type; | 661 | hdev->dev_type = priv->btmrvl_dev.dev_type; |
579 | 662 | ||
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 00da6df9f71e..332475e400cf 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -18,7 +18,6 @@ | |||
18 | * this warranty disclaimer. | 18 | * this warranty disclaimer. |
19 | **/ | 19 | **/ |
20 | 20 | ||
21 | #include <linux/firmware.h> | ||
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
23 | 22 | ||
24 | #include <linux/mmc/sdio_ids.h> | 23 | #include <linux/mmc/sdio_ids.h> |
@@ -102,6 +101,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { | |||
102 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { | 101 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { |
103 | .helper = "mrvl/sd8688_helper.bin", | 102 | .helper = "mrvl/sd8688_helper.bin", |
104 | .firmware = "mrvl/sd8688.bin", | 103 | .firmware = "mrvl/sd8688.bin", |
104 | .cal_data = NULL, | ||
105 | .reg = &btmrvl_reg_8688, | 105 | .reg = &btmrvl_reg_8688, |
106 | .sd_blksz_fw_dl = 64, | 106 | .sd_blksz_fw_dl = 64, |
107 | }; | 107 | }; |
@@ -109,6 +109,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { | |||
109 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { | 109 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { |
110 | .helper = NULL, | 110 | .helper = NULL, |
111 | .firmware = "mrvl/sd8787_uapsta.bin", | 111 | .firmware = "mrvl/sd8787_uapsta.bin", |
112 | .cal_data = NULL, | ||
112 | .reg = &btmrvl_reg_87xx, | 113 | .reg = &btmrvl_reg_87xx, |
113 | .sd_blksz_fw_dl = 256, | 114 | .sd_blksz_fw_dl = 256, |
114 | }; | 115 | }; |
@@ -116,6 +117,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { | |||
116 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { | 117 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { |
117 | .helper = NULL, | 118 | .helper = NULL, |
118 | .firmware = "mrvl/sd8797_uapsta.bin", | 119 | .firmware = "mrvl/sd8797_uapsta.bin", |
120 | .cal_data = "mrvl/sd8797_caldata.conf", | ||
119 | .reg = &btmrvl_reg_87xx, | 121 | .reg = &btmrvl_reg_87xx, |
120 | .sd_blksz_fw_dl = 256, | 122 | .sd_blksz_fw_dl = 256, |
121 | }; | 123 | }; |
@@ -123,6 +125,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { | |||
123 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { | 125 | static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { |
124 | .helper = NULL, | 126 | .helper = NULL, |
125 | .firmware = "mrvl/sd8897_uapsta.bin", | 127 | .firmware = "mrvl/sd8897_uapsta.bin", |
128 | .cal_data = NULL, | ||
126 | .reg = &btmrvl_reg_88xx, | 129 | .reg = &btmrvl_reg_88xx, |
127 | .sd_blksz_fw_dl = 256, | 130 | .sd_blksz_fw_dl = 256, |
128 | }; | 131 | }; |
@@ -1006,6 +1009,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, | |||
1006 | struct btmrvl_sdio_device *data = (void *) id->driver_data; | 1009 | struct btmrvl_sdio_device *data = (void *) id->driver_data; |
1007 | card->helper = data->helper; | 1010 | card->helper = data->helper; |
1008 | card->firmware = data->firmware; | 1011 | card->firmware = data->firmware; |
1012 | card->cal_data = data->cal_data; | ||
1009 | card->reg = data->reg; | 1013 | card->reg = data->reg; |
1010 | card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; | 1014 | card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; |
1011 | } | 1015 | } |
@@ -1034,6 +1038,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func, | |||
1034 | } | 1038 | } |
1035 | 1039 | ||
1036 | card->priv = priv; | 1040 | card->priv = priv; |
1041 | priv->btmrvl_dev.dev = &card->func->dev; | ||
1042 | priv->btmrvl_dev.cal_data = card->cal_data; | ||
1037 | 1043 | ||
1038 | /* Initialize the interface specific function pointers */ | 1044 | /* Initialize the interface specific function pointers */ |
1039 | priv->hw_host_to_card = btmrvl_sdio_host_to_card; | 1045 | priv->hw_host_to_card = btmrvl_sdio_host_to_card; |
@@ -1046,12 +1052,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, | |||
1046 | goto disable_host_int; | 1052 | goto disable_host_int; |
1047 | } | 1053 | } |
1048 | 1054 | ||
1049 | priv->btmrvl_dev.psmode = 1; | ||
1050 | btmrvl_enable_ps(priv); | ||
1051 | |||
1052 | priv->btmrvl_dev.gpio_gap = 0xffff; | ||
1053 | btmrvl_send_hscfg_cmd(priv); | ||
1054 | |||
1055 | return 0; | 1055 | return 0; |
1056 | 1056 | ||
1057 | disable_host_int: | 1057 | disable_host_int: |
@@ -1222,4 +1222,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); | |||
1222 | MODULE_FIRMWARE("mrvl/sd8688.bin"); | 1222 | MODULE_FIRMWARE("mrvl/sd8688.bin"); |
1223 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); | 1223 | MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); |
1224 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); | 1224 | MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); |
1225 | MODULE_FIRMWARE("mrvl/sd8797_caldata.conf"); | ||
1225 | MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); | 1226 | MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); |
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 43d35a609ca9..6872d9ecac07 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h | |||
@@ -85,6 +85,7 @@ struct btmrvl_sdio_card { | |||
85 | u32 ioport; | 85 | u32 ioport; |
86 | const char *helper; | 86 | const char *helper; |
87 | const char *firmware; | 87 | const char *firmware; |
88 | const char *cal_data; | ||
88 | const struct btmrvl_sdio_card_reg *reg; | 89 | const struct btmrvl_sdio_card_reg *reg; |
89 | u16 sd_blksz_fw_dl; | 90 | u16 sd_blksz_fw_dl; |
90 | u8 rx_unit; | 91 | u8 rx_unit; |
@@ -94,6 +95,7 @@ struct btmrvl_sdio_card { | |||
94 | struct btmrvl_sdio_device { | 95 | struct btmrvl_sdio_device { |
95 | const char *helper; | 96 | const char *helper; |
96 | const char *firmware; | 97 | const char *firmware; |
98 | const char *cal_data; | ||
97 | const struct btmrvl_sdio_card_reg *reg; | 99 | const struct btmrvl_sdio_card_reg *reg; |
98 | u16 sd_blksz_fw_dl; | 100 | u16 sd_blksz_fw_dl; |
99 | }; | 101 | }; |
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index d8b7aed6e4a9..c04a3e6fb37c 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -24,6 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <asm/unaligned.h> | ||
27 | 28 | ||
28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
29 | #include <linux/init.h> | 30 | #include <linux/init.h> |
@@ -39,17 +40,17 @@ | |||
39 | #include <net/bluetooth/bluetooth.h> | 40 | #include <net/bluetooth/bluetooth.h> |
40 | #include <net/bluetooth/hci_core.h> | 41 | #include <net/bluetooth/hci_core.h> |
41 | 42 | ||
42 | #define VERSION "1.3" | 43 | #define VERSION "1.4" |
43 | 44 | ||
44 | static bool amp; | 45 | static bool amp; |
45 | 46 | ||
46 | struct vhci_data { | 47 | struct vhci_data { |
47 | struct hci_dev *hdev; | 48 | struct hci_dev *hdev; |
48 | 49 | ||
49 | unsigned long flags; | ||
50 | |||
51 | wait_queue_head_t read_wait; | 50 | wait_queue_head_t read_wait; |
52 | struct sk_buff_head readq; | 51 | struct sk_buff_head readq; |
52 | |||
53 | struct delayed_work open_timeout; | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | static int vhci_open_dev(struct hci_dev *hdev) | 56 | static int vhci_open_dev(struct hci_dev *hdev) |
@@ -99,16 +100,62 @@ static int vhci_send_frame(struct sk_buff *skb) | |||
99 | skb_queue_tail(&data->readq, skb); | 100 | skb_queue_tail(&data->readq, skb); |
100 | 101 | ||
101 | wake_up_interruptible(&data->read_wait); | 102 | wake_up_interruptible(&data->read_wait); |
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int vhci_create_device(struct vhci_data *data, __u8 dev_type) | ||
107 | { | ||
108 | struct hci_dev *hdev; | ||
109 | struct sk_buff *skb; | ||
110 | |||
111 | skb = bt_skb_alloc(4, GFP_KERNEL); | ||
112 | if (!skb) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | hdev = hci_alloc_dev(); | ||
116 | if (!hdev) { | ||
117 | kfree_skb(skb); | ||
118 | return -ENOMEM; | ||
119 | } | ||
120 | |||
121 | data->hdev = hdev; | ||
122 | |||
123 | hdev->bus = HCI_VIRTUAL; | ||
124 | hdev->dev_type = dev_type; | ||
125 | hci_set_drvdata(hdev, data); | ||
126 | |||
127 | hdev->open = vhci_open_dev; | ||
128 | hdev->close = vhci_close_dev; | ||
129 | hdev->flush = vhci_flush; | ||
130 | hdev->send = vhci_send_frame; | ||
102 | 131 | ||
132 | if (hci_register_dev(hdev) < 0) { | ||
133 | BT_ERR("Can't register HCI device"); | ||
134 | hci_free_dev(hdev); | ||
135 | data->hdev = NULL; | ||
136 | kfree_skb(skb); | ||
137 | return -EBUSY; | ||
138 | } | ||
139 | |||
140 | bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; | ||
141 | |||
142 | *skb_put(skb, 1) = 0xff; | ||
143 | *skb_put(skb, 1) = dev_type; | ||
144 | put_unaligned_le16(hdev->id, skb_put(skb, 2)); | ||
145 | skb_queue_tail(&data->readq, skb); | ||
146 | |||
147 | wake_up_interruptible(&data->read_wait); | ||
103 | return 0; | 148 | return 0; |
104 | } | 149 | } |
105 | 150 | ||
106 | static inline ssize_t vhci_get_user(struct vhci_data *data, | 151 | static inline ssize_t vhci_get_user(struct vhci_data *data, |
107 | const char __user *buf, size_t count) | 152 | const char __user *buf, size_t count) |
108 | { | 153 | { |
109 | struct sk_buff *skb; | 154 | struct sk_buff *skb; |
155 | __u8 pkt_type, dev_type; | ||
156 | int ret; | ||
110 | 157 | ||
111 | if (count > HCI_MAX_FRAME_SIZE) | 158 | if (count < 2 || count > HCI_MAX_FRAME_SIZE) |
112 | return -EINVAL; | 159 | return -EINVAL; |
113 | 160 | ||
114 | skb = bt_skb_alloc(count, GFP_KERNEL); | 161 | skb = bt_skb_alloc(count, GFP_KERNEL); |
@@ -120,27 +167,70 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, | |||
120 | return -EFAULT; | 167 | return -EFAULT; |
121 | } | 168 | } |
122 | 169 | ||
123 | skb->dev = (void *) data->hdev; | 170 | pkt_type = *((__u8 *) skb->data); |
124 | bt_cb(skb)->pkt_type = *((__u8 *) skb->data); | ||
125 | skb_pull(skb, 1); | 171 | skb_pull(skb, 1); |
126 | 172 | ||
127 | hci_recv_frame(skb); | 173 | switch (pkt_type) { |
174 | case HCI_EVENT_PKT: | ||
175 | case HCI_ACLDATA_PKT: | ||
176 | case HCI_SCODATA_PKT: | ||
177 | if (!data->hdev) { | ||
178 | kfree_skb(skb); | ||
179 | return -ENODEV; | ||
180 | } | ||
181 | |||
182 | skb->dev = (void *) data->hdev; | ||
183 | bt_cb(skb)->pkt_type = pkt_type; | ||
184 | |||
185 | ret = hci_recv_frame(skb); | ||
186 | break; | ||
187 | |||
188 | case HCI_VENDOR_PKT: | ||
189 | if (data->hdev) { | ||
190 | kfree_skb(skb); | ||
191 | return -EBADFD; | ||
192 | } | ||
128 | 193 | ||
129 | return count; | 194 | cancel_delayed_work_sync(&data->open_timeout); |
195 | |||
196 | dev_type = *((__u8 *) skb->data); | ||
197 | skb_pull(skb, 1); | ||
198 | |||
199 | if (skb->len > 0) { | ||
200 | kfree_skb(skb); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | |||
204 | kfree_skb(skb); | ||
205 | |||
206 | if (dev_type != HCI_BREDR && dev_type != HCI_AMP) | ||
207 | return -EINVAL; | ||
208 | |||
209 | ret = vhci_create_device(data, dev_type); | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | kfree_skb(skb); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | return (ret < 0) ? ret : count; | ||
130 | } | 218 | } |
131 | 219 | ||
132 | static inline ssize_t vhci_put_user(struct vhci_data *data, | 220 | static inline ssize_t vhci_put_user(struct vhci_data *data, |
133 | struct sk_buff *skb, char __user *buf, int count) | 221 | struct sk_buff *skb, |
222 | char __user *buf, int count) | ||
134 | { | 223 | { |
135 | char __user *ptr = buf; | 224 | char __user *ptr = buf; |
136 | int len, total = 0; | 225 | int len; |
137 | 226 | ||
138 | len = min_t(unsigned int, skb->len, count); | 227 | len = min_t(unsigned int, skb->len, count); |
139 | 228 | ||
140 | if (copy_to_user(ptr, skb->data, len)) | 229 | if (copy_to_user(ptr, skb->data, len)) |
141 | return -EFAULT; | 230 | return -EFAULT; |
142 | 231 | ||
143 | total += len; | 232 | if (!data->hdev) |
233 | return len; | ||
144 | 234 | ||
145 | data->hdev->stat.byte_tx += len; | 235 | data->hdev->stat.byte_tx += len; |
146 | 236 | ||
@@ -148,21 +238,19 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, | |||
148 | case HCI_COMMAND_PKT: | 238 | case HCI_COMMAND_PKT: |
149 | data->hdev->stat.cmd_tx++; | 239 | data->hdev->stat.cmd_tx++; |
150 | break; | 240 | break; |
151 | |||
152 | case HCI_ACLDATA_PKT: | 241 | case HCI_ACLDATA_PKT: |
153 | data->hdev->stat.acl_tx++; | 242 | data->hdev->stat.acl_tx++; |
154 | break; | 243 | break; |
155 | |||
156 | case HCI_SCODATA_PKT: | 244 | case HCI_SCODATA_PKT: |
157 | data->hdev->stat.sco_tx++; | 245 | data->hdev->stat.sco_tx++; |
158 | break; | 246 | break; |
159 | } | 247 | } |
160 | 248 | ||
161 | return total; | 249 | return len; |
162 | } | 250 | } |
163 | 251 | ||
164 | static ssize_t vhci_read(struct file *file, | 252 | static ssize_t vhci_read(struct file *file, |
165 | char __user *buf, size_t count, loff_t *pos) | 253 | char __user *buf, size_t count, loff_t *pos) |
166 | { | 254 | { |
167 | struct vhci_data *data = file->private_data; | 255 | struct vhci_data *data = file->private_data; |
168 | struct sk_buff *skb; | 256 | struct sk_buff *skb; |
@@ -185,7 +273,7 @@ static ssize_t vhci_read(struct file *file, | |||
185 | } | 273 | } |
186 | 274 | ||
187 | ret = wait_event_interruptible(data->read_wait, | 275 | ret = wait_event_interruptible(data->read_wait, |
188 | !skb_queue_empty(&data->readq)); | 276 | !skb_queue_empty(&data->readq)); |
189 | if (ret < 0) | 277 | if (ret < 0) |
190 | break; | 278 | break; |
191 | } | 279 | } |
@@ -194,7 +282,7 @@ static ssize_t vhci_read(struct file *file, | |||
194 | } | 282 | } |
195 | 283 | ||
196 | static ssize_t vhci_write(struct file *file, | 284 | static ssize_t vhci_write(struct file *file, |
197 | const char __user *buf, size_t count, loff_t *pos) | 285 | const char __user *buf, size_t count, loff_t *pos) |
198 | { | 286 | { |
199 | struct vhci_data *data = file->private_data; | 287 | struct vhci_data *data = file->private_data; |
200 | 288 | ||
@@ -213,10 +301,17 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait) | |||
213 | return POLLOUT | POLLWRNORM; | 301 | return POLLOUT | POLLWRNORM; |
214 | } | 302 | } |
215 | 303 | ||
304 | static void vhci_open_timeout(struct work_struct *work) | ||
305 | { | ||
306 | struct vhci_data *data = container_of(work, struct vhci_data, | ||
307 | open_timeout.work); | ||
308 | |||
309 | vhci_create_device(data, amp ? HCI_AMP : HCI_BREDR); | ||
310 | } | ||
311 | |||
216 | static int vhci_open(struct inode *inode, struct file *file) | 312 | static int vhci_open(struct inode *inode, struct file *file) |
217 | { | 313 | { |
218 | struct vhci_data *data; | 314 | struct vhci_data *data; |
219 | struct hci_dev *hdev; | ||
220 | 315 | ||
221 | data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL); | 316 | data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL); |
222 | if (!data) | 317 | if (!data) |
@@ -225,35 +320,13 @@ static int vhci_open(struct inode *inode, struct file *file) | |||
225 | skb_queue_head_init(&data->readq); | 320 | skb_queue_head_init(&data->readq); |
226 | init_waitqueue_head(&data->read_wait); | 321 | init_waitqueue_head(&data->read_wait); |
227 | 322 | ||
228 | hdev = hci_alloc_dev(); | 323 | INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout); |
229 | if (!hdev) { | ||
230 | kfree(data); | ||
231 | return -ENOMEM; | ||
232 | } | ||
233 | |||
234 | data->hdev = hdev; | ||
235 | |||
236 | hdev->bus = HCI_VIRTUAL; | ||
237 | hci_set_drvdata(hdev, data); | ||
238 | |||
239 | if (amp) | ||
240 | hdev->dev_type = HCI_AMP; | ||
241 | |||
242 | hdev->open = vhci_open_dev; | ||
243 | hdev->close = vhci_close_dev; | ||
244 | hdev->flush = vhci_flush; | ||
245 | hdev->send = vhci_send_frame; | ||
246 | |||
247 | if (hci_register_dev(hdev) < 0) { | ||
248 | BT_ERR("Can't register HCI device"); | ||
249 | kfree(data); | ||
250 | hci_free_dev(hdev); | ||
251 | return -EBUSY; | ||
252 | } | ||
253 | 324 | ||
254 | file->private_data = data; | 325 | file->private_data = data; |
255 | nonseekable_open(inode, file); | 326 | nonseekable_open(inode, file); |
256 | 327 | ||
328 | schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000)); | ||
329 | |||
257 | return 0; | 330 | return 0; |
258 | } | 331 | } |
259 | 332 | ||
@@ -262,8 +335,12 @@ static int vhci_release(struct inode *inode, struct file *file) | |||
262 | struct vhci_data *data = file->private_data; | 335 | struct vhci_data *data = file->private_data; |
263 | struct hci_dev *hdev = data->hdev; | 336 | struct hci_dev *hdev = data->hdev; |
264 | 337 | ||
265 | hci_unregister_dev(hdev); | 338 | cancel_delayed_work_sync(&data->open_timeout); |
266 | hci_free_dev(hdev); | 339 | |
340 | if (hdev) { | ||
341 | hci_unregister_dev(hdev); | ||
342 | hci_free_dev(hdev); | ||
343 | } | ||
267 | 344 | ||
268 | file->private_data = NULL; | 345 | file->private_data = NULL; |
269 | kfree(data); | 346 | kfree(data); |
@@ -309,3 +386,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); | |||
309 | MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); | 386 | MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); |
310 | MODULE_VERSION(VERSION); | 387 | MODULE_VERSION(VERSION); |
311 | MODULE_LICENSE("GPL"); | 388 | MODULE_LICENSE("GPL"); |
389 | MODULE_ALIAS("devname:vhci"); | ||