Skip to contentSkip to conversation

rt2x00: simplify txstatus_fifo handling

PATCH New Ivo van Doorn 1 participant 10 messages Dec 27, 2010 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

PATCH 1/10 rt2x00: simplify txstatus_fifo handling

From: Johannes Stezenbach <[email protected]>

---
 drivers/net/wireless/rt2x00/rt2800pci.c |   18 ++----------------
 drivers/net/wireless/rt2x00/rt2x00.h    |    2 +-
 2 files changed, 3 insertions(+), 17 deletions(-)
drivers/net/wireless/rt2x00/rt2800pci.c +2 -16
index baa1468..aa97971 100644
@@ -688,14 +688,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 	u32 status;
 	u8 qid;
 
-	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
-		/* Now remove the tx status from the FIFO */
-		if (kfifo_out(&rt2x00dev->txstatus_fifo, &status,
-			      sizeof(status)) != sizeof(status)) {
-			WARN_ON(1);
-			break;
-		}
-
+	while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
 		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
 		if (qid >= QID_RX) {
 			/*
@@ -803,14 +796,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
 			break;
 
-		if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
-			WARNING(rt2x00dev, "TX status FIFO overrun,"
-				" drop tx status report.\n");
-			break;
-		}
-
-		if (kfifo_in(&rt2x00dev->txstatus_fifo, &status,
-			     sizeof(status)) != sizeof(status)) {
+		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &status)) {
 			WARNING(rt2x00dev, "TX status FIFO overrun,"
 				"drop tx status report.\n");
 			break;
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
index c254d5a..af1d3ef 100644
@@ -908,7 +908,7 @@ struct rt2x00_dev {
 	/*
 	 * FIFO for storing tx status reports between isr and tasklet.
 	 */
-	struct kfifo txstatus_fifo;
+	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
 	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
Signature · 1 line
1.7.2.3
#1 lore raw

PATCH 2/10 rt2x00: allow txstatus_fifo w/o txstatus_tasklet

From: Johannes Stezenbach <[email protected]>

When DRIVER_REQUIRE_TXSTATUS_FIFO is set, intialize the txstatus_fifo, but initialize rt2x00dev->txstatus_tasklet only when both DRIVER_REQUIRE_TXSTATUS_FIFO and rt2x00dev->ops->lib->txstatus_tasklet are set.

This allows the txstatus_fifo to be used by rt2800usb which does not use txstatus_tasklet.

---
 drivers/net/wireless/rt2x00/rt2x00dev.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/rt2x00/rt2x00dev.c +5 -5
index fa74acd..97a8911 100644
@@ -813,8 +813,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Allocate tx status FIFO for driver use.
 	 */
-	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) &&
-	    rt2x00dev->ops->lib->txstatus_tasklet) {
+	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
 		/*
 		 * Allocate txstatus fifo and tasklet, we use a size of 512
 		 * for the kfifo which is big enough to store 512/4=128 tx
@@ -828,9 +827,10 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
 			return status;
 
 		/* tasklet for processing the tx status reports. */
-		tasklet_init(&rt2x00dev->txstatus_tasklet,
-			     rt2x00dev->ops->lib->txstatus_tasklet,
-			     (unsigned long)rt2x00dev);
+		if (rt2x00dev->ops->lib->txstatus_tasklet)
+			tasklet_init(&rt2x00dev->txstatus_tasklet,
+				     rt2x00dev->ops->lib->txstatus_tasklet,
+				     (unsigned long)rt2x00dev);
 
 	}
 
Signature · 1 line
1.7.2.3
#2 lore raw

PATCH 3/10 rt2x00: Remove intf->bssid field.

From: Gertjan van Wingerde <[email protected]>

The bssid field in struct rt2x00_intf is only written to once, and is never read from.

Remove this field, as it appears to not be needed.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    5 -----
 drivers/net/wireless/rt2x00/rt2x00mac.c |   11 -----------
 2 files changed, 0 insertions(+), 16 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +0 -5
index af1d3ef..5f7f52f 100644
@@ -365,11 +365,6 @@ struct rt2x00_intf {
 	u8 mac[ETH_ALEN];
 
 	/*
-	 * BBSID of the AP to associate with.
-	 */
-	u8 bssid[ETH_ALEN];
-
-	/*
 	 * beacon->skb must be protected with the mutex.
 	 */
 	struct mutex beacon_skb_mutex;
drivers/net/wireless/rt2x00/rt2x00mac.c +0 -11
index 4cac7ad..23250a5 100644
@@ -614,17 +614,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		return;
 
-	spin_lock(&intf->lock);
-
-	/*
-	 * conf->bssid can be NULL if coming from the internal
-	 * beacon update routine.
-	 */
-	if (changes & BSS_CHANGED_BSSID)
-		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
-
-	spin_unlock(&intf->lock);
-
 	/*
 	 * Call rt2x00_config_intf() outside of the spinlock context since
 	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
Signature · 1 line
1.7.2.3
#3 lore raw

PATCH 4/10 rt2x00: remove intf->mac field.

From: Gertjan van Wingerde <[email protected]>

The mac field of the rt2x00_intf structure is written to once and used twice. In both these uses the mac address is available via other means.

Remove this field as it does not appear to be necessary.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    5 -----
 drivers/net/wireless/rt2x00/rt2x00mac.c |    6 ++----
 2 files changed, 2 insertions(+), 9 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +0 -5
index 5f7f52f..755b723 100644
@@ -360,11 +360,6 @@ struct rt2x00_intf {
 	spinlock_t lock;
 
 	/*
-	 * MAC of the device.
-	 */
-	u8 mac[ETH_ALEN];
-
-	/*
 	 * beacon->skb must be protected with the mutex.
 	 */
 	struct mutex beacon_skb_mutex;
drivers/net/wireless/rt2x00/rt2x00mac.c +2 -4
index 23250a5..f8775c4 100644
@@ -282,9 +282,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 	 * STA interfaces at this time, since this can cause
 	 * invalid behavior in the device.
 	 */
-	memcpy(&intf->mac, vif->addr, ETH_ALEN);
 	rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
-			      intf->mac, NULL);
+			      vif->addr, NULL);
 
 	/*
 	 * Some filters depend on the current working mode. We can force
@@ -492,7 +491,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		      struct ieee80211_key_conf *key)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	struct rt2x00_intf *intf = vif_to_intf(vif);
 	int (*set_key) (struct rt2x00_dev *rt2x00dev,
 			struct rt2x00lib_crypto *crypto,
 			struct ieee80211_key_conf *key);
@@ -516,7 +514,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	if (rt2x00dev->intf_sta_count)
 		crypto.bssidx = 0;
 	else
-		crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1);
+		crypto.bssidx = vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1);
 
 	crypto.cipher = rt2x00crypto_key_to_cipher(key);
 	if (crypto.cipher == CIPHER_NONE)
Signature · 1 line
1.7.2.3
#4 lore raw

PATCH 5/10 rt2x00: Fix pointer errors.

From: Gertjan van Wingerde <[email protected]>

Fix some pointer errors in the various calls to memcpy, memset and memmove.

Although none of these errors are fatal (the expression used now results in the same pointer value) it is better to use the proper expression. All errors are having to deal with arrays.

---
 drivers/net/wireless/rt2x00/rt2x00config.c |    8 ++++----
 drivers/net/wireless/rt2x00/rt2x00mac.c    |    8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2x00config.c +4 -4
index 70ca937..e7f67d5 100644
@@ -62,13 +62,13 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
 	 * This will prevent the device being confused when it wants
 	 * to ACK frames or consideres itself associated.
 	 */
-	memset(&conf.mac, 0, sizeof(conf.mac));
+	memset(conf.mac, 0, sizeof(conf.mac));
 	if (mac)
-		memcpy(&conf.mac, mac, ETH_ALEN);
+		memcpy(conf.mac, mac, ETH_ALEN);
 
-	memset(&conf.bssid, 0, sizeof(conf.bssid));
+	memset(conf.bssid, 0, sizeof(conf.bssid));
 	if (bssid)
-		memcpy(&conf.bssid, bssid, ETH_ALEN);
+		memcpy(conf.bssid, bssid, ETH_ALEN);
 
 	flags |= CONFIG_UPDATE_TYPE;
 	if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
drivers/net/wireless/rt2x00/rt2x00mac.c +4 -4
index f8775c4..a2266c7 100644
@@ -471,17 +471,17 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
 static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
 {
 	if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
-		memcpy(&crypto->key,
+		memcpy(crypto->key,
 		       &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
 		       sizeof(crypto->key));
 
 	if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
-		memcpy(&crypto->tx_mic,
+		memcpy(crypto->tx_mic,
 		       &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
 		       sizeof(crypto->tx_mic));
 
 	if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
-		memcpy(&crypto->rx_mic,
+		memcpy(crypto->rx_mic,
 		       &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
 		       sizeof(crypto->rx_mic));
 }
@@ -532,7 +532,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	if (crypto.cipher == CIPHER_TKIP)
 		memcpy_tkip(&crypto, &key->key[0], key->keylen);
 	else
-		memcpy(&crypto.key, &key->key[0], key->keylen);
+		memcpy(crypto.key, &key->key[0], key->keylen);
 	/*
 	 * Each BSS has a maximum of 4 shared keys.
 	 * Shared key index values:
Signature · 1 line
1.7.2.3
#5 lore raw

PATCH 6/10 rt2x00: Fix panic on frame padding for rt2800 usb devices

From: Ismael Luceno <[email protected]>

Backtrace:
  rt2800usb_write_tx_data
  rt2x00queue_write_tx_frame
  rt2x00mac_tx
  invoke_tx_handlers
  __ieee80211_tx
  ieee80211_tx
  virt_to_head_page
  ieee80211_xmit
  ieee80211_tx_skb
  ieee80211_scan_work
  schedule
  ieee80211_scan_work
  process_one_work
  ...

It tried to expand the skb past it's end using skb_put. So I replaced it with a call to skb_padto, which takes the issue into account.

---
 drivers/net/wireless/rt2x00/rt2800usb.c |   16 ++++++++++++----
 1 files changed, 12 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2800usb.c +12 -4
index 3e0205d..b97a4a5 100644
@@ -369,7 +369,10 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,
 static void rt2800usb_write_tx_data(struct queue_entry *entry,
 					struct txentry_desc *txdesc)
 {
-	u8 padding_len;
+	unsigned int len;
+	int err;
+
+	rt2800_write_tx_data(entry, txdesc);
 
 	/*
 	 * pad(1~3 bytes) is added after each 802.11 payload.
@@ -378,9 +381,14 @@ static void rt2800usb_write_tx_data(struct queue_entry *entry,
 	 * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |
 	 *                 |<------------- tx_pkt_len ------------->|
 	 */
-        rt2800_write_tx_data(entry, txdesc);
-        padding_len = roundup(entry->skb->len + 4, 4) - entry->skb->len;
-        memset(skb_put(entry->skb, padding_len), 0, padding_len);
+	len = roundup(entry->skb->len, 4) + 4;
+	err = skb_padto(entry->skb, len);
+	if (unlikely(err)) {
+		WARNING(entry->queue->rt2x00dev, "TX SKB padding error, out of memory\n");
+		return;
+	}
+
+	entry->skb->len = len;
 }
 
 /*
Signature · 1 line
1.7.2.3
#6 lore raw

PATCH 7/10 rt2x00: Remove superfluous assignment of mpdu_density

From: Helmut Schaa <[email protected]>

The tx desciptor already gets initialized to 0. Hence, there's no need to explicitly assign 0 to mpdu_density here.

---
 drivers/net/wireless/rt2x00/rt2x00ht.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/net/wireless/rt2x00/rt2x00ht.c +0 -2
index c637bca..b7ad46e 100644
@@ -40,8 +40,6 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 	if (tx_info->control.sta)
 		txdesc->mpdu_density =
 		    tx_info->control.sta->ht_cap.ampdu_density;
-	else
-		txdesc->mpdu_density = 0;
 
 	txdesc->ba_size = 7;	/* FIXME: What value is needed? */
 
Signature · 1 line
1.7.2.3
#7 lore raw

PATCH 8/10 rt2x00: Simplify intf->delayed_flags locking

From: Helmut Schaa <[email protected]>

Instead of protecting delayed_flags with a spinlock use atomic bitops to make the code more readable.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    7 +++++--
 drivers/net/wireless/rt2x00/rt2x00dev.c |   15 +--------------
 drivers/net/wireless/rt2x00/rt2x00mac.c |    4 +---
 3 files changed, 7 insertions(+), 19 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +5 -2
index 755b723..b3f77d4 100644
@@ -347,6 +347,10 @@ struct link {
 	struct delayed_work watchdog_work;
 };
 
+enum rt2x00_delayed_flags {
+	DELAYED_UPDATE_BEACON,
+};
+
 /*
  * Interface structure
  * Per interface configuration details, this structure
@@ -374,8 +378,7 @@ struct rt2x00_intf {
 	/*
 	 * Actions that needed rescheduling.
 	 */
-	unsigned int delayed_flags;
-#define DELAYED_UPDATE_BEACON		0x00000001
+	unsigned long delayed_flags;
 
 	/*
 	 * Software sequence counter, this is only required
drivers/net/wireless/rt2x00/rt2x00dev.c +1 -14
index 97a8911..9597a03 100644
@@ -110,19 +110,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 {
 	struct rt2x00_dev *rt2x00dev = data;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	int delayed_flags;
-
-	/*
-	 * Copy all data we need during this action under the protection
-	 * of a spinlock. Otherwise race conditions might occur which results
-	 * into an invalid configuration.
-	 */
-	spin_lock(&intf->lock);
-
-	delayed_flags = intf->delayed_flags;
-	intf->delayed_flags = 0;
-
-	spin_unlock(&intf->lock);
 
 	/*
 	 * It is possible the radio was disabled while the work had been
@@ -133,7 +120,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return;
 
-	if (delayed_flags & DELAYED_UPDATE_BEACON)
+	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
 		rt2x00queue_update_beacon(rt2x00dev, vif, true);
 }
 
drivers/net/wireless/rt2x00/rt2x00mac.c +1 -3
index a2266c7..297d972 100644
@@ -444,9 +444,7 @@ static void rt2x00mac_set_tim_iter(void *data, u8 *mac,
 	    vif->type != NL80211_IFTYPE_WDS)
 		return;
 
-	spin_lock(&intf->lock);
-	intf->delayed_flags |= DELAYED_UPDATE_BEACON;
-	spin_unlock(&intf->lock);
+	set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags);
 }
 
 int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
Signature · 1 line
1.7.2.3
#8 lore raw

PATCH 9/10 rt2x00: Remove unused interface spinlock

From: Helmut Schaa <[email protected]>

Since the last user of intf->lock is gone we can safely remove it.

---
 drivers/net/wireless/rt2x00/rt2x00.h    |    6 ------
 drivers/net/wireless/rt2x00/rt2x00mac.c |    1 -
 2 files changed, 0 insertions(+), 7 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +0 -6
index b3f77d4..84aaf39 100644
@@ -358,12 +358,6 @@ enum rt2x00_delayed_flags {
  */
 struct rt2x00_intf {
 	/*
-	 * All fields within the rt2x00_intf structure
-	 * must be protected with a spinlock.
-	 */
-	spinlock_t lock;
-
-	/*
 	 * beacon->skb must be protected with the mutex.
 	 */
 	struct mutex beacon_skb_mutex;
drivers/net/wireless/rt2x00/rt2x00mac.c +0 -1
index 297d972..b5dad04 100644
@@ -268,7 +268,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 	else
 		rt2x00dev->intf_sta_count++;
 
-	spin_lock_init(&intf->lock);
 	spin_lock_init(&intf->seqlock);
 	mutex_init(&intf->beacon_skb_mutex);
 	intf->beacon = entry;
Signature · 1 line
1.7.2.3
#9 lore raw

PATCH 10/10 rt2x00: Fix comment about removed spinlock

From: Helmut Schaa <[email protected]>

The comment doesn't match the code anymore. Fix that.

---
 drivers/net/wireless/rt2x00/rt2x00mac.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/net/wireless/rt2x00/rt2x00mac.c +1 -4
index b5dad04..658542d 100644
@@ -610,10 +610,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 		return;
 
 	/*
-	 * Call rt2x00_config_intf() outside of the spinlock context since
-	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
-	 * values as arguments we make keep access to rt2x00_intf thread safe
-	 * even without the lock.
+	 * Update the BSSID.
 	 */
 	if (changes & BSS_CHANGED_BSSID)
 		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
Signature · 1 line
1.7.2.3