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