Home | History | Annotate | Download | only in src
      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 
     36 #include <linux/module.h>
     37 #include <linux/kernel.h>
     38 #include <linux/version.h>
     39 #include <net/sock.h>
     40 #include <linux/init.h>
     41 #include <linux/fs.h>
     42 #include <linux/netdevice.h>
     43 #include <linux/ioctl.h>
     44 #include <linux/wireless.h>
     45 #include <linux/etherdevice.h>
     46 #include <linux/netlink.h>
     47 #include <linux/completion.h>
     48 
     49 #ifdef TIWLAN_CARDBUS
     50 #include <linux/pci.h>
     51 #else
     52 #ifdef TIWLAN_OMAP1610
     53 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
     54 #include <asm/arch-omap/tc.h>
     55 #else
     56 #include <mach/tc.h>
     57 #endif
     58 #endif
     59 #ifdef TIWLAN_MSM7000
     60 #include <linux/mmc/core.h>
     61 #include <linux/mmc/card.h>
     62 #include <linux/mmc/sdio_func.h>
     63 #include <linux/mmc/sdio_ids.h>
     64 #endif
     65 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
     66 #include <asm/arch/io.h>
     67 #include <asm/arch/hardware.h>
     68 #include <asm/arch/irqs.h>
     69 #else
     70 #include <mach/io.h>
     71 #include <mach/hardware.h>
     72 #include <mach/irqs.h>
     73 #endif
     74 #endif   /* !TIWLAN_CARDBUS */
     75 
     76 #include <linux/list.h>
     77 #include <linux/spinlock.h>
     78 #include <linux/if_arp.h>
     79 #include <linux/proc_fs.h>
     80 #include <linux/mm.h>
     81 #include <linux/delay.h>
     82 #include <linux/vmalloc.h>
     83 #include <linux/irq.h>
     84 
     85 #include <asm/io.h>
     86 #include <asm/uaccess.h>
     87 #include <asm/pgtable.h>
     88 
     89 #include "esta_drv.h"
     90 #include "srcApi.h"
     91 #include "osApi.h"
     92 #include "whalHwRegs.h"
     93 
     94 #if defined(DEBUG_UNKNOWN_INTERRUPT)
     95 #define _STRING_H
     96 #include "configMgr.h"
     97 #include "whalCtrl.h"
     98 #endif
     99 
    100 #include "bmtrace.h"
    101 #include "osrgstry_parser.h"
    102 #include "osClsfr.h"
    103 #include "TI_IPC_Api.h"
    104 #include "802_11Defs.h"
    105 #include "Ethernet.h"
    106 #include "tiwlan_profile.h"
    107 
    108 #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
    109 #define RX_RATE_INTERVAL_SEC 10
    110 unsigned long num_rx_pkt_new = 0;
    111 static unsigned long num_rx_pkt_last = 0;
    112 #endif
    113 
    114 #ifdef TIWLAN_MSM7000
    115 extern unsigned char *get_wifi_nvs_ram(void);
    116 extern void SDIO_SetFunc( struct sdio_func * );
    117 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
    118 static struct proc_dir_entry *tiwlan_calibration;
    119 #endif
    120 static struct completion sdio_wait;
    121 #ifdef CONFIG_WIFI_CONTROL_FUNC
    122 static struct wifi_platform_data *wifi_control_data = NULL;
    123 #endif
    124 #endif
    125 
    126 /* WiFi chip information functions */
    127 int export_wifi_fw_version( tiwlan_net_dev_t *drv );
    128 int export_wifi_chip_id( void );
    129 
    130 /* Drivers list */
    131 static LIST_HEAD(tiwlan_drv_list);
    132 
    133 /* debug memory access */
    134 static struct proc_dir_entry *tiwlan_deb_entry;
    135 static __u32 memdebug_addr;
    136 static __u32 memdebug_size=1;
    137 static __u32 memdebug_trans_size;
    138 
    139 #define DRV_SHUTDOWN_TEST_DELAY_INTERVAL 100       /* Time in msec to "delay"(/sleep) while waiting for SME to shutdown */
    140 #define DRV_SHUTDOWN_TEST_MAX_COUNTER  20          /* How many delay/sleep iterations to perform while waiting for SME to shutdown) */
    141 
    142 MODULE_DESCRIPTION("TI WLAN Embedded Station Driver");
    143 MODULE_LICENSE("GPL");
    144 
    145 extern int packed_struct_tst(void);
    146 extern int proc_stat_init(TI_HANDLE);
    147 extern int proc_stat_destroy(void);
    148 
    149 typedef void (* tiwlan_drv_isr_t)(int, void *, struct pt_regs *);
    150 
    151 /* network device driver interface */
    152 static int tiwlan_drv_net_open(struct net_device * dev);
    153 static int tiwlan_drv_net_stop(struct net_device * dev);
    154 static int tiwlan_drv_net_xmit(struct sk_buff * skb, struct net_device * dev);
    155 static int tiwlan_drv_dummy_net_xmit(struct sk_buff * skb, struct net_device * dev);
    156 static struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev);
    157 int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
    158 
    159 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
    160 static struct net_device_ops tiwlan_ops_pri = {
    161 	.ndo_open = tiwlan_drv_net_open,
    162 	.ndo_stop = tiwlan_drv_net_stop,
    163 	.ndo_get_stats = tiwlan_drv_net_get_stats,
    164 	.ndo_do_ioctl = ti1610_do_ioctl,
    165 	.ndo_start_xmit = tiwlan_drv_net_xmit,
    166 };
    167 
    168 static struct net_device_ops tiwlan_ops_dummy = {
    169 	.ndo_open = tiwlan_drv_net_open,
    170 	.ndo_stop = tiwlan_drv_net_stop,
    171 	.ndo_get_stats = tiwlan_drv_net_get_stats,
    172 	.ndo_do_ioctl = ti1610_do_ioctl,
    173 	.ndo_start_xmit = tiwlan_drv_dummy_net_xmit,
    174 };
    175 #endif
    176 
    177 #define OS_WRITE_REG(drv,reg,val)   \
    178     os_hwWriteMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), (__u32)(val))
    179 
    180 #define OS_READ_REG(drv,reg,val)    \
    181     os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), &val)
    182 
    183 #ifdef TIWLAN_OMAP1610
    184 static void omap_memif_init(void)
    185 {
    186     printk ("First function offset is: %p\n", omap_memif_init);
    187 #if defined(TIWLAN_OMAP1610_INNOVATOR)
    188     print_info("Setting CS1 Ref Clock = TC/4. \n");
    189     omap_writel(0x00000004, 0xFFFECC40 ); /* wlan change for cs2 to dynamic wait state */
    190     omap_writel(0x0000113a, 0xFFFECC18 ); /* EMIFS (nCS2) configuration */
    191 #elif defined(TIWLAN_OMAP1610_WIPP) || defined(TIWLAN_OMAP1610_CRTWIPP)
    192 
    193 #if defined(TIWLAN_OMAP1610_CRTWIPP)
    194     /*
    195     Init the GPIO to output*/
    196 
    197     /* Set OMAP pin H19 to GPIO57*/
    198 
    199     omap_writel(omap_readl(0xFFFE1014) | 0x00E00000, 0xFFFE1014 );
    200 
    201     /*ELP_REQ (GPIO_57) by GPIO_DIRECTION - set it as output*/
    202     omap_writel(omap_readl(0xFFFBBC34) & (~0x00000200), 0xFFFBBC34 );
    203 #endif  /* TIWLAN_OMAP1610_CRTWIPP */
    204 
    205 /* The below configuration enables GPIO25 and GPIO_27 as output GPIOs - for debug purposes */
    206 #if defined(TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG)
    207 
    208     omap_writel(omap_readl(0xFFFE1030) | 0x00000E00, 0xFFFE1030 );/* enable GPIO25 */
    209     omap_writel(omap_readl(0xFFFE1030) | 0x00000038, 0xFFFE1030 );/* enable GPIO27 */
    210 
    211     omap_writel(omap_readl(0xFFFBEC34) & (~0x00000200), 0xFFFBEC34 );/* Setting direction (as output) for GPIO25 */
    212     omap_writel(omap_readl(0xFFFBEC34) & (~0x00000800), 0xFFFBEC34 );/* Setting direction (as output) for GPIO27 */
    213 #endif   /* TIWLAN_OMAP1610_CRTWIPP_GPIO_DEBUG */
    214 
    215 
    216     /* RECOVERY*/
    217     print_info("Hard reset,perform PMEN toggle\n");
    218     os_hardResetTnetw();
    219 
    220     print_info("Setting CS2 Ref Clock = TC/2. \n");
    221     __raw_writel(0x1, TIWLAN_OMAP1610_REGBASE+0x4cc); /* CLK=80MHz */
    222     omap_writel(0x20, EMIF_CFG_DYNAMIC_WS); /* Full handshake on CS2 */
    223     omap_writel(0x2441, EMIFS_CS2_CONFIG); /* 0x2021 on reworked board */
    224     omap_writel(0, EMIFS_ACS2);
    225 
    226     print_info("%x=0x%lx\n", 0xFFFECC40, omap_readl(0xFFFECC40) );
    227     print_info("%x=0x%lx\n", 0xFFFECC18, omap_readl(0xFFFECC18) );
    228     print_info("%x=0x%lx\n", 0xFFFECC58, omap_readl(0xFFFECC58) );
    229 #endif /* WIPP, CRTWIPP */
    230 }
    231 #endif
    232 
    233 static int tiwlan_register_events(tiwlan_net_dev_t *drv)
    234 {
    235     IPC_EVENT_PARAMS evParams;
    236     int i = 0;
    237 
    238     evParams.uDeliveryType      = DELIVERY_PUSH;
    239     evParams.uProcessID         = 0;
    240     evParams.uEventID           = 0;
    241     evParams.hUserParam        = drv;
    242     evParams.pfEventCallback    = os_IndicateEvent;
    243 
    244 
    245     for (;i < IPC_EVENT_MAX_OS_EVENT;i++)
    246     {
    247         evParams.uEventType = i;
    248 
    249         configMgr_RegisterEvent(drv->adapter.CoreHalCtx,(PUCHAR) &evParams,sizeof(IPC_EVENT_PARAMS));
    250     }
    251 
    252     return OK;
    253 }
    254 
    255 static int tiwlan_deb_read_proc(char *page, char **start, off_t off,
    256                                 int count, int *eof, void *data)
    257 {
    258     __u32 addr=memdebug_addr;
    259     __u32 size=memdebug_size;
    260     __u32 trans_size=memdebug_trans_size;
    261     __u32 end;
    262     int in_line=0, max_in_line;
    263     int limit=count-80;
    264     int i=0;
    265     static int toggle;
    266 
    267     *eof = 1;
    268     if (!addr || !trans_size)
    269         return 0;
    270 
    271     /* fixme: add address validation */
    272 
    273     if (!size)
    274         size=1;
    275 
    276     end = addr + size*trans_size;
    277     if (trans_size==4)
    278         max_in_line = 4;
    279     else if (trans_size==2)
    280         max_in_line = 8;
    281     else
    282         max_in_line = 16;
    283 
    284     while(i<limit && addr<end)
    285     {
    286         if (!in_line)
    287             i += sprintf(page+i, "0x%08x: ", addr);
    288         if (trans_size==4)
    289         {
    290             i += sprintf(page+i, "0x%08x", *(__u32 *)addr);
    291             addr += 4;
    292         }
    293         else if (trans_size==2)
    294         {
    295             i += sprintf(page+i, "0x%04x", *(__u16 *)addr);
    296             addr += 2;
    297         }
    298         else
    299         {
    300             i += sprintf(page+i, "0x%02x", *(__u8 *)addr);
    301             addr += 1;
    302         }
    303         if (++in_line < max_in_line)
    304             *(page+i++)=' ';
    305         else
    306         {
    307             *(page+i++)='\n';
    308             in_line = 0;
    309         }
    310     }
    311     *(page+i++)='\n';
    312     /* For some reason read proc is get called twice for
    313        each "cat" operation
    314     */
    315     if (toggle)
    316         memdebug_addr = addr;
    317     toggle = !toggle;
    318 
    319     return i;
    320 }
    321 
    322 static char *rm_get_token(const char **p_buffer, unsigned long *p_buffer_len,
    323                           char *token, unsigned long token_len,
    324                           char del)
    325 {
    326     const char *buffer=*p_buffer;
    327     __u32 buffer_len = *p_buffer_len;
    328 
    329     while(buffer_len && token_len && *buffer!=del && *buffer)
    330     {
    331         *token++ = *buffer++;
    332         --buffer_len;
    333         --token_len;
    334     }
    335     while (buffer_len && *buffer==del)
    336     {
    337         ++buffer;
    338         --buffer_len;
    339     }
    340     *token = 0;
    341     *p_buffer = buffer;
    342     *p_buffer_len = buffer_len;
    343     return token;
    344 }
    345 
    346 static int tiwlan_deb_write_proc(struct file *file, const char *buffer,
    347                                  unsigned long count, void *data)
    348 {
    349     __u32 addr, size;
    350     char token[15];
    351     __u32 value;
    352     char *end;
    353     int buflen=count;
    354 
    355     /* buffer format is:
    356        d{w,h,b} addr[/size]
    357        s{w,h,b} addr=value
    358     */
    359     /* Parse string */
    360     rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
    361     if (token[0]=='d')
    362     {
    363         /* Display */
    364         if (!strcmp(token, "dw"))
    365             memdebug_trans_size = 4;
    366         else if (!strcmp(token, "dh"))
    367             memdebug_trans_size = 2;
    368         else if (!strcmp(token, "db"))
    369             memdebug_trans_size = 1;
    370         else
    371         {
    372             printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
    373             return buflen;
    374         }
    375         /* Get address */
    376         rm_get_token(&buffer, &count, token, sizeof(token)-1, '/');
    377         addr = simple_strtoul(token, &end, 0);
    378         if ((end && *end) /* || !iopa(addr)*/)
    379         {
    380             printk(KERN_INFO "rm: address <%s> is invalid\n", token);
    381             return buflen;
    382         }
    383         if ((addr & (memdebug_trans_size-1)))
    384         {
    385             printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
    386                    addr, memdebug_trans_size);
    387         }
    388         memdebug_addr = addr;
    389         if (count)
    390         {
    391             /* Get size */
    392             rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
    393             size = simple_strtoul(token, &end, 0);
    394             if (end && *end)
    395             {
    396                 printk(KERN_INFO "rm: size <%s> is invalid. end=<%s>\n",
    397                        token, end);
    398                 return buflen;
    399             }
    400             memdebug_size = size;
    401         }
    402         return buflen;
    403     }
    404     if (token[0]=='s')
    405     {
    406         /* Display */
    407         if (!strcmp(token, "sw"))
    408             size = 4;
    409         else if (!strcmp(token, "sh"))
    410             size = 2;
    411         else if (!strcmp(token, "sb"))
    412             size = 1;
    413         else
    414         {
    415             printk(KERN_INFO "rm: mem file write op is dw|dh|db|sw|sh|sb\n");
    416             return buflen;
    417         }
    418         /* Get address */
    419         rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
    420         addr = simple_strtoul(token, &end, 0);
    421         if ((end && *end) /*|| !iopa(addr)*/)
    422         {
    423             printk(KERN_INFO "rm: address <%s> is invalid\n", token);
    424             return buflen;
    425         }
    426         if ((addr & (size-1)))
    427         {
    428             printk(KERN_INFO "rm: warning: address 0x%x is not aligned to size %u\n",
    429                    addr, size);
    430         }
    431 
    432         /* Get value */
    433         rm_get_token(&buffer, &count, token, sizeof(token)-1, ' ');
    434         value = simple_strtoul(token, &end, 0);
    435         if (end && *end)
    436         {
    437             printk(KERN_INFO "rm: value <%s> is invalid. end <%s>\n",
    438                    token, end);
    439             return buflen;
    440         }
    441         if (size==4)
    442             *(__u32 *)addr = value;
    443         else if (size==2)
    444         {
    445             if (value > 0xffff)
    446             {
    447                 printk(KERN_INFO "rm: value <%s> is out of range\n", token);
    448                 return buflen;
    449             }
    450             *(__u16 *)addr = value;
    451         }
    452         else
    453         {
    454             if (value > 0xff)
    455             {
    456                 printk(KERN_INFO "rm: value <%s> is out of range\n", token);
    457                 return buflen;
    458             }
    459             *(__u8 *)addr = value;
    460         }
    461         memdebug_addr = addr;
    462         memdebug_size = 1;
    463         memdebug_trans_size = size;
    464     }
    465     else
    466         printk(KERN_INFO "rm: operation <%s> is not supported\n", token);
    467     return buflen;
    468 }
    469 
    470 #ifdef TIWLAN_MSM7000
    471 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
    472 #define WIFI_NVS_LEN_OFFSET     0x0C
    473 #define WIFI_NVS_DATA_OFFSET    0x40
    474 #define WIFI_NVS_MAX_SIZE       0x800UL
    475 
    476 static unsigned long tiwlan_get_nvs_size( void )
    477 {
    478     unsigned char *ptr;
    479     unsigned long len;
    480 
    481     ptr = get_wifi_nvs_ram();
    482     if( ptr == NULL ) {
    483         return 0;
    484     }
    485     /* Size in format LE assumed */
    486     memcpy( (void *)&len, (void *)(ptr + WIFI_NVS_LEN_OFFSET), sizeof(len) );
    487     len = min( len, (WIFI_NVS_MAX_SIZE-WIFI_NVS_DATA_OFFSET) );
    488     return len;
    489 }
    490 
    491 static int tiwlan_calibration_read_proc(char *page, char **start, off_t off,
    492                                 int count, int *eof, void *data)
    493 {
    494     unsigned char *ptr;
    495     unsigned long len;
    496 
    497     ptr = get_wifi_nvs_ram();
    498     if( ptr == NULL ) {
    499         return 0;
    500     }
    501     len = tiwlan_get_nvs_size();
    502     /* i += sprintf(page+i, "WiFi Calibration Size = %lu %x bytes\n", len); */
    503     memcpy( (void *)page, (void *)(ptr + WIFI_NVS_DATA_OFFSET), len );
    504     return len;
    505 }
    506 
    507 static int tiwlan_calibration_write_proc(struct file *file, const char *buffer,
    508                                  unsigned long count, void *data)
    509 {
    510     return 0;
    511 }
    512 #endif
    513 #endif
    514 
    515 /*********************************************************************************************/
    516 /*                                      Impelementation                                      */
    517 /*********************************************************************************************/
    518 
    519 static int tiwlan_drv_net_open(struct net_device * dev)
    520 {
    521    tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
    522 
    523    ti_nodprintf(TIWLAN_LOG_INFO, "tiwlan_drv_net_open()\n");
    524 
    525    if (!drv->adapter.CoreHalCtx)
    526       return -ENODEV;
    527 
    528    netif_start_queue(dev);
    529 
    530    return 0;
    531 }
    532 
    533 
    534 static int tiwlan_drv_net_stop(struct net_device * dev)
    535 {
    536    ti_nodprintf(TIWLAN_LOG_ERROR, "tiwlan_drv_net_stop()\n");
    537 
    538    netif_stop_queue(dev);
    539 
    540    return 0;
    541 }
    542 
    543 
    544 /* dummy send packet from Linux TCP/IP stack to WLAN
    545    Used when driver is not initialized
    546  */
    547 static int tiwlan_drv_dummy_net_xmit(struct sk_buff *skb, struct net_device *dev)
    548 {
    549    /* Network stack takes care of deallocation */
    550    return -ENODEV;
    551 }
    552 
    553 void sendFreeFunc(TI_HANDLE pSkb, TI_HANDLE dummy1, TI_STATUS status)
    554 {
    555     struct sk_buff *skb = (struct sk_buff *) pSkb;
    556 
    557     /* print_deb("^^^ free %p %d  bytes (%s)\n", skb->data, skb->len, (status==OK) ? "OK" : "ERROR" ); */
    558     dev_kfree_skb(skb);
    559 }
    560 
    561 #ifdef DM_USE_WORKQUEUE
    562 void tiwlan_add_msdu(tiwlan_net_dev_t *drv, mem_MSDU_T *pMsdu)
    563 {
    564     if( pMsdu == NULL )
    565         return;
    566     pMsdu->msdu_next = NULL;
    567     if( drv->txmit_msdu_next != NULL ) {
    568         drv->txmit_msdu_last->msdu_next = pMsdu;
    569     }
    570     else {
    571         drv->txmit_msdu_next = pMsdu;
    572     }
    573     drv->txmit_msdu_last = pMsdu;
    574 }
    575 
    576 mem_MSDU_T *tiwlan_del_msdu(tiwlan_net_dev_t *drv)
    577 {
    578     mem_MSDU_T *pMsdu = NULL;
    579 
    580     if( drv->txmit_msdu_next != NULL ) {
    581         pMsdu = drv->txmit_msdu_next;
    582         drv->txmit_msdu_next = pMsdu->msdu_next;
    583         if( drv->txmit_msdu_next == NULL ) { /* Last MSDU */
    584             drv->txmit_msdu_last = NULL;
    585         }
    586     }
    587     return( pMsdu );
    588 }
    589 
    590 static void tiwlan_xmit_handler( struct work_struct *work )
    591 {
    592     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, txmit );
    593     mem_MSDU_T *pMsdu;
    594     unsigned long flags;
    595 
    596 #ifdef CONFIG_ANDROID_POWER
    597     android_lock_suspend( &drv->exec_wake_lock );
    598     android_unlock_suspend( &drv->xmit_wake_lock );
    599 #endif
    600     /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
    601     do {
    602         spin_lock_irqsave(&drv->lock, flags);
    603         pMsdu = tiwlan_del_msdu(drv);
    604         spin_unlock_irqrestore(&drv->lock, flags);
    605         if( pMsdu ) {
    606             configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
    607         }
    608     } while( pMsdu != NULL );
    609 #ifdef CONFIG_ANDROID_POWER
    610     android_unlock_suspend( &drv->exec_wake_lock );
    611 #endif
    612 }
    613 #endif
    614 
    615 /* send packet from Linux TCP/IP stack to WLAN
    616  */
    617 static int tiwlan_drv_net_xmit(struct sk_buff *skb, struct net_device *dev)
    618 {
    619     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
    620     int status;
    621     mem_MSDU_T *pMsdu;
    622     UINT32      packetHeaderLength;
    623 
    624 #ifndef NO_COPY_SKB
    625     char *pMsduData;
    626 #else
    627     mem_BD_T *pCurBd=0;
    628 #endif
    629 
    630 #ifdef DRIVER_PROFILE
    631     os_profile (drv, 0, 0);
    632 #endif
    633     bm_trace(20, skb->len, 0);
    634 
    635 #ifdef NO_COPY_SKB
    636 
    637     status = configMgr_allocMSDUBufferOnly(drv->adapter.CoreHalCtx, &pMsdu, OS_ABS_TX_MODULE);
    638     if(status != OK)
    639     {
    640         ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDUBufferOnly failed !!!\n");
    641         ++drv->alloc_msdu_failures;
    642         return -ENOMEM;
    643     }
    644     /* print_deb("$$$ configMgr_allocMSDUBufferOnly()=OK pMsdu=%p\n", pMsdu ); */
    645 
    646     status = configMgr_allocBDs(drv->adapter.CoreHalCtx, 1, &pCurBd);
    647 
    648     if(status != OK) {
    649         ++drv->alloc_msdu_failures;
    650         ti_dprintf(TIWLAN_LOG_ERROR, "  configMgr_allocBDs failed !!!\n");
    651         configMgr_memMngrFreeMSDU(drv->adapter.CoreHalCtx, pMsdu->handle);
    652         return -ENOMEM;
    653     }
    654     /* print_deb("$$$ configMgr_allocBDs()=OK pCurBd=%p first=%p\n", pCurBd, pMsdu->firstBDPtr ); */
    655 
    656     pMsdu->freeFunc = sendFreeFunc;
    657     pMsdu->freeArgs[0] = (UINT32) skb;
    658     pMsdu->dataLen = skb->len;
    659     pMsdu->firstBDPtr = pCurBd;
    660     pCurBd->dataOffset = skb->data-skb->head;
    661     pCurBd->length = skb->len;
    662     pCurBd->data = skb->head;
    663 
    664     drv->stats.tx_packets++;
    665     drv->stats.tx_bytes += skb->len;
    666 
    667 #else /* NO_COPY_SKB */
    668 
    669     /*
    670      * Retrieve the Packet Header length
    671      * from QoS Manager (through configMgr)
    672      * (Header type is determined upon association)
    673      */
    674     packetHeaderLength = configMgr_getPacketHeaderLength(drv->adapter.CoreHalCtx,skb->data,TX_DATA_DATA_MSDU);
    675 
    676    /*
    677     * need to reserve enough space for header translation
    678     * in the same first Bd.
    679     * Allocate enough place also for 802.11 header (24 bytes or 26 for QoS) and LLC (8 bytes)
    680     * to replace the Ethernet header (14 bytes)
    681     */
    682     status = configMgr_allocMSDU(drv->adapter.CoreHalCtx, &pMsdu,
    683                                      skb->len + packetHeaderLength, OS_ABS_TX_MODULE);
    684 
    685     if(status != OK)
    686     {
    687         /*ti_dprintf(TIWLAN_LOG_ERROR, " configMgr_allocMSDU failed !!!\n");*/
    688         ++drv->alloc_msdu_failures;
    689         return -ENOMEM;
    690     }
    691 
    692     /*
    693      * case 1: only legacy wlan header
    694      *
    695      * case 2: only QoS wlan header
    696      *
    697      * case 3: only legacy wlan header with new snap
    698      *
    699      * case 4: only QoS wlan header with new snap
    700      */
    701     pMsdu->firstBDPtr->dataOffset = packetHeaderLength - ETHERNET_HDR_LEN;
    702     pMsduData = pMsdu->firstBDPtr->data + pMsdu->firstBDPtr->dataOffset;
    703     memcpy(pMsduData, skb->data, skb->len);
    704     pMsdu->dataLen = skb->len;
    705     pMsdu->firstBDPtr->length = pMsdu->dataLen + pMsdu->firstBDPtr->dataOffset;
    706 
    707     drv->stats.tx_packets++;
    708     drv->stats.tx_bytes += skb->len;
    709     dev_kfree_skb(skb);
    710 #endif /* NO_COPY_SKB */
    711 
    712     pMsdu->txFlags |= TX_DATA_FROM_OS;
    713     pMsdu->qosTag = 0;
    714     status = OK;
    715 
    716 #ifdef TI_DBG
    717     /* Set packet-os-in time stamp */
    718     /* TODO: the skb time stamp is not good */
    719     /* printk ("\n### sec=%u, usec=%u", skb->stamp.tv_sec, skb->stamp.tv_usec);*/
    720     /* pMsdu->timeStamp[0] = skb->stamp.tv_sec * 1000000 + skb->stamp.tv_usec; */
    721     /* pMsdu->timeStampNum = 1; */
    722 #endif
    723 
    724     bm_trace(21, 0, 0);
    725    /*
    726     * Propagate Msdu through Config Manager.
    727     * Set DTag to zero
    728     * (note that classification is further handled in the Core)
    729     */
    730     if (status == OK) {
    731 #ifdef DM_USE_WORKQUEUE
    732         unsigned long flags;
    733 
    734         spin_lock_irqsave(&drv->lock, flags);
    735         tiwlan_add_msdu(drv, pMsdu);
    736         spin_unlock_irqrestore(&drv->lock, flags);
    737         /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
    738 #ifdef CONFIG_ANDROID_POWER
    739         android_lock_suspend( &drv->xmit_wake_lock );
    740 #endif
    741         queue_work( drv->tiwlan_wq, &drv->txmit );
    742 #else
    743         status = configMgr_sendMsdu(drv->adapter.CoreHalCtx, pMsdu, 0);
    744 #endif
    745     }
    746     else
    747         configMgr_memMngrFreeMSDU (drv->adapter.CoreHalCtx, (UINT32) pMsdu); /* If status != OK , we won't send the MSDU, so we need to free it */
    748 
    749     if(unlikely(status != OK))
    750     {
    751         drv->stats.tx_errors++;
    752 #ifdef NO_COPY_SKB
    753         dev_kfree_skb(skb);
    754 #endif
    755     }
    756 
    757     bm_trace(22, 0, 0);
    758 #ifdef DRIVER_PROFILE
    759     os_profile (drv, 1, 0);
    760 #endif
    761 
    762     return 0;
    763 }
    764 
    765 struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev)
    766 {
    767     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev);
    768     ti_dprintf(TIWLAN_LOG_OTHER, "tiwlan_drv_net_get_stats()\n");
    769 
    770     return &drv->stats;
    771 }
    772 
    773 
    774 static int setup_netif(tiwlan_net_dev_t *drv)
    775 {
    776     struct net_device *dev;
    777     int res;
    778 
    779     dev = alloc_etherdev(0);
    780     if (dev == NULL)
    781     {
    782         ti_dprintf(TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n");
    783         return -ENOMEM;
    784     }
    785     ether_setup(dev);
    786     NETDEV_SET_PRIVATE(dev, drv);
    787     drv->netdev = dev;
    788     strcpy(dev->name, TIWLAN_DRV_IF_NAME);
    789     netif_carrier_off(dev);
    790 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
    791     dev->open = tiwlan_drv_net_open;
    792     dev->stop = tiwlan_drv_net_stop;
    793     dev->hard_start_xmit = tiwlan_drv_dummy_net_xmit;
    794     dev->get_stats = tiwlan_drv_net_get_stats;
    795 #else
    796     dev->netdev_ops = &tiwlan_ops_dummy;
    797 #endif
    798     dev->tx_queue_len = 100;
    799 
    800     res = tiwlan_ioctl_init(dev);
    801     if( res < 0 )
    802     {
    803         ti_dprintf(TIWLAN_LOG_ERROR, "tiwlan_ioctl_init() failed : %d\n", res);
    804         kfree(dev);
    805         return res;
    806     }
    807 
    808     res = register_netdev(dev);
    809     if (res != 0)
    810     {
    811         ti_dprintf(TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res);
    812         kfree(dev);
    813         return res;
    814     }
    815 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    816     SET_MODULE_OWNER(dev);
    817 #endif
    818     return 0;
    819 }
    820 
    821 
    822 /* tiwlan_interrupt
    823    TIWLAN interrupt handler. Disables interrupts and awakes tasklet.
    824 */
    825 #if !(defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI))
    826 static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
    827 {
    828     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
    829 
    830     /*
    831      * Workaround for the Linux 2.6 pending IRQ bug:
    832      * If a pending IRQ is handled on a WLAN ISR, the ISR is called again
    833      * even though it disabled itself in the first call. To protect against
    834      * re-entrance, this flag is checked, and if it is already set (meaning
    835      * that the ISR is called twice before the tasklet was called) nothing is done.
    836      */
    837     if (drv->interrupt_pending == 0)
    838     {
    839         UINT32 interruptVector;
    840 
    841         interruptVector = configMgr_checkInterrupts(drv->adapter.CoreHalCtx);
    842         if (interruptVector != 0)
    843         {
    844             configMgr_disableInterrupts(drv->adapter.CoreHalCtx);
    845             drv->interrupt_pending = 1;
    846             tasklet_schedule (&drv->tl);
    847         }
    848         else
    849         {
    850 #if DEBUG_UNKNOWN_INTERRUPT
    851             ti_dprintf (TIWLAN_LOG_ERROR,
    852                         "%s - ERROR - interrupt isn't TNET interrupt! interrupt vector = 0x%08X\n",
    853                         __FUNCTION__, interruptVector);
    854 #endif
    855         }
    856     }
    857     return IRQ_HANDLED;
    858 }
    859 
    860 #else
    861 
    862 static irqreturn_t tiwlan_interrupt (int irq, void *netdrv, struct pt_regs *cpu_regs)
    863 {
    864     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
    865 
    866     /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
    867     drv->interrupt_pending = 1;
    868 #ifdef DM_USE_WORKQUEUE
    869 #ifdef CONFIG_ANDROID_POWER
    870     android_lock_suspend( &drv->irq_wake_lock );
    871 #endif
    872     queue_work( drv->tiwlan_wq, &drv->tirq );
    873     /* disable_irq( drv->irq ); Dm: No need, we can loose IRQ */
    874 #else
    875     tasklet_schedule( &drv->tl );
    876 #endif
    877     return IRQ_HANDLED;
    878 }
    879 #endif
    880 
    881 
    882 static void tiwlan_poll_irq_handler(unsigned long parm)
    883 {
    884     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)parm;
    885     bm_trace(2, 0, 0);
    886 
    887     tiwlan_interrupt(0, drv, NULL);
    888     mod_timer(&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
    889 }
    890 
    891 static void tiwlan_handle_control_requests( tiwlan_net_dev_t *drv )
    892 {
    893     bm_trace(4, 0, 0);
    894 
    895     /* Handle control requests (timers, ioctls) */
    896     while(!list_empty(&drv->request_q))
    897     {
    898        struct list_head *entry = drv->request_q.next;
    899        tiwlan_req_t *req = list_entry(entry, tiwlan_req_t, list);
    900        tiwlan_req_t tmp_req;
    901        unsigned long flags;
    902 
    903        spin_lock_irqsave(&drv->lock, flags);
    904        list_del_init(entry);
    905        spin_unlock_irqrestore(&drv->lock, flags);
    906 
    907        ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d\n",
    908                   __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected);
    909 
    910        tmp_req.u.req.p1 = 0x1234;
    911        tmp_req.u.req.p2 = 0x4321;
    912        tmp_req.u.req.p3 = 0x1221;
    913        tmp_req.u.req.p4 = 0x4334;
    914        tmp_req.u.req.reply_expected = 0x50;
    915 
    916        req->u.reply = req->u.req.f(req);
    917 
    918        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))
    919        {
    920                printk("\n\n !!! ERROR: STACK CORRUPTION !!! : \nf=%p\n", tmp_req.u.req.f);
    921                if (!req->u.req.reply_expected)
    922                        printk("timer handler: %p\n", (void *)tmp_req.u.req.p1);
    923        }
    924 
    925        ti_nodprintf(TIWLAN_LOG_INFO, "%s: f=0x%x req=0x%x reply_expected=%d reply=%d\n",
    926                   __FUNCTION__, req->u.req.f, req, req->u.req.reply_expected, req->u.reply);
    927        if (req->u.req.reply_expected)
    928        {
    929           ti_nodprintf(TIWLAN_LOG_INFO, "%s: about to awake task\n", __FUNCTION__);
    930           complete(&req->u.req.comp);
    931        }
    932     }
    933 
    934     bm_trace(5, 0, 0);
    935 
    936     /* DbgCB_Insert(0, DBG_MODULE_OS, DBG_TYPE_TASKLET, 1)*/
    937 }
    938 
    939 #ifdef DM_USE_WORKQUEUE
    940 static void tiwlan_irq_handler( struct work_struct *work )
    941 {
    942     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tirq );
    943 
    944     /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
    945 #ifdef CONFIG_ANDROID_POWER
    946     android_lock_suspend( &drv->exec_wake_lock );
    947     android_unlock_suspend( &drv->irq_wake_lock );
    948 #endif
    949     /* if the driver was unloaded by that time we need to ignore all the timers */
    950     if (drv->unload_driver) {
    951 #ifdef CONFIG_ANDROID_POWER
    952         android_unlock_suspend( &drv->exec_wake_lock );
    953 #endif
    954         /* enable_irq( drv->irq ); */
    955         return;
    956     }
    957     configMgr_handleInterrupts( drv->adapter.CoreHalCtx );
    958     tiwlan_handle_control_requests( drv );
    959 #ifdef CONFIG_ANDROID_POWER
    960     if( drv->receive_packet ) {
    961         drv->receive_packet = 0;
    962         /* Keep awake for 500 ms to give a chance to network stack */
    963         android_lock_suspend_auto_expire( &drv->rx_wake_lock, HZ );
    964     }
    965     android_unlock_suspend( &drv->exec_wake_lock );
    966 #endif
    967     /* enable_irq( drv->irq ); */
    968 }
    969 #endif
    970 
    971 /* tiwlan_tasklet_handler
    972    WLAN protocol tasklet. Most of work happens in the
    973    context of this tasklet.
    974 */
    975 #ifdef DM_USE_WORKQUEUE
    976 static void tiwlan_work_handler( struct work_struct *work )
    977 #else
    978 static void tiwlan_tasklet_handler( unsigned long netdrv )
    979 #endif
    980 {
    981 #ifdef DM_USE_WORKQUEUE
    982     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( work, struct tiwlan_net_dev, tw );
    983 #else
    984     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)netdrv;
    985 #endif
    986 #ifdef STACK_PROFILE
    987     unsigned int curr1, base1;
    988     unsigned int curr2, base2;
    989     static unsigned int maximum_stack = 0;
    990 #endif
    991 
    992     /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
    993 #ifdef CONFIG_ANDROID_POWER
    994     android_lock_suspend( &drv->exec_wake_lock );
    995     android_unlock_suspend( &drv->timer_wake_lock );
    996 #endif
    997 
    998     /* if the driver was unloaded by that time we need to ignore all the timers */
    999     if (drv->unload_driver) {
   1000 #ifdef CONFIG_ANDROID_POWER
   1001         android_unlock_suspend( &drv->exec_wake_lock );
   1002 #endif
   1003         return;
   1004     }
   1005 #if 0
   1006     ti_dprintf(TIWLAN_LOG_INFO, "%s in\n" , __FUNCTION__);
   1007 #endif
   1008 
   1009 #ifdef DRIVER_PROFILE
   1010     os_profile (drv, 0, 0);
   1011 #endif
   1012     bm_trace(3, 0, 0);
   1013 
   1014 #ifdef STACK_PROFILE
   1015     curr1 = check_stack_start(&base1);
   1016 #endif
   1017 
   1018     /* Handle bus transaction interrupts */
   1019     if (drv->dma_done)
   1020     {
   1021         drv->dma_done = 0;
   1022         configMgr_HandleBusTxn_Complete(drv->adapter.CoreHalCtx);
   1023     }
   1024 
   1025     /* don't call for "Handle interrupts, timers, ioctls" while recovery process */
   1026     if (configMgr_areInputsFromOsDisabled(drv->adapter.CoreHalCtx) == TRUE) {
   1027 #ifdef CONFIG_ANDROID_POWER
   1028         android_unlock_suspend( &drv->exec_wake_lock );
   1029 #endif
   1030         return;
   1031     }
   1032 
   1033     /* Handle firmware interrupts */
   1034 #ifndef DM_USE_WORKQUEUE
   1035     if (drv->interrupt_pending)
   1036     {
   1037         drv->interrupt_pending = 0;
   1038         configMgr_handleInterrupts(drv->adapter.CoreHalCtx);
   1039     }
   1040 #endif
   1041 
   1042     tiwlan_handle_control_requests( drv );
   1043 
   1044 #ifdef STACK_PROFILE
   1045     curr2 = check_stack_stop(&base2);
   1046 
   1047     if (base2 == base1)
   1048     {
   1049        /* if the current measurement is bigger then the maximum store it and print*/
   1050         if ((curr1 - curr2) > maximum_stack)
   1051         {
   1052             printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n");
   1053             printk("current operation stack use =%d \n",(curr1 - curr2));
   1054             printk("total stack use=%d \n",8192 - curr2 + base2);
   1055             printk("total stack usage= %d percent \n",100 * (8192 - curr2 + base2) / 8192);
   1056                 maximum_stack = curr1 - curr2;
   1057        }
   1058     }
   1059 #endif
   1060 
   1061 #ifdef DRIVER_PROFILE
   1062     os_profile (drv, 1, 0);
   1063 #endif
   1064 
   1065 #if 0
   1066     ti_dprintf(TIWLAN_LOG_INFO, "%s out\n" , __FUNCTION__);
   1067 #endif
   1068 #ifdef CONFIG_ANDROID_POWER
   1069     android_unlock_suspend( &drv->exec_wake_lock );
   1070 #endif
   1071 }
   1072 
   1073 #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
   1074 static void tiwlan_rx_watchdog(struct work_struct *work)
   1075 {
   1076     struct delayed_work *dwork = (struct delayed_work *) container_of(work, struct delayed_work, work);
   1077     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)container_of( dwork, struct tiwlan_net_dev, trxw );
   1078 
   1079     unsigned long num_rx_pkts = num_rx_pkt_new - num_rx_pkt_last;
   1080     /* Contribute 10mA (200mA x 5%) for 1 pkt/sec, and plus 8mA base. */
   1081     unsigned percent = (5 * num_rx_pkts  / RX_RATE_INTERVAL_SEC) + PWRSINK_WIFI_PERCENT_BASE;
   1082 
   1083     if (drv->unload_driver)
   1084         return;
   1085 
   1086     percent = (percent > 100) ? 100 : percent;
   1087     /* printk(KERN_INFO "num_rx_pkts=%ld, percent=%d\n", num_rx_pkts, percent); */
   1088 #ifdef CONFIG_HTC_PWRSINK
   1089     htc_pwrsink_set(PWRSINK_WIFI, percent);
   1090 #else
   1091     trout_pwrsink_set(PWRSINK_WIFI, percent);
   1092 #endif
   1093 
   1094     num_rx_pkt_last = num_rx_pkt_new;
   1095 
   1096     if (drv && drv->tiwlan_wq)
   1097         queue_delayed_work(drv->tiwlan_wq, &drv->trxw, msecs_to_jiffies(MSEC_PER_SEC * RX_RATE_INTERVAL_SEC));
   1098 }
   1099 #endif
   1100 
   1101 /* tiwlan_send_wait_reply
   1102    This internal interface function creates request and sends
   1103    it to the control tasklet for processing.
   1104    The calling process is blocked until the request is replied.
   1105    Function f is being called in the context of the control tasklet.
   1106    The request block that is passed to the function as a parameter
   1107    contains p1, p2, p3, p4.
   1108    The function return code is propagated back to the caller.
   1109    tiwlan_send_req_and_wait returns (*f) return code or
   1110    -ENOMEM if failed to allocate a request.
   1111 */
   1112 int tiwlan_send_wait_reply(tiwlan_net_dev_t *drv,
   1113                            int (*f)(tiwlan_req_t *req),
   1114                            unsigned long p1,
   1115                            unsigned long p2,
   1116                            unsigned long p3,
   1117                            unsigned long p4)
   1118 {
   1119     tiwlan_req_t req;
   1120     unsigned long flags;
   1121 
   1122     /* Send request to tiwlan_tasklet and wait for reply */
   1123     if (!drv->adapter.CoreHalCtx) {
   1124         return STATION_IS_NOT_RUNNING;
   1125     }
   1126 
   1127     req.drv = drv;
   1128     req.u.req.f = f;
   1129     req.u.req.p1 = p1;
   1130     req.u.req.p2 = p2;
   1131     req.u.req.p3 = p3;
   1132     req.u.req.p4 = p4;
   1133     req.u.req.reply_expected = 1;
   1134     init_completion(&req.u.req.comp);
   1135 
   1136     spin_lock_irqsave(&drv->lock, flags);
   1137     list_add_tail(&req.list, &drv->request_q);
   1138     spin_unlock_irqrestore(&drv->lock, flags);
   1139 
   1140 #ifdef DM_USE_WORKQUEUE
   1141     /* printk("TI: %s:\t%lu\n", __FUNCTION__, jiffies); */
   1142 #ifdef CONFIG_ANDROID_POWER
   1143     android_lock_suspend( &drv->timer_wake_lock );
   1144 #endif
   1145     queue_work( drv->tiwlan_wq, &drv->tw );
   1146 #else
   1147     tasklet_schedule( &drv->tl );
   1148 #endif
   1149     wait_for_completion(&req.u.req.comp);
   1150 
   1151     return req.u.reply;
   1152 }
   1153 
   1154 
   1155 #define WLAN_PCMCIA_CFG_REG       0x0524
   1156 /* tiwlan_set_hw_access */
   1157 static int tiwlan_set_hw_access(tiwlan_net_dev_t *drv)
   1158 {
   1159 #ifdef TIWLAN_OMAP1610
   1160     OS_WRITE_REG(drv, HI_CFG, 0x00000a00);
   1161 
   1162 #if ! ((defined(HW_ACCESS_SDIO)||defined(HW_ACCESS_WSPI)) && defined(TNETW1150))
   1163     OS_WRITE_REG(drv, WLAN_PCMCIA_CFG_REG, 0xC6880000);
   1164     OS_WRITE_REG(drv, PCI_ARB_CFG, 0x2);
   1165 #endif
   1166 
   1167 #endif
   1168     return 0;
   1169 }
   1170 
   1171 
   1172 /* tiwlan_free_drv
   1173    Unmap h/w regions and free driver's structure
   1174 */
   1175 static void tiwlan_free_drv(tiwlan_net_dev_t *drv)
   1176 {
   1177 #ifdef TIWLAN_OMAP1610
   1178     if (drv->acx_mem.pa && drv->acx_mem.va)
   1179         iounmap(drv->acx_mem.va);
   1180     if (drv->acx_reg.pa && drv->acx_reg.va && drv->acx_reg.va != drv->acx_reg.va)
   1181         iounmap(drv->acx_reg.va);
   1182 #endif
   1183     kfree(drv);
   1184 }
   1185 
   1186 
   1187 /* tiwlan_alloc_drv
   1188    Allocate driver's structure and map h/w regions
   1189 */
   1190 static tiwlan_net_dev_t *
   1191 tiwlan_alloc_drv(unsigned long reg_start, unsigned long reg_size,
   1192                  unsigned long mem_start, unsigned long mem_size,
   1193                  int map_io, int irq)
   1194 {
   1195     static tiwlan_net_dev_t *drv;
   1196     drv = kmalloc(sizeof(tiwlan_net_dev_t), GFP_KERNEL);
   1197 #ifdef TI_MEM_ALLOC_TRACE
   1198     os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(tiwlan_net_dev_t), GFP_KERNEL, sizeof(tiwlan_net_dev_t));
   1199 #endif/*I_MEM_ALLOC_TRACE*/
   1200 
   1201     if (!drv)
   1202         return NULL;
   1203     memset(drv, 0, sizeof(tiwlan_net_dev_t));
   1204     drv->acx_mem.size = mem_size;
   1205     drv->acx_reg.size = reg_size;
   1206 #ifdef TIWLAN_OMAP1610
   1207     if (map_io)
   1208     {
   1209         drv->acx_mem.pa = mem_start;
   1210         drv->acx_reg.pa = reg_start;
   1211         drv->acx_mem.va = ioremap(drv->acx_mem.pa, drv->acx_mem.size);
   1212         if (drv->acx_mem.pa!=drv->acx_reg.pa || drv->acx_mem.size!=drv->acx_reg.size)
   1213             drv->acx_reg.va = ioremap(drv->acx_reg.pa, drv->acx_reg.size);
   1214         else
   1215             drv->acx_reg.va = drv->acx_mem.va;
   1216     }
   1217     else
   1218     {
   1219         /* Memory is already mapped */
   1220         drv->acx_mem.va = (void *)mem_start;
   1221         drv->acx_reg.va = (void *)reg_start;
   1222     }
   1223 #endif /* Dm: */
   1224     drv->irq = irq;
   1225     return drv;
   1226 }
   1227 
   1228 
   1229 /* tiwlan_init_drv
   1230    Called in process context
   1231  */
   1232 int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info)
   1233 {
   1234     initTable_t *init_table;
   1235     int rc;
   1236     void *pWLAN_Images[4];
   1237 
   1238     /* printk("%s\n", __FUNCTION__); */
   1239     /* It is OK if already initialized */
   1240     if (drv->adapter.CoreHalCtx)
   1241         return 0;
   1242 
   1243     init_table = os_memoryAlloc (drv, sizeof(initTable_t));
   1244 
   1245 #ifdef TI_MEM_ALLOC_TRACE
   1246     osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(initTable_t), GFP_KERNEL, sizeof(initTable_t));
   1247 #endif/*I_MEM_ALLOC_TRACE*/
   1248     if (!init_table)
   1249     {
   1250         ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate init_table\n");
   1251         return -ENOMEM;
   1252     }
   1253 
   1254     if (init_info)
   1255     {
   1256         drv->eeprom_image.size = init_info->eeprom_image_length;
   1257         if (drv->eeprom_image.size)
   1258         {
   1259             drv->eeprom_image.va = os_memoryAlloc (drv, drv->eeprom_image.size);
   1260 
   1261 #ifdef TI_MEM_ALLOC_TRACE
   1262             osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, GFP_KERNEL, drv->eeprom_image.size);
   1263 #endif
   1264             if (!drv->eeprom_image.va)
   1265             {
   1266                 ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for eeprom image\n");
   1267                 drv->eeprom_image.size = 0;
   1268                 return -ENOMEM;
   1269             }
   1270             memcpy (drv->eeprom_image.va, &init_info->data[0], drv->eeprom_image.size );
   1271         }
   1272 
   1273 #ifdef FIRMWARE_DYNAMIC_LOAD
   1274         drv->firmware_image.size = init_info->firmware_image_length;
   1275         if (!drv->firmware_image.size)
   1276         {
   1277             ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n");
   1278             return -EINVAL;
   1279         }
   1280         drv->firmware_image.va = os_memoryAlloc (drv,drv->firmware_image.size);
   1281 #ifdef TI_MEM_ALLOC_TRACE
   1282         osPrintf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, drv->firmware_image.size, GFP_KERNEL, drv->firmware_image.size);
   1283 #endif
   1284         if (!drv->firmware_image.va)
   1285         {
   1286             ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n");
   1287             drv->firmware_image.size = 0;
   1288             if (drv->eeprom_image.va)
   1289                 os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
   1290             return -ENOMEM;
   1291         }
   1292         memcpy (drv->firmware_image.va,
   1293                 &init_info->data[init_info->eeprom_image_length],
   1294                 drv->firmware_image.size);
   1295 #else
   1296         extern unsigned char tiwlan_fwimage[];
   1297         extern unsigned int sizeof_tiwlan_fwimage;
   1298 
   1299         drv->firmware_image.size = sizeof_tiwlan_fwimage;
   1300         drv->firmware_image.va = tiwlan_fwimage;
   1301 #endif
   1302     }
   1303 
   1304     print_deb ("--------- Eeeprom=%p(%lu), Firmware=%p(%lu)\n",
   1305                 drv->eeprom_image.va,
   1306                 drv->eeprom_image.size,
   1307                 drv->firmware_image.va,
   1308                 drv->firmware_image.size);
   1309 
   1310     /* Init defaults */
   1311     if ((rc = osInitTable_IniFile (drv,
   1312                                    init_table,
   1313                                    (init_info && init_info->init_file_length) ?
   1314                                    &init_info->data[init_info->eeprom_image_length+init_info->firmware_image_length] : NULL,
   1315                                    init_info ? init_info->init_file_length : 0)))
   1316     {
   1317         ti_dprintf (TIWLAN_LOG_ERROR, "osInitTable_IniFile failed :cannot initialize defaults\n");
   1318         os_memoryFree (drv, init_table, sizeof(initTable_t));
   1319 
   1320 #ifdef TI_MEM_ALLOC_TRACE
   1321         os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
   1322 #endif
   1323         return rc;
   1324     }
   1325 
   1326     pWLAN_Images[0] = (void *)drv->firmware_image.va;
   1327     pWLAN_Images[1] = (void *)drv->firmware_image.size;
   1328     pWLAN_Images[2] = (void *)drv->eeprom_image.va;
   1329     pWLAN_Images[3] = (void *)drv->eeprom_image.size;
   1330 
   1331     drv->adapter.CoreHalCtx = configMgr_create (drv,
   1332                                                 pWLAN_Images,
   1333                                                 init_table,
   1334                                                 (macAddress_t *) &drv->adapter.CurrentAddr);
   1335     if (!(drv->adapter.CoreHalCtx))
   1336     {
   1337 #ifdef FIRMWARE_DYNAMIC_LOAD
   1338         os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
   1339         os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
   1340 #endif
   1341         os_memoryFree (drv, init_table, sizeof(initTable_t));
   1342         ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate CoreHalCtx\n");
   1343         return -ENOMEM;
   1344     }
   1345 
   1346     drv->interrupt_pending = 0;
   1347     drv->dma_done = 0;
   1348 
   1349     if (drv->irq)
   1350     {
   1351 #ifndef PRIODIC_INTERRUPT
   1352 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1353         unsigned long flags;
   1354         /*
   1355          * Disable all interrupts for not to catch the tiwlan irq
   1356          * between request_irq and disable_irq
   1357          */
   1358         spin_lock_irqsave (&(drv->lock), flags);
   1359         if ((rc = request_irq (drv->irq, tiwlan_interrupt, SA_SHIRQ, drv->netdev->name, drv)))
   1360 #else
   1361         if ((rc = request_irq (drv->irq, (irq_handler_t)tiwlan_interrupt, IRQF_SHARED | IRQF_TRIGGER_FALLING /*Dm:*/, drv->netdev->name, drv)))
   1362 #endif
   1363         {
   1364             print_err ("TIWLAN: Failed to register interrupt handler\n");
   1365             configMgr_stop (drv->adapter.CoreHalCtx);
   1366 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1367             spin_unlock_irqrestore (&drv->lock, flags);
   1368 #endif
   1369             return rc;
   1370         }
   1371 #ifdef CONFIG_ANDROID_POWER
   1372         set_irq_wake(drv->irq, 1);
   1373 #endif
   1374 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1375         set_irq_type (drv->irq, IRQT_FALLING);
   1376 #else
   1377         set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
   1378 #endif
   1379         disable_irq (drv->irq);
   1380 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1381         spin_unlock_irqrestore (&drv->lock, flags);
   1382 #endif
   1383 #else
   1384         printk (" tiwlan_init_drv :PRIODIC_INTERRUPT drv->irq %x\n",drv->irq);
   1385 #endif
   1386     }
   1387     else
   1388     {
   1389         /* Debug mode: polling */
   1390         mod_timer (&drv->poll_timer, jiffies + TIWLAN_IRQ_POLL_INTERVAL);
   1391     }
   1392 
   1393     /*
   1394      * Now that all parts of the driver have been created and handles linked
   1395      * proceed to download the FW code
   1396      */
   1397     configMgr_init (drv,
   1398                     drv->adapter.CoreHalCtx,
   1399                     pWLAN_Images,
   1400                     init_table,
   1401                     (macAddress_t *) &drv->adapter.CurrentAddr);
   1402 
   1403     /* Wait for the download to complete */
   1404     os_WaitComplete ((void *)drv);
   1405 
   1406     os_memoryFree (drv, init_table, sizeof(initTable_t));
   1407 
   1408     if (rc == OK)
   1409     {
   1410         proc_stat_init (drv->adapter.CoreHalCtx);
   1411 #ifdef TI_MEM_ALLOC_TRACE
   1412         osPrintf ("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, sizeof(initTable_t), -sizeof(initTable_t));
   1413 #endif/*I_MEM_ALLOC_TRACE*/
   1414 
   1415        if (drv->adapter.CoreHalCtx == NULL)
   1416        {
   1417            ti_dprintf (TIWLAN_LOG_ERROR, "configMgr_create failed\n");
   1418            return -ENODEV;
   1419        }
   1420 
   1421        /* eeprom buffer is going to be deallocated by the caller. It is no longer needed anyway */
   1422 #if 0
   1423         drv->eeprom_image.va = NULL;
   1424         drv->eeprom_image.size = 0;
   1425 #endif
   1426 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
   1427 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1428         drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, THIS_MODULE); /* Dm: */
   1429 #else
   1430         drv->wl_sock = netlink_kernel_create(NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
   1431 #endif
   1432 #else
   1433         drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE); /* Dm: */
   1434 #endif
   1435         if (drv->wl_sock == NULL)
   1436         {
   1437             ti_dprintf(TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n");
   1438             /* TODO: free in destroy */
   1439             return -EINVAL;
   1440         }
   1441 
   1442         /* Finalize network interface setup */
   1443 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
   1444         drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit;
   1445 #else
   1446         drv->netdev->netdev_ops = &tiwlan_ops_pri;
   1447 #endif
   1448         memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN);
   1449         drv->netdev->addr_len = MAC_ADDR_LEN;
   1450 
   1451         /* Register the relevant events with the event handler */
   1452         tiwlan_register_events (drv);
   1453 
   1454         /* Mark that init stage has succeded */
   1455         drv->initialized = 1;
   1456 
   1457         return 0;
   1458     }
   1459 
   1460     return -ENODEV;
   1461 }
   1462 
   1463 #ifdef CONFIG_ANDROID_POWER
   1464 #ifndef CONFIG_HAS_WAKELOCK
   1465 /* Wrapper for Init wake lock */
   1466 static void android_init_suspend_wakelock(android_suspend_lock_t *lp,char *nm)
   1467 {
   1468     lp->name = nm;
   1469     android_init_suspend_lock( lp );
   1470 }
   1471 #endif
   1472 #endif
   1473 
   1474 /* tiwlan_start_drv
   1475 */
   1476 int tiwlan_start_drv(tiwlan_net_dev_t *drv)
   1477 {
   1478     /* printk("%s\n", __FUNCTION__); */
   1479     if (!drv->initialized)
   1480     {
   1481         ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before initilization has succeeded\n");
   1482         return -ENODEV;
   1483     }
   1484     if (!drv->adapter.CoreHalCtx)
   1485     {
   1486         ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver before creating config_manager\n");
   1487         return -ENODEV;
   1488     }
   1489     if (drv->started)
   1490     {
   1491         /*ti_dprintf(TIWLAN_LOG_ERROR, "Attempt to start driver that has already started\n");*/
   1492         return -EALREADY;
   1493     }
   1494     if (configMgr_start(drv->adapter.CoreHalCtx) != OK)
   1495     {
   1496         print_err("TIWLAN: Failed to start config manager\n");
   1497         return -EINVAL;
   1498     }
   1499     drv->started = 1;
   1500 
   1501 #ifdef SDIO_INTERRUPT_HANDLING_ON
   1502     configMgr_SlaveAckMaskNotification(drv->adapter.CoreHalCtx);
   1503 #endif
   1504     if (drv->netdev)
   1505         netif_start_queue(drv->netdev);
   1506 #ifdef CONFIG_TROUT_PWRSINK
   1507     trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
   1508 #endif
   1509 #ifdef CONFIG_HTC_PWRSINK
   1510     htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
   1511 #endif
   1512     export_wifi_fw_version(drv);
   1513     return 0;
   1514 }
   1515 
   1516 
   1517 /* tiwlan_destroy_drc
   1518 */
   1519 static void tiwlan_destroy_drv(tiwlan_net_dev_t *drv)
   1520 {
   1521     int waitShutdownCounter;
   1522 
   1523     /* close the ipc_kernel socket*/
   1524     if (drv && drv->wl_sock) {
   1525         sock_release(drv->wl_sock->sk_socket);
   1526     }
   1527 
   1528     bm_destroy();
   1529 
   1530     if (drv->started)
   1531         tiwlan_send_wait_reply(drv, tiwlan_stop_and_destroy_drv_request, 0, 0, 0, 0);
   1532     else
   1533         tiwlan_stop_and_destroy_drv(drv);
   1534 
   1535 #ifdef DM_USE_WORKQUEUE
   1536     while( tiwlan_del_msdu(drv) != NULL );
   1537 #endif
   1538     if (drv->adapter.CoreHalCtx)
   1539     {
   1540         /* Delay return to OS until all driver components (HAL/SME) are shutdown */
   1541         for (waitShutdownCounter=1; waitShutdownCounter<=DRV_SHUTDOWN_TEST_MAX_COUNTER; waitShutdownCounter++)
   1542         {
   1543             /* Check if HAL/SME are stopped - If so - exit loop and return to OS */
   1544             if (configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx) == DRIVER_SHUTDOWN_COMPLETE)
   1545             {
   1546                 break;
   1547             }
   1548             /* Delay of 100ms between shutdown test */
   1549             mdelay ( DRV_SHUTDOWN_TEST_DELAY_INTERVAL );
   1550         }
   1551 
   1552         /* If driver was not shutdown properly - destroy all timers "manually" and exit*/
   1553         if ( waitShutdownCounter == DRV_SHUTDOWN_TEST_MAX_COUNTER+1 )
   1554         {
   1555             os_printf("Timeout while waiting for driver to shutdown...Shutdown status flag=0x%x\n",configMgr_DriverShutdownStatus(drv->adapter.CoreHalCtx));
   1556         }
   1557 
   1558         /* drv->unload_driver = 1; Dm: moved to tiwlan_stop_and_destroy_drv */
   1559 
   1560         proc_stat_destroy();
   1561         if (drv->irq) {
   1562 #ifdef CONFIG_ANDROID_POWER
   1563             set_irq_wake(drv->irq, 0);
   1564 #endif
   1565             free_irq(drv->irq, drv);
   1566         }
   1567         else
   1568             del_timer_sync(&drv->poll_timer);
   1569 #ifdef DM_USE_WORKQUEUE
   1570         flush_work(&drv->tirq);
   1571         flush_work(&drv->tw);
   1572         flush_work(&drv->txmit);
   1573 #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
   1574         cancel_delayed_work_sync(&drv->trxw);
   1575 #endif
   1576 #endif
   1577         /* Unload all modules (free memory) & destroy timers */
   1578         configMgr_UnloadModules (drv->adapter.CoreHalCtx);
   1579 
   1580 #ifdef FIRMWARE_DYNAMIC_LOAD
   1581         if( drv->firmware_image.va ) {
   1582             os_memoryFree(drv,drv->firmware_image.va, drv->firmware_image.size);
   1583 #ifdef TI_MEM_ALLOC_TRACE
   1584             os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->firmware_image.size, -drv->firmware_image.size);
   1585 #endif /*I_MEM_ALLOC_TRACE*/
   1586         }
   1587         if( drv->eeprom_image.va )
   1588         {
   1589             os_memoryFree (drv, drv->eeprom_image.va, drv->eeprom_image.size);
   1590 #ifdef TI_MEM_ALLOC_TRACE
   1591             os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, drv->eeprom_image.size, -drv->eeprom_image.size);
   1592 #endif /*I_MEM_ALLOC_TRACE*/
   1593         }
   1594 #endif /*FIRMWARE_DYNAMIC_LOAD*/
   1595     }
   1596 #ifdef DM_USE_WORKQUEUE
   1597 #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
   1598     cancel_delayed_work_sync(&drv->trxw);
   1599 #endif
   1600     destroy_workqueue(drv->tiwlan_wq);
   1601 #endif
   1602 #ifdef CONFIG_TROUT_PWRSINK
   1603     trout_pwrsink_set(PWRSINK_WIFI, 0);
   1604 #endif
   1605 #ifdef CONFIG_HTC_PWRSINK
   1606     htc_pwrsink_set(PWRSINK_WIFI, 0);
   1607 #endif
   1608 #ifdef CONFIG_ANDROID_POWER
   1609     android_uninit_suspend_lock(&drv->irq_wake_lock);
   1610     android_uninit_suspend_lock(&drv->xmit_wake_lock);
   1611     android_uninit_suspend_lock(&drv->timer_wake_lock);
   1612     android_uninit_suspend_lock(&drv->rx_wake_lock);
   1613     android_uninit_suspend_lock(&drv->exec_wake_lock);
   1614 #endif
   1615     unregister_netdev(drv->netdev);
   1616     tiwlan_free_drv(drv);
   1617 }
   1618 
   1619 
   1620 /* tiwlan_create_dev
   1621    Create tiwlan device instance.
   1622    Returns 0 if OK
   1623 */
   1624 static int
   1625 tiwlan_create_drv(unsigned long reg_start, unsigned long reg_size,
   1626                   unsigned long mem_start, unsigned long mem_size,
   1627                   int map_io, int irq,
   1628                   void *priv, tiwlan_net_dev_t **p_drv)
   1629 {
   1630     tiwlan_net_dev_t *drv;
   1631     int rc;
   1632 
   1633     /* printk("%s\n", __FUNCTION__); */
   1634     /* Allocate device and map h/w regions */
   1635     drv = tiwlan_alloc_drv(reg_start, reg_size, mem_start, mem_size, map_io, irq);
   1636     if (!drv)
   1637         return -ENOMEM;
   1638 
   1639     /* Check h/w access */
   1640     if (tiwlan_set_hw_access(drv))
   1641     {
   1642         tiwlan_free_drv(drv);
   1643         return -ENODEV;
   1644     }
   1645 
   1646 #ifdef DM_USE_WORKQUEUE
   1647 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
   1648     drv->tiwlan_wq = create_singlethread_workqueue("tiwlan_wifi_wq");
   1649 #else
   1650     drv->tiwlan_wq = create_freezeable_workqueue("tiwlan_wifi_wq");
   1651 #endif
   1652     if( !(drv->tiwlan_wq) ) {
   1653         tiwlan_free_drv(drv);
   1654         printk(KERN_ERR "Failed to create workqueue\n");
   1655         return -EINVAL;
   1656     }
   1657 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1658     INIT_WORK( &drv->tw, tiwlan_work_handler, &drv->tw );
   1659     INIT_WORK( &drv->txmit, tiwlan_xmit_handler, &drv->txmit );
   1660     INIT_WORK( &drv->tirq, tiwlan_irq_handler, &drv->tirq );
   1661 #else
   1662     INIT_WORK( &drv->tw, tiwlan_work_handler );
   1663     INIT_WORK( &drv->txmit, tiwlan_xmit_handler );
   1664     INIT_WORK( &drv->tirq, tiwlan_irq_handler );
   1665 #endif
   1666     drv->txmit_msdu_next = drv->txmit_msdu_last = NULL;
   1667 #else
   1668     tasklet_init( &drv->tl, tiwlan_tasklet_handler, (unsigned long)drv );
   1669 #endif
   1670 
   1671 #if defined(CONFIG_TROUT_PWRSINK) || defined(CONFIG_HTC_PWRSINK)
   1672 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
   1673     INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog, &drv->trxw );
   1674 #else
   1675     INIT_DELAYED_WORK( &drv->trxw, tiwlan_rx_watchdog );
   1676 #endif
   1677 #endif
   1678 
   1679 #ifdef CONFIG_ANDROID_POWER
   1680     drv->receive_packet = 0;
   1681     android_init_suspend_wakelock(&drv->irq_wake_lock,"tiwlan_irq_wake");
   1682     android_init_suspend_wakelock(&drv->xmit_wake_lock,"tiwlan_xmit_wake");
   1683     android_init_suspend_wakelock(&drv->timer_wake_lock,"tiwlan_timer_wake");
   1684     android_init_suspend_wakelock(&drv->rx_wake_lock,"tiwlan_rx_wake");
   1685     android_init_suspend_wakelock(&drv->exec_wake_lock,"tiwlan_exec_wake");
   1686 #endif
   1687     spin_lock_init(&drv->lock);
   1688     INIT_LIST_HEAD(&drv->request_q);
   1689     init_timer(&drv->poll_timer);
   1690     drv->poll_timer.function = tiwlan_poll_irq_handler;
   1691     drv->poll_timer.data   = (unsigned long)drv;
   1692 
   1693     /* Init the completion obhect needed for init async purpose */
   1694     init_completion(&drv->comp);
   1695 
   1696     /* Register network device */
   1697     rc = setup_netif(drv);
   1698     if (rc)
   1699     {
   1700         tiwlan_free_drv(drv);
   1701         return rc;
   1702     }
   1703     drv->priv = priv;
   1704 
   1705     list_add(&drv->list, &tiwlan_drv_list);
   1706     if (p_drv)
   1707         *p_drv = drv;
   1708 
   1709     drv->initialized = 0;
   1710 
   1711     /* Profiler */
   1712 #ifdef DRIVER_PROFILING
   1713     tiwlan_profile_create (drv);
   1714 #endif
   1715 
   1716     bm_init(drv);
   1717 
   1718 #ifdef NO_USERMODE_WORKAROUND
   1719     rc = tiwlan_init_drv(drv, NULL);
   1720     rc = rc ? rc : tiwlan_start_drv(drv);
   1721 #endif
   1722 
   1723     return 0;
   1724 }
   1725 
   1726 /* tiwlan_stop_driver
   1727 */
   1728 int tiwlan_stop_drv(tiwlan_net_dev_t *drv)
   1729 {
   1730     /* printk("%s\n", __FUNCTION__); */
   1731     if (!drv->adapter.CoreHalCtx)
   1732         return 0;
   1733 
   1734     if (drv->netdev)
   1735         netif_stop_queue(drv->netdev);
   1736 
   1737     drv->started = 0;
   1738     configMgr_stop(drv->adapter.CoreHalCtx);
   1739 
   1740 #ifdef CONFIG_TROUT_PWRSINK
   1741     trout_pwrsink_set(PWRSINK_WIFI, 0);
   1742 #endif
   1743 #ifdef CONFIG_HTC_PWRSINK
   1744     htc_pwrsink_set(PWRSINK_WIFI, 0);
   1745 #endif
   1746     return 0;
   1747 }
   1748 
   1749 /* tiwlan_stop__and_destroy_driver
   1750 */
   1751 int tiwlan_stop_and_destroy_drv(tiwlan_net_dev_t *drv)
   1752 {
   1753     if (!drv->adapter.CoreHalCtx)
   1754         return 0;
   1755 
   1756     if (drv->netdev)
   1757         netif_stop_queue(drv->netdev);
   1758 
   1759     /* Start unload process by calling smeSm_stop, and halting the HAL */
   1760     /* SmeSm_stop finish notification will be one by setting flags */
   1761     configMgr_InitiateUnload(drv->adapter.CoreHalCtx);
   1762     drv->started = 0;
   1763     drv->unload_driver = 1;
   1764     return 0;
   1765 }
   1766 
   1767 /* tiwlan_stop__and_destroy_driver from workqueue
   1768 */
   1769 int tiwlan_stop_and_destroy_drv_request(tiwlan_req_t *req)
   1770 {
   1771     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)(req->drv);
   1772     printk("%s: Called\n",__FUNCTION__);
   1773     return tiwlan_stop_and_destroy_drv(drv);
   1774 }
   1775 
   1776 void *wifi_kernel_prealloc(int section, unsigned long size)
   1777 {
   1778 #ifdef CONFIG_WIFI_CONTROL_FUNC
   1779     if( wifi_control_data && wifi_control_data->mem_prealloc )
   1780         return wifi_control_data->mem_prealloc( section, size );
   1781     else
   1782 #endif
   1783     return NULL;
   1784 }
   1785 
   1786 #ifdef TIWLAN_CARDBUS
   1787 
   1788 static struct pci_device_id tnetw1130_pci_tbl[] __devinitdata =
   1789 {
   1790     { VENDOR_ID_TI, DEVICE_ID_TI_WLAN, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
   1791     { 0, }
   1792 };
   1793 
   1794 static int __devinit
   1795 tnetw1130_pci_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
   1796 {
   1797     tiwlan_net_dev_t *drv;
   1798     int rc;
   1799 
   1800     print_info("tnetw1130_pci_init_one:\n");
   1801     /* IT: for some reason interrupt doesn't work.
   1802        use poling mode for now (comments around
   1803        pcidev->irq below)
   1804     */
   1805     rc = tiwlan_create_drv(pcidev->resource[0].start,
   1806                            pcidev->resource[0].end - pcidev->resource[0].start,
   1807                            pcidev->resource[1].start,
   1808                            pcidev->resource[1].end - pcidev->resource[1].start,
   1809                            1,
   1810                            0/*pcidev->irq*/, pcidev, &drv);
   1811     if (!rc)
   1812         pcidev->driver_data = drv;
   1813     return rc;
   1814 }
   1815 
   1816 void tnetw1130_pci_remove(struct pci_dev *dev)
   1817 {
   1818     tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)dev->driver_data;
   1819     if (drv)
   1820     {
   1821         dev->driver_data = NULL;
   1822         tiwlan_destroy_drv(drv);
   1823     }
   1824 }
   1825 
   1826 static struct pci_driver tnetw1130_pci_driver = {
   1827     .name =      "tnetw1130",
   1828     .id_table =  tnetw1130_pci_tbl,
   1829     .probe = tnetw1130_pci_init_one,
   1830     .remove =    tnetw1130_pci_remove
   1831 };
   1832 
   1833 #endif /* #ifdef TIWLAN_CARDBUS */
   1834 
   1835 #ifdef TIWLAN_OMAP1610
   1836 int omap1610_drv_create(void)
   1837 {
   1838     omap_memif_init();
   1839     return tiwlan_create_drv(TIWLAN_OMAP1610_REGBASE, TIWLAN_OMAP1610_REGSIZE,
   1840                              TIWLAN_OMAP1610_MEMBASE, TIWLAN_OMAP1610_MEMSIZE,
   1841                              0, TIWLAN_OMAP1610_IRQ, NULL, NULL);
   1842 }
   1843 #endif /* #ifdef TIWLAN_OMAP1610 */
   1844 
   1845 #ifdef TIWLAN_MSM7000
   1846 
   1847 #define TROUT_IRQ MSM_GPIO_TO_INT(29)
   1848 
   1849 #ifdef SDIO_INTERRUPT_HANDLING_ON
   1850 static void tiwlan_sdio_irq(struct sdio_func *func)
   1851 {
   1852     printk("%s:\n", __FUNCTION__);
   1853 }
   1854 #endif
   1855 
   1856 static const struct sdio_device_id tiwlan_sdio_ids[] = {
   1857     { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)    },
   1858     {                                       },
   1859 };
   1860 
   1861 MODULE_DEVICE_TABLE(sdio, tiwlan_sdio_ids);
   1862 
   1863 int tiwlan_sdio_init(struct sdio_func *func)
   1864 {
   1865     int rc;
   1866 
   1867     rc = sdio_enable_func(func);
   1868     if (rc)
   1869         return rc;
   1870 
   1871     rc = sdio_set_block_size(func, 512);
   1872     if( rc ) {
   1873         sdio_disable_func(func);
   1874     }
   1875     return rc;
   1876 }
   1877 
   1878 static int tiwlan_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
   1879 {
   1880     int rc;
   1881 
   1882     SDIO_SetFunc( NULL );
   1883     if (func->vendor != VENDOR_ID_TI || func->device != DEVICE_ID_TI_WLAN)
   1884         return -ENODEV;
   1885 
   1886     printk(KERN_INFO
   1887            "TIWLAN: Found SDIO controller (vendor 0x%x, device 0x%x)\n",
   1888            func->vendor, func->device);
   1889 
   1890 #ifdef CONFIG_TROUT_PWRSINK
   1891     trout_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
   1892 #endif
   1893 #ifdef CONFIG_HTC_PWRSINK
   1894     htc_pwrsink_set(PWRSINK_WIFI, PWRSINK_WIFI_PERCENT_BASE);
   1895 #endif
   1896 
   1897     sdio_claim_host(func);
   1898 
   1899     rc = tiwlan_sdio_init(func);
   1900     if (rc)
   1901         goto err2;
   1902 #ifdef SDIO_INTERRUPT_HANDLING_ON
   1903     rc = sdio_claim_irq(func, tiwlan_sdio_irq);
   1904     if (rc)
   1905         goto err1;
   1906 #endif
   1907     SDIO_SetFunc( func );
   1908 
   1909     rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL);
   1910 
   1911     printk(KERN_INFO "TIWLAN: Driver initialized (rc %d)\n", rc);
   1912     complete(&sdio_wait);
   1913     return rc;
   1914 #ifdef SDIO_INTERRUPT_HANDLING_ON
   1915 err1:
   1916     sdio_disable_func(func);
   1917 #endif
   1918 err2:
   1919     sdio_release_host(func);
   1920     complete(&sdio_wait);
   1921     printk(KERN_ERR "TIWLAN: SDIO failure (err %d)\n", rc);
   1922     return rc;
   1923 }
   1924 
   1925 static void tiwlan_sdio_remove(struct sdio_func *func)
   1926 {
   1927     printk(KERN_DEBUG "TIWLAN: Releasing SDIO resources\n");
   1928 #ifdef SDIO_INTERRUPT_HANDLING_ON
   1929     sdio_release_irq(func);
   1930 #endif
   1931     sdio_disable_func(func);
   1932     sdio_release_host(func);
   1933     printk(KERN_DEBUG "TIWLAN: SDIO resources released\n");
   1934 }
   1935 
   1936 static struct sdio_driver tiwlan_sdio_drv = {
   1937     .probe          = tiwlan_sdio_probe,
   1938     .remove         = tiwlan_sdio_remove,
   1939     .name           = "sdio_tiwlan",
   1940     .id_table       = tiwlan_sdio_ids,
   1941 };
   1942 
   1943 #ifdef CONFIG_WIFI_CONTROL_FUNC
   1944 static int wifi_probe( struct platform_device *pdev )
   1945 {
   1946     struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
   1947 
   1948     printk("%s\n", __FUNCTION__);
   1949     if( wifi_ctrl ) {
   1950         wifi_control_data = wifi_ctrl;
   1951         if( wifi_ctrl->set_power )
   1952             wifi_ctrl->set_power(1);		/* Power On */
   1953         if( wifi_ctrl->set_reset )
   1954             wifi_ctrl->set_reset(0);		/* Reset clear */
   1955         if( wifi_ctrl->set_carddetect )
   1956             wifi_ctrl->set_carddetect(1);	/* CardDetect (0->1) */
   1957     }
   1958     return 0;
   1959 }
   1960 
   1961 static int wifi_remove( struct platform_device *pdev )
   1962 {
   1963     struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
   1964 
   1965     printk("%s\n", __FUNCTION__);
   1966     if( wifi_ctrl ) {
   1967         if( wifi_ctrl->set_carddetect )
   1968             wifi_ctrl->set_carddetect(0);	/* CardDetect (1->0) */
   1969         if( wifi_ctrl->set_reset )
   1970             wifi_ctrl->set_reset(1);		/* Reset active */
   1971         if( wifi_ctrl->set_power )
   1972             wifi_ctrl->set_power(0);		/* Power Off */
   1973     }
   1974     return 0;
   1975 }
   1976 
   1977 static struct platform_driver wifi_device = {
   1978     .probe          = wifi_probe,
   1979     .remove         = wifi_remove,
   1980     .suspend        = NULL,
   1981     .resume         = NULL,
   1982     .driver         = {
   1983         .name   = "msm_wifi",
   1984     },
   1985 };
   1986 
   1987 static int wifi_add_dev( void )
   1988 {
   1989     return platform_driver_register( &wifi_device );
   1990 }
   1991 
   1992 static void wifi_del_dev( void )
   1993 {
   1994     platform_driver_unregister( &wifi_device );
   1995 }
   1996 
   1997 int msm_wifi_power( int on )
   1998 {
   1999     printk("%s\n", __FUNCTION__);
   2000     if( wifi_control_data && wifi_control_data->set_power ) {
   2001         wifi_control_data->set_power(on);
   2002     }
   2003     return 0;
   2004 }
   2005 
   2006 int msm_wifi_reset( int on )
   2007 {
   2008     printk("%s\n", __FUNCTION__);
   2009     if( wifi_control_data && wifi_control_data->set_reset ) {
   2010         wifi_control_data->set_reset(on);
   2011     }
   2012     return 0;
   2013 }
   2014 #endif
   2015 #endif /* TIWLAN_MSM7000 */
   2016 
   2017 static int __init tiwlan_module_init(void)
   2018 {
   2019     int rc = 0;
   2020 
   2021     printk(KERN_INFO "TIWLAN: Driver loading\n");
   2022    /* Check sizes of basic structures to ensure that compilation
   2023       options are OK
   2024    */
   2025     if (packed_struct_tst())
   2026         ;/*IT: return -EINVAL; */
   2027 
   2028     tiwlan_deb_entry = create_proc_entry(TIWLAN_DBG_PROC, 0644, NULL);
   2029     if (tiwlan_deb_entry == NULL)
   2030         return -EINVAL;
   2031     tiwlan_deb_entry->read_proc = tiwlan_deb_read_proc;
   2032     tiwlan_deb_entry->write_proc = tiwlan_deb_write_proc;
   2033 #ifdef TIWLAN_MSM7000
   2034     init_completion(&sdio_wait);
   2035 #endif
   2036 #ifdef TIWLAN_CARDBUS
   2037     if ((rc=pci_register_driver(&tnetw1130_pci_driver)) <  0)
   2038         print_err("TIWLAN: PCMCIA driver failed to register\n");
   2039         remove_proc_entry(TIWLAN_DBG_PROC, NULL);
   2040         return rc;
   2041     }
   2042     printk(KERN_INFO "TIWLAN: Driver loaded\n");
   2043     return 0;
   2044 
   2045 #elif defined(TIWLAN_OMAP1610)
   2046     rc = omap1610_drv_create();
   2047     export_wifi_chip_id();
   2048     printk(KERN_INFO "TIWLAN: Driver loaded\n");
   2049     return rc;
   2050 
   2051 #elif defined(TIWLAN_MSM7000)
   2052 #ifdef CONFIG_WIFI_CONTROL_FUNC
   2053     wifi_add_dev();
   2054 #else
   2055     trout_wifi_power(1);          /* Power On */
   2056     trout_wifi_reset(0);          /* Reset clear */
   2057     trout_wifi_set_carddetect(1); /* CardDetect (0->1) */
   2058 #endif
   2059 
   2060     /* Register ourselves as an SDIO driver */
   2061     rc = sdio_register_driver(&tiwlan_sdio_drv);
   2062     if (rc < 0) {
   2063         printk(KERN_ERR "sdio register failed (%d)\n", rc);
   2064         remove_proc_entry(TIWLAN_DBG_PROC, NULL);
   2065         return rc;
   2066     }
   2067     /* rc = tiwlan_create_drv(0, 0, 0, 0, 0, TROUT_IRQ, NULL, NULL); -- Called in probe */
   2068 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
   2069     tiwlan_calibration = create_proc_entry("calibration", 0644, NULL);
   2070     if (tiwlan_calibration) {
   2071         tiwlan_calibration->size = tiwlan_get_nvs_size();
   2072         tiwlan_calibration->read_proc = tiwlan_calibration_read_proc;
   2073         tiwlan_calibration->write_proc = tiwlan_calibration_write_proc;
   2074     }
   2075 #endif
   2076     if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) {
   2077         printk(KERN_ERR "%s: Timed out waiting for device detect\n", __func__);
   2078         remove_proc_entry(TIWLAN_DBG_PROC, NULL);
   2079 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
   2080 	if (tiwlan_calibration)
   2081             remove_proc_entry("calibration", NULL);
   2082 #endif
   2083         sdio_unregister_driver(&tiwlan_sdio_drv);
   2084 #ifdef CONFIG_WIFI_CONTROL_FUNC
   2085         wifi_del_dev();
   2086 #else
   2087         trout_wifi_set_carddetect(0); /* CardDetect (1->0) */
   2088         trout_wifi_reset(1);          /* Reset active */
   2089         trout_wifi_power(0);          /* Power Off */
   2090 #endif
   2091         return -ENODEV;
   2092     }
   2093     export_wifi_chip_id();
   2094     printk(KERN_INFO "TIWLAN: Driver loaded\n");
   2095     return 0;
   2096 
   2097 #else
   2098 
   2099 #error Either TIWLAN_CARDBUS, TIWLAN_OMAP1610 or TIWLAN_MSM7000 must be defined
   2100 
   2101 #endif
   2102 }
   2103 
   2104 static void __exit tiwlan_module_cleanup(void)
   2105 {
   2106     struct list_head *l;
   2107     struct list_head *tmp;
   2108 
   2109     printk(KERN_INFO "TIWLAN: Driver unloading\n");
   2110 #ifdef TIWLAN_CARDBUS
   2111     pci_unregister_driver(&tnetw1130_pci_driver);
   2112 #endif
   2113     list_for_each_safe(l, tmp, &tiwlan_drv_list)
   2114     {
   2115         tiwlan_net_dev_t *drv = (tiwlan_net_dev_t *)list_entry(l, tiwlan_net_dev_t, list);
   2116         list_del(l);
   2117         tiwlan_destroy_drv(drv);
   2118     }
   2119     remove_proc_entry(TIWLAN_DBG_PROC, NULL);
   2120 #ifdef TIWLAN_MSM7000
   2121 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 29))
   2122     if(tiwlan_calibration)
   2123         remove_proc_entry("calibration", NULL);
   2124 #endif
   2125     sdio_unregister_driver(&tiwlan_sdio_drv);
   2126 #ifdef CONFIG_WIFI_CONTROL_FUNC
   2127     wifi_del_dev();
   2128 #else
   2129     trout_wifi_set_carddetect(0); /* CardDetect (1->0) */
   2130     trout_wifi_reset(1);          /* Reset active */
   2131     trout_wifi_power(0);          /* Power Off */
   2132 #endif
   2133 #endif
   2134     printk(KERN_INFO "TIWLAN: Driver unloaded\n");
   2135 }
   2136 
   2137 module_init(tiwlan_module_init);
   2138 module_exit(tiwlan_module_cleanup);
   2139