[PATCH] Get rid of receive queue

Marcelo Tosatti marcelo at kvack.org
Thu Jun 8 17:12:33 EDT 2006


The following patch:

- Gets rid of receive queue
- Use per rx callback pointer instead of global one

Needs testing

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

Next step is to remove the command/event queue and process
command/event responses directly from IRQ context:

- serialize host-to-firmware command download with a per-device
semaphore.

- asynchronous commands are still necessary for a few contexts.
schedule_work() such cases, waiting on a per-device "wakeup_waitqueue"
if device is powered down before attempting to grab the download
semaphore.

- processing of command response made through schedule_work() (to free
load of IRQ context, might not be necessary).

Once thats done and working stable (sleep/wakeup will need very good
testing!), we can remove the main thread and kill PrepareAndSendCommand.

Its about time to run "Lindent" on this source (now that we won't have
to merge external patches).


diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 0370ee3..247f2ff 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -199,11 +199,6 @@ static void if_usb_free(struct usb_card_
 		}
 	}
 
-	if (cardp->skb) {
-		kfree_skb(cardp->skb);
-		cardp->skb = NULL;
-	
-
 	if (cardp->bulk_out_buffer) {
 		kfree(cardp->bulk_out_buffer);
 		cardp->bulk_out_buffer = NULL;
@@ -416,6 +411,12 @@ tx_ret:
 	return ret;
 }
 
+/* read callback private data */
+struct read_cb_info {
+	wlan_private *priv;
+	struct sk_buff *skb;
+};
+
 /**  
  *  @brief This function submit the rx data to OS
  *  @param priv		pointer to wlan_private structure
@@ -424,21 +425,32 @@ tx_ret:
 static int if_usb_submit_rx_urb(wlan_private *priv)
 {
 	struct usb_card_rec	*cardp = priv->wlan_dev.card;
+	struct sk_buff *skb;
+	struct read_cb_info *rinfo;
 	int			ret = WLAN_STATUS_FAILURE;
 	
 	ENTER();
 
-	if(!(cardp->skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
+	if(!(rinfo = kmalloc(sizeof (struct read_cb_info), GFP_ATOMIC))) {
+		PRINTM(FATAL, "No free read_callback_info\n");
+		goto rx_ret;
+	}
+
+	if(!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
 		PRINTM(FATAL, "No free skb\n");
+		kfree(rinfo);
 		goto rx_ret;
 	}
 
+	rinfo->skb = skb;
+	rinfo->priv = priv;
+
 	/* Fill the receive configuration URB and initialise the Rx call back */
 	usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
 			usb_rcvbulkpipe(cardp->udev, cardp->bulk_in_endpointAddr),
-			cardp->skb->tail + IPFIELD_ALIGN_OFFSET,
+			skb->tail + IPFIELD_ALIGN_OFFSET,
 			MRVDRV_ETH_RX_PACKET_BUFFER_SIZE,
-			if_usb_receive, priv);
+			if_usb_receive, rinfo);
 
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
 
@@ -468,7 +480,9 @@ rx_ret:
  */
 static void if_usb_receive(struct urb *urb, struct pt_regs *regs)
 {
-	wlan_private	*priv = (wlan_private *)urb->context;
+	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
+	wlan_private	*priv = rinfo->priv;
+	struct		sk_buff *skb = rinfo->skb;
 	struct		usb_card_rec *cardp = 
 			(struct usb_card_rec *)priv->wlan_dev.card;
 
@@ -479,23 +493,23 @@ static void if_usb_receive(struct urb *u
 
 	FWSyncHeader	SyncFWHeader;
 
+
 #define MRVDRV_MIN_PKT_LEN	30
 
 	ENTER();
 
+	kfree(rinfo);
+
 	cardp->rx_urb_pending = FALSE;
 
 	if (RecvLength) {
 		if (urb->status) {
 			PRINTM(INFO, "URB Status is failed\n");
-			if (cardp->skb) {
-				kfree_skb(cardp->skb);
-				cardp->skb = NULL;
-			}
+			kfree_skb(skb);
 			goto setup_for_next;
 		}
 
-		RecvBuff = cardp->skb->data + IPFIELD_ALIGN_OFFSET;
+		RecvBuff = skb->data + IPFIELD_ALIGN_OFFSET;
 		memcpy(&RecvType, RecvBuff, sizeof(u32));
 		PRINTM(INFO, "Recv length = 0x%x\n", RecvLength);
 		PRINTM(INFO, "Receive type = 0x%X\n", RecvType);
@@ -525,10 +539,7 @@ #define MRVDRV_MIN_PKT_LEN	30
 			cardp->CRC_OK = FALSE;
 		}
 		
-		if (cardp->skb) {
-			kfree_skb(cardp->skb);
-			cardp->skb = NULL;
-		}
+		kfree_skb(skb);
 
 		if (cardp->FWFinalBlk) {
 			cardp->FwDnldOver = TRUE;
@@ -549,33 +560,24 @@ #define MRVDRV_MIN_PKT_LEN	30
 				MESSAGE_HEADER_LEN || RecvLength < MRVDRV_MIN_PKT_LEN) {
 				PRINTM(INFO, "Packet length is Invalid\n");
 
-				if (cardp->skb) {
-					kfree_skb(cardp->skb);
-					cardp->skb = NULL;
-				}
+				kfree_skb(skb);
 
 				break;
 			}
 
-			usb_int_cause |= HIS_RxUpLdRdy;
-			skb_reserve(cardp->skb, IPFIELD_ALIGN_OFFSET);
-		        skb_put(cardp->skb, RecvLength);
-			skb_pull(cardp->skb, MESSAGE_HEADER_LEN);
-			list_add_tail((struct list_head *)cardp->skb,
-				(struct list_head *)&priv->adapter->RxSkbQ);	
+			skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
+		        skb_put(skb, RecvLength);
+			skb_pull(skb, MESSAGE_HEADER_LEN);
+			ProcessRxedPacket(priv, skb);
 
 			priv->wlan_dev.upld_len = (RecvLength - MESSAGE_HEADER_LEN);
 
-			if_usb_interrupt(priv, HIS_RxUpLdRdy, RX_SUCCESS);
 			break;
 
 		case CMD_TYPE_REQUEST: 
 			if (RecvLength > MRVDRV_SIZE_OF_CMD_BUFFER) {
 				PRINTM(INFO, "The receive buffer is too large\n");
-				if (cardp->skb) {
-					kfree_skb(cardp->skb);
-					cardp->skb = NULL;
-				}
+				kfree_skb(skb);
 
 				break;	
 			}
@@ -594,10 +596,8 @@ #define MRVDRV_MIN_PKT_LEN	30
 			memcpy(cmdBuf, RecvBuff+MESSAGE_HEADER_LEN,
 				       		priv->wlan_dev.upld_len);
 			
-			if (cardp->skb) {
-				kfree_skb(cardp->skb);
-				cardp->skb = NULL;
-			}
+			kfree_skb(skb);
+
 			PRINTM(INFO, "Wake up main thread to handle cmd response\n");
 			if_usb_interrupt(priv, HIS_CmdUpLdRdy, RX_SUCCESS);
 			break;
@@ -614,19 +614,13 @@ #define MRVDRV_MIN_PKT_LEN	30
 			priv->adapter->EventCause = wlan_le32_to_cpu(priv->adapter->EventCause) << 3; 
 
 			usb_int_cause |= HIS_CardEvent;
-			if (cardp->skb) {
-				kfree_skb(cardp->skb);
-				cardp->skb = NULL;
-			}
+			kfree_skb(skb);
 			if_usb_interrupt(priv, HIS_CardEvent, RX_SUCCESS);
 			
 			break;
 
 		default:
-			if (cardp->skb) {
-				kfree_skb(cardp->skb);
-				cardp->skb = NULL;
-			}
+			kfree_skb(skb);
 			break;
 	}
 	
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index c752603..e00a7ef 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -60,7 +60,6 @@ struct usb_card_rec
 	void                    (*user_isr)(int, void*, struct pt_regs*);
 	void			*priv;
 	
-	struct sk_buff		*skb;
 	int			bulk_in_size;
 	u8			bulk_in_endpointAddr;
 
diff --git a/drivers/net/wireless/libertas/sbi.h b/drivers/net/wireless/libertas/sbi.h
index ab7abc5..969f5c6 100644
--- a/drivers/net/wireless/libertas/sbi.h
+++ b/drivers/net/wireless/libertas/sbi.h
@@ -43,7 +43,6 @@ #define B_BIT_9		0X200
 #define B_BIT_10	0x400
 
 /** INT Status Bit Definition*/
-#define HIS_RxUpLdRdy			B_BIT_0
 #define HIS_TxDnLdRdy			B_BIT_1
 #define HIS_CmdDnLdRdy			B_BIT_2
 #define HIS_CardEvent			B_BIT_3
diff --git a/drivers/net/wireless/libertas/wlan_cmdresp.c b/drivers/net/wireless/libertas/wlan_cmdresp.c
index f8c3432..4b20dc1 100644
--- a/drivers/net/wireless/libertas/wlan_cmdresp.c
+++ b/drivers/net/wireless/libertas/wlan_cmdresp.c
@@ -86,7 +86,6 @@ void MacEventDisconnected(wlan_private *
 	/* Free Tx and Rx packets */
 	kfree_skb(priv->adapter->CurrentTxSkb);
 	priv->adapter->CurrentTxSkb = NULL;
-	wlan_send_rxskbQ(priv);
 
 	/* report disconnect to upper layer */
 	netif_stop_queue(priv->wlan_dev.netdev);
diff --git a/drivers/net/wireless/libertas/wlan_decl.h b/drivers/net/wireless/libertas/wlan_decl.h
diff --git a/drivers/net/wireless/libertas/wlan_dev.h b/drivers/net/wireless/libertas/wlan_dev.h
index 38c96b1..66d8271 100644
--- a/drivers/net/wireless/libertas/wlan_dev.h
+++ b/drivers/net/wireless/libertas/wlan_dev.h
@@ -302,7 +302,6 @@ #endif /* REASSOCIATION */
 	/** Tx-related variables (for single packet tx) */
 	spinlock_t 		TxSpinLock;
 	struct sk_buff 		*CurrentTxSkb;
-	struct sk_buff		RxSkbQ;
 	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 356b6ac..6f179dd 100644
--- a/drivers/net/wireless/libertas/wlan_fw.c
+++ b/drivers/net/wireless/libertas/wlan_fw.c
@@ -299,7 +299,6 @@ #define SHORT_PREAMBLE_ALLOWED		1
 	Adapter->adhoc_grate_enabled=FALSE;
 
 	Adapter->IntCounter = Adapter->IntCounterSaved = 0;
-	INIT_LIST_HEAD((struct list_head *)&Adapter->RxSkbQ);
 
 	Adapter->EncryptionStatus = Wlan802_11WEPDisabled;
 
diff --git a/drivers/net/wireless/libertas/wlan_join.c b/drivers/net/wireless/libertas/wlan_join.c
diff --git a/drivers/net/wireless/libertas/wlan_main.c b/drivers/net/wireless/libertas/wlan_main.c
index ecd125e..aa8a1a7 100644
--- a/drivers/net/wireless/libertas/wlan_main.c
+++ b/drivers/net/wireless/libertas/wlan_main.c
@@ -282,8 +282,6 @@ static int wlan_close(struct net_device 
 	
 	ENTER();
 
-	/* Flush all the packets upto the OS before stopping */
-	wlan_send_rxskbQ(priv);
 	netif_stop_queue(priv->wlan_dev.netdev);
 	netif_carrier_off(priv->wlan_dev.netdev);
 
@@ -606,24 +604,6 @@ static void wlan_set_multicast_list(stru
 }
 
 /** 
- *  @brief This function pops rx_skb from the rx queue.
- *  
- *  @param RxSkbQ  A pointer to rx_skb queue
- *  @return 	   A pointer to skb
- */
-static struct sk_buff* wlan_pop_rx_skb(struct sk_buff *RxSkbQ)
-{
-	struct sk_buff* skb_data = NULL;
-
-	if(!list_empty((struct list_head *) RxSkbQ)) {
-		skb_data = RxSkbQ->next;	
-		list_del((struct list_head *) RxSkbQ->next);
-	}
-
-	return skb_data;
-}
-
-/** 
  *  @brief This function hanldes the major job in WLAN driver.
  *  it handles the event generated by firmware, rx data received
  *  from firmware and tx data sent from kernel.
@@ -731,17 +711,6 @@ static int wlan_service_main_thread(void
 			wlan_process_rx_command(priv);
 		}
 
-		/* Any received data? */
-		if (Adapter->HisRegCpy & HIS_RxUpLdRdy) {
-			PRINTM(INFO, "main-thread: Rx Packet ready.\n");
-		
-			spin_lock_irqsave(&driver_lock, flags);	
-			Adapter->HisRegCpy &= ~HIS_RxUpLdRdy;
-			spin_unlock_irqrestore(&driver_lock, flags);
-
-			wlan_send_rxskbQ(priv);
-		}
-
 		/* Any Card Event */
 		if (Adapter->HisRegCpy & HIS_CardEvent) {
 			PRINTM(INFO, "main-thread: Card Event Activity.\n");
@@ -1010,8 +979,6 @@ #ifdef ENABLE_PM
         pm_unregister(wlan_pm_dev);
 #endif
 
-	/* Flush all the packets upto the OS before stopping */
-	wlan_send_rxskbQ(priv);
 	netif_stop_queue(priv->wlan_dev.netdev);
 	netif_carrier_off(priv->wlan_dev.netdev);
 
@@ -1055,26 +1022,6 @@ #endif
 	return WLAN_STATUS_SUCCESS;
 }
 
-/**
- * @brief This function sends the rx packets to the os from the skb queue
- *
- * @param priv	A pointer to wlan_private structure
- * @return	n/a
- */
-void wlan_send_rxskbQ(wlan_private *priv)
-{
-	struct sk_buff	*skb;
-
-	ENTER();
-	if (priv->adapter) {
-		while((skb = wlan_pop_rx_skb(&priv->adapter->RxSkbQ))) {
-			if (ProcessRxedPacket(priv, skb) == -ENOMEM)
-					break;
-		}
-	}
-	LEAVE();
-}
-
 /** 
  *  @brief This function finds the CFP in 
  *  region_cfp_table based on region and band parameter.



More information about the libertas-dev mailing list