* [PATCH 16/32] rt2x00: Make sure TX rings are empty when scanning
@ 2006-04-27 22:03 Ivo van Doorn
0 siblings, 0 replies; only message in thread
From: Ivo van Doorn @ 2006-04-27 22:03 UTC (permalink / raw)
To: netdev; +Cc: rt2x00-devel
[-- Attachment #1: Type: text/plain, Size: 15118 bytes --]
From: Ivo van Doorn <IvDoorn@gmail.com>
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 <IvDoorn@gmail.com>
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2400pci.c 2006-04-27 21:48:21.000000000 +0200
@@ -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_de
rt2x00_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);
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500pci.c 2006-04-27 21:48:21.000000000 +0200
@@ -923,7 +923,6 @@ rt2500pci_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;
@@ -936,13 +935,6 @@ rt2500pci_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);
/*
@@ -981,6 +973,18 @@ rt2500pci_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
@@ -1630,6 +1634,14 @@ rt2500pci_stop(struct net_device *net_de
rt2x00_register_write(rt2x00pci, CSR8, reg);
/*
+ * Cancel scanning.
+ */
+ if (rt2x00pci->scan) {
+ rt2x00pci->scan->status = SCANNING_CANCELLED;
+ complete_all(&rt2x00pci->scan->completion);
+ }
+
+ /*
* Free DMA rings.
*/
rt2500pci_free_rings(rt2x00pci);
@@ -1677,35 +1689,23 @@ static void
rt2500pci_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 (rt2500pci_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;
/*
@@ -1742,9 +1742,24 @@ rt2500pci_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 (rt2500pci_tx(net_dev, conf->skb, conf->tx_control))
+ goto exit;
+ }
/*
* Initialize Scanning structure.
@@ -1755,14 +1770,21 @@ rt2500pci_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
@@ -2505,20 +2527,15 @@ rt2500pci_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);
rt2x00pci->workqueue = NULL;
}
- kfree(rt2x00pci->hw.modes);
- rt2x00pci->hw.modes = NULL;
- }
+ kfree(rt2x00pci->hw.modes);
+ rt2x00pci->hw.modes = NULL;
+}
/*
* PCI driver handlers.
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2500usb.c 2006-04-27 21:48:21.000000000 +0200
@@ -769,7 +769,6 @@ rt2500usb_txdone(void *data)
struct net_device *net_dev = usb_get_intfdata(
rt2x00usb->usb_intf);
struct data_entry *entry;
- struct skb_cb *cb;
struct txd *txd;
int ack;
@@ -777,13 +776,6 @@ rt2500usb_txdone(void *data)
entry = rt2x00_get_data_entry_done(ring);
txd = entry->desc_addr;
- /*
- * Check if this frame was send for the scan routine.
- */
- cb = (struct skb_cb*)&entry->skb->cb;
- if (rt2x00usb->scan && cb->scan_complete)
- complete(&rt2x00usb->scan->completion);
-
ack = rt2x00_get_field32(txd->word0, TXD_W0_ACK);
/*
@@ -815,6 +807,18 @@ rt2500usb_txdone(void *data)
rt2x00_ring_index_done_inc(entry->ring);
} while (!rt2x00_ring_empty(ring));
+
+ /*
+ * Check if we are waiting on an empty queue
+ * to start scanning.
+ */
+ if (rt2x00usb->scan
+ && rt2x00_ring_empty(&rt2x00usb->tx)
+ && rt2x00_ring_empty(&rt2x00usb->atim)
+ && rt2x00_ring_empty(&rt2x00usb->prio)) {
+ rt2x00usb->scan->status = SCANNING_READY;
+ complete(&rt2x00usb->scan->completion);
+ }
}
static void
@@ -1368,6 +1372,14 @@ rt2500usb_stop(struct net_device *net_de
rt2x00_register_write(rt2x00usb, MAC_CSR14, 0x2121);
/*
+ * Cancel scanning.
+ */
+ if (rt2x00usb->scan) {
+ rt2x00usb->scan->status = SCANNING_CANCELLED;
+ complete_all(&rt2x00usb->scan->completion);
+ }
+
+ /*
* Free DMA rings.
*/
rt2500usb_free_rings(rt2x00usb);
@@ -1414,36 +1426,23 @@ static void
rt2500usb_scan(void *data)
{
struct rt2x00_usb *rt2x00usb = data;
- struct net_device *net_dev =
- usb_get_intfdata(rt2x00usb->usb_intf);
- struct skb_cb *cb;
if (unlikely(!rt2x00usb->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 (rt2x00usb->scan->conf.skb) {
- cb = (struct skb_cb*)&rt2x00usb->scan->conf.skb->cb;
- cb->scan_complete = 1;
-
- if (rt2500usb_tx(net_dev, rt2x00usb->scan->conf.skb,
- rt2x00usb->scan->conf.tx_control))
- goto exit;
-
- /*
- * Wait for the frame to be correctly transmitted.
- */
+ if (rt2x00usb->scan->status != SCANNING_READY)
wait_for_completion(&rt2x00usb->scan->completion);
- }
/*
* Check if this scan has been cancelled while
* work was still scheduled.
*/
- if (rt2x00usb->scan->cancelled)
+ if (rt2x00usb->scan->status == SCANNING_CANCELLED)
goto exit;
/*
@@ -1480,9 +1479,24 @@ rt2500usb_passive_scan(struct net_device
{
struct rt2x00_usb *rt2x00usb = ieee80211_dev_hw_data(net_dev);
+ if (rt2x00usb->scan)
+ return -EBUSY;
+
+ /*
+ * Allocate scanning structure to store scanning info.
+ */
rt2x00usb->scan = kmalloc(sizeof(struct scanning), GFP_ATOMIC);
if (!rt2x00usb->scan)
- return 0;
+ return -ENOMEM;
+
+ /*
+ * Check if we have to send a packet before the
+ * channel switch.
+ */
+ if (conf->skb) {
+ if (rt2500usb_tx(net_dev, conf->skb, conf->tx_control))
+ goto exit;
+ }
/*
* Initialize Scanning structure.
@@ -1493,14 +1507,21 @@ rt2500usb_passive_scan(struct net_device
rt2x00usb->scan->state = state;
- rt2x00usb->scan->cancelled = 0;
+ rt2x00usb->scan->status = 0;
/*
* Queue work.
*/
- queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work);
+ if (!queue_work(rt2x00usb->workqueue, &rt2x00usb->scan_work))
+ goto exit;
return 0;
+
+exit:
+ kfree(rt2x00usb->scan);
+ rt2x00usb->scan = NULL;
+
+ return -EIO;
}
static int
@@ -2121,19 +2142,14 @@ rt2500usb_uninitialize(struct net_device
kfree(rt2x00usb->eeprom);
- if (rt2x00usb->scan) {
- rt2x00usb->scan->cancelled = 1;
- complete_all(&rt2x00usb->scan->completion);
- }
-
if (likely(rt2x00usb->workqueue)) {
flush_workqueue(rt2x00usb->workqueue);
destroy_workqueue(rt2x00usb->workqueue);
rt2x00usb->workqueue = NULL;
}
- kfree(rt2x00usb->hw.modes);
- rt2x00usb->hw.modes = NULL;
+ kfree(rt2x00usb->hw.modes);
+ rt2x00usb->hw.modes = NULL;
}
/*
diff -uprN wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-rt2x00/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:47:52.000000000 +0200
+++ wireless-dev-rt2x00-patch/drivers/net/wireless/d80211/rt2x00/rt2x00.h 2006-04-27 21:48:21.000000000 +0200
@@ -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));
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2006-04-27 22:02 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-27 22:03 [PATCH 16/32] rt2x00: Make sure TX rings are empty when scanning Ivo van Doorn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).