rt2x00: Make sure TX rings are empty when scanning
Subsystems (3)
PATCH 16/32 rt2x00: Make sure TX rings are empty when scanning
From: Ivo van Doorn <[email protected]>
Improve the waiting when a skb buffer needs to be send before the channel switch. This also makes sure no pending packets are still on the TX ring while making the channel switch.
Signed-off-by Ivo van Doorn <[email protected]>
drivers/net/wireless/d80211/rt2x00/rt2400pci.c +50 -33
@@ -838,7 +838,6 @@ rt2400pci_txdone(void *data)struct rt2x00_pci *rt2x00pci = (struct rt2x00_pci *)ring->dev;struct net_device *net_dev =pci_get_drvdata (rt2x00pci->pci_dev);struct data_entry *entry; -struct skb_cb *cb;struct txd *txd;int tx_status;int ack;
@@ -851,13 +850,6 @@ rt2400pci_txdone(void *data) || !rt2x00_get_field32(txd->word0, TXD_W0_VALID))break ; -/* -* Check if this frame was send for the scan routine. -*/ - cb = (struct skb_cb *)&entry->skb->cb; -if (rt2x00pci->scan && cb->scan_complete) -complete (&rt2x00pci->scan->completion); - ack =rt2x00_get_field32 (txd->word0,TXD_W0_ACK );/*
@@ -896,6 +888,18 @@ rt2400pci_txdone(void *data)rt2x00_ring_index_done_inc (ring); }while (!rt2x00_ring_empty (ring)); + +/* +* Check if we are waiting on an empty queue +* to start scanning. +*/ +if (rt2x00pci->scan + &&rt2x00_ring_empty (&rt2x00pci->tx) + &&rt2x00_ring_empty (&rt2x00pci->atim) + &&rt2x00_ring_empty (&rt2x00pci->prio)) { + rt2x00pci->scan->status =SCANNING_READY ; +complete (&rt2x00pci->scan->completion); + } } static irqreturn_t
@@ -1517,6 +1521,14 @@ rt2400pci_stop(struct net_device *net_dert2x00_register_write (rt2x00pci,CSR8 , reg);/* +* Cancel scanning. +*/ +if (rt2x00pci->scan) { + rt2x00pci->scan->status =SCANNING_CANCELLED ; +complete_all (&rt2x00pci->scan->completion); + } + +/* * Free DMA rings. */ rt2400pci_free_rings (rt2x00pci);
@@ -1564,35 +1576,23 @@ static void rt2400pci_scan(void *data) {struct rt2x00_pci *rt2x00pci = data; -struct net_device *net_dev =pci_get_drvdata (rt2x00pci->pci_dev); -struct skb_cb *cb;if (unlikely (!rt2x00pci->scan))return ;/* -* Check if we have to send a packet before the -* channel switch. +* Before we can start switch the channel for scanning +* we need to wait untill all TX rings are empty to +* guarentee that all frames are send on the correct channel. */ -if (rt2x00pci->scan->conf.skb) { - cb = (struct skb_cb *)&rt2x00pci->scan->conf.skb->cb; - cb->scan_complete =1 ; - -if (rt2400pci_tx (net_dev, rt2x00pci->scan->conf.skb, - rt2x00pci->scan->conf.tx_control)) - goto exit; - -/* -* Wait for the frame to be correctly transmitted. -*/ +if (rt2x00pci->scan->status !=SCANNING_READY )wait_for_completion (&rt2x00pci->scan->completion); - }/* * Check if this scan has been cancelled while * work was still scheduled. */ -if (rt2x00pci->scan->cancelled) +if (rt2x00pci->scan->status ==SCANNING_CANCELLED ) goto exit;/*
@@ -1633,9 +1633,24 @@ rt2400pci_passive_scan(struct net_device {struct rt2x00_pci *rt2x00pci =ieee80211_dev_hw_data (net_dev); +if (rt2x00pci->scan) +return -EBUSY ; + +/* +* Allocate scanning structure to store scanning info. +*/ rt2x00pci->scan =kmalloc (sizeof (struct scanning ),GFP_ATOMIC );if (!rt2x00pci->scan) -return 0 ; +return -ENOMEM ; + +/* +* Check if we have to send a packet before the +* channel switch. +*/ +if (conf->skb) { +if (rt2400pci_tx (net_dev, conf->skb, conf->tx_control)) + goto exit; + }/* * Initialize Scanning structure.
@@ -1646,14 +1661,21 @@ rt2400pci_passive_scan(struct net_device rt2x00pci->scan->state = state; - rt2x00pci->scan->cancelled =0 ; + rt2x00pci->scan->status =0 ;/* * Queue work. */ -queue_work (rt2x00pci->workqueue, &rt2x00pci->scan_work); +if (!queue_work (rt2x00pci->workqueue, &rt2x00pci->scan_work)) + goto exit;return 0 ; + +exit: +kfree (rt2x00pci->scan); + rt2x00pci->scan =NULL ; + +return -EIO ; } static int
@@ -2207,11 +2229,6 @@ rt2400pci_uninitialize(struct net_device rt2x00pci->csr_addr =NULL ; } -if (rt2x00pci->scan) { - rt2x00pci->scan->cancelled =1 ; -complete_all (&rt2x00pci->scan->completion); - } -if (likely (rt2x00pci->workqueue)) {flush_workqueue (rt2x00pci->workqueue);destroy_workqueue (rt2x00pci->workqueue);
drivers/net/wireless/d80211/rt2x00/rt2500pci.c +53 -36
163 lines not on this page · raw message
drivers/net/wireless/d80211/rt2x00/rt2500usb.c +52 -36
162 lines not on this page · raw message
drivers/net/wireless/d80211/rt2x00/rt2x00.h +3 -10
@@ -428,15 +428,6 @@ rt2x00_rf(const struct _rt2x00_chip *chi }/* -* Data to be placed in the skb->cb array. -* therefor this structure may not exceed the 40 bytes. -*/ -struct skb_cb { -int scan_complete; -} __attribute__ ((packed)); - - -/* * data_ring * Data rings are used by the device to send and receive packets. * The data_addr is the base address of the data memory.
@@ -589,7 +580,9 @@ struct scanning{/* * Flag to see if this scan has been cancelled. */ -short cancelled; +short status; +#define SCANNING_READY 0x0001 +#define SCANNING_CANCELLED 0x0002 } __attribute__ ((packed));