linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Please pull 'upstream' branch of rt2x00
@ 2008-12-02 17:19 Ivo van Doorn
  2008-12-02 17:19 ` [PATCH 1/5] rt2x00: Optimize IV/EIV handling Ivo van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:19 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel

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

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

* [PATCH 1/5] rt2x00: Optimize IV/EIV handling
  2008-12-02 17:19 Please pull 'upstream' branch of rt2x00 Ivo van Doorn
@ 2008-12-02 17:19 ` Ivo van Doorn
  2008-12-02 17:20   ` [PATCH 2/5] rt2x00: Store retry limit values Ivo van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:19 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel

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.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 5a858e5..e0fc7c1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -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;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 2e99ab5..7889f91 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -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;
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index a66f80a..ce0fde4 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -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);
 
 		/*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 0c39384..79475a8 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -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);
 
 		/*
-- 
1.5.6.1


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

* [PATCH 2/5] rt2x00: Store retry limit values
  2008-12-02 17:19 ` [PATCH 1/5] rt2x00: Optimize IV/EIV handling Ivo van Doorn
@ 2008-12-02 17:20   ` Ivo van Doorn
  2008-12-02 17:20     ` [PATCH 3/5] rt2x00: Remove duplicate code Ivo van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel

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.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 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(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 780ba73..e7ed56d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 7c62ce1..b3bc8b4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -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;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index b8de9d2..7f908a1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -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);
 
 	/*
-- 
1.5.6.1


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

* [PATCH 3/5] rt2x00: Remove duplicate code
  2008-12-02 17:20   ` [PATCH 2/5] rt2x00: Store retry limit values Ivo van Doorn
@ 2008-12-02 17:20     ` Ivo van Doorn
  2008-12-02 17:20       ` [PATCH 4/5] rt2x00: Implement HW encryption (rt2500usb) Ivo van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel

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

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00config.c |   37 ++++++++++++++-------------
 1 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index b3bc8b4..e66fb31 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -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);
-- 
1.5.6.1


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

* [PATCH 4/5] rt2x00: Implement HW encryption (rt2500usb)
  2008-12-02 17:20     ` [PATCH 3/5] rt2x00: Remove duplicate code Ivo van Doorn
@ 2008-12-02 17:20       ` Ivo van Doorn
  2008-12-02 17:20         ` [PATCH 5/5] rt2x00: Release rt2x00 2.2.3 Ivo van Doorn
  0 siblings, 1 reply; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel

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

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 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(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 95511ac..178b313 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 10cb46a..5f65b7e 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -36,6 +36,13 @@
 #include "rt2500usb.h"
 
 /*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 1;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
  * Register access.
  * All access to the CSR registers will go through the methods
  * rt2500usb_register_read and rt2500usb_register_write.
@@ -323,6 +330,82 @@ static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
 /*
  * Configuration handlers.
  */
+
+/*
+ * rt2500usb does not differentiate between shared and pairwise
+ * keys, so we should use the same function for both key types.
+ */
+static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
+				struct rt2x00lib_crypto *crypto,
+				struct ieee80211_key_conf *key)
+{
+	int timeout;
+	u32 mask;
+	u16 reg;
+
+	if (crypto->cmd == SET_KEY) {
+		/*
+		 * Pairwise key will always be entry 0, but this
+		 * could collide with a shared key on the same
+		 * position...
+		 */
+		mask = TXRX_CSR0_KEY_ID.bit_mask;
+
+		rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+		reg &= mask;
+
+		if (reg && reg == mask)
+			return -ENOSPC;
+
+		reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+
+		key->hw_key_idx += reg ? ffz(reg) : 0;
+
+		/*
+		 * The encryption key doesn't fit within the CSR cache,
+		 * this means we should allocate it seperately and use
+		 * rt2x00usb_vendor_request() to send the key to the hardware.
+		 */
+		reg = KEY_ENTRY(key->hw_key_idx);
+		timeout = REGISTER_TIMEOUT32(sizeof(crypto->key));
+		rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+						    USB_VENDOR_REQUEST_OUT, reg,
+						    crypto->key,
+						    sizeof(crypto->key),
+						    timeout);
+
+		/*
+		 * The driver does not support the IV/EIV generation
+		 * in hardware. However it doesn't support the IV/EIV
+		 * inside the ieee80211 frame either, but requires it
+		 * to be provided seperately for the descriptor.
+		 * rt2x00lib will cut the IV/EIV data out of all frames
+		 * given to us by mac80211, but we must tell mac80211
+		 * to generate the IV/EIV data.
+		 */
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+	}
+
+	/*
+	 * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
+	 * a particular key is valid.
+	 */
+	rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+	rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
+	rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
+
+	mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+	if (crypto->cmd == SET_KEY)
+		mask |= 1 << key->hw_key_idx;
+	else if (crypto->cmd == DISABLE_KEY)
+		mask &= ~(1 << key->hw_key_idx);
+	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, mask);
+	rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+	return 0;
+}
+
 static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
 				    const unsigned int filter_flags)
 {
@@ -844,7 +927,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
 
 	rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0xff);
+	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
 	rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
@@ -1066,7 +1149,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	 * Start writing the descriptor words.
 	 */
 	rt2x00_desc_read(txd, 1, &word);
-	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
 	rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
 	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
 	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1079,6 +1162,11 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
 	rt2x00_desc_write(txd, 2, word);
 
+	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+		_rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+		_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
+	}
+
 	rt2x00_desc_read(txd, 0, &word);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
 	rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1093,7 +1181,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
-	rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
+	rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher);
+	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
 	rt2x00_desc_write(txd, 0, word);
 }
 
@@ -1204,6 +1293,7 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 static void rt2500usb_fill_rxdone(struct queue_entry *entry,
 				  struct rxdone_entry_desc *rxdesc)
 {
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 	__le32 *rxd =
@@ -1231,6 +1321,31 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
 	if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
 		rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
 
+	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+		rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
+		if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
+			rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
+	}
+
+	if (rxdesc->cipher != CIPHER_NONE) {
+		_rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+		_rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+		/* ICV is located at the end of frame */
+
+		/*
+		 * Hardware has stripped IV/EIV data from 802.11 frame during
+		 * decryption. It has provided the data seperately but rt2x00lib
+		 * should decide if it should be reinserted.
+		 */
+		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+		if (rxdesc->cipher != CIPHER_TKIP)
+			rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+			rxdesc->flags |= RX_FLAG_DECRYPTED;
+		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+	}
+
 	/*
 	 * Obtain the status about this packet.
 	 * When frame was received with an OFDM bitrate,
@@ -1238,8 +1353,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
 	 * a CCK bitrate the signal is the rate in 100kbit/s.
 	 */
 	rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-	rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
-	    entry->queue->rt2x00dev->rssi_offset;
+	rxdesc->rssi =
+	    rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset;
 	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 
 	if (rt2x00_get_field32(word0, RXD_W0_OFDM))
@@ -1729,6 +1844,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+	if (!modparam_nohwcrypt) {
+		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
+		__set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags);
+	}
 	__set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags);
 
 	/*
@@ -1748,6 +1867,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
 	.config			= rt2x00mac_config,
 	.config_interface	= rt2x00mac_config_interface,
 	.configure_filter	= rt2x00mac_configure_filter,
+	.set_key		= rt2x00mac_set_key,
 	.get_stats		= rt2x00mac_get_stats,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt2x00mac_conf_tx,
@@ -1769,6 +1889,8 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
 	.kick_tx_queue		= rt2500usb_kick_tx_queue,
 	.fill_rxdone		= rt2500usb_fill_rxdone,
+	.config_shared_key	= rt2500usb_config_key,
+	.config_pairwise_key	= rt2500usb_config_key,
 	.config_filter		= rt2500usb_config_filter,
 	.config_intf		= rt2500usb_config_intf,
 	.config_erp		= rt2500usb_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index dbb5d68..4347dfd 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -447,6 +447,9 @@
 #define SEC_CSR30			0x04bc
 #define SEC_CSR31			0x04be
 
+#define KEY_ENTRY(__idx) \
+	( SEC_CSR0 + ((__idx) * 16) )
+
 /*
  * PHY control registers.
  */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index e7ed56d..03d34bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -653,6 +653,7 @@ enum rt2x00_flags {
 	CONFIG_EXTERNAL_LNA_BG,
 	CONFIG_DOUBLE_ANTENNA,
 	CONFIG_DISABLE_LINK_TUNING,
+	CONFIG_CRYPTO_COPY_IV,
 };
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index e0fc7c1..c6709b3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -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);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 9399733..1e18937 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -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)
 {
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4c03957..fa91ca5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -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,
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 7f908a1..e4a1dbe 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -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
-- 
1.5.6.1


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

* [PATCH 5/5] rt2x00: Release rt2x00 2.2.3
  2008-12-02 17:20       ` [PATCH 4/5] rt2x00: Implement HW encryption (rt2500usb) Ivo van Doorn
@ 2008-12-02 17:20         ` Ivo van Doorn
  0 siblings, 0 replies; 6+ messages in thread
From: Ivo van Doorn @ 2008-12-02 17:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, rt2400-devel


Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 03d34bb..39ecf3b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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"
 
 /*
-- 
1.5.6.1


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

end of thread, other threads:[~2008-12-02 17:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-02 17:19 Please pull 'upstream' branch of rt2x00 Ivo van Doorn
2008-12-02 17:19 ` [PATCH 1/5] rt2x00: Optimize IV/EIV handling Ivo van Doorn
2008-12-02 17:20   ` [PATCH 2/5] rt2x00: Store retry limit values Ivo van Doorn
2008-12-02 17:20     ` [PATCH 3/5] rt2x00: Remove duplicate code Ivo van Doorn
2008-12-02 17:20       ` [PATCH 4/5] rt2x00: Implement HW encryption (rt2500usb) Ivo van Doorn
2008-12-02 17:20         ` [PATCH 5/5] rt2x00: Release rt2x00 2.2.3 Ivo van Doorn

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