PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/net/wireless/tiwlan1251/pform/linux/src/esta_drv.c

http://github.com/CyanogenMod/cm-kernel
C | 2138 lines | 1645 code | 272 blank | 221 comment | 206 complexity | 15117d453a65ef66153bc10a828bc3c0 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /****************************************************************************
  2. **+-----------------------------------------------------------------------+**
  3. **| |**
  4. **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
  5. **| All rights reserved. |**
  6. **| |**
  7. **| Redistribution and use in source and binary forms, with or without |**
  8. **| modification, are permitted provided that the following conditions |**
  9. **| are met: |**
  10. **| |**
  11. **| * Redistributions of source code must retain the above copyright |**
  12. **| notice, this list of conditions and the following disclaimer. |**
  13. **| * Redistributions in binary form must reproduce the above copyright |**
  14. **| notice, this list of conditions and the following disclaimer in |**
  15. **| the documentation and/or other materials provided with the |**
  16. **| distribution. |**
  17. **| * Neither the name Texas Instruments nor the names of its |**
  18. **| contributors may be used to endorse or promote products derived |**
  19. **| from this software without specific prior written permission. |**
  20. **| |**
  21. **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |**
  22. **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |**
  23. **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
  24. **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |**
  25. **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
  26. **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |**
  27. **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
  28. **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
  29. **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |**
  30. **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
  31. **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |**
  32. **| |**
  33. **+-----------------------------------------------------------------------+**
  34. ****************************************************************************/
  35. #include <linux/module.h>
  36. #include <linux/kernel.h>
  37. #include <linux/version.h>
  38. #include <net/sock.h>
  39. #include <linux/init.h>
  40. #include <linux/fs.h>
  41. #include <linux/netdevice.h>
  42. #include <linux/ioctl.h>
  43. #include <linux/wireless.h>
  44. #include <linux/etherdevice.h>
  45. #include <linux/netlink.h>
  46. #include <linux/completion.h>
  47. #ifdef TIWLAN_CARDBUS
  48. #include <linux/pci.h>
  49. #else
  50. #ifdef TIWLAN_OMAP1610
  51. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
  52. #include <asm/arch-omap/tc.h>
  53. #else
  54. #include <mach/tc.h>
  55. #endif
  56. #endif
  57. #ifdef TIWLAN_MSM7000
  58. #include <linux/mmc/core.h>
  59. #include <linux/mmc/card.h>
  60. #include <linux/mmc/sdio_func.h>
  61. #include <linux/mmc/sdio_ids.h>
  62. #endif
  63. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
  64. #include <asm/arch/io.h>
  65. #include <asm/arch/hardware.h>
  66. #include <asm/arch/irqs.h>
  67. #else
  68. #include <mach/io.h>
  69. #include <mach/hardware.h>
  70. #include <mach/irqs.h>
  71. #endif
  72. #endif /* !TIWLAN_CARDBUS */
  73. #include <linux/list.h>
  74. #include <linux/spinlock.h>
  75. #include <linux/if_arp.h>
  76. #include <linux/proc_fs.h>
  77. #include <linux/mm.h>
  78. #include <linux/delay.h>
  79. #include <linux/vmalloc.h>
  80. #include <linux/irq.h>
  81. #include <asm/io.h>
  82. #include <asm/uaccess.h>
  83. #include <asm/pgtable.h>
  84. #include "esta_drv.h"
  85. #include "srcApi.h"
  86. #include "osApi.h"
  87. #include "whalHwRegs.h"
  88. #if defined(DEBUG_UNKNOWN_INTERRUPT)
  89. #define _STRING_H
  90. #include "configMgr.h"
  91. #include "whalCtrl.h"
  92. #endif
  93. #include "bmtrace.h"
  94. #include "osrgstry_parser.h"
  95. #include "osClsfr.h"
  96. #include "TI_IPC_Api.h"
  97. #include "802_11Defs.h"
  98. #include "Ethernet.h"
  99. #include "tiwlan_profile.h"
  100. #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
  101. #define RX_RATE_INTERVAL_SEC 10
  102. unsigned long num_rx_pkt_new = 0;
  103. static unsigned long num_rx_pkt_last = 0;
  104. #endif
  105. #ifdef TIWLAN_MSM7000
  106. extern unsigned char *get_wifi_nvs_ram(void);
  107. extern void SDIO_SetFunc( struct sdio_func * );
  108. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
  109. static struct proc_dir_entry *tiwlan_calibration;
  110. #endif
  111. static struct completion sdio_wait;
  112. #ifdef CONFIG_WIFI_CONTROL_FUNC
  113. static struct wifi_platform_data *wifi_control_data = NULL;
  114. #endif
  115. #endif
  116. /* WiFi chip information functions */
  117. int export_wifi_fw_version( tiwlan_net_dev_t *drv );
  118. int export_wifi_chip_id( void );
  119. /* Drivers list */
  120. static LIST_HEAD(tiwlan_drv_list);
  121. /* debug memory access */
  122. static struct proc_dir_entry *tiwlan_deb_entry;
  123. static __u32 memdebug_addr;
  124. static __u32 memdebug_size=1;
  125. static __u32 memdebug_trans_size;
  126. #define DRV_SHUTDOWN_TEST_DELAY_INTERVAL 100 /* Time in msec to "delay"(/sleep) while waiting for SME to shutdown */
  127. #define DRV_SHUTDOWN_TEST_MAX_COUNTER 20 /* How many delay/sleep iterations to perform while waiting for SME to shutdown) */
  128. MODULE_DESCRIPTION("TI WLAN Embedded Station Driver");
  129. MODULE_LICENSE("GPL");
  130. extern int packed_struct_tst(void);
  131. extern int proc_stat_init(TI_HANDLE);
  132. extern int proc_stat_destroy(void);
  133. typedef void (* tiwlan_drv_isr_t)(int, void *, struct pt_regs *);
  134. /* network device driver interface */
  135. static int tiwlan_drv_net_open(struct net_device * dev);
  136. static int tiwlan_drv_net_stop(struct net_device * dev);
  137. static int tiwlan_drv_net_xmit(struct sk_buff * skb, struct net_device * dev);
  138. static int tiwlan_drv_dummy_net_xmit(struct sk_buff * skb, struct net_device * dev);
  139. static struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev);
  140. int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
  141. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
  142. static struct net_device_ops tiwlan_ops_pri = {
  143. .ndo_open = tiwlan_drv_net_open,
  144. .ndo_stop = tiwlan_drv_net_stop,
  145. .ndo_get_stats = tiwlan_drv_net_get_stats,
  146. .ndo_do_ioctl = ti1610_do_ioctl,
  147. .ndo_start_xmit = tiwlan_drv_net_xmit,
  148. };
  149. static struct net_device_ops tiwlan_ops_dummy = {
  150. .ndo_open = tiwlan_drv_net_open,
  151. .ndo_stop = tiwlan_drv_net_stop,
  152. .ndo_get_stats = tiwlan_drv_net_get_stats,
  153. .ndo_do_ioctl = ti1610_do_ioctl,
  154. .ndo_start_xmit = tiwlan_drv_dummy_net_xmit,
  155. };
  156. #endif
  157. #define OS_WRITE_REG(drv,reg,val) \
  158. os_hwWriteMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), (__u32)(val))
  159. #define OS_READ_REG(drv,reg,val) \
  160. os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), &val)
  161. #ifdef TIWLAN_OMAP1610
  162. static void omap_memif_init(void)
  163. {
  164. printk ("First function offset is: %p\n", omap_memif_init);
  165. #if defined(TIWLAN_OMAP1610_INNOVATOR)
  166. print_info("Setting CS1 Ref Clock = TC/4. \n");
  167. omap_writel(0x00000004, 0xFFFECC40 ); /* wlan change for cs2 to dynamic wait state */
  168. omap_writel(0x0000113a, 0xFFFECC18 ); /* EMIFS (nCS2) configuration */
  169. #elif defined(TIWLAN_OMAP1610_WIPP) || defined(TIWLAN_OMAP1610_CRTWIPP)
  170. #if defined(TIWLAN_OMAP1610_CRTWIPP)
  171. /*
  172. Init the GPIO to output*/
  173. /* Set OMAP pin H19 to GPIO57*/
  174. omap_writel(omap_readl(0xFFFE1014) | 0x00E00000, 0xFFFE1014 );
  175. /*ELP_REQ (GPIO_57) by GPIO_DIRECTION - set it as output*/
  176. omap_writel(omap_readl(0xFFFBBC34) & (~0x00000200), 0xFFFBBC34 );
  177. #endif /* TIWLAN_OMAP1610_CRTWIPP */
  178. /* The below configuration enables GPIO25 and GPIO_27 as output GPIOs - for debug purposes */
  179. #if defined(TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG)
  180. omap_writel(omap_readl(0xFFFE1030) | 0x00000E00, 0xFFFE1030 );/* enable GPIO25 */
  181. omap_writel(omap_readl(0xFFFE1030) | 0x00000038, 0xFFFE1030 );/* enable GPIO27 */
  182. omap_writel(omap_readl(0xFFFBEC34) & (~0x00000200), 0xFFFBEC34 );/* Setting direction (as output) for GPIO25 */
  183. omap_writel(omap_readl(0xFFFBEC34) & (~0x00000800), 0xFFFBEC34 );/* Setting direction (as output) for GPIO27 */
  184. #endif /* TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG */
  185. /* RECOVERY*/
  186. print_info("Hard reset,perform PMEN toggle\n");
  187. os_hardResetTnetw();
  188. print_info("Setting CS2 Ref Clock = TC/2. \n");
  189. __raw_writel(0x1, TIWLAN_OMAP1610_REGBASE+0x4cc); /* CLK=80MHz */
  190. omap_writel(0x20, EMIF_CFG_DYNAMIC_WS); /* Full handshake on CS2 */
  191. omap_writel(0x2441, EMIFS_CS2_CONFIG); /* 0x2021 on reworked board */
  192. omap_writel(0, EMIFS_ACS2);
  193. print_info("%x=0x%lx\n", 0xFFFECC40, omap_readl(0xFFFECC40) );
  194. print_info("%x=0x%lx\n", 0xFFFECC18, omap_readl(0xFFFECC18) );
  195. print_info("%x=0x%lx\n", 0xFFFECC58, omap_readl(0xFFFECC58) );
  196. #endif /* WIPP, CRTWIPP */
  197. }
  198. #endif
  199. static int tiwlan_register_events(tiwlan_net_dev_t *drv)
  200. {
  201. IPC_EVENT_PARAMS evParams;
  202. int i = 0;
  203. evParams.uDeliveryType = DELIVERY_PUSH;
  204. evParams.uProcessID = 0;
  205. evParams.uEventID = 0;
  206. evParams.hUserParam = drv;
  207. evParams.pfEventCallback = os_IndicateEvent;
  208. for (;i < IPC_EVENT_MAX_OS_EVENT;i++)
  209. {
  210. evParams.uEventType = i;
  211. configMgr_RegisterEvent(drv->adapter.CoreHalCtx,(PUCHAR) &evParams,sizeof(IPC_EVENT_PARAMS));
  212. }
  213. return OK;
  214. }
  215. static int tiwlan_deb_read_proc(char *page, char **start, off_t off,
  216. int count, int *eof, void *data)
  217. {
  218. __u32 addr=memdebug_addr;
  219. __u32 size=memdebug_size;
  220. __u32 trans_size=memdebug_trans_size;
  221. __u32 end;
  222. int in_line=0, max_in_line;
  223. int limit=count-80;
  224. int i=0;
  225. static int toggle;
  226. *eof = 1;
  227. if (!addr || !trans_size)
  228. return 0;
  229. /* fixme: add address validation */
  230. if (!size)
  231. size=1;
  232. end = addr + size*trans_size;
  233. if (trans_size==4)
  234. max_in_line = 4;
  235. else if (trans_size==2)
  236. max_in_line = 8;
  237. else
  238. max_in_line = 16;
  239. while(i<limit && addr<end)
  240. {
  241. if (!in_line)
  242. i += sprintf(page+i, "0x%08x: ", addr);
  243. if (trans_size==4)
  244. {
  245. i += sprintf(page+i, "0x%08x", *(__u32 *)addr);
  246. addr += 4;
  247. }
  248. else if (trans_size==2)
  249. {
  250. i += sprintf(page+i, "0x%04x", *(__u16 *)addr);
  251. addr += 2;
  252. }
  253. else
  254. {
  255. i += sprintf(page+i, "0x%02x", *(__u8 *)addr);
  256. addr += 1;
  257. }
  258. if (++in_line < max_in_line)
  259. *(page+i++)=' ';
  260. else
  261. {
  262. *(page+i++)='\n';
  263. in_line = 0;
  264. }
  265. }
  266. *(page+i++)='\n';
  267. /* For some reason read proc is get called twice for
  268. each "cat" operation
  269. */
  270. if (toggle)
  271. memdebug_addr = addr;
  272. toggle = !toggle;
  273. return i;
  274. }
  275. static char *rm_get_token(const char **p_buffer, unsigned long *p_buffer_len,
  276. char *token, unsigned long token_len,
  277. char del)
  278. {
  279. const char *buffer=*p_buffer;
  280. __u32 buffer_len = *p_buffer_len;
  281. while(buffer_len && token_len && *buffer!=del && *buffer)
  282. {
  283. *token++ = *buffer++;
  284. --buffer_len;
  285. --token_len;
  286. }
  287. while (buffer_len && *buffer==del)
  288. {
  289. ++buffer;
  290. --buffer_len;
  291. }
  292. *token = 0;
  293. *p_buffer = buffer;
  294. *p_buffer_len = buffer_len;
  295. return token;
  296. }
  297. static int tiwlan_deb_write_proc(struct file *file, const char *buffer,
  298. unsigned long count, void *data)
  299. {
  300. __u32 addr, size;
  301. char token[15];
  302. __u32 value;
  303. char *end;
  304. int buflen=count;
  305. /* buffer format is:
  306. d{w,h,b} addr[/size]
  307. s{w,h,b} addr=value
  308. */
  309. /* Parse string */
  310. rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
  311. if (token[0]=='d')
  312. {
  313. /* Display */
  314. if (!strcmp(token, "dw"))
  315. memdebug_trans_size = 4;
  316. else if (!strcmp(token, "dh"))
  317. memdebug_trans_size = 2;
  318. else if (!strcmp(token, "db"))
  319. memdebug_trans_size = 1;
  320. else
  321. {
  322. printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
  323. return buflen;
  324. }
  325. /* Get address */
  326. rm_get_token(&buffer, &count, token, sizeof(token)-1, '/');
  327. addr = simple_strtoul(token, &end, 0);
  328. if ((end && *end) /* || !iopa(addr)*/)
  329. {
  330. printk(KERN_INFO "rm: address <%s> is invalid\n", token);
  331. return buflen;
  332. }
  333. if ((addr & (memdebug_trans_size-1)))
  334. {
  335. printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
  336. addr, memdebug_trans_size);
  337. }
  338. memdebug_addr = addr;
  339. if (count)
  340. {
  341. /* Get size */
  342. rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
  343. size = simple_strtoul(token, &end, 0);
  344. if (end && *end)
  345. {
  346. printk(KERN_INFO "rm: size <%s> is invalid. end=<%s>\n",
  347. token, end);
  348. return buflen;
  349. }
  350. memdebug_size = size;
  351. }
  352. return buflen;
  353. }
  354. if (token[0]=='s')
  355. {
  356. /* Display */
  357. if (!strcmp(token, "sw"))
  358. size = 4;
  359. else if (!strcmp(token, "sh"))
  360. size = 2;
  361. else if (!strcmp(token, "sb"))
  362. size = 1;
  363. else
  364. {
  365. printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
  366. return buflen;
  367. }
  368. /* Get address */
  369. rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
  370. addr = simple_strtoul(token, &end, 0);
  371. if ((end && *end) /*|| !iopa(addr)*/)
  372. {
  373. printk(KERN_INFO "rm: address <%s> is invalid\n", token);
  374. return buflen;
  375. }
  376. if ((addr & (size-1)))
  377. {
  378. printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
  379. addr, size);
  380. }
  381. /* Get value */
  382. rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
  383. value = simple_strtoul(token, &end, 0);
  384. if (end && *end)
  385. {
  386. printk(KERN_INFO "rm: value <%s> is invalid. end <%s>\n",
  387. token, end);
  388. return buflen;
  389. }
  390. if (size==4)
  391. *(__u32 *)addr = value;
  392. else if (size==2)
  393. {
  394. if (value > 0xffff)
  395. {
  396. printk(KERN_INFO "rm: value <%s> is out of range\n", token);
  397. return buflen;
  398. }
  399. *(__u16 *)addr = value;
  400. }
  401. else
  402. {
  403. if (value > 0xff)
  404. {
  405. printk(KERN_INFO "rm: value <%s> is out of range\n", token);
  406. return buflen;
  407. }
  408. *(__u8 *)addr = value;
  409. }
  410. memdebug_addr = addr;
  411. memdebug_size = 1;
  412. memdebug_trans_size = size;
  413. }
  414. else
  415. printk(KERN_INFO "rm: operation <%s> is not supported\n", token);
  416. return buflen;
  417. }
  418. #ifdef TIWLAN_MSM7000
  419. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
  420. #define WIFI_NVS_LEN_OFFSET 0x0C
  421. #define WIFI_NVS_DATA_OFFSET 0x40
  422. #define WIFI_NVS_MAX_SIZE 0x800UL
  423. static unsigned long tiwlan_get_nvs_size( void )
  424. {
  425. unsigned char *ptr;
  426. unsigned long len;
  427. ptr = get_wifi_nvs_ram();
  428. if( ptr == NULL ) {
  429. return 0;
  430. }
  431. /* Size in format LE assumed */
  432. memcpy( (void *)&len, (void *)(ptr + WIFI_NVS_LEN_OFFSET), sizeof(len) );
  433. len = min( len, (WIFI_NVS_MAX_SIZE-WIFI_NVS_DATA_OFFSET) );
  434. return len;
  435. }
  436. static int tiwlan_calibration_read_proc(char *page, char **start, off_t off,
  437. int count, int *eof, void *data)
  438. {
  439. unsigned char *ptr;
  440. unsigned long len;
  441. ptr = get_wifi_nvs_ram();
  442. if( ptr == NULL ) {
  443. return 0;
  444. }
  445. len = tiwlan_get_nvs_size();
  446. /* i += sprintf(page+i, "WiFi Calibration Size = %lu %x bytes\n", len); */
  447. memcpy( (void *)page, (void *)(ptr + WIFI_NVS_DATA_OFFSET), len );
  448. return len;
  449. }
  450. static int tiwlan_calibration_write_proc(struct file *file, const char *buffer,
  451. unsigned long count, void *data)
  452. {
  453. return 0;
  454. }
  455. #endif
  456. #endif
  457. /*********************************************************************************************/
  458. /* Impelementation */
  459. /*********************************************************************************************/
  460. static int tiwlan_drv_net_open(struct net_device * dev)
  461. {
  462. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
  463. ti_nodprintf(TIWLAN_LOG_INFO, "tiwlan_drv_net_open()\n");
  464. if (!drv->adapter.CoreHalCtx)
  465. return -ENODEV;
  466. netif_start_queue(dev);
  467. return 0;
  468. }
  469. static int tiwlan_drv_net_stop(struct net_device * dev)
  470. {
  471. ti_nodprintf(TIWLAN_LOG_ERROR, "tiwlan_drv_net_stop()\n");
  472. netif_stop_queue(dev);
  473. return 0;
  474. }
  475. /* dummy send packet from Linux TCP/IP stack to WLAN
  476. Used when driver is not initialized
  477. */
  478. static int tiwlan_drv_dummy_net_xmit(struct sk_buff *skb, struct net_device *dev)
  479. {
  480. /* Network stack takes care of deallocation */
  481. return -ENODEV;
  482. }
  483. void sendFreeFunc(TI_HANDLE pSkb, TI_HANDLE dummy1, TI_STATUS status)
  484. {
  485. struct sk_buff *skb = (struct sk_buff *) pSkb;
  486. /* print_deb("^^^ free %p %d bytes (%s)\n", skb->data, skb->len, (status==OK) ? "OK" : "ERROR" ); */
  487. dev_kfree_skb(skb);
  488. }
  489. #ifdef DM_USE_WORKQUEUE
  490. void tiwlan_add_msdu(tiwlan_net_dev_t *drv, mem_MSDU_T *pMsdu)
  491. {
  492. if( pMsdu == NULL )
  493. return;
  494. pMsdu->msdu_next = NULL;
  495. if( drv->txmit_msdu_next != NULL ) {
  496. drv->txmit_msdu_last->msdu_next = pMsdu;
  497. }
  498. else {
  499. drv->txmit_msdu_next = pMsdu;
  500. }
  501. drv->txmit_msdu_last = pMsdu;
  502. }
  503. mem_MSDU_T *tiwlan_del_msdu(tiwlan_net_dev_t *drv)
  504. {
  505. mem_MSDU_T *pMsdu = NULL;
  506. if( drv->txmit_msdu_next != NULL ) {
  507. pMsdu = drv->txmit_msdu_next;
  508. drv->txmit_msdu_next = pMsdu->msdu_next;
  509. if( drv->txmit_msdu_next == NULL ) { /* Last MSDU */
  510. drv->txmit_msdu_last = NULL;
  511. }
  512. }
  513. return( pMsdu );
  514. }
  515. static void tiwlan_xmit_handler( struct work_struct *work )
  516. {
  517. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, txmit );
  518. mem_MSDU_T *pMsdu;
  519. unsigned long flags;
  520. #ifdef CONFIG_ANDROID_POWER
  521. android_lock_suspend( &drv->exec_wake_lock );
  522. android_unlock_suspend( &drv->xmit_wake_lock );
  523. #endif
  524. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  525. do {
  526. spin_lock_irqsave(&drv->lock, flags);
  527. pMsdu = tiwlan_del_msdu(drv);
  528. spin_unlock_irqrestore(&drv->lock, flags);
  529. if( pMsdu ) {
  530. configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
  531. }
  532. } while( pMsdu != NULL );
  533. #ifdef CONFIG_ANDROID_POWER
  534. android_unlock_suspend( &drv->exec_wake_lock );
  535. #endif
  536. }
  537. #endif
  538. /* send packet from Linux TCP/IP stack to WLAN
  539. */
  540. static int tiwlan_drv_net_xmit(struct sk_buff *skb, struct net_device *dev)
  541. {
  542. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
  543. int status;
  544. mem_MSDU_T *pMsdu;
  545. UINT32 packetHeaderLength;
  546. #ifndef NO_COPY_SKB
  547. char *pMsduData;
  548. #else
  549. mem_BD_T *pCurBd=0;
  550. #endif
  551. #ifdef DRIVER_PROFILE
  552. os_profile (drv, 0, 0);
  553. #endif
  554. bm_trace(20, skb->len, 0);
  555. #ifdef NO_COPY_SKB
  556. status = configMgr_allocMSDUBufferOnly(drv->adapter.CoreHalCtx, &pMsdu, OS_ABS_TX_MODULE);
  557. if(status != OK)
  558. {
  559. ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDUBufferOnly failed !!!\n");
  560. ++drv->alloc_msdu_failures;
  561. return -ENOMEM;
  562. }
  563. /* print_deb("$$$ configMgr_allocMSDUBufferOnly()=OK pMsdu=%p\n", pMsdu ); */
  564. status = configMgr_allocBDs(drv->adapter.CoreHalCtx, 1, &pCurBd);
  565. if(status != OK) {
  566. ++drv->alloc_msdu_failures;
  567. ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocBDs failed !!!\n");
  568. configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, pMsdu->handle);
  569. return -ENOMEM;
  570. }
  571. /* print_deb("$$$ configMgr_allocBDs()=OK pCurBd=%p first=%p\n", pCurBd, pMsdu->firstBDPtr ); */
  572. pMsdu->freeFunc = sendFreeFunc;
  573. pMsdu->freeArgs[0] = (UINT32) skb;
  574. pMsdu->dataLen = skb->len;
  575. pMsdu->firstBDPtr = pCurBd;
  576. pCurBd->dataOffset = skb->data-skb->head;
  577. pCurBd->length = skb->len;
  578. pCurBd->data = skb->head;
  579. drv->stats.tx_packets++;
  580. drv->stats.tx_bytes += skb->len;
  581. #else /* NO_COPY_SKB */
  582. /*
  583. * Retrieve the Packet Header length
  584. * from QoS Manager (through configMgr)
  585. * (Header type is determined upon association)
  586. */
  587. packetHeaderLength = configMgr_getPacketHeaderLength(drv->adapter.CoreHalCtx,skb->data,TX_DATA_DATA_MSDU);
  588. /*
  589. * need to reserve enough space for header translation
  590. * in the same first Bd.
  591. * Allocate enough place also for 802.11 header (24 bytes or 26 for QoS) and LLC (8 bytes)
  592. * to replace the Ethernet header (14 bytes)
  593. */
  594. status = configMgr_allocMSDU(drv->adapter.CoreHalCtx, &pMsdu,
  595. skb->len + packetHeaderLength, OS_ABS_TX_MODULE);
  596. if(status != OK)
  597. {
  598. /*ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDU failed !!!\n");*/
  599. ++drv->alloc_msdu_failures;
  600. return -ENOMEM;
  601. }
  602. /*
  603. * case 1: only legacy wlan header
  604. *
  605. * case 2: only QoS wlan header
  606. *
  607. * case 3: only legacy wlan header with new snap
  608. *
  609. * case 4: only QoS wlan header with new snap
  610. */
  611. pMsdu->firstBDPtr->dataOffset = packetHeaderLength - ETHERNET_HDR_LEN;
  612. pMsduData = pMsdu->firstBDPtr->data + pMsdu->firstBDPtr->dataOffset;
  613. memcpy(pMsduData, skb->data, skb->len);
  614. pMsdu->dataLen = skb->len;
  615. pMsdu->firstBDPtr->length = pMsdu->dataLen + pMsdu->firstBDPtr->dataOffset;
  616. drv->stats.tx_packets++;
  617. drv->stats.tx_bytes += skb->len;
  618. dev_kfree_skb(skb);
  619. #endif /* NO_COPY_SKB */
  620. pMsdu->txFlags |= TX_DATA_FROM_OS;
  621. pMsdu->qosTag = 0;
  622. status = OK;
  623. #ifdef TI_DBG
  624. /* Set packet-os-in time stamp */
  625. /* TODO: the skb time stamp is not good */
  626. /* printk ("\n### sec=%u, usec=%u", skb->stamp.tv_sec, skb->stamp.tv_usec);*/
  627. /* pMsdu->timeStamp[0] = skb->stamp.tv_sec * 1000000 + skb->stamp.tv_usec; */
  628. /* pMsdu->timeStampNum = 1; */
  629. #endif
  630. bm_trace(21, 0, 0);
  631. /*
  632. * Propagate Msdu through Config Manager.
  633. * Set DTag to zero
  634. * (note that classification is further handled in the Core)
  635. */
  636. if (status == OK) {
  637. #ifdef DM_USE_WORKQUEUE
  638. unsigned long flags;
  639. spin_lock_irqsave(&drv->lock, flags);
  640. tiwlan_add_msdu(drv, pMsdu);
  641. spin_unlock_irqrestore(&drv->lock, flags);
  642. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  643. #ifdef CONFIG_ANDROID_POWER
  644. android_lock_suspend( &drv->xmit_wake_lock );
  645. #endif
  646. queue_work( drv->tiwlan_wq, &drv->txmit );
  647. #else
  648. status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
  649. #endif
  650. }
  651. else
  652. configMgr_memMngrFreeMSDU (drv->adapter.CoreHalCtx, (UINT32) pMsdu); /* If status != OK , we won't send the MSDU, so we need to free it */
  653. if(unlikely(status != OK))
  654. {
  655. drv->stats.tx_errors++;
  656. #ifdef NO_COPY_SKB
  657. dev_kfree_skb(skb);
  658. #endif
  659. }
  660. bm_trace(22, 0, 0);
  661. #ifdef DRIVER_PROFILE
  662. os_profile (drv, 1, 0);
  663. #endif
  664. return 0;
  665. }
  666. struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev)
  667. {
  668. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
  669. ti_dprintf(TIWLAN_LOG_OTHER, "tiwlan_drv_net_get_stats()\n");
  670. return &drv->stats;
  671. }
  672. static int setup_netif(tiwlan_net_dev_t *drv)
  673. {
  674. struct net_device *dev;
  675. int res;
  676. dev = alloc_etherdev(0);
  677. if (dev == NULL)
  678. {
  679. ti_dprintf(TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n");
  680. return -ENOMEM;
  681. }
  682. ether_setup(dev);
  683. NETDEV_SET_PRIVATE(dev, drv);
  684. drv->netdev = dev;
  685. strcpy(dev->name, TIWLAN_DRV_IF_NAME);
  686. netif_carrier_off(dev);
  687. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
  688. dev->open = tiwlan_drv_net_open;
  689. dev->stop = tiwlan_drv_net_stop;
  690. dev->hard_start_xmit = tiwlan_drv_dummy_net_xmit;
  691. dev->get_stats = tiwlan_drv_net_get_stats;
  692. #else
  693. dev->netdev_ops = &tiwlan_ops_dummy;
  694. #endif
  695. dev->tx_queue_len = 100;
  696. res = tiwlan_ioctl_init(dev);
  697. if( res < 0 )
  698. {
  699. ti_dprintf(TIWLAN_LOG_ERROR, "tiwlan_ioctl_init() failed : %d\n", res);
  700. kfree(dev);
  701. return res;
  702. }
  703. res = register_netdev(dev);
  704. if (res != 0)
  705. {
  706. ti_dprintf(TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res);
  707. kfree(dev);
  708. return res;
  709. }
  710. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
  711. SET_MODULE_OWNER(dev);
  712. #endif
  713. return 0;
  714. }
  715. /* tiwlan_interrupt
  716. TIWLAN interrupt handler. Disables interrupts and awakes tasklet.
  717. */
  718. #if !(defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI))
  719. static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
  720. {
  721. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
  722. /*
  723. * Workaround for the Linux 2.6 pending IRQ bug:
  724. * If a pending IRQ is handled on a WLAN ISR, the ISR is called again
  725. * even though it disabled itself in the first call. To protect against
  726. * re-entrance, this flag is checked, and if it is already set (meaning
  727. * that the ISR is called twice before the tasklet was called) nothing is done.
  728. */
  729. if (drv->interrupt_pending == 0)
  730. {
  731. UINT32 interruptVector;
  732. interruptVector = configMgr_checkInterrupts(drv->adapter.CoreHalCtx);
  733. if (interruptVector != 0)
  734. {
  735. configMgr_disableInterrupts(drv->adapter.CoreHalCtx);
  736. drv->interrupt_pending = 1;
  737. tasklet_schedule (&drv->tl);
  738. }
  739. else
  740. {
  741. #if DEBUG_UNKNOWN_INTERRUPT
  742. ti_dprintf (TIWLAN_LOG_ERROR,
  743. "%s - ERROR - interrupt isn't TNET interrupt! interrupt vector = 0x%08X\n",
  744. __FUNCTION__, interruptVector);
  745. #endif
  746. }
  747. }
  748. return IRQ_HANDLED;
  749. }
  750. #else
  751. static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
  752. {
  753. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
  754. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  755. drv->interrupt_pending = 1;
  756. #ifdef DM_USE_WORKQUEUE
  757. #ifdef CONFIG_ANDROID_POWER
  758. android_lock_suspend( &drv->irq_wake_lock );
  759. #endif
  760. queue_work( drv->tiwlan_wq, &drv->tirq );
  761. /* disable_irq( drv->irq ); Dm: No need, we can loose IRQ */
  762. #else
  763. tasklet_schedule( &drv->tl );
  764. #endif
  765. return IRQ_HANDLED;
  766. }
  767. #endif
  768. static void tiwlan_poll_irq_handler(unsigned long parm)
  769. {
  770. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)parm;
  771. bm_trace(2, 0, 0);
  772. tiwlan_interrupt(0, drv, NULL);
  773. mod_timer(&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
  774. }
  775. static void tiwlan_handle_control_requests( tiwlan_net_dev_t *drv )
  776. {
  777. bm_trace(4, 0, 0);
  778. /* Handle control requests (timers, ioctls) */
  779. while(!list_empty(&drv->request_q))
  780. {
  781. struct list_head *entry = drv->request_q.next;
  782. tiwlan_req_t *req = list_entry(entry, tiwlan_req_t, list);
  783. tiwlan_req_t tmp_req;
  784. unsigned long flags;
  785. spin_lock_irqsave(&drv->lock, flags);
  786. list_del_init(entry);
  787. spin_unlock_irqrestore(&drv->lock, flags);
  788. ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d\n",
  789. __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected);
  790. tmp_req.u.req.p1 = 0x1234;
  791. tmp_req.u.req.p2 = 0x4321;
  792. tmp_req.u.req.p3 = 0x1221;
  793. tmp_req.u.req.p4 = 0x4334;
  794. tmp_req.u.req.reply_expected = 0x50;
  795. req->u.reply = req->u.req.f(req);
  796. if ((tmp_req.u.req.p1 != 0x1234) || (tmp_req.u.req.p2 != 0x4321) || (tmp_req.u.req.p3 != 0x1221) || (tmp_req.u.req.p4 != 0x4334) || (tmp_req.u.req.reply_expected != 0x50))
  797. {
  798. printk("\n\n !!! ERROR: STACK CORRUPTION !!! : \nf=%p\n", tmp_req.u.req.f);
  799. if (!req->u.req.reply_expected)
  800. printk("timer handler: %p\n", (void *)tmp_req.u.req.p1);
  801. }
  802. ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d reply=%d\n",
  803. __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected, req->u.reply);
  804. if (req->u.req.reply_expected)
  805. {
  806. ti_nodprintf(TIWLAN_LOG_INFO, "%s: about to awake task\n", __FUNCTION__);
  807. complete(&req->u.req.comp);
  808. }
  809. }
  810. bm_trace(5, 0, 0);
  811. /* DbgCB_Insert(0, DBG_MODULE_OS, DBG_TYPE_TASKLET, 1)*/
  812. }
  813. #ifdef DM_USE_WORKQUEUE
  814. static void tiwlan_irq_handler( struct work_struct *work )
  815. {
  816. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tirq );
  817. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  818. #ifdef CONFIG_ANDROID_POWER
  819. android_lock_suspend( &drv->exec_wake_lock );
  820. android_unlock_suspend( &drv->irq_wake_lock );
  821. #endif
  822. /* if the driver was unloaded by that time we need to ignore all the timers */
  823. if (drv->unload_driver) {
  824. #ifdef CONFIG_ANDROID_POWER
  825. android_unlock_suspend( &drv->exec_wake_lock );
  826. #endif
  827. /* enable_irq( drv->irq ); */
  828. return;
  829. }
  830. configMgr_handleInterrupts( drv->adapter.CoreHalCtx );
  831. tiwlan_handle_control_requests( drv );
  832. #ifdef CONFIG_ANDROID_POWER
  833. if( drv->receive_packet ) {
  834. drv->receive_packet = 0;
  835. /* Keep awake for 500 ms to give a chance to network stack */
  836. android_lock_suspend_auto_expire( &drv->rx_wake_lock, HZ );
  837. }
  838. android_unlock_suspend( &drv->exec_wake_lock );
  839. #endif
  840. /* enable_irq( drv->irq ); */
  841. }
  842. #endif
  843. /* tiwlan_tasklet_handler
  844. WLAN protocol tasklet. Most of work happens in the
  845. context of this tasklet.
  846. */
  847. #ifdef DM_USE_WORKQUEUE
  848. static void tiwlan_work_handler( struct work_struct *work )
  849. #else
  850. static void tiwlan_tasklet_handler( unsigned long netdrv )
  851. #endif
  852. {
  853. #ifdef DM_USE_WORKQUEUE
  854. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tw );
  855. #else
  856. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
  857. #endif
  858. #ifdef STACK_PROFILE
  859. unsigned int curr1, base1;
  860. unsigned int curr2, base2;
  861. static unsigned int maximum_stack = 0;
  862. #endif
  863. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  864. #ifdef CONFIG_ANDROID_POWER
  865. android_lock_suspend( &drv->exec_wake_lock );
  866. android_unlock_suspend( &drv->timer_wake_lock );
  867. #endif
  868. /* if the driver was unloaded by that time we need to ignore all the timers */
  869. if (drv->unload_driver) {
  870. #ifdef CONFIG_ANDROID_POWER
  871. android_unlock_suspend( &drv->exec_wake_lock );
  872. #endif
  873. return;
  874. }
  875. #if 0
  876. ti_dprintf(TIWLAN_LOG_INFO, "%s in\n" , __FUNCTION__);
  877. #endif
  878. #ifdef DRIVER_PROFILE
  879. os_profile (drv, 0, 0);
  880. #endif
  881. bm_trace(3, 0, 0);
  882. #ifdef STACK_PROFILE
  883. curr1 = check_stack_start(&base1);
  884. #endif
  885. /* Handle bus transaction interrupts */
  886. if (drv->dma_done)
  887. {
  888. drv->dma_done = 0;
  889. configMgr_HandleBusTxn_Complete(drv->adapter.CoreHalCtx);
  890. }
  891. /* don't call for "Handle interrupts, timers, ioctls" while recovery process */
  892. if (configMgr_areInputsFromOsDisabled(drv->adapter.CoreHalCtx) == TRUE) {
  893. #ifdef CONFIG_ANDROID_POWER
  894. android_unlock_suspend( &drv->exec_wake_lock );
  895. #endif
  896. return;
  897. }
  898. /* Handle firmware interrupts */
  899. #ifndef DM_USE_WORKQUEUE
  900. if (drv->interrupt_pending)
  901. {
  902. drv->interrupt_pending = 0;
  903. configMgr_handleInterrupts(drv->adapter.CoreHalCtx);
  904. }
  905. #endif
  906. tiwlan_handle_control_requests( drv );
  907. #ifdef STACK_PROFILE
  908. curr2 = check_stack_stop(&base2);
  909. if (base2 == base1)
  910. {
  911. /* if the current measurement is bigger then the maximum store it and print*/
  912. if ((curr1 - curr2) > maximum_stack)
  913. {
  914. printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n");
  915. printk("current operation stack use =%d \n",(curr1 - curr2));
  916. printk("total stack use=%d \n",8192 - curr2 + base2);
  917. printk("total stack usage= %d percent \n",100 * (8192 - curr2 + base2) / 8192);
  918. maximum_stack = curr1 - curr2;
  919. }
  920. }
  921. #endif
  922. #ifdef DRIVER_PROFILE
  923. os_profile (drv, 1, 0);
  924. #endif
  925. #if 0
  926. ti_dprintf(TIWLAN_LOG_INFO, "%s out\n" , __FUNCTION__);
  927. #endif
  928. #ifdef CONFIG_ANDROID_POWER
  929. android_unlock_suspend( &drv->exec_wake_lock );
  930. #endif
  931. }
  932. #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
  933. static void tiwlan_rx_watchdog(struct work_struct *work)
  934. {
  935. struct delayed_work *dwork = (struct delayed_work *) container_of(work, struct delayed_work, work);
  936. tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( dwork, struct tiwlan_net_dev, trxw );
  937. unsigned long num_rx_pkts = num_rx_pkt_new - num_rx_pkt_last;
  938. /* Contribute 10mA (200mA x 5%) for 1 pkt/sec, and plus 8mA base. */
  939. unsigned percent = (5 * num_rx_pkts / RX_RATE_INTERVAL_SEC) + PWRSINK_WIFI_PERCENT_BASE;
  940. if (drv->unload_driver)
  941. return;
  942. percent = (percent > 100) ? 100 : percent;
  943. /* printk(KERN_INFO "num_rx_pkts=%ld, percent=%d\n", num_rx_pkts, percent); */
  944. #ifdef CONFIG_HTC_PWRSINK
  945. htc_pwrsink_set(PWRSINK_WIFI, percent);
  946. #else
  947. trout_pwrsink_set(PWRSINK_WIFI, percent);
  948. #endif
  949. num_rx_pkt_last = num_rx_pkt_new;
  950. if (drv && drv->tiwlan_wq)
  951. queue_delayed_work(drv->tiwlan_wq, &drv->trxw, msecs_to_jiffies(MSEC_PER_SEC * RX_RATE_INTERVAL_SEC));
  952. }
  953. #endif
  954. /* tiwlan_send_wait_reply
  955. This internal interface function creates request and sends
  956. it to the control tasklet for processing.
  957. The calling process is blocked until the request is replied.
  958. Function f is being called in the context of the control tasklet.
  959. The request block that is passed to the function as a parameter
  960. contains p1, p2, p3, p4.
  961. The function return code is propagated back to the caller.
  962. tiwlan_send_req_and_wait returns (*f) return code or
  963. -ENOMEM if failed to allocate a request.
  964. */
  965. int tiwlan_send_wait_reply(tiwlan_net_dev_t *drv,
  966. int (*f)(tiwlan_req_t *req),
  967. unsigned long p1,
  968. unsigned long p2,
  969. unsigned long p3,
  970. unsigned long p4)
  971. {
  972. tiwlan_req_t req;
  973. unsigned long flags;
  974. /* Send request to tiwlan_tasklet and wait for reply */
  975. if (!drv->adapter.CoreHalCtx) {
  976. return STATION_IS_NOT_RUNNING;
  977. }
  978. req.drv = drv;
  979. req.u.req.f = f;
  980. req.u.req.p1 = p1;
  981. req.u.req.p2 = p2;
  982. req.u.req.p3 = p3;
  983. req.u.req.p4 = p4;
  984. req.u.req.reply_expected = 1;
  985. init_completion(&req.u.req.comp);
  986. spin_lock_irqsave(&drv->lock, flags);
  987. list_add_tail(&req.list, &drv->request_q);
  988. spin_unlock_irqrestore(&drv->lock, flags);
  989. #ifdef DM_USE_WORKQUEUE
  990. /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
  991. #ifdef CONFIG_ANDROID_POWER
  992. android_lock_suspend( &drv->timer_wake_lock );
  993. #endif
  994. queue_work( drv->tiwlan_wq, &drv->tw );
  995. #else
  996. tasklet_schedule( &drv->tl );
  997. #endif
  998. wait_for_completion(&req.u.req.comp);
  999. return req.u.reply;
  1000. }
  1001. #define WLAN_PCMCIA_CFG_REG 0x0524
  1002. /* tiwlan_set_hw_access */
  1003. static int tiwlan_set_hw_access(tiwlan_net_dev_t *drv)
  1004. {
  1005. #ifdef TIWLAN_OMAP1610
  1006. OS_WRITE_REG(drv, HI_CFG, 0x00000a00);
  1007. #if ! ((defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI)) && defined(TNETW1150))
  1008. OS_WRITE_REG(drv, WLAN_PCMCIA_CFG_REG, 0xC6880000);
  1009. OS_WRITE_REG(drv, PCI_ARB_CFG, 0x2);
  1010. #endif
  1011. #endif
  1012. return 0;
  1013. }
  1014. /* tiwlan_free_drv
  1015. Unmap h/w regions and free driver's structure
  1016. */
  1017. static void tiwlan_free_drv(tiwlan_net_dev_t *drv)
  1018. {
  1019. #ifdef TIWLAN_OMAP1610
  1020. if (drv->acx_mem.pa && drv->acx_mem.va)
  1021. iounmap(drv->acx_mem.va);
  1022. if (drv->acx_reg.pa && drv->acx_reg.va && drv->acx_reg.va != drv->acx_reg.va)
  1023. iounmap(drv->acx_reg.va);
  1024. #endif
  1025. kfree(drv);
  1026. }
  1027. /* tiwlan_alloc_drv
  1028. Allocate driver's structure and map h/w regions
  1029. */
  1030. static tiwlan_net_dev_t *
  1031. tiwlan_alloc_drv(unsigned long reg_start, unsigned long reg_size,
  1032. unsigned long mem_start, unsigned long mem_size,
  1033. int map_io, int irq)
  1034. {
  1035. static tiwlan_net_dev_t *drv;
  1036. drv = kmalloc(sizeof(tiwlan_net_dev_t), GFP_KERNEL);
  1037. #ifdef TI_MEM_ALLOC_TRACE
  1038. os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(tiwlan_net_dev_t), GFP_KERNEL, sizeof(tiwlan_net_dev_t));
  1039. #endif/*I_MEM_ALLOC_TRACE*/
  1040. if (!drv)
  1041. return NULL;
  1042. memset(drv, 0, sizeof(tiwlan_net_dev_t));
  1043. drv->acx_mem.size = mem_size;
  1044. drv->acx_reg.size = reg_size;
  1045. #ifdef TIWLAN_OMAP1610
  1046. if (map_io)
  1047. {
  1048. drv->acx_mem.pa = mem_start;
  1049. drv->acx_reg.pa = reg_start;
  1050. drv->acx_mem.va = ioremap(drv->acx_mem.pa, drv->acx_mem.size);
  1051. if (drv->acx_mem.pa!=drv->acx_reg.pa || drv->acx_mem.size!=drv->acx_reg.size)
  1052. drv->acx_reg.va = ioremap(drv->acx_reg.pa, drv->acx_reg.size);
  1053. else
  1054. drv->acx_reg.va = drv->acx_mem.va;
  1055. }
  1056. else
  1057. {
  1058. /* Memory is already mapped */
  1059. drv->acx_mem.va = (void *)mem_start;
  1060. drv->acx_reg.va = (void *)reg_start;
  1061. }
  1062. #endif /* Dm: */
  1063. drv->irq = irq;
  1064. return drv;
  1065. }
  1066. /* tiwlan_init_drv
  1067. Called in process context
  1068. */
  1069. int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
  1070. {
  1071. initTable_t *init_table;
  1072. int rc;
  1073. void *pWLAN_Images[4];
  1074. /* printk("%s\n", __FUNCTION__); */
  1075. /* It is OK if already initialized */
  1076. if (drv->adapter.CoreHalCtx)
  1077. return 0;
  1078. init_table = os_memoryAlloc (drv, sizeof(initTable_t));
  1079. #ifdef TI_MEM_ALLOC_TRACE
  1080. osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(initTable_t), GFP_KERNEL, sizeof(initTable_t));
  1081. #endif/*I_MEM_ALLOC_TRACE*/
  1082. if (!init_table)
  1083. {
  1084. ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate init_table\n");
  1085. return -ENOMEM;
  1086. }
  1087. if (init_info)
  1088. {
  1089. drv->eeprom_image.size = init_info->eeprom_image_length;
  1090. if (drv->eeprom_image.size)
  1091. {
  1092. drv->eeprom_image.va = os_memoryAlloc (drv, drv->eeprom_image.size);
  1093. #ifdef TI_MEM_ALLOC_TRACE
  1094. osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, GFP_KERNEL, drv->eeprom_image.size);
  1095. #endif
  1096. if (!drv->eeprom_image.va)
  1097. {
  1098. ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for eeprom image\n");
  1099. drv->eeprom_image.size = 0;
  1100. return -ENOMEM;
  1101. }
  1102. memcpy (drv->eeprom_image.va, &init_info->data[0], drv->eeprom_image.size );
  1103. }
  1104. #ifdef FIRMWARE_DYNAMIC_LOAD
  1105. drv->firmware_image.size = init_info->firmware_image_length;
  1106. if (!drv->firmware_image.size)
  1107. {
  1108. ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n");
  1109. return -EINVAL;
  1110. }
  1111. drv->firmware_image.va = os_memoryAlloc (drv,drv->firmware_image.size);
  1112. #ifdef TI_MEM_ALLOC_TRACE
  1113. osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->firmware_image.size, GFP_KERNEL, drv->firmware_image.size);
  1114. #endif
  1115. if (!drv->firmware_image.va)
  1116. {
  1117. ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n");
  1118. drv->firmware_image.size = 0;
  1119. if (drv->eeprom_image.va)
  1120. os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
  1121. return -ENOMEM;
  1122. }
  1123. memcpy (drv->firmware_image.va,
  1124. &init_info->data[init_info->eeprom_image_length],
  1125. drv->firmware_image.size);
  1126. #else
  1127. extern unsigned char tiwlan_fwimage[];
  1128. extern unsigned int sizeof_tiwlan_fwimage;
  1129. drv->firmware_image.size = sizeof_tiwlan_fwimage;
  1130. drv->firmware_image.va = tiwlan_fwimage;
  1131. #endif
  1132. }
  1133. print_deb ("--------- Eeeprom=%p(%lu), Firmware=%p(%lu)\n",
  1134. drv->eeprom_image.va,
  1135. drv->eeprom_image.size,
  1136. drv->firmware_image.va,
  1137. drv->firmware_image.size);
  1138. /* Init defaults */
  1139. if ((rc = osInitTable_IniFile (drv,
  1140. init_table,
  1141. (init_info && init_info->init_file_length) ?
  1142. &init_info->data[init_info->eeprom_image_length+init_info->firmware_image_length] : NULL,
  1143. init_info ? init_info->init_file_length : 0)))
  1144. {
  1145. ti_dprintf (TIWLAN_LOG_ERROR, "osInitTable_IniFile failed :cannot initialize defaults\n");
  1146. os_memoryFree (drv, init_table, sizeof(initTable_t));
  1147. #ifdef TI_MEM_ALLOC_TRACE
  1148. os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
  1149. #endif
  1150. return rc;
  1151. }
  1152. pWLAN_Images[0] = (void *)drv->firmware_image.va;
  1153. pWLAN_Images[1] = (void *)drv->firmware_image.size;
  1154. pWLAN_Images[2] = (void *)drv->eeprom_image.va;
  1155. pWLAN_Images[3] = (void *)drv->eeprom_image.size;
  1156. drv->adapter.CoreHalCtx = configMgr_create (drv,
  1157. pWLAN_Images,
  1158. init_table,
  1159. (macAddress_t *) &drv->adapter.CurrentAddr);
  1160. if (!(drv->adapter.CoreHalCtx))
  1161. {
  1162. #ifdef FIRMWARE_DYNAMIC_LOAD
  1163. os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
  1164. os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
  1165. #endif
  1166. os_memoryFree (drv, init_table, sizeof(initTable_t));
  1167. ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate CoreHalCtx\n");
  1168. return -ENOMEM;
  1169. }
  1170. drv->interrupt_pending = 0;
  1171. drv->dma_done = 0;
  1172. if (drv->irq)
  1173. {
  1174. #ifndef PRIODIC_INTERRUPT
  1175. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
  1176. unsigned long flags;
  1177. /*
  1178. * Disable all interrupts for not to catch the tiwlan irq
  1179. * between request_irq and disable_irq
  1180. */
  1181. spin_lock_irqsave (&(drv->lock), flags);
  1182. if ((rc = request_irq (drv->irq, tiwlan_interrupt, SA_SHIRQ, drv->netdev->name, drv)))
  1183. #else
  1184. if ((rc = request_irq (drv->irq, (irq_handler_t)tiwlan_interrupt, IRQF_SHARED | IRQF_TRIGGER_FALLING /*Dm:*/, drv->netdev->name, drv)))
  1185. #endif
  1186. {
  1187. print_err ("TIWLAN: Failed to register interrupt handler\n");
  1188. configMgr_stop (drv->adapter.CoreHalCtx);
  1189. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
  1190. spin_unlock_irqrestore (&drv->lock, flags);
  1191. #endif
  1192. return rc;
  1193. }
  1194. #ifdef CONFIG_ANDROID_POWER
  1195. set_irq_wake(drv->irq, 1);
  1196. #endif
  1197. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
  1198. set_irq_type (drv->irq, IRQT_FALLING);
  1199. #else
  1200. set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
  1201. #endif
  1202. disable_irq (drv->irq);
  1203. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
  1204. spin_unlock_irqrestore (&drv->lock, flags);
  1205. #endif
  1206. #else
  1207. printk (" tiwlan_init_drv :PRIODIC_INTERRUPT drv->irq %x\n",drv->irq);
  1208. #endif
  1209. }
  1210. else
  1211. {
  1212. /* Debug mode: polling */
  1213. mod_timer (&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
  1214. }
  1215. /*
  1216. * Now that all parts of the driver have been created and handles linked
  1217. * proceed to download the FW code
  1218. */
  1219. configMgr_init (drv,
  1220. drv->adapter.CoreHalCtx,
  1221. pWLAN_Images,
  1222. init_table,
  1223. (macAddress_t *) &drv->adapter.CurrentAddr);
  1224. /* Wait for the download to complete */
  1225. os_WaitComplete ((void *)drv);
  1226. os_memoryFree (drv, init_table, sizeof(initTable_t));
  1227. if (rc == OK)
  1228. {
  1229. proc_stat_init (drv->adapter.CoreHalCtx);
  1230. #ifdef TI_MEM_ALLOC_TRACE
  1231. osPrintf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
  1232. #endif/*I_MEM_ALLOC_TRACE*/
  1233. if (drv->adapter.CoreHalCtx == NULL)
  1234. {
  1235. ti_dprintf (TIWLAN_LOG_ERROR, "configMgr_create failed\n");
  1236. return -ENODEV;
  1237. }
  1238. /* eeprom buffer is going to be deallocated by the caller. It is no longer needed anyway */
  1239. #if 0
  1240. drv->eeprom_image.va = NULL;
  1241. drv->eeprom_image.size = 0;
  1242. #endif
  1243. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
  1244. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
  1245. drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, THIS_MODULE); /* Dm: */
  1246. #else
  1247. drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
  1248. #endif
  1249. #else
  1250. drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
  1251. #endif
  1252. if (drv->wl_sock == NULL)
  1253. {
  1254. ti_dprintf(TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n");
  1255. /* TODO: free in destroy */
  1256. return -EINVAL;
  1257. }
  1258. /* Finalize network interface setup */
  1259. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
  1260. drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit;
  1261. #else
  1262. drv->netdev->netdev_ops = &tiwlan_ops_pri;
  1263. #endif
  1264. memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN);
  1265. drv->netdev->addr_len = MAC_ADDR_LEN;
  1266. /* Register the relevant events with the event handler */
  1267. tiwlan_register_events (drv);
  1268. /* Mark that init stage has succeded */
  1269. drv->initialized = 1;
  1270. return 0;
  1271. }
  1272. return -ENODEV;
  1273. }
  1274. #ifdef CONFIG_ANDROID_POWER
  1275. #ifndef CONFIG_HAS_WAKELOCK
  1276. /* Wrapper for Init wake lock */
  1277. static void android_init_suspend_wakelock(android_suspend_lock_t *lp,char *nm)
  1278. {
  1279. lp->name = nm;
  1280. android_init_suspend_lock( lp );
  1281. }
  1282. #endif
  1283. #endif
  1284. /* tiwlan_start_drv
  1285. */
  1286. int tiwlan_start_drv(tiwlan_net_dev_t *drv)
  1287. {
  1288. /* printk("%s\n", __FUNCTION__); */
  1289. if (!drv->initialized)
  1290. {
  1291. ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before initilization has succeeded\n");
  1292. return -ENODEV;
  1293. }
  1294. if (!drv->adapter.CoreHalCtx)
  1295. {
  1296. ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before creating config_manager\n");
  1297. return -ENODEV;
  1298. }
  1299. if (drv->started)
  1300. {
  1301. /*ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver that has already started\n");*/
  1302. return -EALREADY;
  1303. }
  1304. if (configMgr_start(drv->adapter.CoreHalCtx) != OK)
  1305. {
  1306. print_err("TIWLAN: Failed to start config manager\n");
  1307. return -EINVAL;
  1308. }
  1309. drv->started = 1;
  1310. #ifdef SDIO_INTERRUPT_HANDLING_ON
  1311. configMgr_SlaveAckMaskNotification(drv->adapter.CoreHalCtx);
  1312. #endif
  1313. if (drv->netdev)
  1314. netif_start_queue(drv->netdev);
  1315. #ifdef CONFIG_TROUT_PWRSINK
  1316. trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
  1317. #endif
  1318. #ifdef CONFIG_HTC_PWRSINK
  1319. htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
  1320. #endif
  1321. export_wifi_fw_version(drv);
  1322. return 0;
  1323. }
  1324. /* tiwlan_destroy_drc
  1325. */
  1326. static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv)
  1327. {
  1328. int waitShutdownCounter;
  1329. /* close the ipc_kernel socket*/
  1330. if (drv && drv->wl_sock) {
  1331. sock_release(drv->wl_sock->sk_socket);
  1332. }
  1333. bm_destroy();
  1334. if (drv->started)
  1335. tiwlan_send_wait_reply(drv, tiwlan_stop_and_destroy_drv_request, 0, 0, 0, 0);
  1336. else
  1337. tiwlan_stop_and_destroy_drv(drv);
  1338. #ifdef DM_USE_WORKQUEUE
  1339. while( tiwlan_del_msdu(drv) != NULL );
  1340. #endif
  1341. if (drv->adapter.CoreHalCtx)
  1342. {
  1343. /* Delay return to OS until all driver components (HAL/SME) are shutdown */
  1344. for (waitShutdownCounter=1; waitShutdownCounter<=DRV_SHUTDOWN_TEST_MAX_COUNTER; waitShutdownCounter++)
  1345. {
  1346. /* Check if HAL/SME are stopped - If so - exit loop and return to OS */
  1347. if (configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx) == DRIVER_SHUTDOWN_COMPLETE)
  1348. {
  1349. break;
  1350. }
  1351. /* Delay of 100ms between shutdown test */
  1352. mdelay ( DRV_SHUTDOWN_TEST_DELAY_INTERVAL );
  1353. }
  1354. /* If driver was not shutdown properly - destroy all timers "manually" and exit*/
  1355. if ( waitShutdownCounter == DRV_SHUTDOWN_TEST_MAX_COUNTER+1 )
  1356. {
  1357. os_printf("Timeout while waiting for driver to shutdown...Shutdown status flag=0x%x\n",configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx));
  1358. }
  1359. /* drv->unload_driver = 1; Dm: moved to tiwlan_stop_and_destroy_drv */
  1360. proc_stat_destroy();
  1361. if (drv->irq) {
  1362. #ifdef CONFIG_ANDROID_POWER
  1363. set_irq_wake(drv->irq, 0);
  1364. #endif
  1365. free_irq(drv->irq, drv);
  1366. }
  1367. else
  1368. del_timer_sync(&drv->poll_timer);
  1369. #ifdef DM_USE_WORKQUEUE
  1370. flush_work(&drv->tirq);
  1371. flush_work(&drv->tw);
  1372. flush_work(&drv->txmit);
  1373. #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
  1374. cancel_delayed_work_sync(&drv->trxw);
  1375. #endif
  1376. #endif
  1377. /* Unload all modules (free memory) & destroy timers */
  1378. configMgr_UnloadModules (drv->adapter.CoreHalCtx);
  1379. #ifdef FIRMWARE_DYNAMIC_LOAD
  1380. if( drv->firmware_image.va ) {
  1381. os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
  1382. #ifdef TI_MEM_ALLOC_TRACE
  1383. os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->firmware_image.size, -drv->firmware_image.size);
  1384. #endif /*I_MEM_ALLOC_TRACE*/
  1385. }
  1386. if( drv->eeprom_image.va )
  1387. {
  1388. os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
  1389. #if

Large files files are truncated, but you can click here to view the full file