blob: 2ecddcf45eb46b9c5a2f1dc2005869dd589c022b [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * HCI_SMD (HCI Shared Memory Driver) is Qualcomm's Shared memory driver
3 * for the BT HCI protocol.
4 *
5 * Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
8 *
9 * This file is based on drivers/bluetooth/hci_vhci.c
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/skbuff.h>
27#include <net/bluetooth/bluetooth.h>
28#include <net/bluetooth/hci_core.h>
29#include <net/bluetooth/hci.h>
30#include <mach/msm_smd.h>
Bhasker Netid08d9012011-09-05 19:37:54 +053031#include <linux/wakelock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032
Bhasker Netid08d9012011-09-05 19:37:54 +053033#define EVENT_CHANNEL "APPS_RIVA_BT_CMD"
34#define DATA_CHANNEL "APPS_RIVA_BT_ACL"
35#define RX_Q_MONITOR (1) /* 1 milli second */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036
37struct hci_smd_data {
38 struct hci_dev *hdev;
39
40 struct smd_channel *event_channel;
41 struct smd_channel *data_channel;
Bhasker Netid08d9012011-09-05 19:37:54 +053042 struct wake_lock wake_lock_tx;
43 struct wake_lock wake_lock_rx;
44 struct timer_list rx_q_timer;
Ankur Nandwani034ed892011-10-07 11:15:53 -070045 struct tasklet_struct hci_event_task;
46 struct tasklet_struct hci_data_task;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047};
48struct hci_smd_data hs;
49
Bhasker Netid08d9012011-09-05 19:37:54 +053050/* Rx queue monitor timer function */
51static int is_rx_q_empty(unsigned long arg)
52{
53 struct hci_dev *hdev = (struct hci_dev *) arg;
54 struct sk_buff_head *list_ = &hdev->rx_q;
55 struct sk_buff *list = ((struct sk_buff *)list_)->next;
56 BT_DBG("%s Rx timer triggered", hdev->name);
57
58 if (list == (struct sk_buff *)list_) {
59 BT_DBG("%s RX queue empty", hdev->name);
60 return 1;
61 } else{
62 BT_DBG("%s RX queue not empty", hdev->name);
63 return 0;
64 }
65}
66
67static void release_lock(void)
68{
69 struct hci_smd_data *hsmd = &hs;
70 BT_DBG("Releasing Rx Lock");
71 if (is_rx_q_empty((unsigned long)hsmd->hdev) &&
72 wake_lock_active(&hs.wake_lock_rx))
73 wake_unlock(&hs.wake_lock_rx);
74}
75
76/* Rx timer callback function */
77static void schedule_timer(unsigned long arg)
78{
79 struct hci_dev *hdev = (struct hci_dev *) arg;
80 struct hci_smd_data *hsmd = &hs;
81 BT_DBG("%s Schedule Rx timer", hdev->name);
82
83 if (is_rx_q_empty(arg) && wake_lock_active(&hs.wake_lock_rx)) {
84 BT_DBG("%s RX queue empty", hdev->name);
85 /*
86 * Since the queue is empty, its ideal
87 * to release the wake lock on Rx
88 */
89 wake_unlock(&hs.wake_lock_rx);
90 } else{
91 BT_DBG("%s RX queue not empty", hdev->name);
92 /*
93 * Restart the timer to monitor whether the Rx queue is
94 * empty for releasing the Rx wake lock
95 */
96 mod_timer(&hsmd->rx_q_timer,
97 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
98 }
99}
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101static int hci_smd_open(struct hci_dev *hdev)
102{
103 set_bit(HCI_RUNNING, &hdev->flags);
104 return 0;
105}
106
107
108static int hci_smd_close(struct hci_dev *hdev)
109{
110 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
111 return 0;
112 else
113 return -EPERM;
114}
115
116
117static void hci_smd_destruct(struct hci_dev *hdev)
118{
119 kfree(hdev->driver_data);
120}
121
122static void hci_smd_recv_data(unsigned long arg)
123{
Bhasker Netid08d9012011-09-05 19:37:54 +0530124 int len = 0;
125 int rc = 0;
126 struct sk_buff *skb = NULL;
127 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700128 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530129 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130
131 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530132 if (len <= 0) {
133 BT_ERR("Nothing to read from SMD channel\n");
134 goto out_data;
135 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136 while (len > 0) {
Ankur Nandwanic8150962011-08-24 13:06:23 -0700137 skb = bt_skb_alloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138 if (!skb) {
139 BT_ERR("Error in allocating socket buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530140 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 }
142
Ankur Nandwanic8150962011-08-24 13:06:23 -0700143 buf = kmalloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 if (!buf) {
145 BT_ERR("Error in allocating buffer\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530146 rc = -ENOMEM;
147 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 }
149
Ankur Nandwani531333f2011-10-25 15:47:43 -0700150 rc = smd_read(hsmd->data_channel, (void *)buf, len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151 if (rc < len) {
152 BT_ERR("Error in reading from the channel");
Bhasker Netid08d9012011-09-05 19:37:54 +0530153 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154 }
155
156 memcpy(skb_put(skb, len), buf, len);
157 skb->dev = (void *)hsmd->hdev;
158 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
159
160 skb_orphan(skb);
161
162 rc = hci_recv_frame(skb);
163 if (rc < 0) {
164 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Neti44a792b2011-10-11 19:25:22 +0530165 /*
166 * skb is getting freed in hci_recv_frame, making it
167 * to null to avoid multiple access
168 */
169 skb = NULL;
Bhasker Netid08d9012011-09-05 19:37:54 +0530170 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700171 }
172
173 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530174 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175 len = smd_read_avail(hsmd->data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530176 /*
177 * Start the timer to monitor whether the Rx queue is
178 * empty for releasing the Rx wake lock
179 */
180 BT_DBG("Rx Timer is starting\n");
181 mod_timer(&hsmd->rx_q_timer,
182 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
183 }
184out_data:
185 release_lock();
186 if (rc) {
187 if (skb)
188 kfree_skb(skb);
189 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700190 }
191}
192
193static void hci_smd_recv_event(unsigned long arg)
194{
Bhasker Netid08d9012011-09-05 19:37:54 +0530195 int len = 0;
196 int rc = 0;
197 struct sk_buff *skb = NULL;
198 unsigned char *buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530200 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201
202 len = smd_read_avail(hsmd->event_channel);
203 if (len > HCI_MAX_FRAME_SIZE) {
204 BT_ERR("Frame larger than the allowed size");
Bhasker Netid08d9012011-09-05 19:37:54 +0530205 goto out_event;
206 } else if (len <= 0) {
207 BT_ERR("Nothing to read from SMD channel\n");
208 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209 }
210
211 while (len > 0) {
Ankur Nandwanic8150962011-08-24 13:06:23 -0700212 skb = bt_skb_alloc(len, GFP_ATOMIC);
Bhasker Netid08d9012011-09-05 19:37:54 +0530213 if (!skb) {
214 BT_ERR("Error in allocating socket buffer\n");
215 goto out_event;
216 }
Ankur Nandwanic8150962011-08-24 13:06:23 -0700217 buf = kmalloc(len, GFP_ATOMIC);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218 if (!buf) {
Bhasker Netid08d9012011-09-05 19:37:54 +0530219 BT_ERR("Error in allocating buffer\n");
220 rc = -ENOMEM;
221 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 }
Ankur Nandwani531333f2011-10-25 15:47:43 -0700223 rc = smd_read(hsmd->event_channel, (void *)buf, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530224 if (rc < len) {
225 BT_ERR("Error in reading from the event channel");
226 goto out_event;
227 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228
229 memcpy(skb_put(skb, len), buf, len);
230 skb->dev = (void *)hsmd->hdev;
231 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
232
233 skb_orphan(skb);
234
235 rc = hci_recv_frame(skb);
236 if (rc < 0) {
237 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Neti44a792b2011-10-11 19:25:22 +0530238 /*
239 * skb is getting freed in hci_recv_frame, making it
240 * to null to avoid multiple access
241 */
242 skb = NULL;
Bhasker Netid08d9012011-09-05 19:37:54 +0530243 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700244 }
245
246 kfree(buf);
Bhasker Netid08d9012011-09-05 19:37:54 +0530247 buf = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700248 len = smd_read_avail(hsmd->event_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530249 /*
250 * Start the timer to monitor whether the Rx queue is
251 * empty for releasing the Rx wake lock
252 */
253 BT_DBG("Rx Timer is starting\n");
254 mod_timer(&hsmd->rx_q_timer,
255 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
256 }
257out_event:
258 release_lock();
259 if (rc) {
260 if (skb)
261 kfree_skb(skb);
262 kfree(buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 }
264}
265
266static int hci_smd_send_frame(struct sk_buff *skb)
267{
268 int len;
Bhasker Netid08d9012011-09-05 19:37:54 +0530269 int avail;
270 int ret = 0;
271 wake_lock(&hs.wake_lock_tx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272
273 switch (bt_cb(skb)->pkt_type) {
274 case HCI_COMMAND_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530275 avail = smd_write_avail(hs.event_channel);
276 if (!avail) {
277 BT_ERR("No space available for smd frame");
278 ret = -ENOSPC;
279 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700280 len = smd_write(hs.event_channel, skb->data, skb->len);
281 if (len < skb->len) {
282 BT_ERR("Failed to write Command %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530283 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700284 }
285 break;
286 case HCI_ACLDATA_PKT:
287 case HCI_SCODATA_PKT:
Ankur Nandwani23abeb22011-10-26 16:35:22 -0700288 avail = smd_write_avail(hs.data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530289 if (!avail) {
290 BT_ERR("No space available for smd frame");
291 ret = -ENOSPC;
292 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 len = smd_write(hs.data_channel, skb->data, skb->len);
294 if (len < skb->len) {
295 BT_ERR("Failed to write Data %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530296 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297 }
298 break;
299 default:
300 BT_ERR("Uknown packet type\n");
Bhasker Netid08d9012011-09-05 19:37:54 +0530301 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700302 break;
303 }
Bhasker Netid08d9012011-09-05 19:37:54 +0530304
Anubhav Guptaddf48ec2011-10-03 14:24:13 +0530305 kfree_skb(skb);
Bhasker Netid08d9012011-09-05 19:37:54 +0530306 wake_unlock(&hs.wake_lock_tx);
307 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308}
309
310
311static void hci_smd_notify_event(void *data, unsigned int event)
312{
313 struct hci_dev *hdev = hs.hdev;
314
315 if (!hdev) {
316 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
317 return;
318 }
319
320 switch (event) {
321 case SMD_EVENT_DATA:
Ankur Nandwani034ed892011-10-07 11:15:53 -0700322 tasklet_hi_schedule(&hs.hci_event_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700323 break;
324 case SMD_EVENT_OPEN:
325 hci_smd_open(hdev);
326 break;
327 case SMD_EVENT_CLOSE:
328 hci_smd_close(hdev);
329 break;
330 default:
331 break;
332 }
333}
334
335static void hci_smd_notify_data(void *data, unsigned int event)
336{
337 struct hci_dev *hdev = hs.hdev;
338 if (!hdev) {
339 BT_ERR("HCI device (hdev=NULL)");
340 return;
341 }
342
343 switch (event) {
344 case SMD_EVENT_DATA:
Ankur Nandwani034ed892011-10-07 11:15:53 -0700345 tasklet_hi_schedule(&hs.hci_data_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700346 break;
347 case SMD_EVENT_OPEN:
348 hci_smd_open(hdev);
349 break;
350 case SMD_EVENT_CLOSE:
351 hci_smd_close(hdev);
352 break;
353 default:
354 break;
355 }
356
357}
358
359static int hci_smd_register_dev(struct hci_smd_data *hsmd)
360{
361 struct hci_dev *hdev;
362 int rc;
363
364 /* Initialize and register HCI device */
365 hdev = hci_alloc_dev();
366 if (!hdev) {
367 BT_ERR("Can't allocate HCI device");
368 return -ENOMEM;
369 }
370
371 hsmd->hdev = hdev;
372 hdev->bus = HCI_SMD;
373 hdev->driver_data = hsmd;
374 hdev->open = hci_smd_open;
375 hdev->close = hci_smd_close;
376 hdev->send = hci_smd_send_frame;
377 hdev->destruct = hci_smd_destruct;
378 hdev->owner = THIS_MODULE;
379
Ankur Nandwani034ed892011-10-07 11:15:53 -0700380 tasklet_init(&hsmd->hci_event_task,
381 hci_smd_recv_event, (unsigned long) hsmd);
382 tasklet_init(&hsmd->hci_data_task,
383 hci_smd_recv_data, (unsigned long) hsmd);
384
Bhasker Netid08d9012011-09-05 19:37:54 +0530385 wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND, "msm_smd_Rx");
386 wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND, "msm_smd_Tx");
387 /*
388 * Setup the timer to monitor whether the Rx queue is empty,
389 * to control the wake lock release
390 */
391 setup_timer(&hsmd->rx_q_timer, schedule_timer,
392 (unsigned long) hsmd->hdev);
393
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700394 /* Open the SMD Channel and device and register the callback function */
395 rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
396 &hsmd->event_channel, hdev, hci_smd_notify_event);
397 if (rc < 0) {
398 BT_ERR("Cannot open the command channel");
399 hci_free_dev(hdev);
400 return -ENODEV;
401 }
402
403 rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
404 &hsmd->data_channel, hdev, hci_smd_notify_data);
405 if (rc < 0) {
406 BT_ERR("Failed to open the Data channel\n");
407 hci_free_dev(hdev);
408 return -ENODEV;
409 }
410
411 /* Disable the read interrupts on the channel */
412 smd_disable_read_intr(hsmd->event_channel);
413 smd_disable_read_intr(hsmd->data_channel);
414
415 if (hci_register_dev(hdev) < 0) {
416 BT_ERR("Can't register HCI device");
417 hci_free_dev(hdev);
418 return -ENODEV;
419 }
420
421 return 0;
422}
423
424static void hci_smd_deregister(void)
425{
426 smd_close(hs.event_channel);
427 hs.event_channel = 0;
428 smd_close(hs.data_channel);
429 hs.data_channel = 0;
Bhasker Netid08d9012011-09-05 19:37:54 +0530430 wake_lock_destroy(&hs.wake_lock_rx);
431 wake_lock_destroy(&hs.wake_lock_tx);
432
433 /*Destroy the timer used to monitor the Rx queue for emptiness */
434 del_timer_sync(&hs.rx_q_timer);
Ankur Nandwani034ed892011-10-07 11:15:53 -0700435 tasklet_kill(&hs.hci_event_task);
436 tasklet_kill(&hs.hci_data_task);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700437}
438
439static int hci_smd_init(void)
440{
441 return hci_smd_register_dev(&hs);
442}
443module_init(hci_smd_init);
444
445static void __exit hci_smd_exit(void)
446{
447 hci_smd_deregister();
448}
449module_exit(hci_smd_exit);
450
451MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
452MODULE_DESCRIPTION("Bluetooth SMD driver");
453MODULE_LICENSE("GPL v2");