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