[PATCH] Get rid of transmit queue

Marcelo Tosatti marcelo at kvack.org
Wed Jun 7 19:27:22 EDT 2006


Hi,

Marvell's driver has a transmit queue, buffering operations between
start_xmit and the chip.

This is scheme is flawed, though, as there is only one placeholder for
data in-flight via USB bus - the code queues multiple USB Request Block
requests without waiting for the previous one to complete, potentially
thrashing the contents of the single placeholder.

It is possible to queue several URB's to the host controller for
increased throughput, might be interesting to try that later. There is
no need to use a thread for doing the parallel submission work.

So remove it and do direct transfers from start_xmit. The queue is
restarted after the USB tx callback is receive.

Needs testing. 

Signed-off-by: Marcelo Tosatti <marcelo at kvack.org>


diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 6b61be4..93a60d1 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -146,6 +146,7 @@ static void if_usb_write_bulk_callback(s
 		PRINTM(INFO, "URB status is successfull\n");
 		PRINTM(INFO, "Actual length transmitted %d\n", urb->actual_length);
 		priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+		os_start_queue(priv);
 	}
 
 	if (!cardp->IsFWDnld) {
diff --git a/drivers/net/wireless/libertas/os_macros.h b/drivers/net/wireless/libertas/os_macros.h
index 54695f5..eaa878f 100644
--- a/drivers/net/wireless/libertas/os_macros.h
+++ b/drivers/net/wireless/libertas/os_macros.h
@@ -64,21 +64,6 @@ #define IPFIELD_ALIGN_OFFSET	2
 	return 0;
 }
 
-static inline void os_free_tx_packet(wlan_private *priv)
-{
-	ulong	flags;
-
-	spin_lock_irqsave(&priv->adapter->CurrentTxLock, flags);
-	
-	if (priv->adapter->CurrentTxSkb) {
-		kfree_skb(priv->adapter->CurrentTxSkb);
-	}
-
-	priv->adapter->CurrentTxSkb = NULL;
-	
-	spin_unlock_irqrestore(&priv->adapter->CurrentTxLock, flags);
-}
-
 /* netif carrier_on/off and start(wake)/stop_queue handling
 		carrier_on	carrier_off	start_queue	stop_queue
  open		x(connect)	x(disconnect)	x
diff --git a/drivers/net/wireless/libertas/wlan_cmdresp.c b/drivers/net/wireless/libertas/wlan_cmdresp.c
index 94711ac..dc38a6f 100644
--- a/drivers/net/wireless/libertas/wlan_cmdresp.c
+++ b/drivers/net/wireless/libertas/wlan_cmdresp.c
@@ -84,7 +84,8 @@ void MacEventDisconnected(wlan_private *
 		       		SIOCGIWAP, &wrqu, NULL);
 
 	/* Free Tx and Rx packets */
-	os_free_tx_packet(priv);
+	kfree_skb(priv->adapter->CurrentTxSkb);
+	priv->adapter->CurrentTxSkb = NULL;
 	wlan_send_rxskbQ(priv);
 
 	/* report disconnect to upper layer */
@@ -110,8 +111,6 @@ void MacEventDisconnected(wlan_private *
 	/* reset internal flags */
 	Adapter->AdHocCreated = FALSE;
 
-	cleanup_txqueues(priv);
-		
 	Adapter->SecInfo.WPAEnabled = FALSE;
 	Adapter->SecInfo.WPA2Enabled = FALSE;
 	Adapter->Wpa_ie_len = 0;
diff --git a/drivers/net/wireless/libertas/wlan_decl.h b/drivers/net/wireless/libertas/wlan_decl.h
index ed0368d..d936906 100644
--- a/drivers/net/wireless/libertas/wlan_decl.h
+++ b/drivers/net/wireless/libertas/wlan_decl.h
@@ -80,7 +80,7 @@ void wlan_proc_remove(wlan_private *priv
 void wlan_debug_entry(wlan_private *priv, struct net_device *dev);
 void wlan_debug_remove(wlan_private *priv);
 int wlan_process_rx_command(wlan_private * priv);
-void wlan_process_tx(wlan_private * priv);
+int wlan_process_tx(wlan_private * priv, struct sk_buff *skb);
 void CleanupAndInsertCmd(wlan_private * priv, struct CmdCtrlNode * pTempCmd);
 void MrvDrvCommandTimerFunction(void *FunctionContext);
 
@@ -114,8 +114,5 @@ #if WIRELESS_EXT > 14
 void send_iwevcustom_event(wlan_private *priv, s8 *str);
 #endif
 
-void cleanup_txqueues(wlan_private *priv);
-void wlan_process_txqueue(wlan_private * priv);
-
 
 #endif /* _WLAN_DECL_H_ */
diff --git a/drivers/net/wireless/libertas/wlan_dev.h b/drivers/net/wireless/libertas/wlan_dev.h
index 0f8d124..38c96b1 100644
--- a/drivers/net/wireless/libertas/wlan_dev.h
+++ b/drivers/net/wireless/libertas/wlan_dev.h
@@ -303,8 +303,6 @@ #endif /* REASSOCIATION */
 	spinlock_t 		TxSpinLock;
 	struct sk_buff 		*CurrentTxSkb;
 	struct sk_buff		RxSkbQ;
-	struct sk_buff		TxSkbQ;
-	u32			TxSkbNum;
 	u16			TxLockFlag;			
 	u16			gen_null_pkg;
 	spinlock_t 		CurrentTxLock;
diff --git a/drivers/net/wireless/libertas/wlan_fw.c b/drivers/net/wireless/libertas/wlan_fw.c
index 53e4794..356b6ac 100644
--- a/drivers/net/wireless/libertas/wlan_fw.c
+++ b/drivers/net/wireless/libertas/wlan_fw.c
@@ -301,10 +301,6 @@ #define SHORT_PREAMBLE_ALLOWED		1
 	Adapter->IntCounter = Adapter->IntCounterSaved = 0;
 	INIT_LIST_HEAD((struct list_head *)&Adapter->RxSkbQ);
 
-	INIT_LIST_HEAD((struct list_head *)&Adapter->TxSkbQ);
-	Adapter->TxSkbNum = 0;
-
-
 	Adapter->EncryptionStatus = Wlan802_11WEPDisabled;
 
 	spin_lock_init(&Adapter->CurrentTxLock);
diff --git a/drivers/net/wireless/libertas/wlan_main.c b/drivers/net/wireless/libertas/wlan_main.c
index 97e0466..41ef1df 100644
--- a/drivers/net/wireless/libertas/wlan_main.c
+++ b/drivers/net/wireless/libertas/wlan_main.c
@@ -415,27 +415,20 @@ #endif /* ENABLE_PM */
  */
 static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	int             ret;
+	int             ret = 0;
 	wlan_private   *priv = dev->priv;
 
     	ENTER();
 
-	
+	os_stop_queue(priv);
 
-	if (wlan_tx_packet(priv, skb)) {
-		/* Transmit failed */
-		ret = WLAN_STATUS_FAILURE;
+	if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) {
+		priv->stats.tx_dropped++;
 		goto done;
-	} else {
-		/* Transmit succeeded */
-		if(priv->adapter->TxSkbNum >= MAX_NUM_IN_TX_Q) 
-		{
-			UpdateTransStart(dev);
-			os_stop_queue(priv);
-		}
 	}
-    
-    	ret = WLAN_STATUS_SUCCESS;
+
+	if (wlan_process_tx(priv, skb) == 0)
+		UpdateTransStart(dev);
 done:
 
 	LEAVE();
@@ -671,7 +664,6 @@ static int wlan_service_main_thread(void
 			) ||
 			(
 			!Adapter->IntCounter 
-			&& (priv->wlan_dev.dnld_sent || !Adapter->TxSkbNum )
 			&& (priv->wlan_dev.dnld_sent || Adapter->CurCmd ||
 				list_empty(&Adapter->CmdPendingQ))
 			)
@@ -801,11 +793,6 @@ static int wlan_service_main_thread(void
 			ExecuteNextCommand(priv);
 		}
 
-
-			if(!priv->wlan_dev.dnld_sent && (Adapter->TxLockFlag == 0) 
-					&& !list_empty((struct list_head *)&priv->adapter->TxSkbQ)){
-				wlan_process_txqueue(priv);
-			}
 	}
 
 	wlan_deactivate_thread(thread);
@@ -1026,7 +1013,6 @@ #endif
 
 	/* Flush all the packets upto the OS before stopping */
 	wlan_send_rxskbQ(priv);
-	cleanup_txqueues(priv);
 	os_stop_queue(priv);
 	os_carrier_off(priv);
 
@@ -1070,55 +1056,6 @@ #endif
 	return WLAN_STATUS_SUCCESS;
 }
 
-/********************************************************
-		Global Functions
-********************************************************/
-/** 
- *  @brief Cleanup TX queue
- *  @param priv       pointer to wlan_private
- *  @return 	      N/A
-*/
-void cleanup_txqueues(wlan_private *priv)
-{
-	struct sk_buff	*delNode, *Q;
-
-	Q = &priv->adapter->TxSkbQ;
-	while (!list_empty((struct list_head *)Q)) {
-		delNode = Q->next;
-		list_del((struct list_head *)delNode);
-		kfree_skb(delNode);
-	}
-	priv->adapter->TxSkbNum = 0;
-}
-
-
-/** 
- *  @brief handle TX Queue
- *  @param priv       pointer to wlan_private
- *  @return 	      N/A
-*/
-void wlan_process_txqueue(wlan_private * priv)
-{
-	wlan_adapter   *Adapter = priv->adapter;
-	ulong		flags;
-	struct sk_buff *Q;
-	ENTER();
-	spin_lock_irqsave(&Adapter->CurrentTxLock, flags);
-	if(Adapter->TxSkbNum > 0){
-		Q = &priv->adapter->TxSkbQ;
-		Adapter->CurrentTxSkb = Q->next;	   
-		list_del((struct list_head *) Adapter->CurrentTxSkb);
-		Adapter->TxSkbNum --;
-	}
-	spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
-	if (Adapter->CurrentTxSkb) {
-		wlan_process_tx(priv);
-	}
-	
-	LEAVE();
-}
-
-
 /**
  * @brief This function sends the rx packets to the os from the skb queue
  *
diff --git a/drivers/net/wireless/libertas/wlan_tx.c b/drivers/net/wireless/libertas/wlan_tx.c
index 5423ebe..704d947 100644
--- a/drivers/net/wireless/libertas/wlan_tx.c
+++ b/drivers/net/wireless/libertas/wlan_tx.c
@@ -172,15 +172,14 @@ done:
 	if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)  {
 		/* Keep the skb to echo it back once Tx feedback is 
 		   received from FW */
-		skb_orphan(priv->adapter->CurrentTxSkb);
+		skb_orphan(skb);
 		/* stop processing outgoing pkts */
 		os_stop_queue(priv);
 		/* freeze any packets already in our queues */
 		priv->adapter->TxLockFlag = 1;
-	} else 
-	{
-		os_free_tx_packet(priv);
-		os_start_queue(priv);
+	} else {
+		dev_kfree_skb_any(skb);
+		priv->adapter->CurrentTxSkb = NULL;
 	}
 
 	LEAVE();
@@ -198,12 +197,14 @@ done:
  *  @param priv    A pointer to wlan_private structure
  *  @return 	   n/a
  */
-void wlan_process_tx(wlan_private *priv)
+int wlan_process_tx(wlan_private *priv, struct sk_buff *skb)
 {
 	unsigned long flags;
-	wlan_adapter   *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_FAILURE;
 
 	ENTER();
+
+ 	HEXDUMP("TX Data", skb->data, MIN(skb->len, 100));
     
 	if(priv->wlan_dev.dnld_sent) {
 		PRINTM(MSG, "TX Error: dnld_sent = %d, not sending\n",
@@ -211,8 +212,9 @@ void wlan_process_tx(wlan_private *priv)
 		goto done;
 	}
 
+	priv->adapter->CurrentTxSkb = skb;
 
-	SendSinglePacket(priv, Adapter->CurrentTxSkb);
+	ret = SendSinglePacket(priv, skb);
 
 	spin_lock_irqsave(&driver_lock, flags);
 	priv->adapter->HisRegCpy &= ~HIS_TxDnLdRdy;
@@ -220,41 +222,9 @@ void wlan_process_tx(wlan_private *priv)
 
 done:
 	LEAVE();
-}
-
-/** 
- *  @brief This function queues the packet received from
- *  kernel/upper layer and wake up the main thread to handle it.
- *  
- *  @param priv    A pointer to wlan_private structure
-  * @param skb     A pointer to skb which includes TX packet
- *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
- */
-int wlan_tx_packet(wlan_private *priv, struct sk_buff *skb)
-{
-	ulong		flags;
-	wlan_adapter 	*Adapter = priv->adapter;
-	int		ret = WLAN_STATUS_SUCCESS;
-
-	ENTER();
-
- 	HEXDUMP("TX Data", skb->data, MIN(skb->len, 100));
-
-	spin_lock_irqsave(&Adapter->CurrentTxLock, flags);
-
-	{
-		Adapter->TxSkbNum ++;
-		list_add_tail((struct list_head *) skb,(struct list_head *) &priv->adapter->TxSkbQ);
-		wake_up_interruptible(&priv->MainThread.waitQ);
-	}
-	spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags);
-
-	LEAVE();
-
 	return ret;
 }
 
-
 /** 
  *  @brief This function tells firmware to send a NULL data packet.
  *  





More information about the libertas-dev mailing list