[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