/** 
 * \fn     context_DriverTask
 * \brief  The driver task
 * 
 * This function is the driver's main task that always runs in the driver's 
 * single context, scheduled through the OS (the driver's workqueue in Linux). 
 * Only one instantiation of this task may run at a time!
 * 
 * \note   
 * \param  hContext   - The module handle
 * \return void 
 * \sa     context_RequestSchedule
 */ 
void context_DriverTask (TI_HANDLE hContext)
{
	TContext       *pContext = (TContext *)hContext;
    TContextCbFunc  fCbFunc;
    TI_HANDLE       hCbHndl;
    TI_UINT32       i;
    CL_TRACE_START_L1();

    TRACE0(pContext->hReport, REPORT_SEVERITY_INFORMATION , "context_DriverTask():\n");
    /* For all registered clients do: */
	for (i = 0; i < pContext->uNumClients; i++)
    {
        /* If client is pending and enabled */
        if (pContext->aClientPending[i]  &&  pContext->aClientEnabled[i])
        {
            #ifdef TI_DBG
                pContext->aInvokeCount[i]++; 
                TRACE1(pContext->hReport, REPORT_SEVERITY_INFORMATION , "Invoking - Client=, ID=%d\n", i);
            #endif /* TI_DBG */

            /* Clear client's pending flag */
            pContext->aClientPending[i] = TI_FALSE;

            /* Call client's callback function */
            fCbFunc = pContext->aClientCbFunc[i];
            hCbHndl = pContext->aClientCbHndl[i];
            fCbFunc(hCbHndl);
        }
    }
    CL_TRACE_END_L1("tiwlan_drv.ko", "CONTEXT", "TASK", "");
}
Example #2
0
TI_BOOL os_receivePacket(TI_HANDLE OsContext, void *pRxDesc ,void *pPacket, TI_UINT16 Length)
{
	TWlanDrvIfObj  *drv     = (TWlanDrvIfObj *)OsContext;
	unsigned char  *pdata   = (unsigned char *)((TI_UINT32)pPacket & ~(TI_UINT32)0x3);
	rx_head_t      *rx_head = (rx_head_t *)(pdata -  WSPI_PAD_BYTES - RX_HEAD_LEN_ALIGNED);
	struct sk_buff *skb     = rx_head->skb;

#ifdef TI_DBG
	if ((TI_UINT32)pPacket & 0x3) {
		if ((TI_UINT32)pPacket - (TI_UINT32)skb->data != 2) {
			printk("os_receivePacket() address error skb=0x%x skb->data=0x%x pPacket=0x%x !!!\n",(int)skb, (int)skb->data, (int)pPacket);
		}
	} else {
		if ((TI_UINT32)skb->data != (TI_UINT32)pPacket) {
			printk("os_receivePacket() address error skb=0x%x skb->data=0x%x pPacket=0x%x !!!\n",(int)skb, (int)skb->data, (int)pPacket);
		}
	}
	if (Length != RX_ETH_PKT_LEN(pPacket)) {
		printk("os_receivePacket() Length=%d !=  RX_ETH_PKT_LEN(pPacket)=%d!!!\n",(int)Length, RX_ETH_PKT_LEN(pPacket));
	}

#endif
	/*
	   printk("-->> os_receivePacket() pPacket=0x%x Length=%d skb=0x%x skb->data=0x%x skb->head=0x%x skb->len=%d\n",
			  (int)pPacket, (int)Length, (int)skb, (int)skb->data, (int)skb->head, (int)skb->len);
	*/
	/* Use skb_reserve, it updates both skb->data and skb->tail. */
	skb->data = RX_ETH_PKT_DATA(pPacket);
	skb->tail = skb->data;
	skb_put(skb, RX_ETH_PKT_LEN(pPacket));
	/*
	   printk("-->> os_receivePacket() skb=0x%x skb->data=0x%x skb->head=0x%x skb->len=%d\n",
			  (int)skb, (int)skb->data, (int)skb->head, (int)skb->len);
	*/
	ti_nodprintf(TIWLAN_LOG_INFO, "os_receivePacket - Received EAPOL len-%d\n", WBUF_LEN(pWbuf));

	skb->dev       = drv->netdev;
	skb->protocol  = eth_type_trans(skb, drv->netdev);
	skb->ip_summed = CHECKSUM_NONE;

	drv->stats.rx_packets++;
	drv->stats.rx_bytes += skb->len;

	/* Send the skb to the TCP stack.
	 * it responsibly of the Linux kernel to free the skb
	 */
	{
		CL_TRACE_START_L1();

		os_wake_lock_timeout_enable(drv);

		netif_rx_ni(skb);

		/* Note: Don't change this trace (needed to exclude OS processing from Rx CPU utilization) */
		CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "RX", "");
	}

	return TI_TRUE;
}
Example #3
0
/*
 * \brief	FW interrupt handler, just switch to WLAN context for handling
 * 
 * \param   hFwEvent - FwEvent Driver handle
 * \return  void
 * 
 * \par Description
 * Called by the FW-Interrupt ISR (external context!).
 * Requests the context engine to schedule the driver task for handling the FW-Events.
 * 
 * \sa
 */
void fwEvent_InterruptRequest (TI_HANDLE hFwEvent)
{
    TfwEvent *pFwEvent = (TfwEvent *)hFwEvent;
    CL_TRACE_START_L1();

    TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_InterruptRequest()\n");

    /* Request switch to driver context for handling the FW-Interrupt event */
    context_RequestSchedule (pFwEvent->hContext, pFwEvent->uContextId);

    CL_TRACE_END_L1("tiwlan_drv.ko", "IRQ", "FwEvent", "");
}
/** 
 * \fn     wlanDrvIf_Xmit
 * \brief  Packets transmission
 * 
 * The network stack calls this function in order to transmit a packet
 *     through the WLAN interface.
 * The packet is inserted to the drver Tx queues and its handling is continued
 *     after switching to the driver context.
 *
 * \note   
 * \param  skb - The Linux packet buffer structure
 * \param  dev - The driver network-interface handle
 * \return 0 (= OK)
 * \sa     
 */ 
static int wlanDrvIf_Xmit (struct sk_buff *skb, struct net_device *dev)
{
	TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev);
	TTxCtrlBlk *  pPktCtrlBlk;
	int status;

	CL_TRACE_START_L1();

	os_profile (drv, 0, 0);
	drv->stats.tx_packets++;
	drv->stats.tx_bytes += skb->len;

	/* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */
	pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD);

	pPktCtrlBlk->tTxDescriptor.startTime    = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */
	pPktCtrlBlk->tTxDescriptor.length       = skb->len;
	pPktCtrlBlk->tTxPktParams.pInputPkt     = skb;

	/* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */
	pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data;
	pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN;
	pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN;
	pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN;
	pPktCtrlBlk->tTxnStruct.aLen[2] = 0;

	/* Send the packet to the driver for transmission. */
	status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority);

	/* If failed (queue full or driver not running), drop the packet. */
    if (status != TI_OK)
    {
        drv->stats.tx_errors++;
    }
	os_profile (drv, 1, 0);

	CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", "");

	return 0;
}
/** 
 * \fn     busDrv_TxnDoneCb
 * \brief  Continue async transaction processing (CB)
 * 
 * Called back by the lower (BSP) bus-driver upon Async transaction completion (TxnDone ISR).
 * Call busDrv_SendTxnParts to continue sending the remained transaction parts.
 * 
 * \note   
 * \param  hBusDrv - The module's object
 * \param  status  - The last transaction result - 0 = OK, else Error
 * \return void
 * \sa     busDrv_SendTxnParts
 */ 
static void busDrv_TxnDoneCb (TI_HANDLE hBusDrv, int iStatus)
{
    TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv;
    CL_TRACE_START_L1();

    /* If last transaction part failed, set error in Txn struct, call TxnDone CB and exit. */
    if (iStatus != 0)
    {
        TRACE1(pBusDrv->hReport, REPORT_SEVERITY_ERROR, "busDrv_TxnDoneCb: Status = 0x%x\n", iStatus);

        TXN_PARAM_SET_STATUS(pBusDrv->pCurrTxn, TXN_PARAM_STATUS_ERROR);
        pBusDrv->fTxnDoneCb (pBusDrv->hCbHandle, pBusDrv->pCurrTxn);
        CL_TRACE_END_L1("tiwlan_drv.ko", "TXN_DONE", "BusDrvCB", "");
        return;
    }

    TRACE0(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_TxnDoneCb()\n");

    /* Continue sending the remained transaction parts. */
    busDrv_SendTxnParts (pBusDrv);

    CL_TRACE_END_L1("tiwlan_drv.ko", "TXN_DONE", "BusDrvCB", "");
}
Example #6
0
static int xmit_Bridge (struct sk_buff *skb, struct net_device *dev, TIntraBssBridge *pBssBridgeParam)
{
    TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev);
    TTxCtrlBlk *  pPktCtrlBlk;
    TEthernetHeader *pEthHead = (TEthernetHeader *)(skb->data);
    int status;

    CL_TRACE_START_L1();

    os_profile (drv, 0, 0);
    drv->stats.tx_packets++;
    drv->stats.tx_bytes += skb->len;

    /* Allocate a TxCtrlBlk for the Tx packet and save timestamp, length and packet handle */
    pPktCtrlBlk = TWD_txCtrlBlk_Alloc (drv->tCommon.hTWD);
    if (pPktCtrlBlk == NULL)
    {
        drv->stats.tx_errors++;
        os_profile (drv, 1, 0);
        CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", "");
        return 0;
    }

    /* Set interface type according to net device interface number */
    if (drv->tCommon.eIfRole == IF_ROLE_TYPE_AP) 
        SET_PKT_TYPE_IF_ROLE_AP(pPktCtrlBlk);
    else
        SET_PKT_TYPE_IF_ROLE_STA(pPktCtrlBlk);
    pPktCtrlBlk->tTxDescriptor.startTime    = os_timeStampMs(drv); /* remove use of skb->tstamp.off_usec */
    pPktCtrlBlk->tTxDescriptor.length       = skb->len;
    pPktCtrlBlk->tTxPktParams.pInputPkt     = skb;

    /* Check MGMT packet from hostapd, forward it to the Mgmt-Queue and exit without ethernet header */
    if (HTOWLANS(pEthHead->type) == AP_MGMT_ETH_TYPE)
    {
        /* Copy WLAN header into aPktHdr - format for MGMT packets */
        memcpy (pPktCtrlBlk->aPktHdr, skb->data + ETHERNET_HDR_LEN , WLAN_HDR_LEN );

        /* Skip ethernet header, send as management frame */
        pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_MGMT;
        pPktCtrlBlk->tTxnStruct.aBuf[0] = (TI_UINT8 *)pPktCtrlBlk->aPktHdr;
        pPktCtrlBlk->tTxnStruct.aLen[0] = WLAN_HDR_LEN;
        pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN + WLAN_HDR_LEN;
        pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN - WLAN_HDR_LEN;
        pPktCtrlBlk->tTxnStruct.aLen[2] = 0;
        pPktCtrlBlk->tTxPktParams.uInputPktLen = skb->len;
        pPktCtrlBlk->tTxDescriptor.length = (TI_UINT16)((pPktCtrlBlk->tTxnStruct.aLen[0]) + (pPktCtrlBlk->tTxnStruct.aLen[1]));

        status = txMgmtQ_Xmit (drv->tCommon.hTxMgmtQ, pPktCtrlBlk, TI_TRUE);
    }
    else

    {
    /* Point the first BDL buffer to the Ethernet header, and the second buffer to the rest of the packet */
    pPktCtrlBlk->tTxnStruct.aBuf[0] = skb->data;
    pPktCtrlBlk->tTxnStruct.aLen[0] = ETHERNET_HDR_LEN;
    pPktCtrlBlk->tTxnStruct.aBuf[1] = skb->data + ETHERNET_HDR_LEN;
    pPktCtrlBlk->tTxnStruct.aLen[1] = (TI_UINT16)skb->len - ETHERNET_HDR_LEN;
    pPktCtrlBlk->tTxnStruct.aLen[2] = 0;

    /* Send the packet to the driver for transmission. */
    status = txDataQ_InsertPacket (drv->tCommon.hTxDataQ, pPktCtrlBlk,(TI_UINT8)skb->priority, pBssBridgeParam);
    }

    /* If failed (queue full or driver not running), drop the packet. */
    if (status != TI_OK)
    {
        drv->stats.tx_errors++;
    }
    os_profile (drv, 1, 0);

    CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "TX", "");

    return 0;
}
Example #7
0
/** 
 * \fn     wlanDrvIf_receivePacket
 * \brief  Receive packet from from lower level
 * 
 */ 
TI_BOOL wlanDrvIf_receivePacket(TI_HANDLE OsContext, void *pRxDesc ,void *pPacket, TI_UINT16 Length, TIntraBssBridge *pBridgeDecision)
{
   TWlanDrvIfObj  *drv     = (TWlanDrvIfObj *)OsContext;
   unsigned char  *pdata   = (unsigned char *)((TI_UINT32)pRxDesc & ~(TI_UINT32)0x3);
   rx_head_t      *rx_head = (rx_head_t *)(pdata -  WSPI_PAD_BYTES - RX_HEAD_LEN_ALIGNED);
   struct sk_buff *skb     = rx_head->skb;
   struct sk_buff *new_skb;
   EIntraBssBridgeDecision eBridge = INTRA_BSS_BRIDGE_NO_BRIDGE;


   skb->data = pPacket;
   skb_put(skb, Length);


   skb->dev       = drv->netdev;

   drv->stats.rx_packets++;
   drv->stats.rx_bytes += skb->len;
   /* Intra BSS bridge section */
   if(pBridgeDecision != NULL) 
   {
       eBridge = pBridgeDecision->eDecision;
   }
   if(INTRA_BSS_BRIDGE_NO_BRIDGE == eBridge) 
   {
       /* Forward packet to network stack*/
       CL_TRACE_START_L1();
       skb->protocol  = eth_type_trans(skb, drv->netdev);
       skb->ip_summed = CHECKSUM_NONE;

       
       netif_rx_ni(skb);

       /* Note: Don't change this trace (needed to exclude OS processing from Rx CPU utilization) */
       CL_TRACE_END_L1("tiwlan_drv.ko", "OS", "RX", "");

   }
   else if( INTRA_BSS_BRIDGE_UNICAST == eBridge) 
   {
       /* Send packet to Tx */
       TRACE2(drv->tCommon.hReport, REPORT_SEVERITY_WARNING, " wlanDrvIf_receivePacket() Unicast Bridge data=0x%x len=%d  \n", RX_ETH_PKT_DATA(pPacket), RX_ETH_PKT_LEN(pPacket));
       xmit_Bridge (skb, pDrvStaticHandle->netdev, pBridgeDecision);
   }
   else /* Broadcast/Multicast packet*/
   {
       /* Duplicate packet*/
       new_skb = skb_clone(skb, GFP_ATOMIC);
       skb->protocol  = eth_type_trans(skb, drv->netdev);
       skb->ip_summed = CHECKSUM_NONE;
       netif_rx_ni(skb);

       if(new_skb) 
       {
           xmit_Bridge (new_skb, pDrvStaticHandle->netdev, pBridgeDecision);
       }
       else
       {
           printk (KERN_ERR "%s: skb_clone failed\n", __FUNCTION__);
           return TI_FALSE;
       }
   }
   return TI_TRUE;
}