Skip to contentSkip to conversation

Please pull 'upstream' branch of rt2x00

PATCH New Ivo van Doorn 1 participant 6 messages Dec 2, 2008 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

Hi John,

Here is a new batch of updates for rt2x00.

The first patch (rt2x00: Optimize IV/EIV handling) was send individually a few days ago, but it is probably easier if you pull it along with the rest of the patches during this merge.

Small warning which might be important:
The patch "Implement HW encryption (rt2500usb)" adds support for HW crypto but it does _not_ activate it. The module parameter "nohwcrypt" is set to 1 by default for now. This code has been sleeping in the rt2x00 experimental branch for quite some time now, and doesn't work completely. I hope to debug this further when I have time, but I am hoping that with the code in wireless-testing other people will take a look at it to see what might be going wrong.

Ivo

---
The following changes since commit ca072018d6425a55b3f0e6d8bd3e6217ee509065:
Winkler, Tomas (1):
iwlwifi: TX update chicken bits

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git/ upstream

Ivo van Doorn (5):
rt2x00: Optimize IV/EIV handling
rt2x00: Store retry limit values
rt2x00: Remove duplicate code
rt2x00: Implement HW encryption (rt2500usb)
rt2x00: Release rt2x00 2.2.3

 drivers/net/wireless/rt2x00/Kconfig        |    1 +
 drivers/net/wireless/rt2x00/rt2500usb.c    |  132 ++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2500usb.h    |    3 +
 drivers/net/wireless/rt2x00/rt2x00.h       |    9 ++-
 drivers/net/wireless/rt2x00/rt2x00config.c |   39 +++++----
 drivers/net/wireless/rt2x00/rt2x00crypto.c |   56 ++++++------
 drivers/net/wireless/rt2x00/rt2x00lib.h    |    6 ++
 drivers/net/wireless/rt2x00/rt2x00mac.c    |    2 -
 drivers/net/wireless/rt2x00/rt2x00queue.c  |   17 ++--
 drivers/net/wireless/rt2x00/rt2x00queue.h  |   12 +--
 drivers/net/wireless/rt2x00/rt61pci.c      |    8 +-
 drivers/net/wireless/rt2x00/rt73usb.c      |    8 +-
 12 files changed, 211 insertions(+), 82 deletions(-)
#1 lore raw

PATCH 1/5 rt2x00: Optimize IV/EIV handling

IV and EIV belong to eachother and don't require 2 seperate fields. Instead they can logically be merged into a single array with size 2.

With this approach we can simplify the code in rt2x00crypto.c by using a single memcpy() when copying the iv/eiv data. Additionally we can move some code out of if-statements because the if-statement would always be true.

---
 drivers/net/wireless/rt2x00/rt2x00crypto.c |   44 +++++++++-------------------
 drivers/net/wireless/rt2x00/rt2x00queue.h  |   12 ++-----
 drivers/net/wireless/rt2x00/rt61pci.c      |    8 ++--
 drivers/net/wireless/rt2x00/rt73usb.c      |    8 ++--
 4 files changed, 26 insertions(+), 46 deletions(-)
drivers/net/wireless/rt2x00/rt2x00crypto.c +14 -30
index 5a858e5..e0fc7c1 100644
@@ -78,10 +78,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
 		return;
 
 	/* Copy IV/EIV data */
-	if (iv_len >= 4)
-		memcpy(&skbdesc->iv, skb->data + header_length, 4);
-	if (iv_len >= 8)
-		memcpy(&skbdesc->eiv, skb->data + header_length + 4, 4);
+	memcpy(skbdesc->iv, skb->data + header_length, iv_len);
 
 	/* Move ieee80211 header */
 	memmove(skb->data + iv_len, skb->data, header_length);
@@ -98,7 +95,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 	unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
 	const unsigned int iv_len =
-	    ((!!(skbdesc->iv)) * 4) + ((!!(skbdesc->eiv)) * 4);
+	    ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
 
 	if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED))
 		return;
@@ -109,10 +106,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
 	memmove(skb->data, skb->data + iv_len, header_length);
 
 	/* Copy IV/EIV data */
-	if (iv_len >= 4)
-		memcpy(skb->data + header_length, &skbdesc->iv, 4);
-	if (iv_len >= 8)
-		memcpy(skb->data + header_length + 4, &skbdesc->eiv, 4);
+	memcpy(skb->data + header_length, skbdesc->iv, iv_len);
 
 	/* IV/EIV data has returned into the frame */
 	skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED;
@@ -172,17 +166,9 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
 		header_length);
 	transfer += header_length;
 
-	/* Copy IV data */
-	if (iv_len >= 4) {
-		memcpy(skb->data + transfer, &rxdesc->iv, 4);
-		transfer += 4;
-	}
-
-	/* Copy EIV data */
-	if (iv_len >= 8) {
-		memcpy(skb->data + transfer, &rxdesc->eiv, 4);
-		transfer += 4;
-	}
+	/* Copy IV/EIV data */
+	memcpy(skb->data + transfer, rxdesc->iv, iv_len);
+	transfer += iv_len;
 
 	/* Move payload */
 	if (align) {
@@ -198,16 +184,14 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
 	 */
 	transfer += payload_len;
 
-	/* Copy ICV data */
-	if (icv_len >= 4) {
-		memcpy(skb->data + transfer, &rxdesc->icv, 4);
-		/*
-		 * AES appends 8 bytes, we can't fill the upper
-		 * 4 bytes, but mac80211 doesn't care about what
-		 * we provide here anyway and strips it immediately.
-		 */
-		transfer += icv_len;
-	}
+	/*
+	 * Copy ICV data
+	 * AES appends 8 bytes, we can't fill the upper
+	 * 4 bytes, but mac80211 doesn't care about what
+	 * we provide here anyway and strips it immediately.
+	 */
+	memcpy(skb->data + transfer, &rxdesc->icv, 4);
+	transfer += icv_len;
 
 	/* IV/EIV/ICV has been inserted into frame */
 	rxdesc->size = transfer;
drivers/net/wireless/rt2x00/rt2x00queue.h +4 -8
index 2e99ab5..7889f91 100644
@@ -109,8 +109,7 @@ enum skb_frame_desc_flags {
  * @desc: Pointer to descriptor part of the frame.
  *	Note that this pointer could point to something outside
  *	of the scope of the skb->data pointer.
- * @iv: IV data used during encryption/decryption.
- * @eiv: EIV data used during encryption/decryption.
+ * @iv: IV/EIV data used during encryption/decryption.
  * @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
  * @entry: The entry to which this sk buffer belongs.
  */
@@ -123,8 +122,7 @@ struct skb_frame_desc {
 
 	void *desc;
 
-	__le32 iv;
-	__le32 eiv;
+	__le32 iv[2];
 
 	dma_addr_t skb_dma;
 
@@ -168,8 +166,7 @@ enum rxdone_entry_desc_flags {
  * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
  * @cipher: Cipher type used during decryption.
  * @cipher_status: Decryption status.
- * @iv: IV data used during decryption.
- * @eiv: EIV data used during decryption.
+ * @iv: IV/EIV data used during decryption.
  * @icv: ICV data used during decryption.
  */
 struct rxdone_entry_desc {
@@ -182,8 +179,7 @@ struct rxdone_entry_desc {
 	u8 cipher;
 	u8 cipher_status;
 
-	__le32 iv;
-	__le32 eiv;
+	__le32 iv[2];
 	__le32 icv;
 };
 
drivers/net/wireless/rt2x00/rt61pci.c +4 -4
index a66f80a..ce0fde4 100644
@@ -1778,8 +1778,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-		_rt2x00_desc_write(txd, 3, skbdesc->iv);
-		_rt2x00_desc_write(txd, 4, skbdesc->eiv);
+		_rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+		_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
 	}
 
 	rt2x00_desc_read(txd, 5, &word);
@@ -1949,8 +1949,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
 	}
 
 	if (rxdesc->cipher != CIPHER_NONE) {
-		_rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv);
-		_rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->eiv);
+		_rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
+		_rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
 		_rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
 
 		/*
drivers/net/wireless/rt2x00/rt73usb.c +4 -4
index 0c39384..79475a8 100644
@@ -1428,8 +1428,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
-		_rt2x00_desc_write(txd, 3, skbdesc->iv);
-		_rt2x00_desc_write(txd, 4, skbdesc->eiv);
+		_rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+		_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
 	}
 
 	rt2x00_desc_read(txd, 5, &word);
@@ -1618,8 +1618,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
 	}
 
 	if (rxdesc->cipher != CIPHER_NONE) {
-		_rt2x00_desc_read(rxd, 2, &rxdesc->iv);
-		_rt2x00_desc_read(rxd, 3, &rxdesc->eiv);
+		_rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+		_rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
 		_rt2x00_desc_read(rxd, 4, &rxdesc->icv);
 
 		/*
Signature · 1 line
1.5.6.1
#2 lore raw

PATCH 2/5 rt2x00: Store retry limit values

Store retry limit values in the rt2x00dev structure. This allows the removal of the FIXME where we assumed the long retry is only used when working with RTS frames.

Instead we should check the current retry limit values and decide if the required retry count for this frame is a long or short retry.

---
 drivers/net/wireless/rt2x00/rt2x00.h       |    6 ++++++
 drivers/net/wireless/rt2x00/rt2x00config.c |    2 ++
 drivers/net/wireless/rt2x00/rt2x00queue.c  |    9 +--------
 3 files changed, 9 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +6 -0
index 780ba73..e7ed56d 100644
@@ -803,6 +803,12 @@ struct rt2x00_dev {
 	u16 tx_power;
 
 	/*
+	 * Current retry values.
+	 */
+	u8 short_retry;
+	u8 long_retry;
+
+	/*
 	 * Rssi <-> Dbm offset
 	 */
 	u8 rssi_offset;
drivers/net/wireless/rt2x00/rt2x00config.c +2 -0
index 7c62ce1..b3bc8b4 100644
@@ -194,6 +194,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 
 	rt2x00dev->curr_band = conf->channel->band;
 	rt2x00dev->tx_power = conf->power_level;
+	rt2x00dev->short_retry = conf->short_frame_max_tx_count;
+	rt2x00dev->long_retry = conf->long_frame_max_tx_count;
 
 	rt2x00dev->rx_status.band = conf->channel->band;
 	rt2x00dev->rx_status.freq = conf->channel->center_freq;
drivers/net/wireless/rt2x00/rt2x00queue.c +1 -8
index b8de9d2..7f908a1 100644
@@ -231,14 +231,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	 * Determine retry information.
 	 */
 	txdesc->retry_limit = tx_info->control.rates[0].count - 1;
-	/*
-	 * XXX: If at this point we knew whether the HW is going to use
-	 *	the RETRY_MODE bit or the retry_limit (currently all
-	 *	use the RETRY_MODE bit) we could do something like b43
-	 *	does, set the RETRY_MODE bit when the RC algorithm is
-	 *	requesting more than the long retry limit.
-	 */
-	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+	if (txdesc->retry_limit >= rt2x00dev->long_retry)
 		__set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
 
 	/*
Signature · 1 line
1.5.6.1
#3 lore raw

PATCH 3/5 rt2x00: Remove duplicate code

Simplify rt2x00lib_config_antenna() by moving
duplicate code into a seperate static inlined
function.

---
 drivers/net/wireless/rt2x00/rt2x00config.c |   37 ++++++++++++++-------------
 1 files changed, 19 insertions(+), 18 deletions(-)
drivers/net/wireless/rt2x00/rt2x00config.c +19 -18
index b3bc8b4..e66fb31 100644
@@ -108,33 +108,34 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
 }
 
+static inline
+enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
+					    enum antenna default_ant)
+{
+	if (current_ant != ANTENNA_SW_DIVERSITY)
+		return current_ant;
+	return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
+}
+
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      struct antenna_setup *ant)
 {
+	struct antenna_setup *def = &rt2x00dev->default_ant;
+	struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
 	/*
 	 * Failsafe: Make sure we are not sending the
 	 * ANTENNA_SW_DIVERSITY state to the driver.
 	 * If that happes fallback to hardware default,
 	 * or our own default.
+	 * The calls to rt2x00lib_config_antenna_check()
+	 * might have caused that we restore back to the already
+	 * active setting. If that has happened we can quit.
 	 */
-	if (ant->rx == ANTENNA_SW_DIVERSITY) {
-		if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-			ant->rx = ANTENNA_B;
-		else
-			ant->rx = rt2x00dev->default_ant.rx;
-	}
-	if (ant->tx == ANTENNA_SW_DIVERSITY) {
-		if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-			ant->tx = ANTENNA_B;
-		else
-			ant->tx = rt2x00dev->default_ant.tx;
-	}
+	ant->rx = rt2x00lib_config_antenna_check(ant->rx, def->rx);
+	ant->tx = rt2x00lib_config_antenna_check(ant->tx, def->tx);
 
-	/*
-	 * Only reconfigure when something has changed.
-	 */
-	if (ant->rx == rt2x00dev->link.ant.active.rx &&
-	    ant->tx == rt2x00dev->link.ant.active.tx)
+	if (ant->rx == active->rx && ant->tx == active->tx)
 		return;
 
 	/*
@@ -154,7 +155,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 	rt2x00lib_reset_link_tuner(rt2x00dev);
 	rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
 
-	memcpy(&rt2x00dev->link.ant.active, ant, sizeof(*ant));
+	memcpy(active, ant, sizeof(*ant));
 
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
Signature · 1 line
1.5.6.1
#4 lore raw

PATCH 4/5 rt2x00: Implement HW encryption (rt2500usb)

rt2500usb supports hardware encryption. rt2500usb supports up to 4 shared and pairwise keys.

---
 drivers/net/wireless/rt2x00/Kconfig        |    1 +
 drivers/net/wireless/rt2x00/rt2500usb.c    |  132 ++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2500usb.h    |    3 +
 drivers/net/wireless/rt2x00/rt2x00.h       |    1 +
 drivers/net/wireless/rt2x00/rt2x00crypto.c |   12 +++
 drivers/net/wireless/rt2x00/rt2x00lib.h    |    6 ++
 drivers/net/wireless/rt2x00/rt2x00mac.c    |    2 -
 drivers/net/wireless/rt2x00/rt2x00queue.c  |    8 ++-
 8 files changed, 156 insertions(+), 9 deletions(-)
drivers/net/wireless/rt2x00/Kconfig +1 -0
index 95511ac..178b313 100644
@@ -57,6 +57,7 @@ config RT2500USB
 	tristate "Ralink rt2500 (USB) support"
 	depends on USB
 	select RT2X00_LIB_USB
+	select RT2X00_LIB_CRYPTO
 	---help---
 	  This adds support for rt2500 wireless chipset family.
 	  Supported chips: RT2571 & RT2572.
drivers/net/wireless/rt2x00/rt2500usb.c +127 -5

204 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2500usb.h +3 -0
index dbb5d68..4347dfd 100644
@@ -447,6 +447,9 @@
 #define SEC_CSR30			0x04bc
 #define SEC_CSR31			0x04be
 
+#define KEY_ENTRY(__idx) \
+	( SEC_CSR0 + ((__idx) * 16) )
+
 /*
  * PHY control registers.
  */
drivers/net/wireless/rt2x00/rt2x00.h +1 -0
index e7ed56d..03d34bb 100644
@@ -653,6 +653,7 @@ enum rt2x00_flags {
 	CONFIG_EXTERNAL_LNA_BG,
 	CONFIG_DOUBLE_ANTENNA,
 	CONFIG_DISABLE_LINK_TUNING,
+	CONFIG_CRYPTO_COPY_IV,
 };
 
 /*
drivers/net/wireless/rt2x00/rt2x00crypto.c +12 -0
index e0fc7c1..c6709b3 100644
@@ -69,6 +69,18 @@ unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
 	return overhead;
 }
 
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len)
+{
+	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+	unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
+
+	if (unlikely(!iv_len))
+		return;
+
+	/* Copy IV/EIV data */
+	memcpy(skbdesc->iv, skb->data + header_length, iv_len);
+}
+
 void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
 {
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
drivers/net/wireless/rt2x00/rt2x00lib.h +6 -0
index 9399733..1e18937 100644
@@ -219,6 +219,7 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
 enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
 unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info);
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len);
 void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len);
 void rt2x00crypto_tx_insert_iv(struct sk_buff *skb);
 void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
@@ -235,6 +236,11 @@ static inline unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx
 	return 0;
 }
 
+static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
+					   unsigned int iv_len)
+{
+}
+
 static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
 					     unsigned int iv_len)
 {
drivers/net/wireless/rt2x00/rt2x00mac.c +0 -2
index 4c03957..fa91ca5 100644
@@ -79,10 +79,8 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
 	 * RTS/CTS frame should use the length of the frame plus any
 	 * encryption overhead that will be added by the hardware.
 	 */
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
 	if (!frag_skb->do_not_encrypt)
 		data_length += rt2x00crypto_tx_overhead(tx_info);
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
 	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 		ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
drivers/net/wireless/rt2x00/rt2x00queue.c +6 -2
index 7f908a1..e4a1dbe 100644
@@ -420,8 +420,12 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 	 * 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))
-		rt2x00crypto_tx_remove_iv(skb, iv_len);
+	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
+		if (test_bit(CONFIG_CRYPTO_COPY_IV, &queue->rt2x00dev->flags))
+			rt2x00crypto_tx_copy_iv(skb, iv_len);
+		else
+			rt2x00crypto_tx_remove_iv(skb, iv_len);
+	}
 
 	/*
 	 * It could be possible that the queue was corrupted and this
Signature · 1 line
1.5.6.1
#5 lore raw

PATCH 5/5 rt2x00: Release rt2x00 2.2.3

---
 drivers/net/wireless/rt2x00/rt2x00.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
index 03d34bb..39ecf3b 100644
@@ -44,7 +44,7 @@
 /*
  * Module information.
  */
-#define DRV_VERSION	"2.2.2"
+#define DRV_VERSION	"2.2.3"
 #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
 
 /*
Signature · 1 line
1.5.6.1