|
@@ -39,7 +39,7 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53
|
|
* Function - bcm_transmit()
|
|
* Function - bcm_transmit()
|
|
*
|
|
*
|
|
* Description - This is the main transmit function for our virtual
|
|
* Description - This is the main transmit function for our virtual
|
|
-* interface(veth0). It handles the ARP packets. It
|
|
|
|
|
|
+* interface(eth0). It handles the ARP packets. It
|
|
* clones this packet and then Queue it to a suitable
|
|
* clones this packet and then Queue it to a suitable
|
|
* Queue. Then calls the transmit_packet().
|
|
* Queue. Then calls the transmit_packet().
|
|
*
|
|
*
|
|
@@ -50,118 +50,59 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
*********************************************************************/
|
|
|
|
|
|
-INT bcm_transmit(struct sk_buff *skb, /**< skb */
|
|
|
|
- struct net_device *dev /**< net device pointer */
|
|
|
|
- )
|
|
|
|
|
|
+netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
{
|
|
- PMINI_ADAPTER Adapter = NULL;
|
|
|
|
- USHORT qindex=0;
|
|
|
|
- struct timeval tv;
|
|
|
|
- UINT pkt_type = 0;
|
|
|
|
- UINT calltransmit = 0;
|
|
|
|
-
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__);
|
|
|
|
|
|
+ PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
|
|
|
|
+ SHORT qindex;
|
|
|
|
|
|
- memset(&tv, 0, sizeof(tv));
|
|
|
|
- /* Check for valid parameters */
|
|
|
|
- if(skb == NULL || dev==NULL)
|
|
|
|
- {
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Adapter = GET_BCM_ADAPTER(dev);
|
|
|
|
- if(!Adapter)
|
|
|
|
- {
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
- if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus)
|
|
|
|
- {
|
|
|
|
- if(!netif_queue_stopped(dev)) {
|
|
|
|
- netif_carrier_off(dev);
|
|
|
|
- netif_stop_queue(dev);
|
|
|
|
- }
|
|
|
|
- return STATUS_FAILURE;
|
|
|
|
- }
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len);
|
|
|
|
|
|
+ if (Adapter->device_removed || !Adapter->LinkUpStatus)
|
|
|
|
+ goto drop;
|
|
|
|
|
|
- /*Add Ethernet CS check here*/
|
|
|
|
- if(Adapter->TransferMode == IP_PACKET_ONLY_MODE )
|
|
|
|
- {
|
|
|
|
- pkt_type = ntohs(*(PUSHORT)(skb->data + 12));
|
|
|
|
- /* Get the queue index where the packet is to be queued */
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index.....");
|
|
|
|
|
|
+ if (Adapter->TransferMode != IP_PACKET_ONLY_MODE )
|
|
|
|
+ goto drop;
|
|
|
|
|
|
- qindex = GetPacketQueueIndex(Adapter,skb);
|
|
|
|
|
|
+ qindex = GetPacketQueueIndex(Adapter, skb);
|
|
|
|
|
|
- if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex)
|
|
|
|
- {
|
|
|
|
- if(pkt_type == ETH_ARP_FRAME)
|
|
|
|
- {
|
|
|
|
- /*
|
|
|
|
- Reply directly to ARP request packet
|
|
|
|
- ARP Spoofing only if NO ETH CS rule matches for it
|
|
|
|
- */
|
|
|
|
- BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x",
|
|
|
|
|
|
+ if (INVALID_QUEUE_INDEX==qindex) {
|
|
|
|
+ if (ntohs(eth_hdr(skb)->h_proto) != ETH_ARP_FRAME)
|
|
|
|
+ goto drop;
|
|
|
|
|
|
- (*(PUCHAR)(skb->data + 21)));
|
|
|
|
|
|
+ /*
|
|
|
|
+ Reply directly to ARP request packet
|
|
|
|
+ ARP Spoofing only if NO ETH CS rule matches for it
|
|
|
|
+ */
|
|
|
|
+ reply_to_arp_request(skb);
|
|
|
|
+ return NETDEV_TX_OK;
|
|
|
|
+ }
|
|
|
|
|
|
- reply_to_arp_request(skb);
|
|
|
|
|
|
+ if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
|
|
|
|
+ return NETDEV_TX_BUSY;
|
|
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n");
|
|
|
|
|
|
+ /* Now Enqueue the packet */
|
|
|
|
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
|
|
|
|
+ "bcm_transmit Enqueueing the Packet To Queue %d",qindex);
|
|
|
|
+ spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
+ Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
|
|
|
|
+ Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;
|
|
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,
|
|
|
|
- "Invalid queue index, dropping pkt\n");
|
|
|
|
|
|
+ *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies;
|
|
|
|
+ ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
|
|
|
|
+ Adapter->PackInfo[qindex].LastTxQueue, skb);
|
|
|
|
+ atomic_inc(&Adapter->TotalPacketCount);
|
|
|
|
+ spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
|
|
- dev_kfree_skb(skb);
|
|
|
|
- }
|
|
|
|
- return STATUS_SUCCESS;
|
|
|
|
- }
|
|
|
|
|
|
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n");
|
|
|
|
|
|
- if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
|
|
|
|
- {
|
|
|
|
- atomic_inc(&Adapter->TxDroppedPacketCount);
|
|
|
|
- dev_kfree_skb(skb);
|
|
|
|
- return STATUS_SUCCESS;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Now Enqueue the packet */
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex);
|
|
|
|
- spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
- Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
|
|
|
|
- Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;
|
|
|
|
-
|
|
|
|
- *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies;
|
|
|
|
- ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
|
|
|
|
- Adapter->PackInfo[qindex].LastTxQueue, skb);
|
|
|
|
- atomic_inc(&Adapter->TotalPacketCount);
|
|
|
|
- spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
|
|
|
|
- do_gettimeofday(&tv);
|
|
|
|
-
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n");
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n",
|
|
|
|
- (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec);
|
|
|
|
-
|
|
|
|
- if(calltransmit == 1)
|
|
|
|
- transmit_packets(Adapter);
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- if(!atomic_read(&Adapter->TxPktAvail))
|
|
|
|
- {
|
|
|
|
- atomic_set(&Adapter->TxPktAvail, 1);
|
|
|
|
- wake_up(&Adapter->tx_packet_wait_queue);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<====");
|
|
|
|
|
|
+ /* FIXME - this is racy and incorrect, replace with work queue */
|
|
|
|
+ if (!atomic_read(&Adapter->TxPktAvail)) {
|
|
|
|
+ atomic_set(&Adapter->TxPktAvail, 1);
|
|
|
|
+ wake_up(&Adapter->tx_packet_wait_queue);
|
|
}
|
|
}
|
|
- else
|
|
|
|
- dev_kfree_skb(skb);
|
|
|
|
|
|
+ return NETDEV_TX_OK;
|
|
|
|
|
|
- return STATUS_SUCCESS;
|
|
|
|
|
|
+ drop:
|
|
|
|
+ dev_kfree_skb(skb);
|
|
|
|
+ return NETDEV_TX_OK;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -337,6 +278,13 @@ errExit:
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int tx_pending(PMINI_ADAPTER Adapter)
|
|
|
|
+{
|
|
|
|
+ return (atomic_read(&Adapter->TxPktAvail)
|
|
|
|
+ && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
|
|
|
|
+ || Adapter->device_removed || (1 == Adapter->downloadDDR);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
@ingroup tx_functions
|
|
@ingroup tx_functions
|
|
Transmit thread
|
|
Transmit thread
|
|
@@ -346,40 +294,17 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
|
|
{
|
|
{
|
|
int status = 0;
|
|
int status = 0;
|
|
|
|
|
|
- UINT calltransmit = 1;
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = %p",Adapter);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- while(1)
|
|
|
|
- {
|
|
|
|
- if(Adapter->LinkUpStatus){
|
|
|
|
|
|
+ while(! kthread_should_stop()) {
|
|
|
|
+ /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
|
|
|
|
+ if(Adapter->LinkUpStatus)
|
|
wait_event_timeout(Adapter->tx_packet_wait_queue,
|
|
wait_event_timeout(Adapter->tx_packet_wait_queue,
|
|
- ((atomic_read(&Adapter->TxPktAvail) &&
|
|
|
|
- (MINIMUM_PENDING_DESCRIPTORS <
|
|
|
|
- atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
|
|
|
|
- (Adapter->device_removed == FALSE))) ||
|
|
|
|
- (1 == Adapter->downloadDDR) || kthread_should_stop()
|
|
|
|
- || (TRUE == Adapter->bEndPointHalted)
|
|
|
|
- , msecs_to_jiffies(10));
|
|
|
|
- }
|
|
|
|
- else{
|
|
|
|
- wait_event(Adapter->tx_packet_wait_queue,
|
|
|
|
- ((atomic_read(&Adapter->TxPktAvail) &&
|
|
|
|
- (MINIMUM_PENDING_DESCRIPTORS <
|
|
|
|
- atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
|
|
|
|
- (Adapter->device_removed == FALSE))) ||
|
|
|
|
- (1 == Adapter->downloadDDR) || kthread_should_stop()
|
|
|
|
- || (TRUE == Adapter->bEndPointHalted)
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if(kthread_should_stop() || Adapter->device_removed)
|
|
|
|
- {
|
|
|
|
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
|
|
|
|
- Adapter->transmit_packet_thread = NULL;
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ tx_pending(Adapter), msecs_to_jiffies(10));
|
|
|
|
+ else
|
|
|
|
+ wait_event_interruptible(Adapter->tx_packet_wait_queue,
|
|
|
|
+ tx_pending(Adapter));
|
|
|
|
|
|
|
|
+ if (Adapter->device_removed)
|
|
|
|
+ break;
|
|
|
|
|
|
if(Adapter->downloadDDR == 1)
|
|
if(Adapter->downloadDDR == 1)
|
|
{
|
|
{
|
|
@@ -424,11 +349,13 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- if(calltransmit)
|
|
|
|
- transmit_packets(Adapter);
|
|
|
|
|
|
+ transmit_packets(Adapter);
|
|
|
|
|
|
atomic_set(&Adapter->TxPktAvail, 0);
|
|
atomic_set(&Adapter->TxPktAvail, 0);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
|
|
|
|
+ Adapter->transmit_packet_thread = NULL;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|