blob: 90e7263d9089aa60f85ea30ea9e40ad1b15f38d5 [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 *
Duy Truong790f06d2013-02-13 16:38:12 -08005 * Copyright (c) 2000-2001, 2011-2012 The Linux Foundation. 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>
Sunny Kapdi2a39b802012-05-30 12:47:14 -070025#include <linux/semaphore.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#include <linux/string.h>
27#include <linux/skbuff.h>
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070028#include <linux/wakelock.h>
Sunny Kapdi02eab142012-02-01 13:52:27 -080029#include <linux/workqueue.h>
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070030#include <linux/uaccess.h>
Steve Mucklef132c6c2012-06-06 18:30:57 -070031#include <linux/interrupt.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032#include <net/bluetooth/bluetooth.h>
33#include <net/bluetooth/hci_core.h>
34#include <net/bluetooth/hci.h>
35#include <mach/msm_smd.h>
36
Bhasker Netid08d9012011-09-05 19:37:54 +053037#define EVENT_CHANNEL "APPS_RIVA_BT_CMD"
38#define DATA_CHANNEL "APPS_RIVA_BT_ACL"
Mallikarjuna GB215561d2012-01-23 13:20:38 +053039/* release wakelock in 500ms, not immediately, because higher layers
40 * don't always take wakelocks when they should
41 * This is derived from the implementation for UART transport
42 */
43
44#define RX_Q_MONITOR (500) /* 500 milli second */
Bhasker Neti6d353ee2012-07-04 19:24:23 +053045#define HCI_REGISTER_SET 0
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046
Bhasker Netib54b0b72012-12-05 13:58:17 +053047/* SSR state machine to take care of back to back SSR requests
48 * and handling the incomming BT on/off,Airplane mode toggling and
49 * also spuriour SMD open notification while one SSr is in progress
50 */
51#define STATE_SSR_ON 0x1
52#define STATE_SSR_START 0x02
53#define STATE_SSR_CHANNEL_OPEN_PENDING 0x04
54#define STATE_SSR_PENDING_INIT 0x08
55#define STATE_SSR_COMPLETE 0x00
56#define STATE_SSR_OFF STATE_SSR_COMPLETE
57
58static int ssr_state = STATE_SSR_OFF;
59
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070060
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070061static int hcismd_set;
Sunny Kapdi2a39b802012-05-30 12:47:14 -070062static DEFINE_SEMAPHORE(hci_smd_enable);
63
64static int restart_in_progress;
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070065
66static int hcismd_set_enable(const char *val, struct kernel_param *kp);
67module_param_call(hcismd_set, hcismd_set_enable, NULL, &hcismd_set, 0644);
68
Sunny Kapdid71fbed2012-03-15 18:20:55 -070069static void hci_dev_smd_open(struct work_struct *worker);
Sunny Kapdi02eab142012-02-01 13:52:27 -080070static void hci_dev_restart(struct work_struct *worker);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070071
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072struct hci_smd_data {
73 struct hci_dev *hdev;
Bhasker Neti6d353ee2012-07-04 19:24:23 +053074 unsigned long flags;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075 struct smd_channel *event_channel;
76 struct smd_channel *data_channel;
Bhasker Netid08d9012011-09-05 19:37:54 +053077 struct wake_lock wake_lock_tx;
78 struct wake_lock wake_lock_rx;
79 struct timer_list rx_q_timer;
Bhasker Netiaae61462012-01-12 19:14:25 +053080 struct tasklet_struct rx_task;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081};
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -070082static struct hci_smd_data hs;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083
Bhasker Netid08d9012011-09-05 19:37:54 +053084/* Rx queue monitor timer function */
85static int is_rx_q_empty(unsigned long arg)
86{
87 struct hci_dev *hdev = (struct hci_dev *) arg;
88 struct sk_buff_head *list_ = &hdev->rx_q;
89 struct sk_buff *list = ((struct sk_buff *)list_)->next;
90 BT_DBG("%s Rx timer triggered", hdev->name);
91
92 if (list == (struct sk_buff *)list_) {
93 BT_DBG("%s RX queue empty", hdev->name);
94 return 1;
95 } else{
96 BT_DBG("%s RX queue not empty", hdev->name);
97 return 0;
98 }
99}
100
101static void release_lock(void)
102{
103 struct hci_smd_data *hsmd = &hs;
104 BT_DBG("Releasing Rx Lock");
105 if (is_rx_q_empty((unsigned long)hsmd->hdev) &&
106 wake_lock_active(&hs.wake_lock_rx))
107 wake_unlock(&hs.wake_lock_rx);
108}
109
110/* Rx timer callback function */
111static void schedule_timer(unsigned long arg)
112{
113 struct hci_dev *hdev = (struct hci_dev *) arg;
114 struct hci_smd_data *hsmd = &hs;
115 BT_DBG("%s Schedule Rx timer", hdev->name);
116
117 if (is_rx_q_empty(arg) && wake_lock_active(&hs.wake_lock_rx)) {
118 BT_DBG("%s RX queue empty", hdev->name);
119 /*
120 * Since the queue is empty, its ideal
121 * to release the wake lock on Rx
122 */
123 wake_unlock(&hs.wake_lock_rx);
124 } else{
125 BT_DBG("%s RX queue not empty", hdev->name);
126 /*
127 * Restart the timer to monitor whether the Rx queue is
128 * empty for releasing the Rx wake lock
129 */
130 mod_timer(&hsmd->rx_q_timer,
131 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
132 }
133}
134
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135static int hci_smd_open(struct hci_dev *hdev)
136{
137 set_bit(HCI_RUNNING, &hdev->flags);
138 return 0;
139}
140
141
142static int hci_smd_close(struct hci_dev *hdev)
143{
144 if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
145 return 0;
146 else
147 return -EPERM;
148}
149
150
151static void hci_smd_destruct(struct hci_dev *hdev)
152{
Bhasker Neti60576c62011-12-07 18:45:51 -0800153 if (NULL != hdev->driver_data)
154 kfree(hdev->driver_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155}
156
Bhasker Netiaae61462012-01-12 19:14:25 +0530157static void hci_smd_recv_data(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158{
Bhasker Netid08d9012011-09-05 19:37:54 +0530159 int len = 0;
160 int rc = 0;
161 struct sk_buff *skb = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530163 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164
165 len = smd_read_avail(hsmd->data_channel);
Bhasker Neti60734c02011-11-23 15:17:54 -0800166 if (len > HCI_MAX_FRAME_SIZE) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530167 BT_ERR("Frame larger than the allowed size, flushing frame");
168 smd_read(hsmd->data_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530169 goto out_data;
170 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700171
Bhasker Netiaae61462012-01-12 19:14:25 +0530172 if (len <= 0)
173 goto out_data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174
Bhasker Netiaae61462012-01-12 19:14:25 +0530175 skb = bt_skb_alloc(len, GFP_ATOMIC);
176 if (!skb) {
177 BT_ERR("Error in allocating socket buffer");
178 smd_read(hsmd->data_channel, NULL, len);
179 goto out_data;
Bhasker Netid08d9012011-09-05 19:37:54 +0530180 }
Bhasker Netiaae61462012-01-12 19:14:25 +0530181
182 rc = smd_read(hsmd->data_channel, skb_put(skb, len), len);
183 if (rc < len) {
184 BT_ERR("Error in reading from the channel");
185 goto out_data;
186 }
187
188 skb->dev = (void *)hsmd->hdev;
189 bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
190 skb_orphan(skb);
191
192 rc = hci_recv_frame(skb);
193 if (rc < 0) {
194 BT_ERR("Error in passing the packet to HCI Layer");
195 /*
196 * skb is getting freed in hci_recv_frame, making it
197 * to null to avoid multiple access
198 */
199 skb = NULL;
200 goto out_data;
201 }
202
203 /*
204 * Start the timer to monitor whether the Rx queue is
205 * empty for releasing the Rx wake lock
206 */
207 BT_DBG("Rx Timer is starting");
208 mod_timer(&hsmd->rx_q_timer,
209 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
210
Bhasker Netid08d9012011-09-05 19:37:54 +0530211out_data:
212 release_lock();
Bhasker Netiaae61462012-01-12 19:14:25 +0530213 if (rc)
214 kfree_skb(skb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215}
216
Bhasker Netiaae61462012-01-12 19:14:25 +0530217static void hci_smd_recv_event(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218{
Bhasker Netid08d9012011-09-05 19:37:54 +0530219 int len = 0;
220 int rc = 0;
221 struct sk_buff *skb = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 struct hci_smd_data *hsmd = &hs;
Bhasker Netid08d9012011-09-05 19:37:54 +0530223 wake_lock(&hs.wake_lock_rx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224
225 len = smd_read_avail(hsmd->event_channel);
226 if (len > HCI_MAX_FRAME_SIZE) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530227 BT_ERR("Frame larger than the allowed size, flushing frame");
228 rc = smd_read(hsmd->event_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530229 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230 }
231
232 while (len > 0) {
Ankur Nandwanic8150962011-08-24 13:06:23 -0700233 skb = bt_skb_alloc(len, GFP_ATOMIC);
Bhasker Netid08d9012011-09-05 19:37:54 +0530234 if (!skb) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530235 BT_ERR("Error in allocating socket buffer");
236 smd_read(hsmd->event_channel, NULL, len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530237 goto out_event;
238 }
Bhasker Netiaae61462012-01-12 19:14:25 +0530239
240 rc = smd_read(hsmd->event_channel, skb_put(skb, len), len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530241 if (rc < len) {
242 BT_ERR("Error in reading from the event channel");
243 goto out_event;
244 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700246 skb->dev = (void *)hsmd->hdev;
247 bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
248
249 skb_orphan(skb);
250
251 rc = hci_recv_frame(skb);
252 if (rc < 0) {
253 BT_ERR("Error in passing the packet to HCI Layer");
Bhasker Neti44a792b2011-10-11 19:25:22 +0530254 /*
255 * skb is getting freed in hci_recv_frame, making it
256 * to null to avoid multiple access
257 */
258 skb = NULL;
Bhasker Netid08d9012011-09-05 19:37:54 +0530259 goto out_event;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700260 }
261
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262 len = smd_read_avail(hsmd->event_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530263 /*
264 * Start the timer to monitor whether the Rx queue is
265 * empty for releasing the Rx wake lock
266 */
Bhasker Neti60734c02011-11-23 15:17:54 -0800267 BT_DBG("Rx Timer is starting");
Bhasker Netid08d9012011-09-05 19:37:54 +0530268 mod_timer(&hsmd->rx_q_timer,
269 jiffies + msecs_to_jiffies(RX_Q_MONITOR));
270 }
271out_event:
272 release_lock();
Bhasker Netiaae61462012-01-12 19:14:25 +0530273 if (rc)
274 kfree_skb(skb);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275}
276
277static int hci_smd_send_frame(struct sk_buff *skb)
278{
279 int len;
Bhasker Netid08d9012011-09-05 19:37:54 +0530280 int avail;
281 int ret = 0;
282 wake_lock(&hs.wake_lock_tx);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283
284 switch (bt_cb(skb)->pkt_type) {
285 case HCI_COMMAND_PKT:
Bhasker Netid08d9012011-09-05 19:37:54 +0530286 avail = smd_write_avail(hs.event_channel);
287 if (!avail) {
288 BT_ERR("No space available for smd frame");
289 ret = -ENOSPC;
290 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 len = smd_write(hs.event_channel, skb->data, skb->len);
292 if (len < skb->len) {
293 BT_ERR("Failed to write Command %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530294 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295 }
296 break;
297 case HCI_ACLDATA_PKT:
298 case HCI_SCODATA_PKT:
Ankur Nandwani23abeb22011-10-26 16:35:22 -0700299 avail = smd_write_avail(hs.data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530300 if (!avail) {
301 BT_ERR("No space available for smd frame");
302 ret = -ENOSPC;
303 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700304 len = smd_write(hs.data_channel, skb->data, skb->len);
305 if (len < skb->len) {
306 BT_ERR("Failed to write Data %d", len);
Bhasker Netid08d9012011-09-05 19:37:54 +0530307 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308 }
309 break;
310 default:
Bhasker Neti60734c02011-11-23 15:17:54 -0800311 BT_ERR("Uknown packet type");
Bhasker Netid08d9012011-09-05 19:37:54 +0530312 ret = -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700313 break;
314 }
Bhasker Netid08d9012011-09-05 19:37:54 +0530315
Anubhav Guptaddf48ec2011-10-03 14:24:13 +0530316 kfree_skb(skb);
Bhasker Netid08d9012011-09-05 19:37:54 +0530317 wake_unlock(&hs.wake_lock_tx);
318 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319}
320
Bhasker Netiaae61462012-01-12 19:14:25 +0530321static void hci_smd_rx(unsigned long arg)
322{
323 struct hci_smd_data *hsmd = &hs;
324
325 while ((smd_read_avail(hsmd->event_channel) > 0) ||
326 (smd_read_avail(hsmd->data_channel) > 0)) {
327 hci_smd_recv_event();
328 hci_smd_recv_data();
329 }
330}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331
332static void hci_smd_notify_event(void *data, unsigned int event)
333{
334 struct hci_dev *hdev = hs.hdev;
Bhasker Neti60734c02011-11-23 15:17:54 -0800335 struct hci_smd_data *hsmd = &hs;
Sunny Kapdi02eab142012-02-01 13:52:27 -0800336 struct work_struct *reset_worker;
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700337 struct work_struct *open_worker;
338
Bhasker Neti60734c02011-11-23 15:17:54 -0800339 int len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340
341 if (!hdev) {
342 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
343 return;
344 }
345
346 switch (event) {
347 case SMD_EVENT_DATA:
Bhasker Neti60734c02011-11-23 15:17:54 -0800348 len = smd_read_avail(hsmd->event_channel);
349 if (len > 0)
Bhasker Netiaae61462012-01-12 19:14:25 +0530350 tasklet_hi_schedule(&hs.rx_task);
Bhasker Neti60734c02011-11-23 15:17:54 -0800351 else if (len < 0)
352 BT_ERR("Failed to read event from smd %d", len);
353
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700354 break;
355 case SMD_EVENT_OPEN:
Bhasker Neti60734c02011-11-23 15:17:54 -0800356 BT_INFO("opening HCI-SMD channel :%s", EVENT_CHANNEL);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530357 BT_DBG("SSR state is : %x", ssr_state);
358 if ((ssr_state == STATE_SSR_OFF) ||
359 (ssr_state == STATE_SSR_CHANNEL_OPEN_PENDING)) {
360
361 hci_smd_open(hdev);
362 open_worker = kzalloc(sizeof(*open_worker), GFP_ATOMIC);
363 if (!open_worker) {
364 BT_ERR("Out of memory");
365 break;
366 }
367 if (ssr_state == STATE_SSR_CHANNEL_OPEN_PENDING) {
368 ssr_state = STATE_SSR_PENDING_INIT;
369 BT_INFO("SSR state is : %x", ssr_state);
370 }
371 INIT_WORK(open_worker, hci_dev_smd_open);
372 schedule_work(open_worker);
373
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700374 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 break;
376 case SMD_EVENT_CLOSE:
Bhasker Neti60734c02011-11-23 15:17:54 -0800377 BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530378 BT_DBG("SSR state is : %x", ssr_state);
379 if ((ssr_state == STATE_SSR_OFF) ||
380 (ssr_state == (STATE_SSR_PENDING_INIT))) {
381
382 hci_smd_close(hdev);
383 reset_worker = kzalloc(sizeof(*reset_worker),
384 GFP_ATOMIC);
385 if (!reset_worker) {
386 BT_ERR("Out of memory");
387 break;
388 }
389 ssr_state = STATE_SSR_ON;
390 BT_INFO("SSR state is : %x", ssr_state);
391 INIT_WORK(reset_worker, hci_dev_restart);
392 schedule_work(reset_worker);
393
394 } else if (ssr_state & STATE_SSR_ON) {
395 BT_ERR("SSR state is : %x", ssr_state);
Sunny Kapdi02eab142012-02-01 13:52:27 -0800396 }
Bhasker Netib54b0b72012-12-05 13:58:17 +0530397
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 break;
399 default:
400 break;
401 }
402}
403
404static void hci_smd_notify_data(void *data, unsigned int event)
405{
406 struct hci_dev *hdev = hs.hdev;
Bhasker Neti60734c02011-11-23 15:17:54 -0800407 struct hci_smd_data *hsmd = &hs;
408 int len = 0;
409
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410 if (!hdev) {
Bhasker Netiaae61462012-01-12 19:14:25 +0530411 BT_ERR("Frame for unknown HCI device (hdev=NULL)");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 return;
413 }
414
415 switch (event) {
416 case SMD_EVENT_DATA:
Bhasker Neti60734c02011-11-23 15:17:54 -0800417 len = smd_read_avail(hsmd->data_channel);
418 if (len > 0)
Bhasker Netiaae61462012-01-12 19:14:25 +0530419 tasklet_hi_schedule(&hs.rx_task);
Bhasker Neti60734c02011-11-23 15:17:54 -0800420 else if (len < 0)
421 BT_ERR("Failed to read data from smd %d", len);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 break;
423 case SMD_EVENT_OPEN:
Bhasker Neti60734c02011-11-23 15:17:54 -0800424 BT_INFO("opening HCI-SMD channel :%s", DATA_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 hci_smd_open(hdev);
426 break;
427 case SMD_EVENT_CLOSE:
Bhasker Neti60734c02011-11-23 15:17:54 -0800428 BT_INFO("Closing HCI-SMD channel :%s", DATA_CHANNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 hci_smd_close(hdev);
430 break;
431 default:
432 break;
433 }
434
435}
436
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700437static int hci_smd_hci_register_dev(struct hci_smd_data *hsmd)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438{
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700439 struct hci_dev *hdev;
440
Bhasker Netib54b0b72012-12-05 13:58:17 +0530441 if (hsmd->hdev)
442 hdev = hsmd->hdev;
443 else {
444 BT_ERR("hdev is NULL");
Bhasker Neti6d353ee2012-07-04 19:24:23 +0530445 return 0;
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700446 }
Bhasker Netib54b0b72012-12-05 13:58:17 +0530447 /* Allow the incomming SSR even the prev one at PENDING INIT STATE
448 * since clenup need to be started again from the beging and ignore
449 * or bypass the prev one
450 */
451 if ((ssr_state == STATE_SSR_OFF) ||
452 (ssr_state == STATE_SSR_PENDING_INIT)) {
453
454 if (test_and_set_bit(HCI_REGISTER_SET, &hsmd->flags)) {
455 BT_ERR("HCI device registered already");
456 return 0;
457 } else
458 BT_INFO("HCI device registration is starting");
459 if (hci_register_dev(hdev) < 0) {
460 BT_ERR("Can't register HCI device");
461 hci_free_dev(hdev);
462 hsmd->hdev = NULL;
463 clear_bit(HCI_REGISTER_SET, &hsmd->flags);
464 return -ENODEV;
465 }
466 if (ssr_state == STATE_SSR_PENDING_INIT) {
467 ssr_state = STATE_SSR_COMPLETE;
468 BT_INFO("SSR state is : %x", ssr_state);
469 }
470 } else if (ssr_state)
471 BT_ERR("Registration called in invalid context");
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700472 return 0;
473}
474
475static int hci_smd_register_smd(struct hci_smd_data *hsmd)
476{
477 struct hci_dev *hdev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700478 int rc;
479
480 /* Initialize and register HCI device */
Bhasker Neti60576c62011-12-07 18:45:51 -0800481 hdev = hci_alloc_dev();
482 if (!hdev) {
483 BT_ERR("Can't allocate HCI device");
484 return -ENOMEM;
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700485 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700486
Bhasker Neti60576c62011-12-07 18:45:51 -0800487 hsmd->hdev = hdev;
488 hdev->bus = HCI_SMD;
489 hdev->driver_data = NULL;
490 hdev->open = hci_smd_open;
491 hdev->close = hci_smd_close;
492 hdev->send = hci_smd_send_frame;
493 hdev->destruct = hci_smd_destruct;
494 hdev->owner = THIS_MODULE;
495
Bhasker Netiaae61462012-01-12 19:14:25 +0530496
497 tasklet_init(&hsmd->rx_task,
498 hci_smd_rx, (unsigned long) hsmd);
Bhasker Netid08d9012011-09-05 19:37:54 +0530499 /*
500 * Setup the timer to monitor whether the Rx queue is empty,
501 * to control the wake lock release
502 */
503 setup_timer(&hsmd->rx_q_timer, schedule_timer,
504 (unsigned long) hsmd->hdev);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530505 if (ssr_state == STATE_SSR_START) {
506 ssr_state = STATE_SSR_CHANNEL_OPEN_PENDING;
507 BT_INFO("SSR state is : %x", ssr_state);
508 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 /* Open the SMD Channel and device and register the callback function */
510 rc = smd_named_open_on_edge(EVENT_CHANNEL, SMD_APPS_WCNSS,
511 &hsmd->event_channel, hdev, hci_smd_notify_event);
512 if (rc < 0) {
513 BT_ERR("Cannot open the command channel");
514 hci_free_dev(hdev);
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700515 hsmd->hdev = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516 return -ENODEV;
517 }
518
519 rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
520 &hsmd->data_channel, hdev, hci_smd_notify_data);
521 if (rc < 0) {
Bhasker Neti60734c02011-11-23 15:17:54 -0800522 BT_ERR("Failed to open the Data channel");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 hci_free_dev(hdev);
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700524 hsmd->hdev = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525 return -ENODEV;
526 }
527
528 /* Disable the read interrupts on the channel */
529 smd_disable_read_intr(hsmd->event_channel);
530 smd_disable_read_intr(hsmd->data_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700531 return 0;
532}
533
Bhasker Neti60576c62011-12-07 18:45:51 -0800534static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535{
Bhasker Netiaae61462012-01-12 19:14:25 +0530536 tasklet_kill(&hs.rx_task);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530537 if (ssr_state)
538 BT_DBG("SSR state is : %x", ssr_state);
539 /* Though the hci_smd driver is not registered with the hci
540 * need to close the opened channels as a part of cleaup
541 */
Bhasker Neti6d353ee2012-07-04 19:24:23 +0530542 if (!test_and_clear_bit(HCI_REGISTER_SET, &hsmd->flags)) {
543 BT_ERR("HCI device un-registered already");
Bhasker Netib54b0b72012-12-05 13:58:17 +0530544 } else {
Bhasker Neti6d353ee2012-07-04 19:24:23 +0530545 BT_INFO("HCI device un-registration going on");
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530546
Bhasker Netib54b0b72012-12-05 13:58:17 +0530547 if (hsmd->hdev) {
548 if (hci_unregister_dev(hsmd->hdev) < 0)
549 BT_ERR("Can't unregister HCI device %s",
550 hsmd->hdev->name);
551
552 hci_free_dev(hsmd->hdev);
553 hsmd->hdev = NULL;
554 }
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530555 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700556 smd_close(hs.event_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700557 smd_close(hs.data_channel);
Bhasker Netid08d9012011-09-05 19:37:54 +0530558
Ankur Nandwani327e0502011-11-11 15:47:25 -0800559 if (wake_lock_active(&hs.wake_lock_rx))
560 wake_unlock(&hs.wake_lock_rx);
Bhasker Neti60576c62011-12-07 18:45:51 -0800561 if (wake_lock_active(&hs.wake_lock_tx))
562 wake_unlock(&hs.wake_lock_tx);
Ankur Nandwani327e0502011-11-11 15:47:25 -0800563
Bhasker Netid08d9012011-09-05 19:37:54 +0530564 /*Destroy the timer used to monitor the Rx queue for emptiness */
Royston Rodrigueseee6c962011-12-22 16:42:45 +0530565 if (hs.rx_q_timer.function) {
566 del_timer_sync(&hs.rx_q_timer);
567 hs.rx_q_timer.function = NULL;
568 hs.rx_q_timer.data = 0;
569 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570}
571
Sunny Kapdi02eab142012-02-01 13:52:27 -0800572static void hci_dev_restart(struct work_struct *worker)
573{
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700574 down(&hci_smd_enable);
575 restart_in_progress = 1;
Bhasker Netib54b0b72012-12-05 13:58:17 +0530576 BT_DBG("SSR state is : %x", ssr_state);
577
578 if (ssr_state == STATE_SSR_ON) {
579 ssr_state = STATE_SSR_START;
580 BT_INFO("SSR state is : %x", ssr_state);
581 } else {
582 BT_ERR("restart triggered in wrong context");
583 up(&hci_smd_enable);
584 kfree(worker);
585 return;
586 }
Sunny Kapdi02eab142012-02-01 13:52:27 -0800587 hci_smd_deregister_dev(&hs);
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700588 hci_smd_register_smd(&hs);
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700589 up(&hci_smd_enable);
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700590 kfree(worker);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530591
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700592}
593
594static void hci_dev_smd_open(struct work_struct *worker)
595{
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700596 down(&hci_smd_enable);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530597 if (ssr_state)
598 BT_DBG("SSR state is : %x", ssr_state);
599
600 if ((ssr_state != STATE_SSR_OFF) &&
601 (ssr_state != (STATE_SSR_PENDING_INIT))) {
602 up(&hci_smd_enable);
603 kfree(worker);
604 return;
605 }
606
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700607 if (restart_in_progress == 1) {
608 /* Allow wcnss to initialize */
609 restart_in_progress = 0;
610 msleep(10000);
611 }
Bhasker Netib54b0b72012-12-05 13:58:17 +0530612
Sunny Kapdid71fbed2012-03-15 18:20:55 -0700613 hci_smd_hci_register_dev(&hs);
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700614 up(&hci_smd_enable);
Sunny Kapdi02eab142012-02-01 13:52:27 -0800615 kfree(worker);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530616
Sunny Kapdi02eab142012-02-01 13:52:27 -0800617}
618
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700619static int hcismd_set_enable(const char *val, struct kernel_param *kp)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620{
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700621 int ret = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700623 pr_err("hcismd_set_enable %d", hcismd_set);
624
625 down(&hci_smd_enable);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700626
627 ret = param_set_int(val, kp);
628
629 if (ret)
630 goto done;
631
Bhasker Netib54b0b72012-12-05 13:58:17 +0530632 /* Ignore the all incomming register de-register requests in case of
633 * SSR is in-progress
634 */
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700635 switch (hcismd_set) {
636
637 case 1:
Bhasker Netib54b0b72012-12-05 13:58:17 +0530638 if ((hs.hdev == NULL) && (ssr_state == STATE_SSR_OFF))
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700639 hci_smd_register_smd(&hs);
Bhasker Netib54b0b72012-12-05 13:58:17 +0530640 else if (ssr_state)
641 BT_ERR("SSR is in progress,state is : %x", ssr_state);
642
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700643 break;
644 case 0:
Bhasker Netib54b0b72012-12-05 13:58:17 +0530645 if (ssr_state == STATE_SSR_OFF)
646 hci_smd_deregister_dev(&hs);
647 else if (ssr_state)
648 BT_ERR("SSR is in progress,state is : %x", ssr_state);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700649 break;
650 default:
651 ret = -EFAULT;
652 }
653
654done:
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700655 up(&hci_smd_enable);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700656 return ret;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700657}
Bhasker Neti60576c62011-12-07 18:45:51 -0800658static int __init hci_smd_init(void)
659{
660 wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND,
661 "msm_smd_Rx");
662 wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
663 "msm_smd_Tx");
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700664 restart_in_progress = 0;
Bhasker Netib54b0b72012-12-05 13:58:17 +0530665 ssr_state = STATE_SSR_OFF;
Sunny Kapdi2a39b802012-05-30 12:47:14 -0700666 hs.hdev = NULL;
Bhasker Neti60576c62011-12-07 18:45:51 -0800667 return 0;
668}
669module_init(hci_smd_init);
Ankur Nandwani8ffe4e72011-10-10 21:51:48 -0700670
Bhasker Neti60576c62011-12-07 18:45:51 -0800671static void __exit hci_smd_exit(void)
672{
673 wake_lock_destroy(&hs.wake_lock_rx);
674 wake_lock_destroy(&hs.wake_lock_tx);
675}
676module_exit(hci_smd_exit);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677
678MODULE_AUTHOR("Ankur Nandwani <ankurn@codeaurora.org>");
679MODULE_DESCRIPTION("Bluetooth SMD driver");
680MODULE_LICENSE("GPL v2");