* [PATCH 10/28] rt2x00: Create write_tx_data and kick_tx_queue functions
@ 2007-02-28 14:07 Ivo van Doorn
0 siblings, 0 replies; only message in thread
From: Ivo van Doorn @ 2007-02-28 14:07 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless
Create write_tx_data and kick_tx_queue functions. This will make
the tx() function itself more generic which is something we need
when we are going to add the rt2x00lib module.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c b/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c
index afdaa9a..e9ff871 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c
@@ -1557,6 +1557,67 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
/*
+ * TX data initialization
+ */
+static int rt2400pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ struct data_ring *ring, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+ struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct data_desc *txd = entry->priv;
+ u32 word;
+ u16 fc;
+
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ rt2x00_desc_read(txd, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ memcpy(entry->data_addr, skb->data, skb->len);
+ rt2400pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
+ skb->len, control);
+ memcpy(&entry->tx_status.control, control, sizeof(*control));
+ entry->skb = skb;
+
+ fc = le16_to_cpu(ieee80211hdr->frame_control);
+ if (is_cts_frame(fc) || is_rts_frame(fc))
+ SET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
+
+ rt2x00_ring_index_inc(ring);
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+
+ return 0;
+}
+
+static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, TXCSR0, ®);
+ if (queue == IEEE80211_TX_QUEUE_DATA0)
+ rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA1)
+ rt2x00_set_field32(®, TXCSR0_KICK_TX, 1);
+ else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+ rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
+ rt2x00_register_write(rt2x00dev, TXCSR0, reg);
+}
+
+/*
* Interrupt functions.
*/
static void rt2400pci_beacondone(struct work_struct *work)
@@ -1670,7 +1731,7 @@ static void rt2400pci_txdone(struct work_struct *work)
* was succesfull.
*/
ack = rt2x00_get_field32(word, TXD_W0_ACK);
- rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+ rts = GET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
ack, rts);
@@ -1694,7 +1755,7 @@ static void rt2400pci_txdone(struct work_struct *work)
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_desc_write(txd, 0, word);
- CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
+ CLEAR_FLAG(entry, ENTRY_RTS_CTS_FRAME);
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
@@ -1795,12 +1856,8 @@ static int rt2400pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
struct sk_buff *skb_rts;
u16 frame_control;
- u32 word;
- u32 reg;
int res;
/*
@@ -1840,45 +1897,10 @@ static int rt2400pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}
}
- entry = rt2x00_get_data_entry(ring);
- txd = rt2x00_desc_addr(entry);
- rt2x00_desc_read(txd, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- rt2x00_get_field32(word, TXD_W0_VALID)) {
- ERROR("Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- control->queue, DRV_PROJECT);
- ieee80211_stop_queue(hw, control->queue);
+ if (rt2400pci_write_tx_data(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
- }
-
- /*
- * Set the software sequence number.
- */
- rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
-
- memcpy(rt2x00_data_addr(entry), skb->data, skb->len);
- rt2400pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- if (is_rts_frame(frame_control))
- SET_FLAG(entry, ENTRY_RTS_FRAME);
- entry->skb = skb;
- rt2x00_ring_index_inc(ring);
-
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(hw, control->queue);
-
- rt2x00_register_read(rt2x00dev, TXCSR0, ®);
- if (control->queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(®, TXCSR0_KICK_TX, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
- rt2x00_register_write(rt2x00dev, TXCSR0, reg);
+ rt2400pci_kick_tx_queue(rt2x00dev, control->queue);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c b/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c
index 1793040..73551b3 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c
@@ -1716,6 +1716,67 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
/*
+ * TX data initialization
+ */
+static int rt2500pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ struct data_ring *ring, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+ struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct data_desc *txd = entry->priv;
+ u32 word;
+ u16 fc;
+
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ rt2x00_desc_read(txd, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ memcpy(entry->data_addr, skb->data, skb->len);
+ rt2500pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
+ skb->len, control);
+ memcpy(&entry->tx_status.control, control, sizeof(*control));
+ entry->skb = skb;
+
+ fc = le16_to_cpu(ieee80211hdr->frame_control);
+ if (is_cts_frame(fc) || is_rts_frame(fc))
+ SET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
+
+ rt2x00_ring_index_inc(ring);
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+
+ return 0;
+}
+
+static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, TXCSR0, ®);
+ if (queue == IEEE80211_TX_QUEUE_DATA0)
+ rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA1)
+ rt2x00_set_field32(®, TXCSR0_KICK_TX, 1);
+ else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
+ rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
+ rt2x00_register_write(rt2x00dev, TXCSR0, reg);
+}
+
+/*
* Interrupt functions.
*/
static void rt2500pci_beacondone(struct work_struct *work)
@@ -1836,7 +1897,7 @@ static void rt2500pci_txdone(struct work_struct *work)
* was succesfull.
*/
ack = rt2x00_get_field32(word, TXD_W0_ACK);
- rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+ rts = GET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
ack, rts);
@@ -1860,7 +1921,7 @@ static void rt2500pci_txdone(struct work_struct *work)
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_desc_write(txd, 0, word);
- CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
+ CLEAR_FLAG(entry, ENTRY_RTS_CTS_FRAME);
entry->skb = NULL;
rt2x00_ring_index_done_inc(ring);
@@ -1961,12 +2022,8 @@ static int rt2500pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
struct sk_buff *skb_rts;
u16 frame_control;
- u32 word;
- u32 reg;
int res;
/*
@@ -2006,45 +2063,10 @@ static int rt2500pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}
}
- entry = rt2x00_get_data_entry(ring);
- txd = rt2x00_desc_addr(entry);
- rt2x00_desc_read(txd, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- rt2x00_get_field32(word, TXD_W0_VALID)) {
- ERROR("Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- control->queue, DRV_PROJECT);
- ieee80211_stop_queue(hw, control->queue);
+ if (rt2500pci_write_tx_data(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
- }
-
- /*
- * Set the software sequence number.
- */
- rt2x00_set_sequence(skb, &rt2x00dev->interface.sequence);
-
- memcpy(rt2x00_data_addr(entry), skb->data, skb->len);
- rt2500pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- if (is_rts_frame(frame_control))
- SET_FLAG(entry, ENTRY_RTS_FRAME);
- entry->skb = skb;
- rt2x00_ring_index_inc(ring);
-
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(hw, control->queue);
-
- rt2x00_register_read(rt2x00dev, TXCSR0, ®);
- if (control->queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(®, TXCSR0_KICK_TX, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
- rt2x00_register_write(rt2x00dev, TXCSR0, reg);
+ rt2500pci_kick_tx_queue(rt2x00dev, control->queue);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c
index a4b410a..49e70ca 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c
@@ -1679,6 +1679,72 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
/*
+ * TX data initialization
+ */
+static int rt2500usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ struct data_ring *ring, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct usb_device *usb_dev =
+ interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+ struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct data_desc *txd;
+ u32 length = skb->len;
+ u16 fc;
+
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue( rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
+ txd = (struct data_desc*)skb->data;
+ rt2500usb_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
+ skb->len, control);
+ memcpy(&entry->tx_status.control, control, sizeof(*control));
+ entry->skb = skb;
+
+ fc = le16_to_cpu(ieee80211hdr->frame_control);
+ if (is_cts_frame(fc) || is_rts_frame(fc))
+ SET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
+
+ /*
+ * Length passed to usb_fill_urb cannot be an odd number,
+ * so add 1 byte to make it even.
+ */
+ length += rt2x00dev->hw->extra_tx_headroom;
+ if (length % 2)
+ length++;
+
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
+ usb_fill_bulk_urb(
+ entry->priv,
+ usb_dev,
+ usb_sndbulkpipe(usb_dev, 1),
+ skb->data,
+ length,
+ rt2500usb_interrupt,
+ entry);
+ usb_submit_urb(entry->priv, GFP_ATOMIC);
+
+ rt2x00_ring_index_inc(ring);
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue( rt2x00dev->hw, control->queue);
+
+ return 0;
+}
+
+/*
* Interrupt functions.
*/
static void rt2500usb_beacondone(struct work_struct *work)
@@ -1817,7 +1883,7 @@ static void rt2500usb_txdone(struct work_struct *work)
* was succesfull.
*/
ack = rt2x00_get_field32(word, TXD_W0_ACK);
- rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+ rts = GET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
ack, rts);
@@ -1836,7 +1902,7 @@ static void rt2500usb_txdone(struct work_struct *work)
else
dev_kfree_skb(entry->skb);
- CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
+ CLEAR_FLAG(entry, ENTRY_RTS_CTS_FRAME);
entry->skb = NULL;
rt2x00_ring_index_done_inc(entry->ring);
@@ -1890,15 +1956,10 @@ static int rt2500usb_tx(struct ieee80211_hw *hw,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
- struct usb_device *usb_dev =
- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
struct sk_buff *skb_rts;
u16 frame_control;
int res;
- int length;
/*
* Determine which ring to put packet on.
@@ -1937,48 +1998,8 @@ static int rt2500usb_tx(struct ieee80211_hw *hw,
}
}
- entry = rt2x00_get_data_entry(ring);
- txd = rt2x00_txdesc_addr(entry);
-
- if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
- ERROR("Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- control->queue, DRV_PROJECT);
- ieee80211_stop_queue(hw, control->queue);
+ if (rt2500usb_write_tx_data(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
- }
-
- memcpy(rt2x00_txdata_addr(entry), skb->data, skb->len);
- rt2500usb_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- if (is_rts_frame(frame_control))
- SET_FLAG(entry, ENTRY_RTS_FRAME);
- entry->skb = skb;
-
- /*
- * Length passed to usb_fill_urb cannot be an odd number,
- * so add 1 byte to make it even.
- */
- length = skb->len + ring->desc_size;
- if (length % 2)
- length++;
-
- SET_FLAG(entry, ENTRY_OWNER_NIC);
- usb_fill_bulk_urb(
- rt2x00_urb(entry),
- usb_dev,
- usb_sndbulkpipe(usb_dev, 1),
- entry->data_addr,
- length,
- rt2500usb_interrupt,
- entry);
- usb_submit_urb(rt2x00_urb(entry), GFP_ATOMIC);
-
- rt2x00_ring_index_inc(ring);
-
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(hw, control->queue);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2x00.h b/drivers/net/wireless/mac80211/rt2x00/rt2x00.h
index fe9ac7d..d6e968c 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/mac80211/rt2x00/rt2x00.h
@@ -135,6 +135,9 @@ static int rt2x00_debug_level = 0;
#define is_rts_frame(__fc) \
( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && \
(((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)) )
+#define is_cts_frame(__fc) \
+ ( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && \
+ (((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)) )
#define is_probe_resp(__fc) \
( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && \
(((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)) )
@@ -518,8 +521,8 @@ struct data_entry {
* Status flags
*/
unsigned int flags;
-#define ENTRY_OWNER_NIC 0x00000001
-#define ENTRY_RTS_FRAME 0x00000002
+#define ENTRY_OWNER_NIC 0x00000001
+#define ENTRY_RTS_CTS_FRAME 0x00000002
/*
* Ring we belong to.
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt61pci.c b/drivers/net/wireless/mac80211/rt2x00/rt61pci.c
index 58b90cd..5685871 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/mac80211/rt2x00/rt61pci.c
@@ -2180,6 +2180,70 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
/*
+ * TX data initialization
+ */
+static int rt61pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ struct data_ring *ring, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+ struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct data_desc *txd = entry->priv;
+ u32 word;
+ u16 fc;
+
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ rt2x00_desc_read(txd, 0, &word);
+
+ if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ memcpy(entry->data_addr, skb->data, skb->len);
+ rt61pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr, skb->len, control);
+ memcpy(&entry->tx_status.control, control, sizeof(*control));
+ entry->skb = skb;
+
+ fc = le16_to_cpu(ieee80211hdr->frame_control);
+ if (is_cts_frame(fc) || is_rts_frame(fc))
+ SET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
+
+ rt2x00_ring_index_inc(ring);
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+
+ return 0;
+}
+
+static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
+{
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, TX_CNTL_CSR, ®);
+ if (queue == IEEE80211_TX_QUEUE_DATA0)
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA1)
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA2)
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA3)
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1);
+ else if (queue == IEEE80211_TX_QUEUE_DATA4)
+ rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT, 1);
+ rt2x00_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+}
+
+/*
* Interrupt functions.
*/
static void rt61pci_beacondone(struct work_struct *work)
@@ -2289,7 +2353,7 @@ static void rt61pci_txdone_entry(struct data_entry *entry, u32 sta_csr4)
* was succesfull.
*/
ack = rt2x00_get_field32(word, TXD_W0_ACK);
- rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+ rts = GET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
ack, rts);
@@ -2313,7 +2377,7 @@ static void rt61pci_txdone_entry(struct data_entry *entry, u32 sta_csr4)
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_desc_write(txd, 0, word);
- CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
+ CLEAR_FLAG(entry, ENTRY_RTS_CTS_FRAME);
entry->skb = NULL;
rt2x00_ring_index_done_inc(entry->ring);
@@ -2450,12 +2514,8 @@ static int rt61pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
struct sk_buff *skb_rts;
u16 frame_control;
- u32 word;
- u32 reg;
int res;
/*
@@ -2495,44 +2555,10 @@ static int rt61pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}
}
- entry = rt2x00_get_data_entry(ring);
- txd = rt2x00_desc_addr(entry);
- rt2x00_desc_read(txd, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- rt2x00_get_field32(word, TXD_W0_VALID)) {
- ERROR("Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- control->queue, DRV_PROJECT);
- ieee80211_stop_queue(hw, control->queue);
+ if (rt61pci_write_tx_data(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
- }
-
- memcpy(rt2x00_data_addr(entry), skb->data, skb->len);
- rt61pci_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- if (is_rts_frame(frame_control))
- SET_FLAG(entry, ENTRY_RTS_FRAME);
- entry->skb = skb;
-
- rt2x00_ring_index_inc(ring);
-
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(hw, control->queue);
- rt2x00_register_read(rt2x00dev, TX_CNTL_CSR, ®);
- if (control->queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA2)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA3)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1);
- else if (control->queue == IEEE80211_TX_QUEUE_DATA4)
- rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT, 1);
- rt2x00_register_write(rt2x00dev, TX_CNTL_CSR, reg);
+ rt61pci_kick_tx_queue(rt2x00dev, control->queue);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c
index e43404c..43a07dc 100644
--- a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c
@@ -1952,6 +1952,71 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
}
/*
+ * TX data initialization
+ */
+static int rt73usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
+ struct data_ring *ring, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct usb_device *usb_dev =
+ interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+ struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct data_desc *txd;
+ u32 length = skb->len;
+ u16 fc;
+
+ if (rt2x00_ring_full(ring)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
+ ERROR("Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ control->queue, DRV_PROJECT);
+ ieee80211_stop_queue( rt2x00dev->hw, control->queue);
+ return -EINVAL;
+ }
+
+ skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
+ txd = (struct data_desc*)skb->data;
+ rt73usb_write_tx_desc(rt2x00dev, txd, ieee80211hdr, skb->len, control);
+ memcpy(&entry->tx_status.control, control, sizeof(*control));
+ entry->skb = skb;
+
+ fc = le16_to_cpu(ieee80211hdr->frame_control);
+ if (is_cts_frame(fc) || is_rts_frame(fc))
+ SET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
+
+ /*
+ * Length passed to usb_fill_urb cannot be an odd number,
+ * so add 1 byte to make it even.
+ */
+ length += rt2x00dev->hw->extra_tx_headroom;
+ if (length % 2)
+ length++;
+
+ SET_FLAG(entry, ENTRY_OWNER_NIC);
+ usb_fill_bulk_urb(
+ entry->priv,
+ usb_dev,
+ usb_sndbulkpipe(usb_dev, 1),
+ skb->data,
+ length,
+ rt73usb_interrupt,
+ entry);
+ usb_submit_urb(entry->priv, GFP_ATOMIC);
+
+ rt2x00_ring_index_inc(ring);
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+
+ return 0;
+}
+
+/*
* Interrupt functions.
*/
static void rt73usb_beacondone(struct work_struct *work)
@@ -2082,7 +2147,7 @@ static void rt73usb_txdone(struct work_struct *work)
* was succesfull.
*/
ack = rt2x00_get_field32(word, TXD_W0_ACK);
- rts = GET_FLAG(entry, ENTRY_RTS_FRAME);
+ rts = GET_FLAG(entry, ENTRY_RTS_CTS_FRAME);
tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
rt2x00_update_tx_stats(rt2x00dev, &entry->tx_status, tx_status,
ack, rts);
@@ -2101,7 +2166,7 @@ static void rt73usb_txdone(struct work_struct *work)
else
dev_kfree_skb(entry->skb);
- CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
+ CLEAR_FLAG(entry, ENTRY_RTS_CTS_FRAME);
entry->skb = NULL;
rt2x00_ring_index_done_inc(entry->ring);
@@ -2154,15 +2219,10 @@ static int rt73usb_tx(struct ieee80211_hw *hw,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
- struct usb_device *usb_dev =
- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_ring *ring;
- struct data_entry *entry;
- struct data_desc *txd;
struct sk_buff *skb_rts;
u16 frame_control;
int res;
- int length;
/*
* Determine which ring to put packet on.
@@ -2201,48 +2261,8 @@ static int rt73usb_tx(struct ieee80211_hw *hw,
}
}
- entry = rt2x00_get_data_entry(ring);
- txd = rt2x00_desc_addr(entry);
-
- if (GET_FLAG(entry, ENTRY_OWNER_NIC)) {
- ERROR("Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
- control->queue, DRV_PROJECT);
- ieee80211_stop_queue(hw, control->queue);
+ if (rt73usb_write_tx_data(rt2x00dev, ring, skb, control))
return NETDEV_TX_BUSY;
- }
-
- memcpy(rt2x00_data_addr(entry), skb->data, skb->len);
- rt73usb_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- if (is_rts_frame(frame_control))
- SET_FLAG(entry, ENTRY_RTS_FRAME);
- entry->skb = skb;
-
- /*
- * Length passed to usb_fill_urb cannot be an odd number,
- * so add 1 byte to make it even.
- */
- length = skb->len + ring->desc_size;
- if (length % 2)
- length++;
-
- SET_FLAG(entry, ENTRY_OWNER_NIC);
- usb_fill_bulk_urb(
- rt2x00_urb(entry),
- usb_dev,
- usb_sndbulkpipe(usb_dev, 1),
- entry->data_addr,
- length,
- rt73usb_interrupt,
- entry);
- usb_submit_urb(rt2x00_urb(entry), GFP_ATOMIC);
-
- rt2x00_ring_index_inc(ring);
-
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(hw, control->queue);
return NETDEV_TX_OK;
}
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2007-02-28 14:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-02-28 14:07 [PATCH 10/28] rt2x00: Create write_tx_data and kick_tx_queue functions Ivo van Doorn
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.