1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Marvell Bluetooth driver |
4 | * |
5 | * Copyright (C) 2009, Marvell International Ltd. |
6 | **/ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/of.h> |
10 | #include <net/bluetooth/bluetooth.h> |
11 | #include <net/bluetooth/hci_core.h> |
12 | #include <linux/mmc/sdio_func.h> |
13 | |
14 | #include "btmrvl_drv.h" |
15 | #include "btmrvl_sdio.h" |
16 | |
17 | #define VERSION "1.0" |
18 | |
19 | /* |
20 | * This function is called by interface specific interrupt handler. |
21 | * It updates Power Save & Host Sleep states, and wakes up the main |
22 | * thread. |
23 | */ |
24 | void btmrvl_interrupt(struct btmrvl_private *priv) |
25 | { |
26 | priv->adapter->ps_state = PS_AWAKE; |
27 | |
28 | priv->adapter->wakeup_tries = 0; |
29 | |
30 | priv->adapter->int_count++; |
31 | |
32 | if (priv->adapter->hs_state == HS_ACTIVATED) { |
33 | BT_DBG("BT: HS DEACTIVATED in ISR!" ); |
34 | priv->adapter->hs_state = HS_DEACTIVATED; |
35 | } |
36 | |
37 | wake_up_interruptible(&priv->main_thread.wait_q); |
38 | } |
39 | EXPORT_SYMBOL_GPL(btmrvl_interrupt); |
40 | |
41 | bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb) |
42 | { |
43 | struct hci_event_hdr *hdr = (void *) skb->data; |
44 | |
45 | if (hdr->evt == HCI_EV_CMD_COMPLETE) { |
46 | struct hci_ev_cmd_complete *ec; |
47 | u16 opcode; |
48 | |
49 | ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE); |
50 | opcode = __le16_to_cpu(ec->opcode); |
51 | |
52 | if (priv->btmrvl_dev.sendcmdflag) { |
53 | priv->btmrvl_dev.sendcmdflag = false; |
54 | priv->adapter->cmd_complete = true; |
55 | wake_up_interruptible(&priv->adapter->cmd_wait_q); |
56 | |
57 | if (hci_opcode_ogf(opcode) == 0x3F) { |
58 | BT_DBG("vendor event skipped: opcode=%#4.4x" , |
59 | opcode); |
60 | kfree_skb(skb); |
61 | return false; |
62 | } |
63 | } |
64 | } |
65 | |
66 | return true; |
67 | } |
68 | EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt); |
69 | |
70 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) |
71 | { |
72 | struct btmrvl_adapter *adapter = priv->adapter; |
73 | struct btmrvl_event *event; |
74 | int ret = 0; |
75 | |
76 | event = (struct btmrvl_event *) skb->data; |
77 | if (event->ec != 0xff) { |
78 | BT_DBG("Not Marvell Event=%x" , event->ec); |
79 | ret = -EINVAL; |
80 | goto exit; |
81 | } |
82 | |
83 | switch (event->data[0]) { |
84 | case BT_EVENT_AUTO_SLEEP_MODE: |
85 | if (!event->data[2]) { |
86 | if (event->data[1] == BT_PS_ENABLE) |
87 | adapter->psmode = 1; |
88 | else |
89 | adapter->psmode = 0; |
90 | BT_DBG("PS Mode:%s" , |
91 | (adapter->psmode) ? "Enable" : "Disable" ); |
92 | } else { |
93 | BT_DBG("PS Mode command failed" ); |
94 | } |
95 | break; |
96 | |
97 | case BT_EVENT_HOST_SLEEP_CONFIG: |
98 | if (!event->data[3]) |
99 | BT_DBG("gpio=%x, gap=%x" , event->data[1], |
100 | event->data[2]); |
101 | else |
102 | BT_DBG("HSCFG command failed" ); |
103 | break; |
104 | |
105 | case BT_EVENT_HOST_SLEEP_ENABLE: |
106 | if (!event->data[1]) { |
107 | adapter->hs_state = HS_ACTIVATED; |
108 | if (adapter->psmode) |
109 | adapter->ps_state = PS_SLEEP; |
110 | wake_up_interruptible(&adapter->event_hs_wait_q); |
111 | BT_DBG("HS ACTIVATED!" ); |
112 | } else { |
113 | BT_DBG("HS Enable failed" ); |
114 | } |
115 | break; |
116 | |
117 | case BT_EVENT_MODULE_CFG_REQ: |
118 | if (priv->btmrvl_dev.sendcmdflag && |
119 | event->data[1] == MODULE_BRINGUP_REQ) { |
120 | BT_DBG("EVENT:%s" , |
121 | ((event->data[2] == MODULE_BROUGHT_UP) || |
122 | (event->data[2] == MODULE_ALREADY_UP)) ? |
123 | "Bring-up succeed" : "Bring-up failed" ); |
124 | |
125 | if (event->length > 3 && event->data[3]) |
126 | priv->btmrvl_dev.dev_type = HCI_AMP; |
127 | else |
128 | priv->btmrvl_dev.dev_type = HCI_PRIMARY; |
129 | |
130 | BT_DBG("dev_type: %d" , priv->btmrvl_dev.dev_type); |
131 | } else if (priv->btmrvl_dev.sendcmdflag && |
132 | event->data[1] == MODULE_SHUTDOWN_REQ) { |
133 | BT_DBG("EVENT:%s" , (event->data[2]) ? |
134 | "Shutdown failed" : "Shutdown succeed" ); |
135 | } else { |
136 | BT_DBG("BT_CMD_MODULE_CFG_REQ resp for APP" ); |
137 | ret = -EINVAL; |
138 | } |
139 | break; |
140 | |
141 | case BT_EVENT_POWER_STATE: |
142 | if (event->data[1] == BT_PS_SLEEP) |
143 | adapter->ps_state = PS_SLEEP; |
144 | BT_DBG("EVENT:%s" , |
145 | (adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE" ); |
146 | break; |
147 | |
148 | default: |
149 | BT_DBG("Unknown Event=%d" , event->data[0]); |
150 | ret = -EINVAL; |
151 | break; |
152 | } |
153 | |
154 | exit: |
155 | if (!ret) |
156 | kfree_skb(skb); |
157 | |
158 | return ret; |
159 | } |
160 | EXPORT_SYMBOL_GPL(btmrvl_process_event); |
161 | |
162 | static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 opcode, |
163 | const void *param, u8 len) |
164 | { |
165 | struct sk_buff *skb; |
166 | struct hci_command_hdr *hdr; |
167 | |
168 | if (priv->surprise_removed) { |
169 | BT_ERR("Card is removed" ); |
170 | return -EFAULT; |
171 | } |
172 | |
173 | skb = bt_skb_alloc(HCI_COMMAND_HDR_SIZE + len, GFP_KERNEL); |
174 | if (!skb) { |
175 | BT_ERR("No free skb" ); |
176 | return -ENOMEM; |
177 | } |
178 | |
179 | hdr = skb_put(skb, HCI_COMMAND_HDR_SIZE); |
180 | hdr->opcode = cpu_to_le16(opcode); |
181 | hdr->plen = len; |
182 | |
183 | if (len) |
184 | skb_put_data(skb, data: param, len); |
185 | |
186 | hci_skb_pkt_type(skb) = MRVL_VENDOR_PKT; |
187 | |
188 | skb_queue_head(list: &priv->adapter->tx_queue, newsk: skb); |
189 | |
190 | priv->btmrvl_dev.sendcmdflag = true; |
191 | |
192 | priv->adapter->cmd_complete = false; |
193 | |
194 | wake_up_interruptible(&priv->main_thread.wait_q); |
195 | |
196 | if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q, |
197 | priv->adapter->cmd_complete || |
198 | priv->surprise_removed, |
199 | WAIT_UNTIL_CMD_RESP)) |
200 | return -ETIMEDOUT; |
201 | |
202 | if (priv->surprise_removed) |
203 | return -EFAULT; |
204 | |
205 | return 0; |
206 | } |
207 | |
208 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd) |
209 | { |
210 | int ret; |
211 | |
212 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, param: &subcmd, len: 1); |
213 | if (ret) |
214 | BT_ERR("module_cfg_cmd(%x) failed" , subcmd); |
215 | |
216 | return ret; |
217 | } |
218 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); |
219 | |
220 | static int btmrvl_enable_sco_routing_to_host(struct btmrvl_private *priv) |
221 | { |
222 | int ret; |
223 | u8 subcmd = 0; |
224 | |
225 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_ROUTE_SCO_TO_HOST, param: &subcmd, len: 1); |
226 | if (ret) |
227 | BT_ERR("BT_CMD_ROUTE_SCO_TO_HOST command failed: %#x" , ret); |
228 | |
229 | return ret; |
230 | } |
231 | |
232 | int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd) |
233 | { |
234 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; |
235 | int ret; |
236 | |
237 | if (!card->support_pscan_win_report) |
238 | return 0; |
239 | |
240 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_PSCAN_WIN_REPORT_ENABLE, |
241 | param: &subcmd, len: 1); |
242 | if (ret) |
243 | BT_ERR("PSCAN_WIN_REPORT_ENABLE command failed: %#x" , ret); |
244 | |
245 | return ret; |
246 | } |
247 | EXPORT_SYMBOL_GPL(btmrvl_pscan_window_reporting); |
248 | |
249 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) |
250 | { |
251 | int ret; |
252 | u8 param[2]; |
253 | |
254 | param[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; |
255 | param[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); |
256 | |
257 | BT_DBG("Sending HSCFG Command, gpio=0x%x, gap=0x%x" , |
258 | param[0], param[1]); |
259 | |
260 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, len: 2); |
261 | if (ret) |
262 | BT_ERR("HSCFG command failed" ); |
263 | |
264 | return ret; |
265 | } |
266 | EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); |
267 | |
268 | int btmrvl_enable_ps(struct btmrvl_private *priv) |
269 | { |
270 | int ret; |
271 | u8 param; |
272 | |
273 | if (priv->btmrvl_dev.psmode) |
274 | param = BT_PS_ENABLE; |
275 | else |
276 | param = BT_PS_DISABLE; |
277 | |
278 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, param: ¶m, len: 1); |
279 | if (ret) |
280 | BT_ERR("PSMODE command failed" ); |
281 | |
282 | return 0; |
283 | } |
284 | EXPORT_SYMBOL_GPL(btmrvl_enable_ps); |
285 | |
286 | int btmrvl_enable_hs(struct btmrvl_private *priv) |
287 | { |
288 | struct btmrvl_adapter *adapter = priv->adapter; |
289 | int ret; |
290 | |
291 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, len: 0); |
292 | if (ret) { |
293 | BT_ERR("Host sleep enable command failed" ); |
294 | return ret; |
295 | } |
296 | |
297 | ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q, |
298 | adapter->hs_state || |
299 | priv->surprise_removed, |
300 | WAIT_UNTIL_HS_STATE_CHANGED); |
301 | if (ret < 0 || priv->surprise_removed) { |
302 | BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d" , |
303 | ret, adapter->hs_state, adapter->ps_state, |
304 | adapter->wakeup_tries); |
305 | } else if (!ret) { |
306 | BT_ERR("hs_enable timeout: %d,%d,%d" , adapter->hs_state, |
307 | adapter->ps_state, adapter->wakeup_tries); |
308 | ret = -ETIMEDOUT; |
309 | } else { |
310 | BT_DBG("host sleep enabled: %d,%d,%d" , adapter->hs_state, |
311 | adapter->ps_state, adapter->wakeup_tries); |
312 | ret = 0; |
313 | } |
314 | |
315 | return ret; |
316 | } |
317 | EXPORT_SYMBOL_GPL(btmrvl_enable_hs); |
318 | |
319 | int btmrvl_prepare_command(struct btmrvl_private *priv) |
320 | { |
321 | int ret = 0; |
322 | |
323 | if (priv->btmrvl_dev.hscfgcmd) { |
324 | priv->btmrvl_dev.hscfgcmd = 0; |
325 | btmrvl_send_hscfg_cmd(priv); |
326 | } |
327 | |
328 | if (priv->btmrvl_dev.pscmd) { |
329 | priv->btmrvl_dev.pscmd = 0; |
330 | btmrvl_enable_ps(priv); |
331 | } |
332 | |
333 | if (priv->btmrvl_dev.hscmd) { |
334 | priv->btmrvl_dev.hscmd = 0; |
335 | |
336 | if (priv->btmrvl_dev.hsmode) { |
337 | ret = btmrvl_enable_hs(priv); |
338 | } else { |
339 | ret = priv->hw_wakeup_firmware(priv); |
340 | priv->adapter->hs_state = HS_DEACTIVATED; |
341 | BT_DBG("BT: HS DEACTIVATED due to host activity!" ); |
342 | } |
343 | } |
344 | |
345 | return ret; |
346 | } |
347 | |
348 | static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb) |
349 | { |
350 | int ret = 0; |
351 | |
352 | if (!skb || !skb->data) |
353 | return -EINVAL; |
354 | |
355 | if (!skb->len || ((skb->len + BTM_HEADER_LEN) > BTM_UPLD_SIZE)) { |
356 | BT_ERR("Tx Error: Bad skb length %d : %d" , |
357 | skb->len, BTM_UPLD_SIZE); |
358 | return -EINVAL; |
359 | } |
360 | |
361 | skb_push(skb, BTM_HEADER_LEN); |
362 | |
363 | /* header type: byte[3] |
364 | * HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor |
365 | * header length: byte[2][1][0] |
366 | */ |
367 | |
368 | skb->data[0] = (skb->len & 0x0000ff); |
369 | skb->data[1] = (skb->len & 0x00ff00) >> 8; |
370 | skb->data[2] = (skb->len & 0xff0000) >> 16; |
371 | skb->data[3] = hci_skb_pkt_type(skb); |
372 | |
373 | if (priv->hw_host_to_card) |
374 | ret = priv->hw_host_to_card(priv, skb->data, skb->len); |
375 | |
376 | return ret; |
377 | } |
378 | |
379 | static void btmrvl_init_adapter(struct btmrvl_private *priv) |
380 | { |
381 | int buf_size; |
382 | |
383 | skb_queue_head_init(list: &priv->adapter->tx_queue); |
384 | |
385 | priv->adapter->ps_state = PS_AWAKE; |
386 | |
387 | buf_size = ALIGN_SZ(SDIO_BLOCK_SIZE, BTSDIO_DMA_ALIGN); |
388 | priv->adapter->hw_regs_buf = kzalloc(size: buf_size, GFP_KERNEL); |
389 | if (!priv->adapter->hw_regs_buf) { |
390 | priv->adapter->hw_regs = NULL; |
391 | BT_ERR("Unable to allocate buffer for hw_regs." ); |
392 | } else { |
393 | priv->adapter->hw_regs = |
394 | (u8 *)ALIGN_ADDR(priv->adapter->hw_regs_buf, |
395 | BTSDIO_DMA_ALIGN); |
396 | BT_DBG("hw_regs_buf=%p hw_regs=%p" , |
397 | priv->adapter->hw_regs_buf, priv->adapter->hw_regs); |
398 | } |
399 | |
400 | init_waitqueue_head(&priv->adapter->cmd_wait_q); |
401 | init_waitqueue_head(&priv->adapter->event_hs_wait_q); |
402 | } |
403 | |
404 | static void btmrvl_free_adapter(struct btmrvl_private *priv) |
405 | { |
406 | skb_queue_purge(list: &priv->adapter->tx_queue); |
407 | |
408 | kfree(objp: priv->adapter->hw_regs_buf); |
409 | kfree(objp: priv->adapter); |
410 | |
411 | priv->adapter = NULL; |
412 | } |
413 | |
414 | static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
415 | { |
416 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
417 | |
418 | BT_DBG("type=%d, len=%d" , hci_skb_pkt_type(skb), skb->len); |
419 | |
420 | if (priv->adapter->is_suspending || priv->adapter->is_suspended) { |
421 | BT_ERR("%s: Device is suspending or suspended" , __func__); |
422 | return -EBUSY; |
423 | } |
424 | |
425 | switch (hci_skb_pkt_type(skb)) { |
426 | case HCI_COMMAND_PKT: |
427 | hdev->stat.cmd_tx++; |
428 | break; |
429 | |
430 | case HCI_ACLDATA_PKT: |
431 | hdev->stat.acl_tx++; |
432 | break; |
433 | |
434 | case HCI_SCODATA_PKT: |
435 | hdev->stat.sco_tx++; |
436 | break; |
437 | } |
438 | |
439 | skb_queue_tail(list: &priv->adapter->tx_queue, newsk: skb); |
440 | |
441 | if (!priv->adapter->is_suspended) |
442 | wake_up_interruptible(&priv->main_thread.wait_q); |
443 | |
444 | return 0; |
445 | } |
446 | |
447 | static int btmrvl_flush(struct hci_dev *hdev) |
448 | { |
449 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
450 | |
451 | skb_queue_purge(list: &priv->adapter->tx_queue); |
452 | |
453 | return 0; |
454 | } |
455 | |
456 | static int btmrvl_close(struct hci_dev *hdev) |
457 | { |
458 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
459 | |
460 | skb_queue_purge(list: &priv->adapter->tx_queue); |
461 | |
462 | return 0; |
463 | } |
464 | |
465 | static int btmrvl_open(struct hci_dev *hdev) |
466 | { |
467 | return 0; |
468 | } |
469 | |
470 | static int btmrvl_download_cal_data(struct btmrvl_private *priv, |
471 | u8 *data, int len) |
472 | { |
473 | int ret; |
474 | |
475 | data[0] = 0x00; |
476 | data[1] = 0x00; |
477 | data[2] = 0x00; |
478 | data[3] = len; |
479 | |
480 | print_hex_dump_bytes("Calibration data: " , |
481 | DUMP_PREFIX_OFFSET, data, BT_CAL_HDR_LEN + len); |
482 | |
483 | ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, param: data, |
484 | BT_CAL_HDR_LEN + len); |
485 | if (ret) |
486 | BT_ERR("Failed to download calibration data" ); |
487 | |
488 | return 0; |
489 | } |
490 | |
491 | static int btmrvl_check_device_tree(struct btmrvl_private *priv) |
492 | { |
493 | struct device_node *dt_node; |
494 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; |
495 | u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; |
496 | int ret = 0; |
497 | u16 gpio, gap; |
498 | |
499 | if (card->plt_of_node) { |
500 | dt_node = card->plt_of_node; |
501 | ret = of_property_read_u16(np: dt_node, propname: "marvell,wakeup-pin" , |
502 | out_value: &gpio); |
503 | if (ret) |
504 | gpio = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; |
505 | |
506 | ret = of_property_read_u16(np: dt_node, propname: "marvell,wakeup-gap-ms" , |
507 | out_value: &gap); |
508 | if (ret) |
509 | gap = (u8)(priv->btmrvl_dev.gpio_gap & 0x00ff); |
510 | |
511 | priv->btmrvl_dev.gpio_gap = (gpio << 8) + gap; |
512 | |
513 | ret = of_property_read_u8_array(np: dt_node, propname: "marvell,cal-data" , |
514 | out_values: cal_data + BT_CAL_HDR_LEN, |
515 | BT_CAL_DATA_SIZE); |
516 | if (ret) |
517 | return ret; |
518 | |
519 | BT_DBG("Use cal data from device tree" ); |
520 | ret = btmrvl_download_cal_data(priv, data: cal_data, |
521 | BT_CAL_DATA_SIZE); |
522 | if (ret) |
523 | BT_ERR("Fail to download calibrate data" ); |
524 | } |
525 | |
526 | return ret; |
527 | } |
528 | |
529 | static int btmrvl_setup(struct hci_dev *hdev) |
530 | { |
531 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
532 | int ret; |
533 | |
534 | ret = btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ); |
535 | if (ret) |
536 | return ret; |
537 | |
538 | priv->btmrvl_dev.gpio_gap = 0xfffe; |
539 | |
540 | btmrvl_check_device_tree(priv); |
541 | |
542 | btmrvl_enable_sco_routing_to_host(priv); |
543 | |
544 | btmrvl_pscan_window_reporting(priv, 0x01); |
545 | |
546 | priv->btmrvl_dev.psmode = 1; |
547 | btmrvl_enable_ps(priv); |
548 | |
549 | btmrvl_send_hscfg_cmd(priv); |
550 | |
551 | return 0; |
552 | } |
553 | |
554 | static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) |
555 | { |
556 | struct sk_buff *skb; |
557 | long ret; |
558 | u8 buf[8]; |
559 | |
560 | buf[0] = MRVL_VENDOR_PKT; |
561 | buf[1] = sizeof(bdaddr_t); |
562 | memcpy(buf + 2, bdaddr, sizeof(bdaddr_t)); |
563 | |
564 | skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, plen: sizeof(buf), param: buf, |
565 | HCI_INIT_TIMEOUT); |
566 | if (IS_ERR(ptr: skb)) { |
567 | ret = PTR_ERR(ptr: skb); |
568 | BT_ERR("%s: changing btmrvl device address failed (%ld)" , |
569 | hdev->name, ret); |
570 | return ret; |
571 | } |
572 | kfree_skb(skb); |
573 | |
574 | return 0; |
575 | } |
576 | |
577 | static bool btmrvl_wakeup(struct hci_dev *hdev) |
578 | { |
579 | struct btmrvl_private *priv = hci_get_drvdata(hdev); |
580 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; |
581 | |
582 | return device_may_wakeup(dev: &card->func->dev); |
583 | } |
584 | |
585 | /* |
586 | * This function handles the event generated by firmware, rx data |
587 | * received from firmware, and tx data sent from kernel. |
588 | */ |
589 | static int btmrvl_service_main_thread(void *data) |
590 | { |
591 | struct btmrvl_thread *thread = data; |
592 | struct btmrvl_private *priv = thread->priv; |
593 | struct btmrvl_adapter *adapter = priv->adapter; |
594 | wait_queue_entry_t wait; |
595 | struct sk_buff *skb; |
596 | ulong flags; |
597 | |
598 | init_waitqueue_entry(wq_entry: &wait, current); |
599 | |
600 | for (;;) { |
601 | add_wait_queue(wq_head: &thread->wait_q, wq_entry: &wait); |
602 | |
603 | set_current_state(TASK_INTERRUPTIBLE); |
604 | if (kthread_should_stop() || priv->surprise_removed) { |
605 | BT_DBG("main_thread: break from main thread" ); |
606 | break; |
607 | } |
608 | |
609 | if (adapter->wakeup_tries || |
610 | ((!adapter->int_count) && |
611 | (!priv->btmrvl_dev.tx_dnld_rdy || |
612 | skb_queue_empty(list: &adapter->tx_queue)))) { |
613 | BT_DBG("main_thread is sleeping..." ); |
614 | schedule(); |
615 | } |
616 | |
617 | set_current_state(TASK_RUNNING); |
618 | |
619 | remove_wait_queue(wq_head: &thread->wait_q, wq_entry: &wait); |
620 | |
621 | BT_DBG("main_thread woke up" ); |
622 | |
623 | if (kthread_should_stop() || priv->surprise_removed) { |
624 | BT_DBG("main_thread: break from main thread" ); |
625 | break; |
626 | } |
627 | |
628 | spin_lock_irqsave(&priv->driver_lock, flags); |
629 | if (adapter->int_count) { |
630 | adapter->int_count = 0; |
631 | spin_unlock_irqrestore(lock: &priv->driver_lock, flags); |
632 | priv->hw_process_int_status(priv); |
633 | } else if (adapter->ps_state == PS_SLEEP && |
634 | !skb_queue_empty(list: &adapter->tx_queue)) { |
635 | spin_unlock_irqrestore(lock: &priv->driver_lock, flags); |
636 | adapter->wakeup_tries++; |
637 | priv->hw_wakeup_firmware(priv); |
638 | continue; |
639 | } else { |
640 | spin_unlock_irqrestore(lock: &priv->driver_lock, flags); |
641 | } |
642 | |
643 | if (adapter->ps_state == PS_SLEEP) |
644 | continue; |
645 | |
646 | if (!priv->btmrvl_dev.tx_dnld_rdy || |
647 | priv->adapter->is_suspended) |
648 | continue; |
649 | |
650 | skb = skb_dequeue(list: &adapter->tx_queue); |
651 | if (skb) { |
652 | if (btmrvl_tx_pkt(priv, skb)) |
653 | priv->btmrvl_dev.hcidev->stat.err_tx++; |
654 | else |
655 | priv->btmrvl_dev.hcidev->stat.byte_tx += skb->len; |
656 | |
657 | kfree_skb(skb); |
658 | } |
659 | } |
660 | |
661 | return 0; |
662 | } |
663 | |
664 | int btmrvl_register_hdev(struct btmrvl_private *priv) |
665 | { |
666 | struct hci_dev *hdev = NULL; |
667 | struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; |
668 | int ret; |
669 | |
670 | hdev = hci_alloc_dev(); |
671 | if (!hdev) { |
672 | BT_ERR("Can not allocate HCI device" ); |
673 | goto err_hdev; |
674 | } |
675 | |
676 | priv->btmrvl_dev.hcidev = hdev; |
677 | hci_set_drvdata(hdev, data: priv); |
678 | |
679 | hdev->bus = HCI_SDIO; |
680 | hdev->open = btmrvl_open; |
681 | hdev->close = btmrvl_close; |
682 | hdev->flush = btmrvl_flush; |
683 | hdev->send = btmrvl_send_frame; |
684 | hdev->setup = btmrvl_setup; |
685 | hdev->set_bdaddr = btmrvl_set_bdaddr; |
686 | hdev->wakeup = btmrvl_wakeup; |
687 | SET_HCIDEV_DEV(hdev, &card->func->dev); |
688 | |
689 | hdev->dev_type = priv->btmrvl_dev.dev_type; |
690 | |
691 | ret = hci_register_dev(hdev); |
692 | if (ret < 0) { |
693 | BT_ERR("Can not register HCI device" ); |
694 | goto err_hci_register_dev; |
695 | } |
696 | |
697 | #ifdef CONFIG_DEBUG_FS |
698 | btmrvl_debugfs_init(hdev); |
699 | #endif |
700 | |
701 | return 0; |
702 | |
703 | err_hci_register_dev: |
704 | hci_free_dev(hdev); |
705 | |
706 | err_hdev: |
707 | /* Stop the thread servicing the interrupts */ |
708 | kthread_stop(k: priv->main_thread.task); |
709 | |
710 | btmrvl_free_adapter(priv); |
711 | kfree(objp: priv); |
712 | |
713 | return -ENOMEM; |
714 | } |
715 | EXPORT_SYMBOL_GPL(btmrvl_register_hdev); |
716 | |
717 | struct btmrvl_private *btmrvl_add_card(void *card) |
718 | { |
719 | struct btmrvl_private *priv; |
720 | |
721 | priv = kzalloc(size: sizeof(*priv), GFP_KERNEL); |
722 | if (!priv) { |
723 | BT_ERR("Can not allocate priv" ); |
724 | goto err_priv; |
725 | } |
726 | |
727 | priv->adapter = kzalloc(size: sizeof(*priv->adapter), GFP_KERNEL); |
728 | if (!priv->adapter) { |
729 | BT_ERR("Allocate buffer for btmrvl_adapter failed!" ); |
730 | goto err_adapter; |
731 | } |
732 | |
733 | btmrvl_init_adapter(priv); |
734 | |
735 | BT_DBG("Starting kthread..." ); |
736 | priv->main_thread.priv = priv; |
737 | spin_lock_init(&priv->driver_lock); |
738 | |
739 | init_waitqueue_head(&priv->main_thread.wait_q); |
740 | priv->main_thread.task = kthread_run(btmrvl_service_main_thread, |
741 | &priv->main_thread, "btmrvl_main_service" ); |
742 | if (IS_ERR(ptr: priv->main_thread.task)) |
743 | goto err_thread; |
744 | |
745 | priv->btmrvl_dev.card = card; |
746 | priv->btmrvl_dev.tx_dnld_rdy = true; |
747 | |
748 | return priv; |
749 | |
750 | err_thread: |
751 | btmrvl_free_adapter(priv); |
752 | |
753 | err_adapter: |
754 | kfree(objp: priv); |
755 | |
756 | err_priv: |
757 | return NULL; |
758 | } |
759 | EXPORT_SYMBOL_GPL(btmrvl_add_card); |
760 | |
761 | int btmrvl_remove_card(struct btmrvl_private *priv) |
762 | { |
763 | struct hci_dev *hdev; |
764 | |
765 | hdev = priv->btmrvl_dev.hcidev; |
766 | |
767 | wake_up_interruptible(&priv->adapter->cmd_wait_q); |
768 | wake_up_interruptible(&priv->adapter->event_hs_wait_q); |
769 | |
770 | kthread_stop(k: priv->main_thread.task); |
771 | |
772 | #ifdef CONFIG_DEBUG_FS |
773 | btmrvl_debugfs_remove(hdev); |
774 | #endif |
775 | |
776 | hci_unregister_dev(hdev); |
777 | |
778 | hci_free_dev(hdev); |
779 | |
780 | priv->btmrvl_dev.hcidev = NULL; |
781 | |
782 | btmrvl_free_adapter(priv); |
783 | |
784 | kfree(objp: priv); |
785 | |
786 | return 0; |
787 | } |
788 | EXPORT_SYMBOL_GPL(btmrvl_remove_card); |
789 | |
790 | MODULE_AUTHOR("Marvell International Ltd." ); |
791 | MODULE_DESCRIPTION("Marvell Bluetooth driver ver " VERSION); |
792 | MODULE_VERSION(VERSION); |
793 | MODULE_LICENSE("GPL v2" ); |
794 | |