blob: dbd1bd4fb9fd5dd87df13ee51c7c190fe2313567 [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 *
Bhasker Netiaae61462012-01-12 19:14:25 +05305 * Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 * 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>
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070027#include <linux/wakelock.h>
28#include <linux/uaccess.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#include <net/bluetooth/bluetooth.h>
30#include <net/bluetooth/hci_core.h>
31#include <net/bluetooth/hci.h>
32#include <mach/msm_smd.h>
33
Bhasker Netid08d9012011-09-05 19:37:54 +053034#define EVENT_CHANNEL "APPS_RIVA_BT_CMD"
35#define DATA_CHANNEL "APPS_RIVA_BT_ACL"
Mallikarjuna GB215561d2012-01-23 13:20:38 +053036/* release wakelock in 500ms, not immediately, because higher layers
37 * don't always take wakelocks when they should
38 * This is derived from the implementation for UART transport
39 */
40
41#define RX_Q_MONITOR (500) /* 500 milli second */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070043
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070044static int hcismd_set;
45static DEFINE_MUTEX(hci_smd_enable);
46
47static int hcismd_set_enable(const char *val, struct kernel_param *kp);
48module_param_call(hcismd_set, hcismd_set_enable, NULL, &hcismd_set, 0644);
49
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051struct hci_smd_data {
52 struct hci_dev *hdev;
53
54 struct smd_channel *event_channel;
55 struct smd_channel *data_channel;
Bhasker Netid08d9012011-09-05 19:37:54 +053056 struct wake_lock wake_lock_tx;
57 struct wake_lock wake_lock_rx;
58 struct timer_list rx_q_timer;
Bhasker Netiaae61462012-01-12 19:14:25 +053059 struct tasklet_struct rx_task;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060};
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070061static struct hci_smd_data hs;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070062
Bhasker Netid08d9012011-09-05 19:37:54 +053063/* Rx queue monitor timer function */
64static int is_rx_q_empty(unsigned long arg)
65{
66 struct hci_dev *hdev = (struct hci_dev *) arg;
67 struct sk_buff_head *list_ = &hdev->rx_q;
68 struct sk_buff *list = ((struct sk_buff *)list_)->next;
69 BT_DBG("%s Rx timer triggered", hdev->name);
70
71 if (list == (struct sk_buff *)list_) {
72 BT_DBG("%s RX queue empty", hdev->name);
73 return 1;
74 } else{
75 BT_DBG("%s RX queue not empty", hdev->name);
76 return 0;
77 }
78}
79
80static void release_lock(void)
81{
82 struct hci_smd_data *hsmd = &hs;
83 BT_DBG("Releasing Rx Lock");
84 if (is_rx_q_empty((unsigned long)hsmd->hdev) &&
85 wake_lock_active(&hs.wake_lock_rx))
86 wake_unlock(&hs.wake_lock_rx);
87}
88
89/* Rx timer callback function */
90static void schedule_timer(unsigned long arg)
91{
92 struct hci_dev *hdev = (struct hci_dev *) arg;
93 struct hci_smd_data *hsmd = &hs;
94 BT_DBG("%s Schedule Rx timer", hdev->name);
95
96 if (is_rx_q_empty(arg) && wake_lock_active(&hs.wake_lock_rx)) {
97 BT_DBG("%s RX queue empty", hdev->name);
98 /*
99 * Since the queue is empty, its ideal
100 * to release the wake lock on Rx
101 */
102 wake_unlock(&hs.wake_lock_rx);
103 } else{
104 BT_DBG("%s RX queue not empty", hdev->name);
105 /*
106 * Restart the timer to monitor whether the Rx queue is
107 * empty for releasing the Rx wake lock
108 */
109 mod_timer(&hsmd->rx_q_timer,
110 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
111 }
112}
113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114static int hci_smd_open(struct hci_dev *hdev)
115{
116 set_bit(HCI_RUNNING, &hdev->flags);
117 return 0;
118}
119
120
121static int hci_smd_close(struct hci_dev *hdev)
122{
123 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
124 return 0;
125 else
126 return -EPERM;
127}
128
129
130static void hci_smd_destruct(struct hci_dev *hdev)
131{
Bhasker Neti60576c62011-12-07 18:45:51 -0800132 if (NULL != hdev->driver_data)
133 kfree(hdev->driver_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134}
135
Bhasker Netiaae61462012-01-12 19:14:25 +0530136static void hci_smd_recv_data(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137{
Bhasker Netid08d9012011-09-05 19:37:54 +0530138 int len = 0;
139 int rc = 0;
140 struct sk_buff *skb = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530142 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143
144 len = smd_read_avail(hsmd->data_channel);
Bhasker Neti60734c02011-11-23 15:17:54 -0800145 if (len > HCI_MAX_FRAME_SIZE) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530146 BT_ERR("Frame larger than the allowed size, flushing frame");
147 smd_read(hsmd->data_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530148 goto out_data;
149 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150
Bhasker Netiaae61462012-01-12 19:14:25 +0530151 if (len <= 0)
152 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153
Bhasker Netiaae61462012-01-12 19:14:25 +0530154 skb = bt_skb_alloc(len, GFP_ATOMIC);
155 if (!skb) {
156 BT_ERR("Error in allocating socket buffer");
157 smd_read(hsmd->data_channel, NULL, len);
158 goto out_data;
Bhasker Netid08d9012011-09-05 19:37:54 +0530159 }
Bhasker Netiaae61462012-01-12 19:14:25 +0530160
161 rc = smd_read(hsmd->data_channel, skb_put(skb, len), len);
162 if (rc < len) {
163 BT_ERR("Error in reading from the channel");
164 goto out_data;
165 }
166
167 skb->dev = (void *)hsmd->hdev;
168 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
169 skb_orphan(skb);
170
171 rc = hci_recv_frame(skb);
172 if (rc < 0) {
173 BT_ERR("Error in passing the packet to HCI Layer");
174 /*
175 * skb is getting freed in hci_recv_frame, making it
176 * to null to avoid multiple access
177 */
178 skb = NULL;
179 goto out_data;
180 }
181
182 /*
183 * Start the timer to monitor whether the Rx queue is
184 * empty for releasing the Rx wake lock
185 */
186 BT_DBG("Rx Timer is starting");
187 mod_timer(&hsmd->rx_q_timer,
188 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
189
Bhasker Netid08d9012011-09-05 19:37:54 +0530190out_data:
191 release_lock();
Bhasker Netiaae61462012-01-12 19:14:25 +0530192 if (rc)
193 kfree_skb(skb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194}
195
Bhasker Netiaae61462012-01-12 19:14:25 +0530196static void hci_smd_recv_event(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197{
Bhasker Netid08d9012011-09-05 19:37:54 +0530198 int len = 0;
199 int rc = 0;
200 struct sk_buff *skb = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530202 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700203
204 len = smd_read_avail(hsmd->event_channel);
205 if (len > HCI_MAX_FRAME_SIZE) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530206 BT_ERR("Frame larger than the allowed size, flushing frame");
207 rc = smd_read(hsmd->event_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530208 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) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530214 BT_ERR("Error in allocating socket buffer");
215 smd_read(hsmd->event_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530216 goto out_event;
217 }
Bhasker Netiaae61462012-01-12 19:14:25 +0530218
219 rc = smd_read(hsmd->event_channel, skb_put(skb, len), len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530220 if (rc < len) {
221 BT_ERR("Error in reading from the event channel");
222 goto out_event;
223 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 skb->dev = (void *)hsmd->hdev;
226 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
227
228 skb_orphan(skb);
229
230 rc = hci_recv_frame(skb);
231 if (rc < 0) {
232 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Neti44a792b2011-10-11 19:25:22 +0530233 /*
234 * skb is getting freed in hci_recv_frame, making it
235 * to null to avoid multiple access
236 */
237 skb = NULL;
Bhasker Netid08d9012011-09-05 19:37:54 +0530238 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700239 }
240
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241 len = smd_read_avail(hsmd->event_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530242 /*
243 * Start the timer to monitor whether the Rx queue is
244 * empty for releasing the Rx wake lock
245 */
Bhasker Neti60734c02011-11-23 15:17:54 -0800246 BT_DBG("Rx Timer is starting");
Bhasker Netid08d9012011-09-05 19:37:54 +0530247 mod_timer(&hsmd->rx_q_timer,
248 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
249 }
250out_event:
251 release_lock();
Bhasker Netiaae61462012-01-12 19:14:25 +0530252 if (rc)
253 kfree_skb(skb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254}
255
256static int hci_smd_send_frame(struct sk_buff *skb)
257{
258 int len;
Bhasker Netid08d9012011-09-05 19:37:54 +0530259 int avail;
260 int ret = 0;
261 wake_lock(&hs.wake_lock_tx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262
263 switch (bt_cb(skb)->pkt_type) {
264 case HCI_COMMAND_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530265 avail = smd_write_avail(hs.event_channel);
266 if (!avail) {
267 BT_ERR("No space available for smd frame");
268 ret = -ENOSPC;
269 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270 len = smd_write(hs.event_channel, skb->data, skb->len);
271 if (len < skb->len) {
272 BT_ERR("Failed to write Command %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530273 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 }
275 break;
276 case HCI_ACLDATA_PKT:
277 case HCI_SCODATA_PKT:
Ankur Nandwani23abeb22011-10-26 16:35:22 -0700278 avail = smd_write_avail(hs.data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530279 if (!avail) {
280 BT_ERR("No space available for smd frame");
281 ret = -ENOSPC;
282 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 len = smd_write(hs.data_channel, skb->data, skb->len);
284 if (len < skb->len) {
285 BT_ERR("Failed to write Data %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530286 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 }
288 break;
289 default:
Bhasker Neti60734c02011-11-23 15:17:54 -0800290 BT_ERR("Uknown packet type");
Bhasker Netid08d9012011-09-05 19:37:54 +0530291 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292 break;
293 }
Bhasker Netid08d9012011-09-05 19:37:54 +0530294
Anubhav Guptaddf48ec2011-10-03 14:24:13 +0530295 kfree_skb(skb);
Bhasker Netid08d9012011-09-05 19:37:54 +0530296 wake_unlock(&hs.wake_lock_tx);
297 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298}
299
Bhasker Netiaae61462012-01-12 19:14:25 +0530300static void hci_smd_rx(unsigned long arg)
301{
302 struct hci_smd_data *hsmd = &hs;
303
304 while ((smd_read_avail(hsmd->event_channel) > 0) ||
305 (smd_read_avail(hsmd->data_channel) > 0)) {
306 hci_smd_recv_event();
307 hci_smd_recv_data();
308 }
309}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700310
311static void hci_smd_notify_event(void *data, unsigned int event)
312{
313 struct hci_dev *hdev = hs.hdev;
Bhasker Neti60734c02011-11-23 15:17:54 -0800314 struct hci_smd_data *hsmd = &hs;
315 int len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700316
317 if (!hdev) {
318 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
319 return;
320 }
321
322 switch (event) {
323 case SMD_EVENT_DATA:
Bhasker Neti60734c02011-11-23 15:17:54 -0800324 len = smd_read_avail(hsmd->event_channel);
325 if (len > 0)
Bhasker Netiaae61462012-01-12 19:14:25 +0530326 tasklet_hi_schedule(&hs.rx_task);
Bhasker Neti60734c02011-11-23 15:17:54 -0800327 else if (len < 0)
328 BT_ERR("Failed to read event from smd %d", len);
329
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700330 break;
331 case SMD_EVENT_OPEN:
Bhasker Neti60734c02011-11-23 15:17:54 -0800332 BT_INFO("opening HCI-SMD channel :%s", EVENT_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333 hci_smd_open(hdev);
334 break;
335 case SMD_EVENT_CLOSE:
Bhasker Neti60734c02011-11-23 15:17:54 -0800336 BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 hci_smd_close(hdev);
338 break;
339 default:
340 break;
341 }
342}
343
344static void hci_smd_notify_data(void *data, unsigned int event)
345{
346 struct hci_dev *hdev = hs.hdev;
Bhasker Neti60734c02011-11-23 15:17:54 -0800347 struct hci_smd_data *hsmd = &hs;
348 int len = 0;
349
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700350 if (!hdev) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530351 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 return;
353 }
354
355 switch (event) {
356 case SMD_EVENT_DATA:
Bhasker Neti60734c02011-11-23 15:17:54 -0800357 len = smd_read_avail(hsmd->data_channel);
358 if (len > 0)
Bhasker Netiaae61462012-01-12 19:14:25 +0530359 tasklet_hi_schedule(&hs.rx_task);
Bhasker Neti60734c02011-11-23 15:17:54 -0800360 else if (len < 0)
361 BT_ERR("Failed to read data from smd %d", len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700362 break;
363 case SMD_EVENT_OPEN:
Bhasker Neti60734c02011-11-23 15:17:54 -0800364 BT_INFO("opening HCI-SMD channel :%s", DATA_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 hci_smd_open(hdev);
366 break;
367 case SMD_EVENT_CLOSE:
Bhasker Neti60734c02011-11-23 15:17:54 -0800368 BT_INFO("Closing HCI-SMD channel :%s", DATA_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 hci_smd_close(hdev);
370 break;
371 default:
372 break;
373 }
374
375}
376
377static int hci_smd_register_dev(struct hci_smd_data *hsmd)
378{
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700379 static struct hci_dev *hdev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380 int rc;
381
382 /* Initialize and register HCI device */
Bhasker Neti60576c62011-12-07 18:45:51 -0800383 hdev = hci_alloc_dev();
384 if (!hdev) {
385 BT_ERR("Can't allocate HCI device");
386 return -ENOMEM;
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700387 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700388
Bhasker Neti60576c62011-12-07 18:45:51 -0800389 hsmd->hdev = hdev;
390 hdev->bus = HCI_SMD;
391 hdev->driver_data = NULL;
392 hdev->open = hci_smd_open;
393 hdev->close = hci_smd_close;
394 hdev->send = hci_smd_send_frame;
395 hdev->destruct = hci_smd_destruct;
396 hdev->owner = THIS_MODULE;
397
Bhasker Netiaae61462012-01-12 19:14:25 +0530398
399 tasklet_init(&hsmd->rx_task,
400 hci_smd_rx, (unsigned long) hsmd);
Bhasker Netid08d9012011-09-05 19:37:54 +0530401 /*
402 * Setup the timer to monitor whether the Rx queue is empty,
403 * to control the wake lock release
404 */
405 setup_timer(&hsmd->rx_q_timer, schedule_timer,
406 (unsigned long) hsmd->hdev);
407
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700408 /* Open the SMD Channel and device and register the callback function */
409 rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
410 &hsmd->event_channel, hdev, hci_smd_notify_event);
411 if (rc < 0) {
412 BT_ERR("Cannot open the command channel");
413 hci_free_dev(hdev);
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530414 hdev = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415 return -ENODEV;
416 }
417
418 rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
419 &hsmd->data_channel, hdev, hci_smd_notify_data);
420 if (rc < 0) {
Bhasker Neti60734c02011-11-23 15:17:54 -0800421 BT_ERR("Failed to open the Data channel");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 hci_free_dev(hdev);
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530423 hdev = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 return -ENODEV;
425 }
426
427 /* Disable the read interrupts on the channel */
428 smd_disable_read_intr(hsmd->event_channel);
429 smd_disable_read_intr(hsmd->data_channel);
Bhasker Neti60576c62011-12-07 18:45:51 -0800430 if (hci_register_dev(hdev) < 0) {
431 BT_ERR("Can't register HCI device");
432 hci_free_dev(hdev);
433 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700435 return 0;
436}
437
Bhasker Neti60576c62011-12-07 18:45:51 -0800438static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439{
Bhasker Netiaae61462012-01-12 19:14:25 +0530440 tasklet_kill(&hs.rx_task);
441
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530442 if (hsmd->hdev) {
443 if (hci_unregister_dev(hsmd->hdev) < 0)
444 BT_ERR("Can't unregister HCI device %s",
445 hsmd->hdev->name);
446
447 hci_free_dev(hsmd->hdev);
448 hsmd->hdev = NULL;
449 }
450
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 smd_close(hs.event_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452 smd_close(hs.data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530453
Ankur Nandwani327e0502011-11-11 15:47:25 -0800454 if (wake_lock_active(&hs.wake_lock_rx))
455 wake_unlock(&hs.wake_lock_rx);
Bhasker Neti60576c62011-12-07 18:45:51 -0800456 if (wake_lock_active(&hs.wake_lock_tx))
457 wake_unlock(&hs.wake_lock_tx);
Ankur Nandwani327e0502011-11-11 15:47:25 -0800458
Bhasker Netid08d9012011-09-05 19:37:54 +0530459 /*Destroy the timer used to monitor the Rx queue for emptiness */
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530460 if (hs.rx_q_timer.function) {
461 del_timer_sync(&hs.rx_q_timer);
462 hs.rx_q_timer.function = NULL;
463 hs.rx_q_timer.data = 0;
464 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465}
466
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700467static int hcismd_set_enable(const char *val, struct kernel_param *kp)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468{
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700469 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700470
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700471 mutex_lock(&hci_smd_enable);
472
473 ret = param_set_int(val, kp);
474
475 if (ret)
476 goto done;
477
478 switch (hcismd_set) {
479
480 case 1:
481 hci_smd_register_dev(&hs);
482 break;
483 case 0:
Bhasker Neti60576c62011-12-07 18:45:51 -0800484 hci_smd_deregister_dev(&hs);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700485 break;
486 default:
487 ret = -EFAULT;
488 }
489
490done:
491 mutex_unlock(&hci_smd_enable);
492 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493}
Bhasker Neti60576c62011-12-07 18:45:51 -0800494static int __init hci_smd_init(void)
495{
496 wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND,
497 "msm_smd_Rx");
498 wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
499 "msm_smd_Tx");
500 return 0;
501}
502module_init(hci_smd_init);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700503
Bhasker Neti60576c62011-12-07 18:45:51 -0800504static void __exit hci_smd_exit(void)
505{
506 wake_lock_destroy(&hs.wake_lock_rx);
507 wake_lock_destroy(&hs.wake_lock_tx);
508}
509module_exit(hci_smd_exit);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700510
511MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
512MODULE_DESCRIPTION("Bluetooth SMD driver");
513MODULE_LICENSE("GPL v2");