/** * \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; }
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; }