>From Ivo van Doorn <[EMAIL PROTECTED]>
Support RTS.
When rts is required, create the frame and send it out
before the rest of the frames.
Signed-off-by: Ivo van Doorn <[EMAIL PROTECTED]>
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 17:24:56.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
2006-07-23 18:16:35.000000000 +0200
@@ -863,6 +863,36 @@
}
/*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt2400pci_create_rts(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_hdr *hdr, unsigned short duration)
+{
+ struct ieee80211_hdr *ieee80211hdr;
+ struct sk_buff *skb;
+ u16 temp;
+
+ skb = dev_alloc_skb(IEEE80211_HEADER);
+ if (!skb)
+ return NULL;
+
+ /*
+ * Copy the entire header over to RTS frame.
+ */
+ memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+ ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+ temp = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_RTS << 4);
+ ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+ ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+ ieee80211hdr->seq_ctrl = 0;
+
+ return skb;
+}
+
+/*
* TX descriptor initialization
*/
static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -876,15 +906,32 @@
u16 length_low;
u16 signal;
u16 service;
+ u16 frame_control;
+ u8 bitrate;
+ int tx_rate;
+
+ /*
+ * Check which rate should be used for this frame.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+ control->rts_cts_rate)
+ tx_rate = control->rts_cts_rate;
+ else
+ tx_rate = control->tx_rate;
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
/*
- * TODO: IFS can be various values, where can we find
- * which one we want to use?
+ * Set IFS to IFS_SIFS when the this is not the first fragment,
+ * or this fragment came after RTS/CTS.
*/
- rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+ if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+ control->use_rts_cts)
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+ else
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
if (control->queue == IEEE80211_TX_QUEUE_BEACON)
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 1);
@@ -896,16 +943,15 @@
*/
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
- if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+ if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
- /*
- * TODO: Does this field mean device will send RTS, or that this
- * frame is an RTS frame?
- */
- rt2x00_set_field32(&txd->word0, TXD_W0_RTS, control->use_rts_cts);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 1);
+ else
+ rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 0);
rt2x00_set_field32(&txd->word2, TXD_W2_DATABYTE_COUNT, skb->len);
@@ -918,9 +964,9 @@
* Convert length to microseconds.
*/
residual = get_duration_res(length,
- DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+ DEVICE_GET_RATE_FIELD(tx_rate, RATE));
length = get_duration(length,
- DEVICE_GET_RATE_FIELD(control->tx_rate, RATE));
+ DEVICE_GET_RATE_FIELD(tx_rate, RATE));
if (residual)
length++;
@@ -938,8 +984,8 @@
length_high = 0x8000 | 0x0700 | (length >> 8);
length_low = 0x8000 | 0x0800 | (length & 0xff);
- signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+ signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
service = 0x0600 | 0x0004;
@@ -1089,8 +1135,9 @@
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
- ieee80211_tx_status(ring->net_dev,
- entry->skb, &entry->tx_status);
+ if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
@@ -1574,10 +1621,14 @@
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
struct data_entry *entry;
struct txd *txd;
+ struct sk_buff *skb_rts;
+ u16 frame_control;
u32 reg;
+ int res;
/*
* Determine which ring to put packet on.
@@ -1596,6 +1647,27 @@
return NETDEV_TX_BUSY;
}
+ /*
+ * If RTS is required. and this frame is not RTS,
+ * create and queue that frame first.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (control->use_rts_cts &&
+ WLAN_FC_GET_STYPE(frame_control) != WLAN_FC_STYPE_RTS) {
+ skb_rts = rt2400pci_create_rts(rt2x00dev,
+ ieee80211hdr, control->rts_cts_duration);
+ if (!skb_rts) {
+ WARNING("Failed to create RTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ res = rt2400pci_tx(net_dev, skb_rts, control);
+ if (res) {
+ WARNING("Failed to send RTS frame.\n");
+ return res;
+ }
+ }
+
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
@@ -1610,6 +1682,8 @@
memcpy(entry->data_addr, skb->data, skb->len);
rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 17:31:27.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
2006-07-23 18:16:41.000000000 +0200
@@ -936,6 +936,36 @@
}
/*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt2500pci_create_rts(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_hdr *hdr, unsigned short duration)
+{
+ struct ieee80211_hdr *ieee80211hdr;
+ struct sk_buff *skb;
+ u16 temp;
+
+ skb = dev_alloc_skb(IEEE80211_HEADER);
+ if (!skb)
+ return NULL;
+
+ /*
+ * Copy the entire header over to RTS frame.
+ */
+ memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+ ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+ temp = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_RTS << 4);
+ ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+ ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+ ieee80211hdr->seq_ctrl = 0;
+
+ return skb;
+}
+
+/*
* TX descriptor initialization
*/
static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -951,6 +981,19 @@
u16 signal;
u16 service;
u8 rate;
+ u16 frame_control;
+ u8 bitrate;
+ int tx_rate;
+
+ /*
+ * Check which rate should be used for this frame.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+ control->rts_cts_rate)
+ tx_rate = control->rts_cts_rate;
+ else
+ tx_rate = control->tx_rate;
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -965,26 +1008,29 @@
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
/*
- * TODO: IFS can be various values, where can we find
- * which one we want to use?
+ * Set IFS to IFS_SIFS when the this is not the first fragment,
+ * or this fragment came after RTS/CTS.
*/
- rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+ if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+ control->use_rts_cts)
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+ else
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
/*
* TODO: How can we determine if we want long retry or short retry?
*/
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
- if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+ if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
- /*
- * TODO: Does this field mean device will send RTS, or that this
- * frame is an RTS frame?
- */
- rt2x00_set_field32(&txd->word10, TXD_W10_RTS, control->use_rts_cts);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 1);
+ else
+ rt2x00_set_field32(&txd->word10, TXD_W10_RTS, 0);
rt2x00_set_field32(&txd->word0, TXD_W0_DATABYTE_COUNT, skb->len);
@@ -1002,7 +1048,7 @@
* this can be done by checking if bit 4 or higher
* is set in the ratemask.
*/
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, RATEMASK) & 0x0ff0) {
+ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
residual = 0;
@@ -1013,7 +1059,7 @@
length_low = (length & 0x3f);
} else {
- rate = DEVICE_GET_RATE_FIELD(control->tx_rate, RATE);
+ rate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 0);
@@ -1027,8 +1073,8 @@
length_low = length & 0xff;
}
- signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+ signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
service = 0x0600 | 0x0004;
@@ -1189,8 +1235,9 @@
entry->tx_status.retry_count = rt2x00_get_field32(
txd->word0, TXD_W0_RETRY_COUNT);
- ieee80211_tx_status(ring->net_dev,
- entry->skb, &entry->tx_status);
+ if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
@@ -1709,10 +1756,14 @@
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
struct data_entry *entry;
struct txd *txd;
+ struct sk_buff *skb_rts;
+ u16 frame_control;
u32 reg;
+ int res;
/*
* Determine which ring to put packet on.
@@ -1731,6 +1782,27 @@
return NETDEV_TX_BUSY;
}
+ /*
+ * If RTS is required. and this frame is not RTS,
+ * create and queue that frame first.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (control->use_rts_cts &&
+ WLAN_FC_GET_STYPE(frame_control) != WLAN_FC_STYPE_RTS) {
+ skb_rts = rt2500pci_create_rts(rt2x00dev,
+ ieee80211hdr, control->rts_cts_duration);
+ if (!skb_rts) {
+ WARNING("Failed to create RTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ res = rt2500pci_tx(net_dev, skb_rts, control);
+ if (res) {
+ WARNING("Failed to send RTS frame.\n");
+ return res;
+ }
+ }
+
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
@@ -1745,6 +1817,8 @@
memcpy(entry->data_addr, skb->data, skb->len);
rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 17:31:13.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
2006-07-23 18:15:52.000000000 +0200
@@ -766,6 +766,36 @@
}
/*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt2500usb_create_rts(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_hdr *hdr, unsigned short duration)
+{
+ struct ieee80211_hdr *ieee80211hdr;
+ struct sk_buff *skb;
+ u16 temp;
+
+ skb = dev_alloc_skb(IEEE80211_HEADER);
+ if (!skb)
+ return NULL;
+
+ /*
+ * Copy the entire header over to RTS frame.
+ */
+ memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+ ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+ temp = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_RTS << 4);
+ ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+ ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+ ieee80211hdr->seq_ctrl = 0;
+
+ return skb;
+}
+
+/*
* TX descriptor initialization
*/
static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -780,7 +810,19 @@
u8 length_low;
u8 signal;
u8 service;
- u8 rate;
+ u16 frame_control;
+ u8 bitrate;
+ int tx_rate;
+
+ /*
+ * Check which rate should be used for this frame.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+ control->rts_cts_rate)
+ tx_rate = control->rts_cts_rate;
+ else
+ tx_rate = control->tx_rate;
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -794,15 +836,19 @@
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
/*
- * TODO: IFS can be various values, where can we find
- * which one we want to use?
+ * Set IFS to IFS_SIFS when the this is not the first fragment,
+ * or this fragment came after RTS/CTS.
*/
- rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+ if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+ control->use_rts_cts)
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+ else
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_LIMIT,
control->retry_limit);
- if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+ if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
@@ -828,7 +874,7 @@
* this can be done by checking if bit 4 or higher
* is set in the ratemask.
*/
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, RATEMASK) & 0x0ff0) {
+ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
residual = 0;
@@ -839,7 +885,7 @@
length_low = (length & 0x3f);
} else {
- rate = DEVICE_GET_RATE_FIELD(control->tx_rate, RATE);
+ rate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 0);
@@ -853,8 +899,8 @@
length_low = length & 0xff;
}
- signal = DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+ signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x08;
service = 0x04;
@@ -1017,9 +1063,10 @@
rt2x00_bbp_read(rt2x00dev, 0,
(u8*)&entry->tx_status.ack_signal);
-
- ieee80211_tx_status(ring->net_dev,
- entry->skb, &entry->tx_status);
+
+ if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
entry->skb = NULL;
@@ -1415,11 +1462,15 @@
struct sk_buff *skb, struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ 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 txd *txd;
+ struct sk_buff *skb_rts;
+ u16 frame_control;
+ int res;
/*
* Determine which ring to put packet on.
@@ -1438,6 +1489,27 @@
return NETDEV_TX_BUSY;
}
+ /*
+ * If RTS is required. and this frame is not RTS,
+ * create and queue that frame first.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (control->use_rts_cts &&
+ WLAN_FC_GET_STYPE(frame_control) != WLAN_FC_STYPE_RTS) {
+ skb_rts = rt2500usb_create_rts(rt2x00dev,
+ ieee80211hdr, control->rts_cts_duration);
+ if (!skb_rts) {
+ WARNING("Failed to create RTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ res = rt2500usb_tx(net_dev, skb_rts, control);
+ if (res) {
+ WARNING("Failed to send RTS frame.\n");
+ return res;
+ }
+ }
+
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
@@ -1451,6 +1523,8 @@
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
SET_FLAG(entry, ENTRY_OWNER_NIC);
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00.h
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00.h
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 16:59:40.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00.h
2006-07-23 18:09:00.000000000 +0200
@@ -139,6 +139,16 @@
};
/*
+ * IFS backoff values
+ */
+enum ifs {
+ IFS_BACKOFF = 0,
+ IFS_SIFS = 1,
+ IFS_NEW_BACKOFF = 2,
+ IFS_NONE = 3,
+};
+
+/*
* Macros for determining which is the lowest or highest bit
* set in a 16 or 32 bit variable.
*/
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
2006-07-23 15:53:34.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
2006-07-23 17:59:04.000000000 +0200
@@ -84,6 +84,12 @@
*/
struct data_entry {
/*
+ * Status flag.
+ */
+ unsigned int flags;
+#define ENTRY_RTS_FRAME 0x00000001
+
+ /*
* sk_buff for the packet which is being transmitted
* in this entry (Only used with TX related rings).
*/
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
2006-07-23 15:23:15.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt2x00usb.h
2006-07-23 17:58:43.000000000 +0200
@@ -56,6 +56,7 @@
unsigned int flags;
#define ENTRY_OWNER_NIC 0x00000001
#define ENTRY_TYPE_RX 0x00000002
+#define ENTRY_RTS_FRAME 0x00000004
/*
* Ring we belong to.
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt61pci.c
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 17:31:05.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt61pci.c
2006-07-23 18:16:51.000000000 +0200
@@ -1202,6 +1202,36 @@
}
/*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt61pci_create_rts(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_hdr *hdr, unsigned short duration)
+{
+ struct ieee80211_hdr *ieee80211hdr;
+ struct sk_buff *skb;
+ u16 temp;
+
+ skb = dev_alloc_skb(IEEE80211_HEADER);
+ if (!skb)
+ return NULL;
+
+ /*
+ * Copy the entire header over to RTS frame.
+ */
+ memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+ ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+ temp = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_RTS << 4);
+ ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+ ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+ ieee80211hdr->seq_ctrl = 0;
+
+ return skb;
+}
+
+/*
* TX descriptor initialization
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -1217,6 +1247,19 @@
u16 signal;
u16 service;
u8 rate;
+ u16 frame_control;
+ u8 bitrate;
+ int tx_rate;
+
+ /*
+ * Check which rate should be used for this frame.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+ control->rts_cts_rate)
+ tx_rate = control->rts_cts_rate;
+ else
+ tx_rate = control->tx_rate;
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -1231,17 +1274,21 @@
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
/*
- * TODO: IFS can be various values, where can we find
- * which one we want to use?
+ * Set IFS to IFS_SIFS when the this is not the first fragment,
+ * or this fragment came after RTS/CTS.
*/
- rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+ if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+ control->use_rts_cts)
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+ else
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
/*
* TODO: How can we determine if we want long retry or short retry?
*/
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
- if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+ if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
@@ -1277,7 +1324,7 @@
* this can be done by checking if bit 4 or higher
* is set in the ratemask.
*/
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, RATEMASK) & 0x0ff0) {
+ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
/*
@@ -1288,7 +1335,7 @@
length_low = (length & 0x3f);
} else {
- rate = DEVICE_GET_RATE_FIELD(control->tx_rate, RATE);
+ rate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 0);
@@ -1302,8 +1349,8 @@
length_low = length & 0xff;
}
- signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+ signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
service = 0x04;
@@ -1470,8 +1517,9 @@
entry->tx_status.retry_count = rt2x00_get_field32(
reg, STA_CSR4_RETRY_COUNT);
- ieee80211_tx_status(ring->net_dev,
- entry->skb, &entry->tx_status);
+ if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
entry->skb = NULL;
@@ -2158,10 +2206,14 @@
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
struct data_ring *ring;
struct data_entry *entry;
struct txd *txd;
+ struct sk_buff *skb_rts;
+ u16 frame_control;
u32 reg;
+ int res;
/*
* Determine which ring to put packet on.
@@ -2180,6 +2232,27 @@
return NETDEV_TX_BUSY;
}
+ /*
+ * If RTS is required. and this frame is not RTS,
+ * create and queue that frame first.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (control->use_rts_cts &&
+ WLAN_FC_GET_STYPE(frame_control) != WLAN_FC_STYPE_RTS) {
+ skb_rts = rt61pci_create_rts(rt2x00dev,
+ ieee80211hdr, control->rts_cts_duration);
+ if (!skb_rts) {
+ WARNING("Failed to create RTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ res = rt61pci_tx(net_dev, skb_rts, control);
+ if (res) {
+ WARNING("Failed to send RTS frame.\n");
+ return res;
+ }
+ }
+
entry = rt2x00_get_data_entry(ring);
txd = entry->desc_addr;
@@ -2194,6 +2267,8 @@
memcpy(entry->data_addr, skb->data, skb->len);
rt61pci_write_tx_desc(rt2x00dev, txd, skb, control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
rt2x00_ring_index_inc(ring);
diff -rU3 wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt73usb.c
wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt73usb.c
--- wireless-dev-txpower/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 17:30:57.000000000 +0200
+++ wireless-dev-rts/drivers/net/wireless/d80211/rt2x00/rt73usb.c
2006-07-23 18:17:01.000000000 +0200
@@ -932,6 +932,36 @@
}
/*
+ * RTS frame creation.
+ */
+static struct sk_buff* rt73usb_create_rts(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_hdr *hdr, unsigned short duration)
+{
+ struct ieee80211_hdr *ieee80211hdr;
+ struct sk_buff *skb;
+ u16 temp;
+
+ skb = dev_alloc_skb(IEEE80211_HEADER);
+ if (!skb)
+ return NULL;
+
+ /*
+ * Copy the entire header over to RTS frame.
+ */
+ memcpy(skb_put(skb, IEEE80211_HEADER), hdr, IEEE80211_HEADER);
+ ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+
+ temp = (WLAN_FC_TYPE_CTRL << 2) | (WLAN_FC_STYPE_RTS << 4);
+ ieee80211hdr->frame_control = cpu_to_le16(temp);
+
+ ieee80211hdr->duration_id += cpu_to_le16(duration);
+
+ ieee80211hdr->seq_ctrl = 0;
+
+ return skb;
+}
+
+/*
* TX descriptor initialization
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
@@ -947,6 +977,19 @@
u16 signal;
u16 service;
u8 rate;
+ u16 frame_control;
+ u8 bitrate;
+ int tx_rate;
+
+ /*
+ * Check which rate should be used for this frame.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS &&
+ control->rts_cts_rate)
+ tx_rate = control->rts_cts_rate;
+ else
+ tx_rate = control->tx_rate;
rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 1);
rt2x00_set_field32(&txd->word0, TXD_W0_ACK, !control->no_ack);
@@ -961,17 +1004,21 @@
rt2x00_set_field32(&txd->word0, TXD_W0_TIMESTAMP, 0);
/*
- * TODO: IFS can be various values, where can we find
- * which one we want to use?
+ * Set IFS to IFS_SIFS when the this is not the first fragment,
+ * or this fragment came after RTS/CTS.
*/
- rt2x00_set_field32(&txd->word0, TXD_W0_IFS, 0);
+ if ((WLAN_GET_SEQ_FRAG(le16_to_cpu(ieee80211hdr->seq_ctrl)) > 0) ||
+ control->use_rts_cts)
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_SIFS);
+ else
+ rt2x00_set_field32(&txd->word0, TXD_W0_IFS, IFS_BACKOFF);
/*
* TODO: How can we determine if we want long retry or short retry?
*/
rt2x00_set_field32(&txd->word0, TXD_W0_RETRY_MODE, 0);
- if (ieee80211hdr->frame_control & WLAN_FC_MOREFRAG)
+ if (frame_control & WLAN_FC_MOREFRAG)
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
@@ -1007,7 +1054,7 @@
* this can be done by checking if bit 4 or higher
* is set in the ratemask.
*/
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, RATEMASK) & 0x0ff0) {
+ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
/*
@@ -1018,7 +1065,7 @@
length_low = (length & 0x3f);
} else {
- rate = DEVICE_GET_RATE_FIELD(control->tx_rate, RATE);
+ rate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 0);
@@ -1032,8 +1079,8 @@
length_low = length & 0xff;
}
- signal = 0x8500 | DEVICE_GET_RATE_FIELD(control->tx_rate, PLCP);
- if (DEVICE_GET_RATE_FIELD(control->tx_rate, PREAMBLE))
+ signal = 0x8500 | DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
+ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
signal |= 0x0008;
service = 0x04;
@@ -1205,8 +1252,9 @@
rt2x00_bbp_read(rt2x00dev, 32,
(u8*)&entry->tx_status.ack_signal);
- ieee80211_tx_status(ring->net_dev,
- entry->skb, &entry->tx_status);
+ if (!GET_FLAG(entry, ENTRY_RTS_FRAME))
+ ieee80211_tx_status(ring->net_dev,
+ entry->skb, &entry->tx_status);
entry->skb = NULL;
@@ -1728,11 +1776,15 @@
struct sk_buff *skb, struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ 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 txd *txd;
+ struct sk_buff *skb_rts;
+ u16 frame_control;
+ int res;
/*
* Determine which ring to put packet on.
@@ -1751,6 +1803,27 @@
return NETDEV_TX_BUSY;
}
+ /*
+ * If RTS is required. and this frame is not RTS,
+ * create and queue that frame first.
+ */
+ frame_control = le16_to_cpu(ieee80211hdr->frame_control);
+ if (control->use_rts_cts &&
+ WLAN_FC_GET_STYPE(frame_control) != WLAN_FC_STYPE_RTS) {
+ skb_rts = rt73usb_create_rts(rt2x00dev,
+ ieee80211hdr, control->rts_cts_duration);
+ if (!skb_rts) {
+ WARNING("Failed to create RTS frame.\n");
+ return NETDEV_TX_BUSY;
+ }
+
+ res = rt73usb_tx(net_dev, skb_rts, control);
+ if (res) {
+ WARNING("Failed to send RTS frame.\n");
+ return res;
+ }
+ }
+
entry = rt2x00_get_data_entry(ring);
txd = rt2x00usb_txdesc_addr(entry);
@@ -1764,6 +1837,8 @@
memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
rt73usb_write_tx_desc(rt2x00dev, txd, skb, control);
+ if (WLAN_FC_GET_STYPE(frame_control) == WLAN_FC_STYPE_RTS)
+ SET_FLAG(entry, ENTRY_RTS_FRAME);
entry->skb = skb;
SET_FLAG(entry, ENTRY_OWNER_NIC);
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html