sh: Ignore R_SH_NONE module relocations.
[pandora-kernel.git] / drivers / staging / ath6kl / os / linux / ar6k_pal.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 // 
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 //
19 //
20 //
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23
24 #include "ar6000_drv.h"
25 #ifdef AR6K_ENABLE_HCI_PAL
26 #include <net/bluetooth/bluetooth.h>
27 #include <net/bluetooth/hci_core.h>
28 #include <ar6k_pal.h>
29
30 extern unsigned int setupbtdev;
31 #define bt_check_bit(val, bit) (val & bit)
32 #define bt_set_bit(val, bit) (val |= bit)
33 #define bt_clear_bit(val, bit) (val &= ~bit)
34
35 /* export ATH_AR6K_DEBUG_HCI_PAL=yes in host/localmake.linux.inc
36  * to enable debug information */
37 #ifdef HCIPAL_DEBUG
38 #define PRIN_LOG(format, args...) printk(KERN_ALERT "%s:%d - %s Msg:" format "\n",__FUNCTION__, __LINE__, __FILE__, ## args) 
39 #else
40 #define PRIN_LOG(format, args...)
41 #endif
42
43 /**********************************
44  * HCI PAL private info structure 
45  *********************************/
46 typedef struct ar6k_hci_pal_info_s{
47
48         unsigned long ulFlags;
49 #define HCI_NORMAL_MODE (1)
50 #define HCI_REGISTERED (1<<1)
51         struct hci_dev *hdev;            /* BT Stack HCI dev */
52         struct ar6_softc *ar;
53
54 }ar6k_hci_pal_info_t;
55
56 /*** BT Stack Entrypoints *******/
57 /***************************************
58  * bt_open - open a handle to the device
59  ***************************************/
60 static int bt_open(struct hci_dev *hdev)
61 {
62         PRIN_LOG("HCI PAL: bt_open - enter - x\n");
63         set_bit(HCI_RUNNING, &hdev->flags);
64         set_bit(HCI_UP, &hdev->flags);
65         set_bit(HCI_INIT, &hdev->flags);         
66         return 0;
67 }
68
69 /***************************************
70  * bt_close - close handle to the device
71  ***************************************/
72 static int bt_close(struct hci_dev *hdev)
73 {
74         PRIN_LOG("HCI PAL: bt_close - enter\n");
75         clear_bit(HCI_RUNNING, &hdev->flags);
76         return 0;
77 }
78
79 /*****************************
80  * bt_ioctl - ioctl processing
81  *****************************/
82 static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
83 {
84         PRIN_LOG("HCI PAL: bt_ioctl - enter\n");
85         return -ENOIOCTLCMD;
86 }
87
88 /**************************************
89  * bt_flush - flush outstanding packets
90  **************************************/
91 static int bt_flush(struct hci_dev *hdev)
92 {
93         PRIN_LOG("HCI PAL: bt_flush - enter\n");
94         return 0;
95 }
96
97 /***************
98  * bt_destruct  
99  ***************/
100 static void bt_destruct(struct hci_dev *hdev)
101 {
102         PRIN_LOG("HCI PAL: bt_destruct - enter\n");
103         /* nothing to do here */
104 }
105
106 /****************************************************
107  * Invoked from bluetooth stack via hdev->send()
108  * to send the packet out via ar6k to PAL firmware.
109  *
110  * For HCI command packet wmi_send_hci_cmd() is invoked.
111  * wmi_send_hci_cmd adds WMI_CMD_HDR and sends the packet
112  * to PAL firmware.
113  *
114  * For HCI ACL data packet wmi_data_hdr_add is invoked 
115  * to add WMI_DATA_HDR to the packet.  ar6000_acl_data_tx 
116  * is then invoked to send the packet to PAL firmware.
117  ******************************************************/
118 static int btpal_send_frame(struct sk_buff *skb)
119 {
120         struct hci_dev *hdev = (struct hci_dev *)skb->dev;
121         HCI_TRANSPORT_PACKET_TYPE type;
122         ar6k_hci_pal_info_t *pHciPalInfo;
123         int status = 0;
124         struct sk_buff *txSkb = NULL;
125         struct ar6_softc *ar;
126
127         if (!hdev) {
128                 PRIN_LOG("HCI PAL: btpal_send_frame - no device\n");
129                 return -ENODEV;
130         }
131
132         if (!test_bit(HCI_RUNNING, &hdev->flags)) {
133                 PRIN_LOG("HCI PAL: btpal_send_frame - not open\n");
134                 return -EBUSY;
135         }
136
137         pHciPalInfo = (ar6k_hci_pal_info_t *)hdev->driver_data;   
138         A_ASSERT(pHciPalInfo != NULL);
139         ar = pHciPalInfo->ar;
140
141         PRIN_LOG("+btpal_send_frame type: %d \n",bt_cb(skb)->pkt_type);
142         type = HCI_COMMAND_TYPE;
143
144         switch (bt_cb(skb)->pkt_type) {
145                 case HCI_COMMAND_PKT:
146                         type = HCI_COMMAND_TYPE;
147                         hdev->stat.cmd_tx++;
148                         break;
149
150                 case HCI_ACLDATA_PKT:
151                         type = HCI_ACL_TYPE;
152                         hdev->stat.acl_tx++;
153                         break;
154
155                 case HCI_SCODATA_PKT:
156                         /* we don't support SCO over the pal */
157                         kfree_skb(skb);
158                         return 0;
159                 default:
160                         A_ASSERT(false);
161                         kfree_skb(skb);
162                         return 0;
163         } 
164
165         if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_HCI_DUMP)) {
166                 A_PRINTF(">>> Send HCI %s packet len: %d\n",
167                                 (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
168                                 skb->len);
169                 if (type == HCI_COMMAND_TYPE) {
170                         PRIN_LOG("    HCI Command: OGF:0x%X OCF:0x%X \r\n", 
171                                         HCI_GET_OP_CODE(skb-data) >> 10, HCI_GET_OP_CODE(skb-data) & 0x3FF);
172                 }
173                 AR_DEBUG_PRINTBUF(skb->data,skb->len,"BT HCI SEND Packet Dump");
174         }
175
176         do {
177                 if(type == HCI_COMMAND_TYPE)
178                 {
179                         PRIN_LOG("HCI command");
180
181                         if (ar->arWmiReady == false)
182                         {
183                                 PRIN_LOG("WMI not ready ");
184                                 break;
185                         }
186
187                         if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != 0)
188                         {
189                                 PRIN_LOG("send hci cmd error");
190                                 break;
191                         }
192                 }
193                 else if(type == HCI_ACL_TYPE)
194                 {
195                         void *osbuf;
196
197                         PRIN_LOG("ACL data");
198                         if (ar->arWmiReady == false)
199                         {
200                                 PRIN_LOG("WMI not ready");
201                                 break;
202                         }
203
204                         /* need to add WMI header so allocate a skb with more space */
205                         txSkb = bt_skb_alloc(TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ + 
206                                         sizeof(WMI_DATA_HDR) + skb->len, 
207                                         GFP_ATOMIC);
208
209                         if (txSkb == NULL) {
210                                 status = A_NO_MEMORY;
211                                 PRIN_LOG("No memory");
212                                 break;
213                         }
214
215                         bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
216                         txSkb->dev = (void *)pHciPalInfo->hdev;
217                         skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ + sizeof(WMI_DATA_HDR));
218                         memcpy(txSkb->data, skb->data, skb->len);
219                         skb_put(txSkb,skb->len);
220                         /* Add WMI packet type */
221                         osbuf = (void *)txSkb;
222
223                         if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
224                                 PRIN_LOG("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n");
225                         } else {
226                                 /* Send data buffer over HTC */
227                                 PRIN_LOG("acl data tx");
228                                 ar6000_acl_data_tx(osbuf, ar->arNetDev);
229                         }
230                         txSkb = NULL;
231                 }
232         } while (false);
233
234         if (txSkb != NULL) {
235                 PRIN_LOG("Free skb");
236                 kfree_skb(txSkb);    
237         }
238         kfree_skb(skb);        
239         return 0;
240 }
241
242
243 /***********************************************
244  * Unregister HCI device and free HCI device info
245  ***********************************************/
246 static void bt_cleanup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
247 {   
248         int err;      
249
250         if (bt_check_bit(pHciPalInfo->ulFlags, HCI_REGISTERED)) {
251                 bt_clear_bit(pHciPalInfo->ulFlags, HCI_REGISTERED);
252                 clear_bit(HCI_RUNNING, &pHciPalInfo->hdev->flags);
253                 clear_bit(HCI_UP, &pHciPalInfo->hdev->flags);
254                 clear_bit(HCI_INIT, &pHciPalInfo->hdev->flags);   
255                 A_ASSERT(pHciPalInfo->hdev != NULL);
256                 /* unregister */
257                 PRIN_LOG("Unregister PAL device");
258                 if ((err = hci_unregister_dev(pHciPalInfo->hdev)) < 0) {
259                         PRIN_LOG("HCI PAL: failed to unregister with bluetooth %d\n",err);
260                 }          
261         }
262
263         kfree(pHciPalInfo->hdev);
264         pHciPalInfo->hdev = NULL;
265 }
266
267 /*********************************************************
268  * Allocate HCI device and store in PAL private info structure.
269  *********************************************************/
270 static int bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
271 {
272         int status = 0;
273         struct hci_dev *pHciDev = NULL;
274
275         if (!setupbtdev) {
276                 return 0;
277         } 
278
279         do {
280                 /* allocate a BT HCI struct for this device */
281                 pHciDev = hci_alloc_dev();
282                 if (NULL == pHciDev) {
283                         PRIN_LOG("HCI PAL driver - failed to allocate BT HCI struct \n");
284                         status = A_NO_MEMORY;
285                         break;
286                 }    
287
288                 /* save the device, we'll register this later */
289                 pHciPalInfo->hdev = pHciDev;       
290                 SET_HCI_BUS_TYPE(pHciDev, HCI_VIRTUAL, HCI_80211);
291                 pHciDev->driver_data = pHciPalInfo;
292                 pHciDev->open     = bt_open;
293                 pHciDev->close    = bt_close;
294                 pHciDev->send     = btpal_send_frame;
295                 pHciDev->ioctl    = bt_ioctl;
296                 pHciDev->flush    = bt_flush;
297                 pHciDev->destruct = bt_destruct;
298                 pHciDev->owner = THIS_MODULE; 
299                 /* driver is running in normal BT mode */
300                 PRIN_LOG("Normal mode enabled");
301                 bt_set_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE);
302
303         } while (false);
304
305         if (status) {
306                 bt_cleanup_hci_pal(pHciPalInfo);    
307         }
308         return status;
309 }
310
311 /**********************************************
312  * Cleanup HCI device and free HCI PAL private info
313  *********************************************/
314 void ar6k_cleanup_hci_pal(void *ar_p)
315 {
316         struct ar6_softc *ar = (struct ar6_softc *)ar_p;
317         ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)ar->hcipal_info;
318
319         if (pHciPalInfo != NULL) {
320                 bt_cleanup_hci_pal(pHciPalInfo);   
321                 A_FREE(pHciPalInfo);
322                 ar->hcipal_info = NULL;
323         }
324 }
325
326 /****************************
327  *  Register HCI device
328  ****************************/
329 static bool ar6k_pal_transport_ready(void *pHciPal)
330 {
331         ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
332
333         PRIN_LOG("HCI device transport ready");
334         if(pHciPalInfo == NULL)
335                 return false;
336
337         if (hci_register_dev(pHciPalInfo->hdev) < 0) {
338                 PRIN_LOG("Can't register HCI device");
339                 hci_free_dev(pHciPalInfo->hdev);
340                 return false;
341         }
342         PRIN_LOG("HCI device registered");
343         pHciPalInfo->ulFlags |= HCI_REGISTERED;
344         return true;
345 }
346
347 /**************************************************
348  * Called from ar6k driver when command or ACL data 
349  * packet is received. Pass the packet to bluetooth
350  * stack via hci_recv_frame.
351  **************************************************/
352 bool ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
353 {
354         struct sk_buff *skb = (struct sk_buff *)osbuf;
355         ar6k_hci_pal_info_t *pHciPalInfo;
356         bool success = false;
357         u8 btType = 0;
358         pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
359
360         do {
361
362                 /* if normal mode is not enabled pass on to the stack
363                  * by returning failure */
364                 if(!(pHciPalInfo->ulFlags & HCI_NORMAL_MODE))
365                 {
366                         PRIN_LOG("Normal mode not enabled");
367                         break;
368                 }
369
370                 if (!test_bit(HCI_RUNNING, &pHciPalInfo->hdev->flags)) {
371                         PRIN_LOG("HCI PAL: HCI - not running\n");
372                         break;
373                 }
374
375                 if(*((short *)A_NETBUF_DATA(skb)) == WMI_ACL_DATA_EVENTID)
376                         btType = HCI_ACLDATA_PKT;
377                 else
378                         btType = HCI_EVENT_PKT;
379                 /* pull 4 bytes which contains WMI packet type */
380                 A_NETBUF_PULL(skb, sizeof(int));
381                 bt_cb(skb)->pkt_type = btType;
382                 skb->dev = (void *)pHciPalInfo->hdev;
383
384                 /* pass the received event packet up the stack */    
385                 if (hci_recv_frame(skb) != 0) {
386                         PRIN_LOG("HCI PAL: hci_recv_frame failed \n");
387                         break;
388                 } else {
389                         PRIN_LOG("HCI PAL: Indicated RCV of type:%d, Length:%d \n",HCI_EVENT_PKT, skb->len);
390                 }
391                 PRIN_LOG("hci recv success");
392                 success = true;
393         }while(false);
394         return success;
395 }
396
397 /**********************************************************
398  * HCI PAL init function called from ar6k when it is loaded..
399  * Allocates PAL private info, stores the same in ar6k private info.
400  * Registers a HCI device.
401  * Registers packet receive callback function with ar6k 
402  **********************************************************/
403 int ar6k_setup_hci_pal(void *ar_p)
404 {
405         int status = 0;
406         ar6k_hci_pal_info_t *pHciPalInfo;
407         ar6k_pal_config_t ar6k_pal_config;
408         struct ar6_softc *ar = (struct ar6_softc *)ar_p;
409
410         do {
411
412                 pHciPalInfo = (ar6k_hci_pal_info_t *)A_MALLOC(sizeof(ar6k_hci_pal_info_t));
413
414                 if (NULL == pHciPalInfo) {
415                         status = A_NO_MEMORY;
416                         break;    
417                 }
418
419                 A_MEMZERO(pHciPalInfo, sizeof(ar6k_hci_pal_info_t));
420                 ar->hcipal_info = pHciPalInfo;
421                 pHciPalInfo->ar = ar;
422
423                 status = bt_setup_hci_pal(pHciPalInfo);
424                 if (status) {
425                         break;    
426                 }
427
428                 if(bt_check_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE))
429                         PRIN_LOG("HCI PAL: running in normal mode... \n");    
430                 else 
431                         PRIN_LOG("HCI PAL: running in test mode... \n");     
432
433                 ar6k_pal_config.fpar6k_pal_recv_pkt = ar6k_pal_recv_pkt;
434                 register_pal_cb(&ar6k_pal_config);
435                 ar6k_pal_transport_ready(ar->hcipal_info);
436         } while (false);
437
438         if (status) {
439                 ar6k_cleanup_hci_pal(ar);    
440         }
441         return status;
442 }
443 #else  /* AR6K_ENABLE_HCI_PAL */
444 int ar6k_setup_hci_pal(void *ar_p)
445 {
446         return 0;
447 }
448 void ar6k_cleanup_hci_pal(void *ar_p)
449 {
450 }
451 #endif /* AR6K_ENABLE_HCI_PAL */
452
453 #ifdef EXPORT_HCI_PAL_INTERFACE
454 /*****************************************************
455  * Register init and callback function with ar6k
456  * when PAL driver is a separate kernel module.
457  ****************************************************/
458 int ar6k_register_hci_pal(struct hci_transport_callbacks *hciTransCallbacks);
459 static int __init pal_init_module(void)
460 {
461         struct hci_transport_callbacks hciTransCallbacks;
462
463         hciTransCallbacks.setupTransport = ar6k_setup_hci_pal;
464         hciTransCallbacks.cleanupTransport = ar6k_cleanup_hci_pal;
465
466         if(ar6k_register_hci_pal(&hciTransCallbacks) != 0)
467                 return -ENODEV;
468
469         return 0;
470 }
471
472 static void __exit pal_cleanup_module(void)
473 {
474 }
475
476 module_init(pal_init_module);
477 module_exit(pal_cleanup_module);
478 MODULE_LICENSE("Dual BSD/GPL");
479 #endif