[PATCH 014/510] beceem: make transmit thread interruptible

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Stephen Hemminger <stephen.hemminger@xxxxxxxxxx>

Kernel complains loudly if thread does long uninterruptible sleep.
Also, dont wake up every 10ms even if no data present (wastes power).

Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxxxx>
---
 drivers/staging/bcm/Transmit.c |  195 +++++++++++++---------------------------
 1 files changed, 61 insertions(+), 134 deletions(-)

diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
index 9932d71..1f69625 100644
--- a/drivers/staging/bcm/Transmit.c
+++ b/drivers/staging/bcm/Transmit.c
@@ -39,7 +39,7 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53
 * Function    -	bcm_transmit()
 *
 * 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
 * 		 		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;
 }
 
+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
 Transmit thread
@@ -346,40 +294,17 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter  /**< pointer to adapter object*/
 {
 	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,
-				((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)
 		{
@@ -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);
 	}
+
+	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
+	Adapter->transmit_packet_thread = NULL;
 	return 0;
 }
 
-- 
1.7.3.2

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux