1 /* 2 * WlanDrvIf.c 3 * 4 * Copyright(c) 1998 - 2009 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 * src/esta_drv.c 37 * 38 * Kernel level portion of eSTA DK Linux module driver 39 * 40 */ 41 42 43 /** \file WlanDrvIf.c 44 * \brief The OS-Dependent interfaces of the WLAN driver with external applications: 45 * - Configuration utilities (including download, configuration and activation) 46 * - Network Stack (Tx and Rx) 47 * - Interrupts 48 * - Events to external applications 49 * 50 * \see WlanDrvIf.h, Wext.c 51 */ 52 53 54 #include <net/sock.h> 55 #include <linux/etherdevice.h> 56 #include <linux/delay.h> 57 #include <linux/netlink.h> 58 59 #include "WlanDrvIf.h" 60 #include "osApi.h" 61 #include "host_platform.h" 62 #include "context.h" 63 #include "CmdHndlr.h" 64 #include "WlanDrvWext.h" 65 #include "DrvMain.h" 66 #include "txDataQueue_Api.h" 67 #include "txMgmtQueue_Api.h" 68 #include "TWDriver.h" 69 #include "Ethernet.h" 70 #ifdef TI_DBG 71 #include "tracebuf_api.h" 72 #endif 73 /* PM hooks */ 74 #ifdef TI_CONFIG_PM_HOOKS 75 #include "SdioDrv.h" 76 static int wlanDrvIf_pm_resume(void); 77 static int wlanDrvIf_pm_suspend(void); 78 #endif 79 #include "bmtrace_api.h" 80 #ifdef STACK_PROFILE 81 #include "stack_profile.h" 82 #endif 83 84 /* save driver handle just for module cleanup */ 85 static TWlanDrvIfObj *pDrvStaticHandle; 86 87 #define OS_SPECIFIC_RAM_ALLOC_LIMIT (0xFFFFFFFF) /* assume OS never reach that limit */ 88 89 90 MODULE_DESCRIPTION("TI WLAN Embedded Station Driver"); 91 MODULE_LICENSE("GPL"); 92 93 94 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31)) 95 static int wlanDrvIf_Xmit(struct sk_buff *skb, struct net_device *dev); 96 static int wlanDrvIf_XmitDummy(struct sk_buff *skb, struct net_device *dev); 97 static struct net_device_stats *wlanDrvIf_NetGetStat(struct net_device *dev); 98 int wlanDrvIf_Open(struct net_device *dev); 99 int wlanDrvIf_Release(struct net_device *dev); 100 101 static struct net_device_ops tiwlan_ops_pri = { 102 .ndo_open = wlanDrvIf_Open, 103 .ndo_stop = wlanDrvIf_Release, 104 .ndo_get_stats = wlanDrvIf_NetGetStat, 105 .ndo_do_ioctl = NULL, 106 .ndo_start_xmit = wlanDrvIf_Xmit, 107 }; 108 109 static struct net_device_ops tiwlan_ops_dummy = { 110 .ndo_open = wlanDrvIf_Open, 111 .ndo_stop = wlanDrvIf_Release, 112 .ndo_get_stats = wlanDrvIf_NetGetStat, 113 .ndo_do_ioctl = NULL, 114 .ndo_start_xmit = wlanDrvIf_XmitDummy, 115 }; 116 #endif 117 118 /** 119 * \fn wlanDrvIf_Xmit 120 * \brief Packets transmission 121 * 122 * The network stack calls this function in order to transmit a packet 123 * through the WLAN interface. 124 * The packet is inserted to the drver Tx queues and its handling is continued 125 * after switching to the driver context. 126 * 127 * \note 128 * \param skb - The Linux packet buffer structure 129 * \param dev - The driver network-interface handle 130 * \return 0 (= OK) 131 * \sa 132 */ 133 static int wlanDrvIf_Xmit (struct sk_buff *skb, struct net_device *dev) 134 { 135 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 136 TTxCtrlBlk * pPktCtrlBlk; 137 int status; 138 139 CL_TRACE_START_L1(); 140 141 os_profile (drv, 0, 0); 142 drv->stats.tx_packets++; 143 drv->stats.tx_bytes += skb->len; 144 145 /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */ 146 pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD); 147 148 pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */ 149 pPktCtrlBlk->tTxDescriptor.length = skb->len; 150 pPktCtrlBlk->tTxPktParams.pInputPkt = skb; 151 152 /* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */ 153 pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data; 154 pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN; 155 pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN; 156 pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN; 157 pPktCtrlBlk->tTxnStruct.aLen[2] = 0; 158 159 /* Send the packet to the driver for transmission. */ 160 status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority); 161 162 /* If failed (queue full or driver not running), drop the packet. */ 163 if (status != TI_OK) 164 { 165 drv->stats.tx_errors++; 166 } 167 os_profile (drv, 1, 0); 168 169 CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", ""); 170 171 return 0; 172 } 173 /*--------------------------------------------------------------------------------------*/ 174 /** 175 * \fn wlanDrvIf_FreeTxPacket 176 * \brief Free the OS Tx packet 177 * 178 * Free the OS Tx packet after driver processing is finished. 179 * 180 * \note 181 * \param hOs - The OAL object handle 182 * \param pPktCtrlBlk - The packet CtrlBlk 183 * \param eStatus - The packet transmission status (OK/NOK) 184 * \return void 185 * \sa 186 */ 187 /*--------------------------------------------------------------------------------------*/ 188 189 void wlanDrvIf_FreeTxPacket (TI_HANDLE hOs, TTxCtrlBlk *pPktCtrlBlk, TI_STATUS eStatus) 190 { 191 dev_kfree_skb((struct sk_buff *)pPktCtrlBlk->tTxPktParams.pInputPkt); 192 } 193 194 /** 195 * \fn wlanDrvIf_XmitDummy 196 * \brief Dummy transmission handler 197 * 198 * This function is registered at the network stack interface as the packets-transmission 199 * handler (replacing wlanDrvIf_Xmit) when the driver is not operational. 200 * Using this dummy handler is more efficient then checking the driver state for every 201 * packet transmission. 202 * 203 * \note 204 * \param skb - The Linux packet buffer structure 205 * \param dev - The driver network-interface handle 206 * \return error 207 * \sa wlanDrvIf_Xmit 208 */ 209 static int wlanDrvIf_XmitDummy (struct sk_buff *skb, struct net_device *dev) 210 { 211 /* Just return error. The driver is not running (network stack frees the packet) */ 212 return -ENODEV; 213 } 214 215 216 /** 217 * \fn wlanDrvIf_NetGetStat 218 * \brief Provides driver statistics 219 * 220 * Provides driver Tx and Rx statistics to network stack. 221 * 222 * \note 223 * \param dev - The driver network-interface handle 224 * \return The statistics pointer 225 * \sa 226 */ 227 static struct net_device_stats *wlanDrvIf_NetGetStat (struct net_device *dev) 228 { 229 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 230 ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_NetGetStat()\n"); 231 232 return &drv->stats; 233 } 234 235 236 /** 237 * \fn wlanDrvIf_UpdateDriverState 238 * \brief Update the driver state 239 * 240 * The DrvMain uses this function to update the OAL with the driver steady state 241 * that is relevant for the driver users. 242 * 243 * \note 244 * \param hOs - The driver object handle 245 * \param eDriverState - The new driver state 246 * \return void 247 * \sa 248 */ 249 void wlanDrvIf_UpdateDriverState (TI_HANDLE hOs, EDriverSteadyState eDriverState) 250 { 251 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; 252 253 ti_dprintf(TIWLAN_LOG_OTHER, "wlanDrvIf_UpdateDriverState(): State = %d\n", eDriverState); 254 255 /* Save the new state */ 256 drv->tCommon.eDriverState = eDriverState; 257 258 /* If the new state is not RUNNING, replace the Tx handler to a dummy one. */ 259 if (eDriverState != DRV_STATE_RUNNING) { 260 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) 261 drv->netdev->hard_start_xmit = wlanDrvIf_XmitDummy; 262 #else 263 drv->netdev->netdev_ops = &tiwlan_ops_dummy; 264 #endif 265 } 266 } 267 268 269 /** 270 * \fn wlanDrvIf_HandleInterrupt 271 * \brief The WLAN interrupt handler 272 * 273 * The WLAN driver interrupt handler called in the interrupt context. 274 * The actual handling is done in the driver's context after switching to the workqueue. 275 * 276 * \note 277 * \param irq - The interrupt type 278 * \param hDrv - The driver object handle 279 * \param cpu_regs - The CPU registers 280 * \return IRQ_HANDLED 281 * \sa 282 */ 283 irqreturn_t wlanDrvIf_HandleInterrupt (int irq, void *hDrv, struct pt_regs *cpu_regs) 284 { 285 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hDrv; 286 287 TWD_InterruptRequest (drv->tCommon.hTWD); 288 289 return IRQ_HANDLED; 290 } 291 292 293 /** 294 * \fn PollIrqHandler 295 * \brief WLAN IRQ polling handler - for debug! 296 * 297 * A debug option to catch the WLAN events in polling instead of interrupts. 298 * A timer calls this function periodically to check the interrupt status register. 299 * 300 * \note 301 * \param parm - The driver object handle 302 * \return void 303 * \sa 304 */ 305 #ifdef PRIODIC_INTERRUPT 306 static void wlanDrvIf_PollIrqHandler (TI_HANDLE parm) 307 { 308 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)parm; 309 310 wlanDrvIf_HandleInterrupt (0, drv, NULL); 311 os_periodicIntrTimerStart (drv); 312 } 313 #endif 314 315 316 /** 317 * \fn wlanDrvIf_DriverTask 318 * \brief The driver task 319 * 320 * This is the driver's task, where most of its job is done. 321 * External contexts just save required information and schedule the driver's 322 * task to continue the handling. 323 * See more information in the context engine module (context.c). 324 * 325 * \note 326 * \param hDrv - The driver object handle 327 * \return void 328 * \sa 329 */ 330 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) 331 static void wlanDrvIf_DriverTask (void *hDrv) 332 { 333 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hDrv; 334 #else 335 static void wlanDrvIf_DriverTask(struct work_struct *work) 336 { 337 #ifdef STACK_PROFILE 338 register unsigned long sp asm ("sp"); 339 unsigned long local_sp = sp; 340 #endif 341 TWlanDrvIfObj *drv = container_of(work, TWlanDrvIfObj, tWork); 342 #endif 343 344 #ifdef STACK_PROFILE 345 unsigned long curr1, base1; 346 unsigned long curr2, base2; 347 static unsigned long maximum_stack = 0; 348 #endif 349 os_profile (drv, 0, 0); 350 351 #ifdef STACK_PROFILE 352 curr1 = check_stack_start(&base1, local_sp + 4, 0); 353 #endif 354 355 /* Call the driver main task */ 356 context_DriverTask (drv->tCommon.hContext); 357 358 os_profile (drv, 1, 0); 359 os_wake_lock_timeout(drv); 360 os_wake_unlock(drv); 361 #ifdef STACK_PROFILE 362 curr2 = check_stack_stop(&base2, 0); 363 if (base2 == base1) { 364 /* if the current measurement is bigger then the maximum store it and print*/ 365 if ((curr1 - curr2) > maximum_stack) { 366 printk("STACK PROFILER GOT THE LOCAL MAXIMMUM!!!! \n"); 367 printk("current operation stack use=%lu \n",(curr1 - curr2)); 368 printk("total stack use=%lu \n",8192 - curr2 + base2); 369 printk("total stack usage=%lu percent \n",100 * (8192 - curr2 + base2) / 8192); 370 maximum_stack = curr1 - curr2; 371 } 372 } 373 #endif 374 } 375 376 377 /** 378 * \fn wlanDrvIf_LoadFiles 379 * \brief Load init files from loader 380 * 381 * This function is called from the loader context right after the driver 382 * is created (in IDLE state). 383 * It copies the following files to the driver's memory: 384 * - Ini-File - The driver's default parameters values 385 * - NVS-File - The NVS data for FW usage 386 * - FW-Image - The FW program image 387 * 388 * \note 389 * \param drv - The driver object handle 390 * \return void 391 * \sa wlanDrvIf_GetFile 392 */ 393 int wlanDrvIf_LoadFiles (TWlanDrvIfObj *drv, TLoaderFilesData *pInitFiles) 394 { 395 if (!pInitFiles) 396 { 397 ti_dprintf (TIWLAN_LOG_ERROR, "No Init Files!\n"); 398 return -EINVAL; 399 } 400 401 if (drv->tCommon.eDriverState != DRV_STATE_IDLE) 402 { 403 ti_dprintf (TIWLAN_LOG_ERROR, "Trying to load files not in IDLE state!\n"); 404 return -EINVAL; 405 } 406 407 if (pInitFiles->uIniFileLength) 408 { 409 drv->tCommon.tIniFile.uSize = pInitFiles->uIniFileLength; 410 drv->tCommon.tIniFile.pImage = kmalloc (pInitFiles->uIniFileLength, GFP_KERNEL); 411 #ifdef TI_MEM_ALLOC_TRACE 412 os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, pInitFiles->uIniFileLength, GFP_KERNEL, pInitFiles->uIniFileLength); 413 #endif 414 if (!drv->tCommon.tIniFile.pImage) 415 { 416 ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for Ini-File!\n"); 417 return -ENOMEM; 418 } 419 memcpy (drv->tCommon.tIniFile.pImage, 420 &pInitFiles->data[pInitFiles->uNvsFileLength + pInitFiles->uFwFileLength], 421 drv->tCommon.tIniFile.uSize); 422 } 423 424 if (pInitFiles->uNvsFileLength) 425 { 426 drv->tCommon.tNvsImage.uSize = pInitFiles->uNvsFileLength; 427 drv->tCommon.tNvsImage.pImage = kmalloc (drv->tCommon.tNvsImage.uSize, GFP_KERNEL); 428 #ifdef TI_MEM_ALLOC_TRACE 429 os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", 430 __FUNCTION__, __LINE__, drv->tCommon.tNvsImage.uSize, GFP_KERNEL, drv->tCommon.tNvsImage.uSize); 431 #endif 432 if (!drv->tCommon.tNvsImage.pImage) 433 { 434 ti_dprintf (TIWLAN_LOG_ERROR, "Cannot allocate buffer for NVS image\n"); 435 return -ENOMEM; 436 } 437 memcpy (drv->tCommon.tNvsImage.pImage, &pInitFiles->data[0], drv->tCommon.tNvsImage.uSize ); 438 } 439 440 drv->tCommon.tFwImage.uSize = pInitFiles->uFwFileLength; 441 if (!drv->tCommon.tFwImage.uSize) 442 { 443 ti_dprintf (TIWLAN_LOG_ERROR, "No firmware image\n"); 444 return -EINVAL; 445 } 446 drv->tCommon.tFwImage.pImage = os_memoryAlloc (drv, drv->tCommon.tFwImage.uSize); 447 #ifdef TI_MEM_ALLOC_TRACE 448 os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", 449 __FUNCTION__, __LINE__, drv->tCommon.tFwImage.uSize, GFP_KERNEL, drv->tCommon.tFwImage.uSize); 450 #endif 451 if (!drv->tCommon.tFwImage.pImage) 452 { 453 ti_dprintf(TIWLAN_LOG_ERROR, "Cannot allocate buffer for firmware image\n"); 454 return -ENOMEM; 455 } 456 memcpy (drv->tCommon.tFwImage.pImage, 457 &pInitFiles->data[pInitFiles->uNvsFileLength], 458 drv->tCommon.tFwImage.uSize); 459 460 ti_dprintf(TIWLAN_LOG_OTHER, "--------- Eeeprom=%p(%lu), Firmware=%p(%lu), IniFile=%p(%lu)\n", 461 drv->tCommon.tNvsImage.pImage, drv->tCommon.tNvsImage.uSize, 462 drv->tCommon.tFwImage.pImage, drv->tCommon.tFwImage.uSize, 463 drv->tCommon.tIniFile.pImage, drv->tCommon.tIniFile.uSize); 464 465 return 0; 466 } 467 468 469 /** 470 * \fn wlanDrvIf_GetFile 471 * \brief Provides access to a requested init file 472 * 473 * Provide the requested file information and call the requester callback. 474 * Note that in Linux the files were previously loaded to driver memory 475 * by the loader (see wlanDrvIf_LoadFiles). 476 * 477 * \note 478 * \param hOs - The driver object handle 479 * \param pFileInfo - The requested file's properties 480 * \return TI_OK 481 * \sa wlanDrvIf_LoadFiles 482 */ 483 int wlanDrvIf_GetFile (TI_HANDLE hOs, TFileInfo *pFileInfo) 484 { 485 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; 486 487 if (drv == NULL || pFileInfo == NULL) { 488 ti_dprintf(TIWLAN_LOG_ERROR, "wlanDrv_GetFile: ERROR: Null File Handler, Exiting"); 489 return TI_NOK; 490 } 491 492 /* Future option for getting the FW image part by part */ 493 pFileInfo->hOsFileDesc = NULL; 494 495 /* Fill the file's location and size in the file's info structure */ 496 switch (pFileInfo->eFileType) 497 { 498 case FILE_TYPE_INI: 499 pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tIniFile.pImage; 500 pFileInfo->uLength = drv->tCommon.tIniFile.uSize; 501 break; 502 case FILE_TYPE_NVS: 503 pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tNvsImage.pImage; 504 pFileInfo->uLength = drv->tCommon.tNvsImage.uSize; 505 break; 506 case FILE_TYPE_FW: 507 if (drv->tCommon.tFwImage.pImage == NULL) 508 { 509 ti_dprintf(TIWLAN_LOG_ERROR, "wlanDrv_GetFile: ERROR: no Firmware image, exiting\n"); 510 return TI_NOK; 511 } 512 513 pFileInfo->pBuffer = (TI_UINT8 *)drv->tCommon.tFwImage.pImage; 514 pFileInfo->bLast = TI_FALSE; 515 pFileInfo->uLength = 0; 516 pFileInfo->uOffset = 0; 517 pFileInfo->uChunkBytesLeft = 0; 518 pFileInfo->uChunksLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); 519 /* check uChunksLeft's Validity */ 520 if (( pFileInfo->uChunksLeft == 0 ) || ( pFileInfo->uChunksLeft > MAX_CHUNKS_IN_FILE )) 521 { 522 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() Read Invalid Chunks Left: %d!\n",pFileInfo->uChunksLeft); 523 return TI_NOK; 524 } 525 pFileInfo->pBuffer += DRV_ADDRESS_SIZE; 526 /* FALL THROUGH */ 527 case FILE_TYPE_FW_NEXT: 528 /* check dec. validity */ 529 if ( pFileInfo->uChunkBytesLeft >= pFileInfo->uLength ) 530 { 531 pFileInfo->uChunkBytesLeft -= pFileInfo->uLength; 532 } 533 /* invalid Dec. */ 534 else 535 { 536 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_GetFile() No. of Bytes Left < File Length\n"); 537 return TI_NOK; 538 } 539 pFileInfo->pBuffer += pFileInfo->uLength; 540 541 /* Finished reading all Previous Chunk */ 542 if ( pFileInfo->uChunkBytesLeft == 0 ) 543 { 544 /* check dec. validity */ 545 if ( pFileInfo->uChunksLeft > 0 ) 546 { 547 pFileInfo->uChunksLeft--; 548 } 549 /* invalid Dec. */ 550 else 551 { 552 ti_dprintf (TIWLAN_LOG_ERROR, "No. of Bytes Left = 0 and Chunks Left <= 0\n"); 553 return TI_NOK; 554 } 555 /* read Chunk's address */ 556 pFileInfo->uAddress = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); 557 pFileInfo->pBuffer += DRV_ADDRESS_SIZE; 558 /* read Portion's length */ 559 pFileInfo->uChunkBytesLeft = BYTE_SWAP_LONG( *((TI_UINT32*)(pFileInfo->pBuffer)) ); 560 pFileInfo->pBuffer += DRV_ADDRESS_SIZE; 561 } 562 /* Reading Chunk is NOT complete */ 563 else 564 { 565 pFileInfo->uAddress += pFileInfo->uLength; 566 } 567 568 if ( pFileInfo->uChunkBytesLeft < OS_SPECIFIC_RAM_ALLOC_LIMIT ) 569 { 570 pFileInfo->uLength = pFileInfo->uChunkBytesLeft; 571 } 572 else 573 { 574 pFileInfo->uLength = OS_SPECIFIC_RAM_ALLOC_LIMIT; 575 } 576 577 /* If last chunk to download */ 578 if (( pFileInfo->uChunksLeft == 0 ) && 579 ( pFileInfo->uLength == pFileInfo->uChunkBytesLeft )) 580 { 581 pFileInfo->bLast = TI_TRUE; 582 } 583 584 break; 585 } 586 587 /* Call the requester callback */ 588 if (pFileInfo->fCbFunc) 589 { 590 pFileInfo->fCbFunc (pFileInfo->hCbHndl); 591 } 592 593 return TI_OK; 594 } 595 596 597 /** 598 * \fn wlanDrvIf_SetMacAddress 599 * \brief Set STA MAC address 600 * 601 * Called by DrvMain from init process. 602 * Copies STA MAC address to the network interface structure. 603 * 604 * \note 605 * \param hOs - The driver object handle 606 * \param pMacAddr - The STA MAC address 607 * \return TI_OK 608 * \sa wlanDrvIf_LoadFiles 609 */ 610 void wlanDrvIf_SetMacAddress (TI_HANDLE hOs, TI_UINT8 *pMacAddr) 611 { 612 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; 613 614 /* Copy STA MAC address to the network interface structure */ 615 MAC_COPY (drv->netdev->dev_addr, pMacAddr); 616 } 617 618 619 /** 620 * \fn wlanDrvIf_Start 621 * \brief Start driver 622 * 623 * Called by network stack upon opening network interface (ifconfig up). 624 * Can also be called from user application or CLI for flight mode. 625 * Start the driver initialization process up to OPERATIONAL state. 626 * 627 * \note 628 * \param dev - The driver network-interface handle 629 * \return 0 if succeeded, error if driver not available 630 * \sa wlanDrvIf_Stop 631 */ 632 int wlanDrvIf_Start (struct net_device *dev) 633 { 634 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 635 int status; 636 637 ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Start()\n"); 638 printk("%s\n", __func__); 639 if (!drv->tCommon.hDrvMain) 640 { 641 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver not created!\n"); 642 return -ENODEV; 643 } 644 645 if (DRV_STATE_FAILED == drv->tCommon.eDriverState) 646 { 647 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Start() Driver failed!\n"); 648 return -ENODEV; 649 } 650 651 /* 652 * Insert Start command in DrvMain action queue, request driver scheduling 653 * and wait for action completion (all init process). 654 */ 655 os_wake_lock_timeout_enable(drv); 656 status = drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_START); 657 return (status) ? -1 : 0; 658 } 659 660 int wlanDrvIf_Open (struct net_device *dev) 661 { 662 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 663 int status = 0; 664 665 ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Open()\n"); 666 printk("%s\n", __func__); 667 if (!drv->tCommon.hDrvMain) { 668 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Open() Driver not created!\n"); 669 return -ENODEV; 670 } 671 672 if (drv->tCommon.eDriverState == DRV_STATE_STOPPED || 673 drv->tCommon.eDriverState == DRV_STATE_IDLE) { 674 status = wlanDrvIf_Start(dev); 675 } 676 677 /* 678 * Finalize network interface setup 679 */ 680 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) 681 drv->netdev->hard_start_xmit = wlanDrvIf_Xmit; 682 #else 683 drv->netdev->netdev_ops = &tiwlan_ops_pri; 684 #endif 685 drv->netdev->addr_len = MAC_ADDR_LEN; 686 netif_start_queue (dev); 687 688 /* register 3430 PM hooks in our SDIO driver */ 689 #ifdef TI_CONFIG_PM_HOOKS 690 #ifndef CONFIG_MMC_EMBEDDED_SDIO 691 sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend); 692 #endif 693 #endif 694 return status; 695 } 696 697 /** 698 * \fn wlanDrvIf_Stop 699 * \brief Stop driver 700 * 701 * Called by network stack upon closing network interface (ifconfig down). 702 * Can also be called from user application or CLI for flight mode. 703 * Stop the driver and turn off the device. 704 * 705 * \note 706 * \param dev - The driver network-interface handle 707 * \return 0 (OK) 708 * \sa wlanDrvIf_Start 709 */ 710 int wlanDrvIf_Stop (struct net_device *dev) 711 { 712 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 713 714 ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Stop()\n"); 715 printk("%s\n", __func__); 716 717 if (DRV_STATE_FAILED == drv->tCommon.eDriverState) 718 { 719 return -ENODEV; 720 } 721 722 /* 723 * Insert Stop command in DrvMain action queue, request driver scheduling 724 * and wait for Stop process completion. 725 */ 726 os_wake_lock_timeout_enable(drv); 727 drvMain_InsertAction (drv->tCommon.hDrvMain, ACTION_TYPE_STOP); 728 return 0; 729 } 730 731 int wlanDrvIf_Release (struct net_device *dev) 732 { 733 /* TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); */ 734 735 ti_dprintf (TIWLAN_LOG_OTHER, "wlanDrvIf_Release()\n"); 736 printk("%s\n", __func__); 737 /* Disable network interface queue */ 738 netif_stop_queue (dev); 739 return 0; 740 } 741 742 /* 3430 PM hooks */ 743 #ifdef TI_CONFIG_PM_HOOKS 744 static int wlanDrvIf_pm_resume(void) 745 { 746 return(wlanDrvIf_Open(pDrvStaticHandle->netdev)); 747 } 748 749 static int wlanDrvIf_pm_suspend(void) 750 { 751 wlanDrvIf_Release(pDrvStaticHandle->netdev); 752 return(wlanDrvIf_Stop(pDrvStaticHandle->netdev)); 753 } 754 #endif 755 756 /** 757 * \fn wlanDrvIf_SetupNetif 758 * \brief Setup driver network interface 759 * 760 * Called in driver creation process. 761 * Setup driver network interface. 762 * 763 * \note 764 * \param drv - The driver object handle 765 * \return 0 - OK, else - failure 766 * \sa 767 */ 768 static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv) 769 { 770 struct net_device *dev; 771 int res; 772 773 /* Allocate network interface structure for the driver */ 774 dev = alloc_etherdev (0); 775 if (dev == NULL) 776 { 777 ti_dprintf (TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n"); 778 return -ENOMEM; 779 } 780 781 /* Setup the network interface */ 782 ether_setup (dev); 783 784 NETDEV_SET_PRIVATE(dev,drv); 785 drv->netdev = dev; 786 strcpy (dev->name, TIWLAN_DRV_IF_NAME); 787 netif_carrier_off (dev); 788 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31)) 789 /* the following is required on at least BSP 23.8 and higher. 790 Without it, the Open function of the driver will not be called 791 when trying to 'ifconfig up' the interface */ 792 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) 793 dev->validate_addr = NULL; 794 #endif 795 dev->open = wlanDrvIf_Open; 796 dev->stop = wlanDrvIf_Release; 797 dev->hard_start_xmit = wlanDrvIf_XmitDummy; 798 dev->get_stats = wlanDrvIf_NetGetStat; 799 dev->do_ioctl = NULL; 800 #else 801 dev->netdev_ops = &tiwlan_ops_dummy; 802 #endif 803 dev->tx_queue_len = 100; 804 805 /* Initialize Wireless Extensions interface (WEXT) */ 806 wlanDrvWext_Init (dev); 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 /* 816 On the latest Kernel there is no more support for the below macro. 817 */ 818 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) 819 SET_MODULE_OWNER (dev); 820 #endif 821 return 0; 822 } 823 824 /** 825 * \fn wlanDrvIf_CommandDone 826 * \brief Free current command semaphore. 827 * 828 * This routine is called whenever a command has finished executing and Free current command semaphore. 829 * 830 * \note 831 * \param hOs - The driver object handle 832 * \param pSignalObject - handle to complete mechanism per OS 833 * \param CmdResp_p - respond structure (TCmdRespUnion) for OSE OS only 834 * \return 0 - OK, else - failure 835 * \sa wlanDrvIf_Destroy 836 */ 837 void wlanDrvIf_CommandDone (TI_HANDLE hOs, void *pSignalObject, TI_UINT8 *CmdResp_p) 838 { 839 /* Free semaphore */ 840 os_SignalObjectSet (hOs, pSignalObject); 841 } 842 843 844 /** 845 * \fn wlanDrvIf_Create 846 * \brief Create the driver instance 847 * 848 * Allocate driver object. 849 * Initialize driver OS resources (IRQ, workqueue, events socket) 850 * Setup driver network interface. 851 * Create and link all driver modules. 852 * 853 * \note 854 * \param void 855 * \return 0 - OK, else - failure 856 * \sa wlanDrvIf_Destroy 857 */ 858 static int wlanDrvIf_Create (void) 859 { 860 TWlanDrvIfObj *drv; /* Dm: Failure is not cleaned properly !!! */ 861 int rc; 862 863 /* Allocate driver's structure */ 864 drv = kmalloc (sizeof(TWlanDrvIfObj), GFP_KERNEL); 865 if (!drv) 866 { 867 return -ENOMEM; 868 } 869 #ifdef TI_DBG 870 tb_init(TB_OPTION_NONE); 871 #endif 872 pDrvStaticHandle = drv; /* save for module destroy */ 873 #ifdef TI_MEM_ALLOC_TRACE 874 os_printf ("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, sizeof(TWlanDrvIfObj), GFP_KERNEL, sizeof(TWlanDrvIfObj)); 875 #endif 876 memset (drv, 0, sizeof(TWlanDrvIfObj)); 877 878 /* Dm: drv->irq = TNETW_IRQ; */ 879 drv->tCommon.eDriverState = DRV_STATE_IDLE; 880 881 drv->tiwlan_wq = create_freezeable_workqueue(DRIVERWQ_NAME); 882 if (!drv->tiwlan_wq) { 883 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to create workQ!\n"); 884 rc = -EINVAL; 885 goto drv_create_end_1; 886 } 887 drv->wl_packet = 0; 888 drv->wl_count = 0; 889 #ifdef CONFIG_HAS_WAKELOCK 890 wake_lock_init(&drv->wl_wifi, WAKE_LOCK_SUSPEND, "wifi_wake"); 891 wake_lock_init(&drv->wl_rxwake, WAKE_LOCK_SUSPEND, "wifi_rx_wake"); 892 #endif 893 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) 894 INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask, (void *)drv); 895 #else 896 INIT_WORK(&drv->tWork, wlanDrvIf_DriverTask); 897 #endif 898 spin_lock_init (&drv->lock); 899 900 /* Setup driver network interface. */ 901 rc = wlanDrvIf_SetupNetif (drv); 902 if (rc) { 903 goto drv_create_end_2; 904 } 905 906 /* Create the events socket interface */ 907 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) 908 drv->wl_sock = netlink_kernel_create( NETLINK_USERSOCK, 0, NULL, THIS_MODULE ); 909 #else 910 drv->wl_sock = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 0, NULL, NULL, THIS_MODULE ); 911 #endif 912 if (drv->wl_sock == NULL) { 913 ti_dprintf (TIWLAN_LOG_ERROR, "netlink_kernel_create() failed !\n"); 914 rc = -EINVAL; 915 goto drv_create_end_3; 916 } 917 918 /* Create all driver modules and link their handles */ 919 rc = drvMain_Create (drv, 920 &drv->tCommon.hDrvMain, 921 &drv->tCommon.hCmdHndlr, 922 &drv->tCommon.hContext, 923 &drv->tCommon.hTxDataQ, 924 &drv->tCommon.hTxMgmtQ, 925 &drv->tCommon.hTxCtrl, 926 &drv->tCommon.hTWD, 927 &drv->tCommon.hEvHandler, 928 &drv->tCommon.hCmdDispatch, 929 &drv->tCommon.hReport); 930 if (rc != TI_OK) { 931 ti_dprintf (TIWLAN_LOG_ERROR, "%s: Failed to dvrMain_Create!\n", __func__); 932 rc = -EINVAL; 933 goto drv_create_end_4; 934 } 935 /* 936 * Initialize interrupts (or polling mode for debug): 937 */ 938 #ifdef PRIODIC_INTERRUPT 939 /* Debug mode: Polling (the timer is started by HwInit process) */ 940 drv->hPollTimer = os_timerCreate ((TI_HANDLE)drv, wlanDrvIf_PollIrqHandler, (TI_HANDLE)drv); 941 #else 942 /* Normal mode: Interrupts (the default mode) */ 943 rc = hPlatform_initInterrupt (drv, (void*)wlanDrvIf_HandleInterrupt); 944 if (rc) { 945 ti_dprintf (TIWLAN_LOG_ERROR, "wlanDrvIf_Create(): Failed to register interrupt handler!\n"); 946 goto drv_create_end_5; 947 } 948 #endif /* PRIODIC_INTERRUPT */ 949 return 0; 950 drv_create_end_5: 951 /* Destroy all driver modules */ 952 if (drv->tCommon.hDrvMain) { 953 drvMain_Destroy (drv->tCommon.hDrvMain); 954 } 955 drv_create_end_4: 956 if (drv->wl_sock) { 957 sock_release (drv->wl_sock->sk_socket); 958 } 959 960 drv_create_end_3: 961 /* Release the driver network interface */ 962 if (drv->netdev) { 963 unregister_netdev (drv->netdev); 964 free_netdev (drv->netdev); 965 } 966 967 drv_create_end_2: 968 #ifdef CONFIG_HAS_WAKELOCK 969 wake_lock_destroy(&drv->wl_wifi); 970 wake_lock_destroy(&drv->wl_rxwake); 971 #endif 972 if (drv->tiwlan_wq) 973 destroy_workqueue(drv->tiwlan_wq); 974 975 drv_create_end_1: 976 kfree(drv); 977 printk("%s: Fail\n", __func__); 978 return rc; 979 } 980 981 982 /** 983 * \fn wlanDrvIf_Destroy 984 * \brief Destroy the driver instance 985 * 986 * Destroy all driver modules. 987 * Release driver OS resources (IRQ, workqueue, events socket) 988 * Release driver network interface. 989 * Free init files memory. 990 * Free driver object. 991 * 992 * \note 993 * \param drv - The driver object handle 994 * \return void 995 * \sa wlanDrvIf_Create 996 */ 997 static void wlanDrvIf_Destroy (TWlanDrvIfObj *drv) 998 { 999 if (!drv) 1000 return; 1001 1002 if (drv->tiwlan_wq) { 1003 cancel_work_sync(&drv->tWork); 1004 flush_workqueue(drv->tiwlan_wq); 1005 } 1006 1007 /* Release the driver network interface */ 1008 if (drv->netdev) { 1009 netif_stop_queue (drv->netdev); 1010 wlanDrvIf_Stop (drv->netdev); 1011 unregister_netdev (drv->netdev); 1012 free_netdev (drv->netdev); 1013 } 1014 1015 /* Destroy all driver modules */ 1016 if (drv->tCommon.hDrvMain) { 1017 drvMain_Destroy (drv->tCommon.hDrvMain); 1018 } 1019 1020 /* close the ipc_kernel socket*/ 1021 if (drv && drv->wl_sock) 1022 { 1023 sock_release (drv->wl_sock->sk_socket); 1024 } 1025 /* Release the driver interrupt (or polling timer) */ 1026 #ifdef PRIODIC_INTERRUPT 1027 os_timerDestroy (drv, drv->hPollTimer); 1028 #else 1029 if (drv->irq) 1030 { 1031 hPlatform_freeInterrupt(drv); 1032 } 1033 #endif 1034 if (drv->tiwlan_wq) 1035 destroy_workqueue(drv->tiwlan_wq); 1036 1037 #ifdef CONFIG_HAS_WAKELOCK 1038 wake_lock_destroy(&drv->wl_wifi); 1039 wake_lock_destroy(&drv->wl_rxwake); 1040 #endif 1041 /* 1042 * Free init files memory 1043 */ 1044 if (drv->tCommon.tFwImage.pImage) 1045 { 1046 os_memoryFree (drv, drv->tCommon.tFwImage.pImage, drv->tCommon.tFwImage.uSize); 1047 #ifdef TI_MEM_ALLOC_TRACE 1048 os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", 1049 __FUNCTION__, __LINE__, drv->tCommon.tFwImage.uSize, -drv->tCommon.tFwImage.uSize); 1050 #endif 1051 } 1052 if (drv->tCommon.tNvsImage.pImage) 1053 { 1054 kfree (drv->tCommon.tNvsImage.pImage); 1055 #ifdef TI_MEM_ALLOC_TRACE 1056 os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", 1057 __FUNCTION__, __LINE__, drv->tCommon.tNvsImage.uSize, -drv->tCommon.tNvsImage.uSize); 1058 #endif 1059 } 1060 if (drv->tCommon.tIniFile.pImage) 1061 { 1062 kfree (drv->tCommon.tIniFile.pImage); 1063 #ifdef TI_MEM_ALLOC_TRACE 1064 os_printf ("MTT:%s:%d ::kfree(0x%p) : %d\n", 1065 __FUNCTION__, __LINE__, drv->tCommon.tIniFile.uSize, -drv->tCommon.tIniFile.uSize); 1066 #endif 1067 } 1068 1069 /* Free the driver object */ 1070 #ifdef TI_DBG 1071 tb_destroy(); 1072 #endif 1073 kfree (drv); 1074 } 1075 1076 1077 /** 1078 * \fn wlanDrvIf_ModuleInit & wlanDrvIf_ModuleExit 1079 * \brief Linux Init/Exit functions 1080 * 1081 * The driver Linux Init/Exit functions (insmod/rmmod) 1082 * 1083 * \note 1084 * \param void 1085 * \return Init: 0 - OK, else - failure. Exit: void 1086 * \sa wlanDrvIf_Create, wlanDrvIf_Destroy 1087 */ 1088 #ifndef TI_SDIO_STANDALONE 1089 static int sdc_ctrl = 2; 1090 module_param(sdc_ctrl, int, S_IRUGO | S_IWUSR | S_IWGRP); 1091 1092 extern int sdioDrv_init(int sdcnum); 1093 extern void sdioDrv_exit(void); 1094 #endif 1095 1096 static int __init wlanDrvIf_ModuleInit (void) 1097 { 1098 printk(KERN_INFO "TIWLAN: driver init\n"); 1099 #ifndef TI_SDIO_STANDALONE 1100 #ifndef CONFIG_MMC_EMBEDDED_SDIO 1101 sdioDrv_init(sdc_ctrl); 1102 #endif 1103 #endif 1104 return wlanDrvIf_Create (); 1105 } 1106 1107 static void __exit wlanDrvIf_ModuleExit (void) 1108 { 1109 wlanDrvIf_Destroy (pDrvStaticHandle); 1110 #ifndef TI_SDIO_STANDALONE 1111 #ifndef CONFIG_MMC_EMBEDDED_SDIO 1112 sdioDrv_exit(); 1113 #endif 1114 #endif 1115 printk (KERN_INFO "TI WLAN: driver unloaded\n"); 1116 } 1117 1118 1119 /** 1120 * \fn wlanDrvIf_StopTx 1121 * \brief block Tx thread until wlanDrvIf_ResumeTx called . 1122 * 1123 * This routine is called whenever we need to stop the network stack to send us pakets since one of our Q's is full. 1124 * 1125 * \note 1126 * \param hOs - The driver object handle 1127 * \return 1128 * \sa wlanDrvIf_StopTx 1129 */ 1130 void wlanDrvIf_StopTx (TI_HANDLE hOs) 1131 { 1132 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; 1133 1134 netif_stop_queue (drv->netdev); 1135 } 1136 1137 /** 1138 * \fn wlanDrvIf_ResumeTx 1139 * \brief Resume Tx thread . 1140 * 1141 * This routine is called whenever we need to resume the network stack to send us pakets since our Q's are empty. 1142 * 1143 * \note 1144 * \param hOs - The driver object handle 1145 * \return 1146 * \sa wlanDrvIf_ResumeTx 1147 */ 1148 void wlanDrvIf_ResumeTx (TI_HANDLE hOs) 1149 { 1150 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)hOs; 1151 1152 netif_wake_queue (drv->netdev); 1153 } 1154 1155 module_init (wlanDrvIf_ModuleInit); 1156 module_exit (wlanDrvIf_ModuleExit); 1157