linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3]: multi-rate retry support for mac80211/ath5k
@ 2008-09-30 11:20 Felix Fietkau
  2008-09-30 11:22 ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Felix Fietkau
  0 siblings, 1 reply; 6+ messages in thread
From: Felix Fietkau @ 2008-09-30 11:20 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

Hi,

This is the updated series of my previous mac80211/ath5k patches,
split up for easier review.

- Felix

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mac80211: free up 2 bytes in skb->cb
  2008-09-30 11:20 [PATCH 0/3]: multi-rate retry support for mac80211/ath5k Felix Fietkau
@ 2008-09-30 11:22 ` Felix Fietkau
  2008-09-30 11:24   ` [PATCH 2/3] mac80211: add multi-rate retry support Felix Fietkau
  2008-09-30 18:44   ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Johannes Berg
  0 siblings, 2 replies; 6+ messages in thread
From: Felix Fietkau @ 2008-09-30 11:22 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

Free up 2 bytes in skb->cb to be used for multi-rate retry.
Move iv_len and icv_len initialization into key alloc.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -337,8 +337,6 @@
 			unsigned long jiffies;
 			s8 rts_cts_rate_idx, alt_retry_rate_idx;
 			u8 retry_limit;
-			u8 icv_len;
-			u8 iv_len;
 		} control;
 		struct {
 			u64 ampdu_ack_map;
@@ -635,6 +633,8 @@
  */
 struct ieee80211_key_conf {
 	enum ieee80211_key_alg alg;
+	u8 icv_len;
+	u8 iv_len;
 	u8 hw_key_idx;
 	u8 flags;
 	s8 keyidx;
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -252,7 +252,7 @@
 		}
 
 		/* Hardware appends ICV. */
-		plcp_fragment_len += info->control.icv_len;
+		plcp_fragment_len += info->control.hw_key->icv_len;
 
 		key_idx = b43_kidx_to_fw(dev, key_idx);
 		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
@@ -260,7 +260,7 @@
 		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
 			   B43_TXH_MAC_KEYALG;
 		wlhdr_len = ieee80211_hdrlen(fctl);
-		iv_len = min((size_t) info->control.iv_len,
+		iv_len = min((size_t) info->control.hw_key->iv_len,
 			     ARRAY_SIZE(txhdr->iv));
 		memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
 	}
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -243,7 +243,7 @@
 
 		if (key->enabled) {
 			/* Hardware appends ICV. */
-			plcp_fragment_len += info->control.icv_len;
+			plcp_fragment_len += info->control.hw_key->icv_len;
 
 			key_idx = b43legacy_kidx_to_fw(dev, key_idx);
 			mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
@@ -252,7 +252,7 @@
 				   B43legacy_TX4_MAC_KEYALG_SHIFT) &
 				   B43legacy_TX4_MAC_KEYALG;
 			wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
-			iv_len = min((size_t)info->control.iv_len,
+			iv_len = min((size_t)info->control.hw_key->iv_len,
 				     ARRAY_SIZE(txhdr->iv));
 			memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
 		} else {
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -313,9 +313,6 @@
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-	info->control.iv_len = WEP_IV_LEN;
-	info->control.icv_len = WEP_ICV_LEN;
-
 	if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
 		if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
 			return -1;
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -152,9 +152,6 @@
 	int len, tail;
 	u8 *pos;
 
-	info->control.icv_len = TKIP_ICV_LEN;
-	info->control.iv_len = TKIP_IV_LEN;
-
 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
 		/* hwaccel - with no need for preallocated room for IV/ICV */
@@ -374,9 +371,6 @@
 	u8 *pos, *pn;
 	int i;
 
-	info->control.icv_len = CCMP_MIC_LEN;
-	info->control.iv_len = CCMP_HDR_LEN;
-
 	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
 		/* hwaccel - with no need for preallocated room for CCMP "
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1164,7 +1164,7 @@
 
 	if (info->control.hw_key) {
 		keyidx = info->control.hw_key->hw_key_idx;
-		pktlen += info->control.icv_len;
+		pktlen += info->control.hw_key->icv_len;
 	}
 	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
 		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -237,7 +237,7 @@
 
 	if (tx_info->control.hw_key) {
 		txctl->keyix = tx_info->control.hw_key->hw_key_idx;
-		txctl->frmlen += tx_info->control.icv_len;
+		txctl->frmlen += tx_info->control.hw_key->icv_len;
 
 		if (tx_info->control.hw_key->alg == ALG_WEP)
 			txctl->keytype = ATH9K_KEY_TYPE_WEP;
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -56,10 +56,10 @@
 	 * note that these lengths should only be added when
 	 * mac80211 does not generate it.
 	 */
-	overhead += tx_info->control.icv_len;
+	overhead += key->icv_len;
 
 	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
-		overhead += tx_info->control.iv_len;
+		overhead += key->iv_len;
 
 	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
 		if (key->alg == ALG_TKIP)
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -374,7 +374,7 @@
 	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
 	struct txentry_desc txdesc;
 	struct skb_frame_desc *skbdesc;
-	unsigned int iv_len = IEEE80211_SKB_CB(skb)->control.iv_len;
+	unsigned int iv_len;
 
 	if (unlikely(rt2x00queue_full(queue)))
 		return -EINVAL;
@@ -410,8 +410,11 @@
 	 * the frame so we can provide it to the driver seperately.
 	 */
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
-	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags))
+	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) &&
+		(IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) {
+		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
 		rt2x00crypto_tx_remove_iv(skb, iv_len);
+	}
 
 	/*
 	 * It could be possible that the queue was corrupted and this
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -281,6 +281,20 @@
 	key->conf.alg = alg;
 	key->conf.keyidx = idx;
 	key->conf.keylen = key_len;
+	switch (alg) {
+	case ALG_WEP:
+		key->conf.iv_len = WEP_IV_LEN;
+		key->conf.icv_len = WEP_ICV_LEN;
+		break;
+	case ALG_TKIP:
+		key->conf.iv_len = TKIP_IV_LEN;
+		key->conf.icv_len = TKIP_ICV_LEN;
+		break;
+	case ALG_CCMP:
+		key->conf.iv_len = CCMP_HDR_LEN;
+		key->conf.icv_len = CCMP_MIC_LEN;
+		break;
+	}
 	memcpy(key->conf.key, key_data, key_len);
 	INIT_LIST_HEAD(&key->list);
 	INIT_LIST_HEAD(&key->todo);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/3] mac80211: add multi-rate retry support
  2008-09-30 11:22 ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Felix Fietkau
@ 2008-09-30 11:24   ` Felix Fietkau
  2008-09-30 11:25     ` [PATCH 3/3] ath5k: implement multi-rate retry support and fix tx status reporting Felix Fietkau
  2008-09-30 18:46     ` [PATCH 2/3] mac80211: add multi-rate retry support Johannes Berg
  2008-09-30 18:44   ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Johannes Berg
  1 sibling, 2 replies; 6+ messages in thread
From: Felix Fietkau @ 2008-09-30 11:24 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

This patch adjusts the rate control API to allow multi-rate retry
if supported by the driver. The ieee80211_hw struct specifies how
many alternate rate selections the driver supports.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -292,6 +292,20 @@
 #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \
 	(IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *))
 
+/* maximum number of alternate rate retry stages */
+#define IEEE80211_TX_MAX_ALTRATE	3
+
+/**
+ * struct ieee80211_tx_altrate - alternate rate selection/status
+ *
+ * @rate_idx: rate index to attempt to send with
+ * @limit: number of retries before fallback
+ */
+struct ieee80211_tx_altrate {
+	s8 rate_idx;
+	u8 limit;
+};
+
 /**
  * struct ieee80211_tx_info - skb transmit information
  *
@@ -335,12 +349,14 @@
 			struct ieee80211_key_conf *hw_key;
 			struct ieee80211_sta *sta;
 			unsigned long jiffies;
-			s8 rts_cts_rate_idx, alt_retry_rate_idx;
+			s8 rts_cts_rate_idx;
 			u8 retry_limit;
+			struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE];
 		} control;
 		struct {
 			u64 ampdu_ack_map;
 			int ack_signal;
+			struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1];
 			u8 retry_count;
 			bool excessive_retries;
 			u8 ampdu_ack_len;
@@ -828,6 +844,9 @@
  *	within &struct ieee80211_vif.
  * @sta_data_size: size (in bytes) of the drv_priv data area
  *	within &struct ieee80211_sta.
+ *
+ * @max_altrates: maximum number of alternate rate retry stages
+ * @max_altrate_tries: maximum number of tries for each stage
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -844,6 +863,8 @@
 	u16 ampdu_queues;
 	u16 max_listen_interval;
 	s8 max_signal;
+	u8 max_altrates;
+	u8 max_altrate_tries;
 };
 
 struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy);
@@ -900,11 +921,11 @@
 
 static inline struct ieee80211_rate *
 ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
-			     const struct ieee80211_tx_info *c)
+			     const struct ieee80211_tx_info *c, int idx)
 {
-	if (c->control.alt_retry_rate_idx < 0)
+	if (c->control.retries[idx].rate_idx < 0)
 		return NULL;
-	return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx];
+	return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx];
 }
 
 /**
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -208,7 +208,7 @@
 	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
 	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
 	rate_ofdm = b43_is_ofdm_rate(rate);
-	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate;
+	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
 	rate_fb = fbrate->hw_value;
 	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
 
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -210,7 +210,7 @@
 
 	rate = tx_rate->hw_value;
 	rate_ofdm = b43legacy_is_ofdm_rate(rate);
-	rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate;
+	rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
 	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
 
 	txhdr->mac_frame_ctl = wlhdr->frame_control;
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -292,8 +292,8 @@
 	entry->plcp_len = cpu_to_le16(plcp_len);
 	entry->tx_buf = cpu_to_le32(mapping);
 	entry->frame_len = cpu_to_le32(skb->len);
-	entry->flags2 = info->control.alt_retry_rate_idx >= 0 ?
-		ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0;
+	entry->flags2 = info->control.retries[0].rate_idx >= 0 ?
+		ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
 	entry->retry_limit = info->control.retry_limit;
 	entry->flags = cpu_to_le32(tx_flags);
 	__skb_queue_tail(&ring->queue, skb);
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -454,15 +454,16 @@
 		if (unlikely(rsel.probe_idx >= 0)) {
 			info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 			tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-			info->control.alt_retry_rate_idx = tx->rate_idx;
+			info->control.retries[0].rate_idx = tx->rate_idx;
+			info->control.retries[0].limit = tx->local->hw.max_altrate_tries;
 			tx->rate_idx = rsel.probe_idx;
-		} else
-			info->control.alt_retry_rate_idx = -1;
+		} else if (info->control.retries[0].limit == 0)
+			info->control.retries[0].rate_idx = -1;
 
 		if (unlikely(tx->rate_idx < 0))
 			return TX_DROP;
 	} else
-		info->control.alt_retry_rate_idx = -1;
+		info->control.retries[0].rate_idx = -1;
 
 	if (tx->sdata->bss_conf.use_cts_prot &&
 	    (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
@@ -521,7 +522,7 @@
 		 * frames.
 		 * TODO: The last fragment could still use multiple retry
 		 * rates. */
-		info->control.alt_retry_rate_idx = -1;
+		info->control.retries[0].rate_idx = -1;
 	}
 
 	/* Use CTS protection for unicast frames sent using extended rates if
@@ -551,7 +552,7 @@
 		int idx;
 
 		/* Do not use multiple retry rates when using RTS/CTS */
-		info->control.alt_retry_rate_idx = -1;
+		info->control.retries[0].rate_idx = -1;
 
 		/* Use min(data rate, max base rate) as CTS/RTS rate */
 		rate = &sband->bitrates[tx->rate_idx];


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/3] ath5k: implement multi-rate retry support and fix tx status reporting
  2008-09-30 11:24   ` [PATCH 2/3] mac80211: add multi-rate retry support Felix Fietkau
@ 2008-09-30 11:25     ` Felix Fietkau
  2008-09-30 18:46     ` [PATCH 2/3] mac80211: add multi-rate retry support Johannes Berg
  1 sibling, 0 replies; 6+ messages in thread
From: Felix Fietkau @ 2008-09-30 11:25 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

Clean up the tx status reporting, fix retry counters (short retries are
virtual collisions, not actual retries). Implement multi-rate retry
support.
This also fixes strong throughput fluctuations with rc80211_pid

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -583,6 +583,11 @@
 		}
 	}
 
+	/* set up multi-rate retry capabilities */
+	if (sc->ah->ah_version == AR5K_AR5212) {
+		hw->max_altrates = 3;
+		hw->max_altrate_tries = 15;
+	}
 
 	/* ready to process interrupts */
 	__clear_bit(ATH_STAT_INVALID, sc->status);
@@ -1149,7 +1154,9 @@
 	struct sk_buff *skb = bf->skb;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
-	int ret;
+	struct ieee80211_rate *rate;
+	unsigned int mrr_rate[3], mrr_tries[3];
+	int i, ret;
 
 	flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
 
@@ -1174,6 +1181,21 @@
 	if (ret)
 		goto err_unmap;
 
+	for (i = 0; i < 3; i++) {
+		rate = ieee80211_get_alt_retry_rate(sc->hw, info, i);
+		if (rate) {
+			mrr_rate[i] = rate->hw_value;
+			mrr_tries[i] = info->control.retries[i].limit;
+		} else {
+			mrr_rate[i] = 0;
+			mrr_tries[i] = 0;
+		}
+	}
+	ah->ah_setup_mrr_tx_desc(ah, ds,
+		mrr_rate[0], mrr_tries[0],
+		mrr_rate[1], mrr_tries[1],
+		mrr_rate[2], mrr_tries[2]);
+
 	ds->ds_link = 0;
 	ds->ds_data = bf->skbaddr;
 
@@ -1790,7 +1812,7 @@
 	struct ath5k_desc *ds;
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
-	int ret;
+	int i, ret;
 
 	spin_lock(&txq->lock);
 	list_for_each_entry_safe(bf, bf0, &txq->q, list) {
@@ -1812,7 +1834,23 @@
 		pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
 				PCI_DMA_TODEVICE);
 
-		info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
+		info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
+				ts.ts_rate[ts.ts_final_idx]);
+		info->status.retry_count = ts.ts_longretry;
+
+		for (i = 0; i < 4; i++) {
+			struct ieee80211_tx_altrate *r =
+				&info->status.retries[i];
+
+			if (ts.ts_rate[i]) {
+				r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
+				r->limit = ts.ts_retry[i];
+			} else {
+				r->rate_idx = -1;
+				r->limit = 0;
+			}
+		}
+
 		if (unlikely(ts.ts_status)) {
 			sc->ll_stats.dot11ACKFailureCount++;
 			if (ts.ts_status & AR5K_TXERR_XRETRY)
--- a/drivers/net/wireless/ath5k/desc.c
+++ b/drivers/net/wireless/ath5k/desc.c
@@ -318,6 +318,15 @@
 	return 0;
 }
 
+/* no mrr support for cards older than 5212 */
+static int
+ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc,
+	unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
+	u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3)
+{
+	return 0;
+}
+
 /*
  * Proccess the tx status descriptor on 5210/5211
  */
@@ -352,8 +361,10 @@
 		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
 	ts->ts_antenna = 1;
 	ts->ts_status = 0;
-	ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
+	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
 		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+	ts->ts_retry[0] = ts->ts_longretry;
+	ts->ts_final_idx = 0;
 
 	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
 		if (tx_status->tx_status_0 &
@@ -405,29 +416,43 @@
 		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
 	ts->ts_status = 0;
 
-	switch (AR5K_REG_MS(tx_status->tx_status_1,
-			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
-	case 0:
-		ts->ts_rate = tx_ctl->tx_control_3 &
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-		break;
+	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
+			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
+
+	/* The longretry counter has the number of un-acked retries
+	 * for the final rate. To get the total number of retries
+	 * we have to add the retry counters for the other rates
+	 * as well
+	 */
+	ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry;
+	switch (ts->ts_final_idx) {
+	case 3:
+		ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3,
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+
+		ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2,
+			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+		ts->ts_longretry += ts->ts_retry[2];
+		/* fall through */
+	case 2:
+		ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3,
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+
+		ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2,
+			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+		ts->ts_longretry += ts->ts_retry[1];
+		/* fall through */
 	case 1:
-		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
+		ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3,
 			AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
+
+		ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2,
 			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
-		break;
-	case 2:
-		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
-			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
-		break;
-	case 3:
-		ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
-			AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-		ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
-			AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
+		ts->ts_longretry += ts->ts_retry[0];
+		/* fall through */
+	case 0:
+		ts->ts_rate[0] = tx_ctl->tx_control_3 &
+			AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
 		break;
 	}
 
@@ -653,7 +678,7 @@
 	} else {
 		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
 		ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
-		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc;
+		ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr;
 		ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
 	}
 
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -418,7 +418,9 @@
 	u16	ts_seqnum;
 	u16	ts_tstamp;
 	u8	ts_status;
-	u8	ts_rate;
+	u8	ts_rate[4];
+	u8	ts_retry[4];
+	u8	ts_final_idx;
 	s8	ts_rssi;
 	u8	ts_shortretry;
 	u8	ts_longretry;


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] mac80211: free up 2 bytes in skb->cb
  2008-09-30 11:22 ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Felix Fietkau
  2008-09-30 11:24   ` [PATCH 2/3] mac80211: add multi-rate retry support Felix Fietkau
@ 2008-09-30 18:44   ` Johannes Berg
  1 sibling, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2008-09-30 18:44 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 6397 bytes --]

On Tue, 2008-09-30 at 13:22 +0200, Felix Fietkau wrote:
> Free up 2 bytes in skb->cb to be used for multi-rate retry.
> Move iv_len and icv_len initialization into key alloc.
> 
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>

The mac80211 changes look good to me, the driver stuff I cannot really
judge.

> 
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -337,8 +337,6 @@
>  			unsigned long jiffies;
>  			s8 rts_cts_rate_idx, alt_retry_rate_idx;
>  			u8 retry_limit;
> -			u8 icv_len;
> -			u8 iv_len;
>  		} control;
>  		struct {
>  			u64 ampdu_ack_map;
> @@ -635,6 +633,8 @@
>   */
>  struct ieee80211_key_conf {
>  	enum ieee80211_key_alg alg;
> +	u8 icv_len;
> +	u8 iv_len;
>  	u8 hw_key_idx;
>  	u8 flags;
>  	s8 keyidx;
> --- a/drivers/net/wireless/b43/xmit.c
> +++ b/drivers/net/wireless/b43/xmit.c
> @@ -252,7 +252,7 @@
>  		}
>  
>  		/* Hardware appends ICV. */
> -		plcp_fragment_len += info->control.icv_len;
> +		plcp_fragment_len += info->control.hw_key->icv_len;
>  
>  		key_idx = b43_kidx_to_fw(dev, key_idx);
>  		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
> @@ -260,7 +260,7 @@
>  		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
>  			   B43_TXH_MAC_KEYALG;
>  		wlhdr_len = ieee80211_hdrlen(fctl);
> -		iv_len = min((size_t) info->control.iv_len,
> +		iv_len = min((size_t) info->control.hw_key->iv_len,
>  			     ARRAY_SIZE(txhdr->iv));
>  		memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
>  	}
> --- a/drivers/net/wireless/b43legacy/xmit.c
> +++ b/drivers/net/wireless/b43legacy/xmit.c
> @@ -243,7 +243,7 @@
>  
>  		if (key->enabled) {
>  			/* Hardware appends ICV. */
> -			plcp_fragment_len += info->control.icv_len;
> +			plcp_fragment_len += info->control.hw_key->icv_len;
>  
>  			key_idx = b43legacy_kidx_to_fw(dev, key_idx);
>  			mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
> @@ -252,7 +252,7 @@
>  				   B43legacy_TX4_MAC_KEYALG_SHIFT) &
>  				   B43legacy_TX4_MAC_KEYALG;
>  			wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
> -			iv_len = min((size_t)info->control.iv_len,
> +			iv_len = min((size_t)info->control.hw_key->iv_len,
>  				     ARRAY_SIZE(txhdr->iv));
>  			memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
>  		} else {
> --- a/net/mac80211/wep.c
> +++ b/net/mac80211/wep.c
> @@ -313,9 +313,6 @@
>  {
>  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
>  
> -	info->control.iv_len = WEP_IV_LEN;
> -	info->control.icv_len = WEP_ICV_LEN;
> -
>  	if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
>  		if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
>  			return -1;
> --- a/net/mac80211/wpa.c
> +++ b/net/mac80211/wpa.c
> @@ -152,9 +152,6 @@
>  	int len, tail;
>  	u8 *pos;
>  
> -	info->control.icv_len = TKIP_ICV_LEN;
> -	info->control.iv_len = TKIP_IV_LEN;
> -
>  	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
>  	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
>  		/* hwaccel - with no need for preallocated room for IV/ICV */
> @@ -374,9 +371,6 @@
>  	u8 *pos, *pn;
>  	int i;
>  
> -	info->control.icv_len = CCMP_MIC_LEN;
> -	info->control.iv_len = CCMP_HDR_LEN;
> -
>  	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
>  	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
>  		/* hwaccel - with no need for preallocated room for CCMP "
> --- a/drivers/net/wireless/ath5k/base.c
> +++ b/drivers/net/wireless/ath5k/base.c
> @@ -1164,7 +1164,7 @@
>  
>  	if (info->control.hw_key) {
>  		keyidx = info->control.hw_key->hw_key_idx;
> -		pktlen += info->control.icv_len;
> +		pktlen += info->control.hw_key->icv_len;
>  	}
>  	ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
>  		ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
> --- a/drivers/net/wireless/ath9k/xmit.c
> +++ b/drivers/net/wireless/ath9k/xmit.c
> @@ -237,7 +237,7 @@
>  
>  	if (tx_info->control.hw_key) {
>  		txctl->keyix = tx_info->control.hw_key->hw_key_idx;
> -		txctl->frmlen += tx_info->control.icv_len;
> +		txctl->frmlen += tx_info->control.hw_key->icv_len;
>  
>  		if (tx_info->control.hw_key->alg == ALG_WEP)
>  			txctl->keytype = ATH9K_KEY_TYPE_WEP;
> --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
> @@ -56,10 +56,10 @@
>  	 * note that these lengths should only be added when
>  	 * mac80211 does not generate it.
>  	 */
> -	overhead += tx_info->control.icv_len;
> +	overhead += key->icv_len;
>  
>  	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
> -		overhead += tx_info->control.iv_len;
> +		overhead += key->iv_len;
>  
>  	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
>  		if (key->alg == ALG_TKIP)
> --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
> @@ -374,7 +374,7 @@
>  	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
>  	struct txentry_desc txdesc;
>  	struct skb_frame_desc *skbdesc;
> -	unsigned int iv_len = IEEE80211_SKB_CB(skb)->control.iv_len;
> +	unsigned int iv_len;
>  
>  	if (unlikely(rt2x00queue_full(queue)))
>  		return -EINVAL;
> @@ -410,8 +410,11 @@
>  	 * the frame so we can provide it to the driver seperately.
>  	 */
>  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
> -	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags))
> +	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) &&
> +		(IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) {
> +		iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
>  		rt2x00crypto_tx_remove_iv(skb, iv_len);
> +	}
>  
>  	/*
>  	 * It could be possible that the queue was corrupted and this
> --- a/net/mac80211/key.c
> +++ b/net/mac80211/key.c
> @@ -281,6 +281,20 @@
>  	key->conf.alg = alg;
>  	key->conf.keyidx = idx;
>  	key->conf.keylen = key_len;
> +	switch (alg) {
> +	case ALG_WEP:
> +		key->conf.iv_len = WEP_IV_LEN;
> +		key->conf.icv_len = WEP_ICV_LEN;
> +		break;
> +	case ALG_TKIP:
> +		key->conf.iv_len = TKIP_IV_LEN;
> +		key->conf.icv_len = TKIP_ICV_LEN;
> +		break;
> +	case ALG_CCMP:
> +		key->conf.iv_len = CCMP_HDR_LEN;
> +		key->conf.icv_len = CCMP_MIC_LEN;
> +		break;
> +	}
>  	memcpy(key->conf.key, key_data, key_len);
>  	INIT_LIST_HEAD(&key->list);
>  	INIT_LIST_HEAD(&key->todo);
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/3] mac80211: add multi-rate retry support
  2008-09-30 11:24   ` [PATCH 2/3] mac80211: add multi-rate retry support Felix Fietkau
  2008-09-30 11:25     ` [PATCH 3/3] ath5k: implement multi-rate retry support and fix tx status reporting Felix Fietkau
@ 2008-09-30 18:46     ` Johannes Berg
  1 sibling, 0 replies; 6+ messages in thread
From: Johannes Berg @ 2008-09-30 18:46 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: linux-wireless

[-- Attachment #1: Type: text/plain, Size: 457 bytes --]

On Tue, 2008-09-30 at 13:24 +0200, Felix Fietkau wrote:
> This patch adjusts the rate control API to allow multi-rate retry
> if supported by the driver. The ieee80211_hw struct specifies how
> many alternate rate selections the driver supports.
> 
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>

Would be good to look at all the drivers and see whether they currently
use the retry rate (set max to 1) or not (set max to 0) I think.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-09-30 18:46 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-30 11:20 [PATCH 0/3]: multi-rate retry support for mac80211/ath5k Felix Fietkau
2008-09-30 11:22 ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Felix Fietkau
2008-09-30 11:24   ` [PATCH 2/3] mac80211: add multi-rate retry support Felix Fietkau
2008-09-30 11:25     ` [PATCH 3/3] ath5k: implement multi-rate retry support and fix tx status reporting Felix Fietkau
2008-09-30 18:46     ` [PATCH 2/3] mac80211: add multi-rate retry support Johannes Berg
2008-09-30 18:44   ` [PATCH 1/3] mac80211: free up 2 bytes in skb->cb Johannes Berg

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).