Skip to contentSkip to conversation

Please pull 'upstream' branch of rt2x00

PATCH In review Ivo van Doorn 5 participants 13 messages Aug 4, 2008 – Aug 5, 2008 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

Hi John,

Only 5 patches, but they do bump rt2x00 to a new version: 2.2.0 This series will add HW crypto support to rt2x00, by default it has been enabled for rt61pci and rt73usb.

rt2500usb has also been created, but currently does not work since it requires different handling then rt61pci and rt73usb. Because I am focussing on different areas in rt2x00 now, it will take some time before I get back to rt2500usb HW crypto (if there are any volunteers to take a shot at rt2500usb HW crypto, they are welcome).

rt2500pci supports HW crypto as well, but I won't implement it due to the way it has to be enabled. It comes down to the fact that during TX the key has to be provided, and after the encryption an interupt will be raised after which the frame can be kicked to the air. In the RX path the same happens, including that after RX the key has to be provided as well. This will cause the number of IRQ events to double during HW crypto, and several changes are required in mac80211 to make it possible. Because of that I see no point in doing anything with it.

Ivo

----
The following changes since commit 2471b779e2f93d76bd4c041e4a8f5a27c859d7ce:
John W. Linville (1):
Revert "mac80211: add direct probe before association"

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: Implement HW encryption
rt2x00: Implement HW encryption (rt61pci)
rt2x00: Implement HW encryption (rt73usb)
rt2x00: Gather channel information in structure
rt2x00: Release rt2x00 2.2.0

 drivers/net/wireless/rt2x00/Kconfig        |    6 +
 drivers/net/wireless/rt2x00/Makefile       |    1 +
 drivers/net/wireless/rt2x00/rt2400pci.c    |   40 ++--
 drivers/net/wireless/rt2x00/rt2400pci.h    |   22 +--
 drivers/net/wireless/rt2x00/rt2500pci.c    |   39 +++--
 drivers/net/wireless/rt2x00/rt2500pci.h    |   17 +-
 drivers/net/wireless/rt2x00/rt2500usb.c    |   39 +++--
 drivers/net/wireless/rt2x00/rt2500usb.h    |   17 +-
 drivers/net/wireless/rt2x00/rt2x00.h       |   64 +++++-
 drivers/net/wireless/rt2x00/rt2x00config.c |    4 +
 drivers/net/wireless/rt2x00/rt2x00crypto.c |  215 +++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00debug.c  |   97 +++++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c    |   48 +++--
 drivers/net/wireless/rt2x00/rt2x00lib.h    |   47 ++++
 drivers/net/wireless/rt2x00/rt2x00mac.c    |  110 +++++++++-
 drivers/net/wireless/rt2x00/rt2x00queue.c  |   81 +++++++-
 drivers/net/wireless/rt2x00/rt2x00queue.h  |   73 ++++++-
 drivers/net/wireless/rt2x00/rt2x00reg.h    |   19 ++-
 drivers/net/wireless/rt2x00/rt61pci.c      |  298 ++++++++++++++++++++++++--
 drivers/net/wireless/rt2x00/rt61pci.h      |   38 ++--
 drivers/net/wireless/rt2x00/rt73usb.c      |  314 +++++++++++++++++++++++++---
 drivers/net/wireless/rt2x00/rt73usb.h      |   38 ++--
 22 files changed, 1418 insertions(+), 209 deletions(-)
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00crypto.c
#1 lore raw

PATCH 1/5 rt2x00: Implement HW encryption

Various rt2x00 devices support hardware encryption.

Most of them require the IV/EIV to be generated by mac80211, but require it to be provided seperately instead of within the frame itself. This means that rt2x00lib should extract the data from the frame and place it in the frame descriptor. During RX the IV/EIV is provided in the descriptor by the hardware which means that it should be inserted into the frame by rt2x00lib.

---
 drivers/net/wireless/rt2x00/Kconfig        |    4 +
 drivers/net/wireless/rt2x00/Makefile       |    1 +
 drivers/net/wireless/rt2x00/rt2x00.h       |   39 +++++-
 drivers/net/wireless/rt2x00/rt2x00crypto.c |  215 ++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00debug.c  |   97 +++++++++++++
 drivers/net/wireless/rt2x00/rt2x00dev.c    |   30 ++++-
 drivers/net/wireless/rt2x00/rt2x00lib.h    |   47 ++++++
 drivers/net/wireless/rt2x00/rt2x00mac.c    |  110 +++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00queue.c  |   81 ++++++++++-
 drivers/net/wireless/rt2x00/rt2x00queue.h  |   73 +++++++++-
 drivers/net/wireless/rt2x00/rt2x00reg.h    |   19 +++-
 11 files changed, 686 insertions(+), 30 deletions(-)
 create mode 100644 drivers/net/wireless/rt2x00/rt2x00crypto.c
drivers/net/wireless/rt2x00/Kconfig +4 -0
index d485a86..2f60e17 100644
@@ -33,6 +33,10 @@ config RT2X00_LIB_FIRMWARE
 	depends on RT2X00_LIB
 	select FW_LOADER
 
+config RT2X00_LIB_CRYPTO
+	boolean
+	depends on RT2X00_LIB
+
 config RT2X00_LIB_RFKILL
 	boolean
 	depends on RT2X00_LIB
drivers/net/wireless/rt2x00/Makefile +1 -0
index 1087dbc..917cb4f 100644
@@ -3,6 +3,7 @@ rt2x00lib-y				+= rt2x00mac.o
 rt2x00lib-y				+= rt2x00config.o
 rt2x00lib-y				+= rt2x00queue.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)	+= rt2x00debug.o
+rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)	+= rt2x00crypto.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL)	+= rt2x00rfkill.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
drivers/net/wireless/rt2x00/rt2x00.h +37 -2
index 8b10ea4..ae5c090 100644
@@ -452,6 +452,23 @@ struct rt2x00lib_erp {
 };
 
 /*
+ * Configuration structure for hardware encryption.
+ */
+struct rt2x00lib_crypto {
+	enum cipher cipher;
+
+	enum set_key_cmd cmd;
+	const u8 *address;
+
+	u32 bssidx;
+	u32 aid;
+
+	u8 key[16];
+	u8 tx_mic[8];
+	u8 rx_mic[8];
+};
+
+/*
  * Configuration structure wrapper around the
  * rt2x00 interface configuration handler.
  */
@@ -547,6 +564,12 @@ struct rt2x00lib_ops {
 	/*
 	 * Configuration handlers.
 	 */
+	int (*config_shared_key) (struct rt2x00_dev *rt2x00dev,
+				  struct rt2x00lib_crypto *crypto,
+				  struct ieee80211_key_conf *key);
+	int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev,
+				    struct rt2x00lib_crypto *crypto,
+				    struct ieee80211_key_conf *key);
 	void (*config_filter) (struct rt2x00_dev *rt2x00dev,
 			       const unsigned int filter_flags);
 	void (*config_intf) (struct rt2x00_dev *rt2x00dev,
@@ -609,7 +632,7 @@ enum rt2x00_flags {
 	DEVICE_DIRTY_CONFIG,
 
 	/*
-	 * Driver features
+	 * Driver requirements
 	 */
 	DRIVER_REQUIRE_FIRMWARE,
 	DRIVER_REQUIRE_BEACON_GUARD,
@@ -618,9 +641,14 @@ enum rt2x00_flags {
 	DRIVER_REQUIRE_DMA,
 
 	/*
-	 * Driver configuration
+	 * Driver features
 	 */
 	CONFIG_SUPPORT_HW_BUTTON,
+	CONFIG_SUPPORT_HW_CRYPTO,
+
+	/*
+	 * Driver configuration
+	 */
 	CONFIG_FRAME_TYPE,
 	CONFIG_RF_SEQUENCE,
 	CONFIG_EXTERNAL_LNA_A,
@@ -966,6 +994,13 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 				unsigned int changed_flags,
 				unsigned int *total_flags,
 				int mc_count, struct dev_addr_list *mc_list);
+#ifdef CONFIG_RT2X00_LIB_CRYPTO
+int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		      const u8 *local_address, const u8 *address,
+		      struct ieee80211_key_conf *key);
+#else
+#define rt2x00mac_set_key	NULL
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
 int rt2x00mac_get_stats(struct ieee80211_hw *hw,
 			struct ieee80211_low_level_stats *stats);
 int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
drivers/net/wireless/rt2x00/rt2x00crypto.c new file +215 -0

215 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00debug.c +97 -0

145 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00dev.c +26 -4
index f42283a..1829522 100644
@@ -508,6 +508,15 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
 
 	/*
+	 * If the IV/EIV data was stripped from the frame before it was
+	 * passed to the hardware, we should now reinsert it again because
+	 * mac80211 will expect the the same data to be present it the
+	 * frame as it was passed to us.
+	 */
+	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+		rt2x00crypto_tx_insert_iv(entry->skb);
+
+	/*
 	 * Send frame to debugfs immediately, after this call is completed
 	 * we are going to overwrite the skb->cb array.
 	 */
@@ -585,7 +594,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_hdr *hdr;
 	const struct rt2x00_rate *rate;
-	unsigned int header_size;
+	unsigned int header_length;
 	unsigned int align;
 	unsigned int i;
 	int idx = -1;
@@ -613,10 +622,19 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 	 * The data behind the ieee80211 header must be
 	 * aligned on a 4 byte boundary.
 	 */
-	header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
-	align = ((unsigned long)(entry->skb->data + header_size)) & 3;
+	header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+	align = ((unsigned long)(entry->skb->data + header_length)) & 3;
 
-	if (align) {
+	/*
+	 * Hardware might have stripped the IV/EIV/ICV data,
+	 * in that case it is possible that the data was
+	 * provided seperately (through hardware descriptor)
+	 * in which case we should reinsert the data into the frame.
+	 */
+	if ((rxdesc.flags & RX_FLAG_IV_STRIPPED)) {
+		rt2x00crypto_rx_insert_iv(entry->skb, align,
+					  header_length, &rxdesc);
+	} else if (align) {
 		skb_push(entry->skb, align);
 		/* Move entire frame in 1 command */
 		memmove(entry->skb->data, entry->skb->data + align,
@@ -657,6 +675,10 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 	    (rxdesc.dev_flags & RXDONE_MY_BSS))
 		rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi);
 
+	rt2x00debug_update_crypto(rt2x00dev,
+				  rxdesc.cipher,
+				  rxdesc.cipher_status);
+
 	rt2x00dev->link.qual.rx_success++;
 
 	rx_status->mactime = rxdesc.timestamp;
drivers/net/wireless/rt2x00/rt2x00lib.h +47 -0

62 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00mac.c +102 -8

150 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00queue.c +73 -8

133 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00queue.h +66 -7

150 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt2x00reg.h +18 -1
index 7e88ce5..6d5acf9 100644
@@ -27,6 +27,16 @@
 #define RT2X00REG_H
 
 /*
+ * RX crypto status
+ */
+enum rx_crypto {
+	RX_CRYPTO_SUCCESS = 0,
+	RX_CRYPTO_FAIL_ICV = 1,
+	RX_CRYPTO_FAIL_MIC = 2,
+	RX_CRYPTO_FAIL_KEY = 3,
+};
+
+/*
  * Antenna values
  */
 enum antenna {
@@ -104,7 +114,14 @@ enum cipher {
  */
 	CIPHER_CKIP64 = 5,
 	CIPHER_CKIP128 = 6,
-	CIPHER_TKIP_NO_MIC = 7,
+	CIPHER_TKIP_NO_MIC = 7, /* Don't send to device */
+
+/*
+ * Max cipher type.
+ * Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128
+ * are excluded due to limitations in mac80211.
+ */
+	CIPHER_MAX = 4,
 };
 
 /*
Signature · 1 line
1.5.6.1
#2 lore raw

PATCH 2/5 rt2x00: Implement HW encryption (rt61pci)

rt61pci supports hardware encryption.
rt61pci supports up to 4 shared keys and up to 64 pairwise keys.

---
 drivers/net/wireless/rt2x00/Kconfig   |    1 +
 drivers/net/wireless/rt2x00/rt61pci.c |  256 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt61pci.h |   21 +++-
 3 files changed, 270 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/Kconfig +1 -0
index 2f60e17..f333f61 100644
@@ -107,6 +107,7 @@ config RT61PCI
 	depends on PCI
 	select RT2X00_LIB_PCI
 	select RT2X00_LIB_FIRMWARE
+	select RT2X00_LIB_CRYPTO
 	select CRC_ITU_T
 	select EEPROM_93CX6
 	---help---
drivers/net/wireless/rt2x00/rt61pci.c +250 -6

325 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt61pci.h +19 -2
index 1004d5b..6d591ce 100644
@@ -134,6 +134,16 @@
 #define PAIRWISE_KEY_TABLE_BASE		0x1200
 #define PAIRWISE_TA_TABLE_BASE		0x1a00
 
+#define SHARED_KEY_ENTRY(__idx) \
+	( SHARED_KEY_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+	( PAIRWISE_KEY_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+	( PAIRWISE_TA_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
 struct hw_key_entry {
 	u8 key[16];
 	u8 tx_mic[8];
@@ -142,7 +152,8 @@ struct hw_key_entry {
 
 struct hw_pairwise_ta_entry {
 	u8 address[6];
-	u8 reserved[2];
+	u8 cipher;
+	u8 reserved;
 } __attribute__ ((packed));
 
 /*
@@ -662,6 +673,10 @@ struct hw_pairwise_ta_entry {
  * SEC_CSR4: Pairwise key table lookup control.
  */
 #define SEC_CSR4			0x30b0
+#define SEC_CSR4_ENABLE_BSS0		FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1		FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2		FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3		FIELD32(0x00000008)
 
 /*
  * SEC_CSR5: shared key table security mode register.
@@ -1428,8 +1443,10 @@ struct hw_pairwise_ta_entry {
 
 /*
  * Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
  */
-#define RXD_W4_RESERVED			FIELD32(0xffffffff)
+#define RXD_W4_ICV			FIELD32(0xffffffff)
 
 /*
  * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
Signature · 1 line
1.5.6.1
#3 lore raw

PATCH 3/5 rt2x00: Implement HW encryption (rt73usb)

rt73usb supports hardware encryption.
rt73usb supports up to 4 shared keys and up to 64 pairwise keys.

---
 drivers/net/wireless/rt2x00/Kconfig   |    1 +
 drivers/net/wireless/rt2x00/rt73usb.c |  271 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt73usb.h |   21 +++-
 3 files changed, 285 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/Kconfig +1 -0
index f333f61..11f590d 100644
@@ -156,6 +156,7 @@ config RT73USB
 	depends on USB
 	select RT2X00_LIB_USB
 	select RT2X00_LIB_FIRMWARE
+	select RT2X00_LIB_CRYPTO
 	select CRC_ITU_T
 	---help---
 	  This adds support for rt2501 wireless chipset family.
drivers/net/wireless/rt2x00/rt73usb.c +265 -6

341 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt73usb.h +19 -2
index 1484935..91e04d3 100644
@@ -92,6 +92,16 @@
 #define PAIRWISE_KEY_TABLE_BASE		0x1200
 #define PAIRWISE_TA_TABLE_BASE		0x1a00
 
+#define SHARED_KEY_ENTRY(__idx) \
+	( SHARED_KEY_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+	( PAIRWISE_KEY_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+	( PAIRWISE_TA_TABLE_BASE + \
+		((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
 struct hw_key_entry {
 	u8 key[16];
 	u8 tx_mic[8];
@@ -100,7 +110,8 @@ struct hw_key_entry {
 
 struct hw_pairwise_ta_entry {
 	u8 address[6];
-	u8 reserved[2];
+	u8 cipher;
+	u8 reserved;
 } __attribute__ ((packed));
 
 /*
@@ -563,6 +574,10 @@ struct hw_pairwise_ta_entry {
  * SEC_CSR4: Pairwise key table lookup control.
  */
 #define SEC_CSR4			0x30b0
+#define SEC_CSR4_ENABLE_BSS0		FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1		FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2		FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3		FIELD32(0x00000008)
 
 /*
  * SEC_CSR5: shared key table security mode register.
@@ -1010,8 +1025,10 @@ struct hw_pairwise_ta_entry {
 
 /*
  * Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
  */
-#define RXD_W4_RESERVED			FIELD32(0xffffffff)
+#define RXD_W4_ICV			FIELD32(0xffffffff)
 
 /*
  * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
Signature · 1 line
1.5.6.1
#4 lore raw

PATCH 4/5 rt2x00: Gather channel information in structure

Channel information which is read from EEPROM should be read into an array containing per-channel information. This removes the requirement of multiple arrays and makes the channel handling a bit cleaner and easier to expand.

---
 drivers/net/wireless/rt2x00/rt2400pci.c    |   40 +++++++++++++++----------
 drivers/net/wireless/rt2x00/rt2400pci.h    |   22 +++++---------
 drivers/net/wireless/rt2x00/rt2500pci.c    |   39 +++++++++++++++++--------
 drivers/net/wireless/rt2x00/rt2500pci.h    |   17 +++--------
 drivers/net/wireless/rt2x00/rt2500usb.c    |   39 +++++++++++++++++--------
 drivers/net/wireless/rt2x00/rt2500usb.h    |   17 +++--------
 drivers/net/wireless/rt2x00/rt2x00.h       |   23 ++++++++++-----
 drivers/net/wireless/rt2x00/rt2x00config.c |    4 ++
 drivers/net/wireless/rt2x00/rt2x00dev.c    |   18 ++---------
 drivers/net/wireless/rt2x00/rt61pci.c      |   42 ++++++++++++++++-----------
 drivers/net/wireless/rt2x00/rt61pci.h      |   17 +++--------
 drivers/net/wireless/rt2x00/rt73usb.c      |   43 +++++++++++++++------------
 drivers/net/wireless/rt2x00/rt73usb.h      |   17 +++--------
 13 files changed, 176 insertions(+), 162 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +24 -16
index 4c0538d..0107cec 100644
@@ -1404,7 +1404,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
  * RF value list for RF2420 & RF2421
  * Supports: 2.4 GHz
  */
-static const struct rf_channel rf_vals_bg[] = {
+static const struct rf_channel rf_vals_b[] = {
 	{ 1,  0x00022058, 0x000c1fda, 0x00000101, 0 },
 	{ 2,  0x00022058, 0x000c1fee, 0x00000101, 0 },
 	{ 3,  0x00022058, 0x000c2002, 0x00000101, 0 },
@@ -1421,10 +1421,11 @@ static const struct rf_channel rf_vals_bg[] = {
 	{ 14, 0x00022058, 0x000c20fa, 0x00000101, 0 },
 };
 
-static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	u8 *txpower;
+	struct channel_info *info;
+	char *tx_power;
 	unsigned int i;
 
 	/*
@@ -1440,23 +1441,28 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 						   EEPROM_MAC_ADDR_0));
 
 	/*
-	 * Convert tx_power array in eeprom.
-	 */
-	txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
-	/*
 	 * Initialize hw_mode information.
 	 */
 	spec->supported_bands = SUPPORT_BAND_2GHZ;
 	spec->supported_rates = SUPPORT_RATE_CCK;
-	spec->tx_power_a = NULL;
-	spec->tx_power_bg = txpower;
-	spec->tx_power_default = DEFAULT_TXPOWER;
 
-	spec->num_channels = ARRAY_SIZE(rf_vals_bg);
-	spec->channels = rf_vals_bg;
+	spec->num_channels = ARRAY_SIZE(rf_vals_b);
+	spec->channels = rf_vals_b;
+
+	/*
+	 * Create channel information array
+	 */
+	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	spec->channels_info = info;
+
+	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+	for (i = 0; i < 14; i++)
+		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+	return 0;
 }
 
 static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1477,7 +1483,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Initialize hw specifications.
 	 */
-	rt2400pci_probe_hw_mode(rt2x00dev);
+	retval = rt2400pci_probe_hw_mode(rt2x00dev);
+	if (retval)
+		return retval;
 
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
drivers/net/wireless/rt2x00/rt2400pci.h +8 -14
index bc55642..bbff381 100644
@@ -938,19 +938,13 @@
 #define MAX_TXPOWER	62
 #define DEFAULT_TXPOWER	39
 
-#define TXPOWER_FROM_DEV(__txpower)					\
-({									\
-	((__txpower) > MAX_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER :	\
-	((__txpower) < MIN_TXPOWER) ? DEFAULT_TXPOWER - MIN_TXPOWER :	\
-	(((__txpower) - MAX_TXPOWER) + MIN_TXPOWER);			\
-})
-
-#define TXPOWER_TO_DEV(__txpower)			\
-({							\
-	(__txpower) += MIN_TXPOWER;			\
-	((__txpower) <= MIN_TXPOWER) ? MAX_TXPOWER :	\
-	(((__txpower) >= MAX_TXPOWER) ? MIN_TXPOWER :	\
-	(MAX_TXPOWER - ((__txpower) - MIN_TXPOWER)));	\
-})
+#define __CLAMP_TX(__txpower) \
+	clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER)
+
+#define TXPOWER_FROM_DEV(__txpower) \
+	((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
+
+#define TXPOWER_TO_DEV(__txpower) \
+	MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)
 
 #endif /* RT2400PCI_H */
drivers/net/wireless/rt2x00/rt2500pci.c +26 -13
index 181a146..e0ff76f 100644
@@ -1721,10 +1721,11 @@ static const struct rf_channel rf_vals_5222[] = {
 	{ 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
 };
 
-static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	u8 *txpower;
+	struct channel_info *info;
+	char *tx_power;
 	unsigned int i;
 
 	/*
@@ -1741,20 +1742,10 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 						   EEPROM_MAC_ADDR_0));
 
 	/*
-	 * Convert tx_power array in eeprom.
-	 */
-	txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
-	/*
 	 * Initialize hw_mode information.
 	 */
 	spec->supported_bands = SUPPORT_BAND_2GHZ;
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-	spec->tx_power_a = NULL;
-	spec->tx_power_bg = txpower;
-	spec->tx_power_default = DEFAULT_TXPOWER;
 
 	if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
 		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
@@ -1776,6 +1767,26 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		spec->num_channels = ARRAY_SIZE(rf_vals_5222);
 		spec->channels = rf_vals_5222;
 	}
+
+	/*
+	 * Create channel information array
+	 */
+	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	spec->channels_info = info;
+
+	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+	for (i = 0; i < 14; i++)
+		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+	if (spec->num_channels > 14) {
+		for (i = 14; i < spec->num_channels; i++)
+			info[i].tx_power1 = DEFAULT_TXPOWER;
+	}
+
+	return 0;
 }
 
 static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1796,7 +1807,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Initialize hw specifications.
 	 */
-	rt2500pci_probe_hw_mode(rt2x00dev);
+	retval = rt2500pci_probe_hw_mode(rt2x00dev);
+	if (retval)
+		return retval;
 
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
drivers/net/wireless/rt2x00/rt2500pci.h +5 -12
index 42f3769..8c26bef 100644
@@ -1223,17 +1223,10 @@
 #define MAX_TXPOWER	31
 #define DEFAULT_TXPOWER	24
 
-#define TXPOWER_FROM_DEV(__txpower)		\
-({						\
-	((__txpower) > MAX_TXPOWER) ?		\
-		DEFAULT_TXPOWER : (__txpower);	\
-})
-
-#define TXPOWER_TO_DEV(__txpower)			\
-({							\
-	((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER :	\
-	(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER :	\
-	(__txpower));					\
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+	(((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
 
 #endif /* RT2500PCI_H */
drivers/net/wireless/rt2x00/rt2500usb.c +26 -13
index c6f6eb6..df78bd3 100644
@@ -1652,10 +1652,11 @@ static const struct rf_channel rf_vals_5222[] = {
 	{ 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 },
 };
 
-static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 {
 	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	u8 *txpower;
+	struct channel_info *info;
+	char *tx_power;
 	unsigned int i;
 
 	/*
@@ -1674,20 +1675,10 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 						   EEPROM_MAC_ADDR_0));
 
 	/*
-	 * Convert tx_power array in eeprom.
-	 */
-	txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
-	for (i = 0; i < 14; i++)
-		txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-
-	/*
 	 * Initialize hw_mode information.
 	 */
 	spec->supported_bands = SUPPORT_BAND_2GHZ;
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-	spec->tx_power_a = NULL;
-	spec->tx_power_bg = txpower;
-	spec->tx_power_default = DEFAULT_TXPOWER;
 
 	if (rt2x00_rf(&rt2x00dev->chip, RF2522)) {
 		spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
@@ -1709,6 +1700,26 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		spec->num_channels = ARRAY_SIZE(rf_vals_5222);
 		spec->channels = rf_vals_5222;
 	}
+
+	/*
+	 * Create channel information array
+	 */
+	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	spec->channels_info = info;
+
+	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
+	for (i = 0; i < 14; i++)
+		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
+
+	if (spec->num_channels > 14) {
+		for (i = 14; i < spec->num_channels; i++)
+			info[i].tx_power1 = DEFAULT_TXPOWER;
+	}
+
+	return 0;
 }
 
 static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
@@ -1729,7 +1740,9 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Initialize hw specifications.
 	 */
-	rt2500usb_probe_hw_mode(rt2x00dev);
+	retval = rt2500usb_probe_hw_mode(rt2x00dev);
+	if (retval)
+		return retval;
 
 	/*
 	 * This device requires the atim queue
drivers/net/wireless/rt2x00/rt2500usb.h +5 -12
index 4769ffe..89e5ed2 100644
@@ -825,17 +825,10 @@
 #define MAX_TXPOWER	31
 #define DEFAULT_TXPOWER	24
 
-#define TXPOWER_FROM_DEV(__txpower)		\
-({						\
-	((__txpower) > MAX_TXPOWER) ?		\
-		DEFAULT_TXPOWER : (__txpower);	\
-})
-
-#define TXPOWER_TO_DEV(__txpower)			\
-({							\
-	((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER :	\
-	(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER :	\
-	(__txpower));					\
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+	(((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
 
 #endif /* RT2500USB_H */
drivers/net/wireless/rt2x00/rt2x00.h +15 -8
index ae5c090..61f853f 100644
@@ -144,6 +144,17 @@ struct rf_channel {
 };
 
 /*
+ * Channel information structure
+ */
+struct channel_info {
+	unsigned int flags;
+#define GEOGRAPHY_ALLOWED	0x00000001
+
+	short tx_power1;
+	short tx_power2;
+};
+
+/*
  * Antenna setup values.
  */
 struct antenna_setup {
@@ -394,10 +405,7 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
  * @num_channels: Number of supported channels. This is used as array size
  *	for @tx_power_a, @tx_power_bg and @channels.
  * @channels: Device/chipset specific channel values (See &struct rf_channel).
- * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
- * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
- * @tx_power_default: Default TX power value to use when either
- *	@tx_power_a or @tx_power_bg is missing.
+ * @channels_info: Additional information for channels (See &struct channel_info).
  */
 struct hw_mode_spec {
 	unsigned int supported_bands;
@@ -410,10 +418,7 @@ struct hw_mode_spec {
 
 	unsigned int num_channels;
 	const struct rf_channel *channels;
-
-	const u8 *tx_power_a;
-	const u8 *tx_power_bg;
-	u8 tx_power_default;
+	const struct channel_info *channels_info;
 };
 
 /*
@@ -425,7 +430,9 @@ struct hw_mode_spec {
  */
 struct rt2x00lib_conf {
 	struct ieee80211_conf *conf;
+
 	struct rf_channel rf;
+	struct channel_info channel;
 
 	struct antenna_setup ant;
 
drivers/net/wireless/rt2x00/rt2x00config.c +4 -0
index d134c3b..ea37c79 100644
@@ -245,6 +245,10 @@ config:
 		memcpy(&libconf.rf,
 		       &rt2x00dev->spec.channels[conf->channel->hw_value],
 		       sizeof(libconf.rf));
+
+		memcpy(&libconf.channel,
+		       &rt2x00dev->spec.channels_info[conf->channel->hw_value],
+		       sizeof(libconf.channel));
 	}
 
 	if (flags & CONFIG_UPDATE_ANTENNA) {
drivers/net/wireless/rt2x00/rt2x00dev.c +4 -14
index 1829522..328ff8b 100644
@@ -818,7 +818,6 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
 	struct ieee80211_rate *rates;
 	unsigned int num_rates;
 	unsigned int i;
-	unsigned char tx_power;
 
 	num_rates = 0;
 	if (spec->supported_rates & SUPPORT_RATE_CCK)
@@ -844,20 +843,9 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
 	 * Initialize Channel list.
 	 */
 	for (i = 0; i < spec->num_channels; i++) {
-		if (spec->channels[i].channel <= 14) {
-			if (spec->tx_power_bg)
-				tx_power = spec->tx_power_bg[i];
-			else
-				tx_power = spec->tx_power_default;
-		} else {
-			if (spec->tx_power_a)
-				tx_power = spec->tx_power_a[i];
-			else
-				tx_power = spec->tx_power_default;
-		}
-
 		rt2x00lib_channel(&channels[i],
-				  spec->channels[i].channel, tx_power, i);
+				  spec->channels[i].channel,
+				  spec->channels_info[i].tx_power1, i);
 	}
 
 	/*
@@ -909,6 +897,8 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
 		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
 		rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 	}
+
+	kfree(rt2x00dev->spec.channels_info);
 }
 
 static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
drivers/net/wireless/rt2x00/rt61pci.c +25 -17

75 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt61pci.h +5 -12
index 6d591ce..8ec1451 100644
@@ -1482,17 +1482,10 @@ struct hw_pairwise_ta_entry {
 #define MAX_TXPOWER	31
 #define DEFAULT_TXPOWER	24
 
-#define TXPOWER_FROM_DEV(__txpower)		\
-({						\
-	((__txpower) > MAX_TXPOWER) ?		\
-		DEFAULT_TXPOWER : (__txpower);	\
-})
-
-#define TXPOWER_TO_DEV(__txpower)			\
-({							\
-	((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER :	\
-	(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER :	\
-	(__txpower));					\
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+	(((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
 
 #endif /* RT61PCI_H */
drivers/net/wireless/rt2x00/rt73usb.c +24 -19

75 lines not on this page · raw message

drivers/net/wireless/rt2x00/rt73usb.h +5 -12
index 91e04d3..868386c 100644
@@ -1050,17 +1050,10 @@ struct hw_pairwise_ta_entry {
 #define MAX_TXPOWER	31
 #define DEFAULT_TXPOWER	24
 
-#define TXPOWER_FROM_DEV(__txpower)		\
-({						\
-	((__txpower) > MAX_TXPOWER) ?		\
-		DEFAULT_TXPOWER : (__txpower);	\
-})
-
-#define TXPOWER_TO_DEV(__txpower)			\
-({							\
-	((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER :	\
-	(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER :	\
-	(__txpower));					\
-})
+#define TXPOWER_FROM_DEV(__txpower) \
+	(((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_TO_DEV(__txpower) \
+	clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER)
 
 #endif /* RT73USB_H */
Signature · 1 line
1.5.6.1
#5 lore raw

PATCH 5/5 rt2x00: Release rt2x00 2.2.0

---
 drivers/net/wireless/rt2x00/rt2x00.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
index 61f853f..7476a4e 100644
@@ -44,7 +44,7 @@
 /*
  * Module information.
  */
-#define DRV_VERSION	"2.1.8"
+#define DRV_VERSION	"2.2.0"
 #define DRV_PROJECT	"http://rt2x00.serialmonkey.com"
 
 /*
Signature · 1 line
1.5.6.1
#6 lore raw

Re: [PATCH 3/5] rt2x00: Implement HW encryption (rt73usb)

In reply to Ivo van Doorn
Quoted 435 lines · Ivo van Doorn

rt73usb supports hardware encryption.
rt73usb supports up to 4 shared keys and up to 64 pairwise keys.

---
 drivers/net/wireless/rt2x00/Kconfig   |    1 +
 drivers/net/wireless/rt2x00/rt73usb.c |  271 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt73usb.h |   21 +++-
 3 files changed, 285 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/Kconfig +1 -0
index f333f61..11f590d 100644
@@ -156,6 +156,7 @@ config RT73USB
       depends on USB
       select RT2X00_LIB_USB
       select RT2X00_LIB_FIRMWARE
+       select RT2X00_LIB_CRYPTO
       select CRC_ITU_T
       ---help---
         This adds support for rt2501 wireless chipset family.
drivers/net/wireless/rt2x00/rt73usb.c +265 -6
index 9761eaa..ddba747 100644
@@ -357,6 +357,219 @@ static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev,
 /*
 * Configuration handlers.
 */
+static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
+                                    struct rt2x00lib_crypto *crypto,
+                                    struct ieee80211_key_conf *key)
+{
+       struct hw_key_entry key_entry;
+       struct rt2x00_field32 field;
+       int timeout;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for shared keys. We have 1 register
+                * with key valid bits. The goal is simple, read
+                * the register, if that is full we have no slots
+                * left.
+                * Note that each BSS is allowed to have up to 4
+                * shared keys, so put a mask over the allowed
+                * entries.
+                */
+               mask = (0xf << crypto->bssidx);
+
+               rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+               reg &= mask;
+
+               if (reg && reg == mask)
+                       return -ENOSPC;
+
+               key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               reg = SHARED_KEY_ENTRY(key->hw_key_idx);
+               timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+               rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                                   USB_VENDOR_REQUEST_OUT, reg,
+                                                   &key_entry,
+                                                   sizeof(key_entry),
+                                                   timeout);
+
+               /*
+                * The cipher types are stored over 2 registers.
+                * bssidx 0 and 1 keys are stored in SEC_CSR1 and
+                * bssidx 1 and 2 keys are stored in SEC_CSR5.
+                * Using the correct defines correctly will cause overhead,
+                * so just calculate the correct offset.
+                */
+               if (key->hw_key_idx < 8) {
+                       field.bit_offset = (3 * key->hw_key_idx);
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt73usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt73usb_register_write(rt2x00dev, SEC_CSR1, reg);
+               } else {
+                       field.bit_offset = (3 * (key->hw_key_idx - 8));
+                       field.bit_mask = 0x7 << field.bit_offset;
+
+                       rt73usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+                       rt2x00_set_field32(&reg, field, crypto->cipher);
+                       rt73usb_register_write(rt2x00dev, SEC_CSR5, reg);
+               }
+
+               /*
+                * 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;
+       }
+
+       /*
+        * SEC_CSR0 contains only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead we use
+        * a calculation to determine the correct bit directly.
+        */
+       mask = 1 << key->hw_key_idx;
+
+       rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+       if (crypto->cmd == SET_KEY)
+               reg |= mask;
+       else if (crypto->cmd == DISABLE_KEY)
+               reg &= ~mask;
+       rt73usb_register_write(rt2x00dev, SEC_CSR0, reg);
+
+       return 0;
+}
+
+static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+                                      struct rt2x00lib_crypto *crypto,
+                                      struct ieee80211_key_conf *key)
+{
+       struct hw_pairwise_ta_entry addr_entry;
+       struct hw_key_entry key_entry;
+       int timeout;
+       u32 mask;
+       u32 reg;
+
+       if (crypto->cmd == SET_KEY) {
+               /*
+                * rt2x00lib can't determine the correct free
+                * key_idx for pairwise keys. We have 2 registers
+                * with key valid bits. The goal is simple, read
+                * the first register, if that is full move to
+                * the next register.
+                * When both registers are full, we drop the key,
+                * otherwise we use the first invalid entry.
+                */
+               rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (reg && reg == ~0) {
+                       key->hw_key_idx = 32;
+                       rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+                       if (reg && reg == ~0)
+                               return -ENOSPC;
+               }
+
+               key->hw_key_idx += reg ? (ffz(reg) - 1) : 0;
+
+               /*
+                * Upload key to hardware
+                */
+               memcpy(key_entry.key, crypto->key,
+                      sizeof(key_entry.key));
+               memcpy(key_entry.tx_mic, crypto->tx_mic,
+                      sizeof(key_entry.tx_mic));
+               memcpy(key_entry.rx_mic, crypto->rx_mic,
+                      sizeof(key_entry.rx_mic));
+
+               reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+               timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
+               rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+                                                   USB_VENDOR_REQUEST_OUT, reg,
+                                                   &key_entry,
+                                                   sizeof(key_entry),
+                                                   timeout);
+
+               /*
+                * Send the address and cipher type to the hardware register.
+                * This data fits within the CSR cache size, so we can use
+                * rt73usb_register_multiwrite() directly.
+                */
+               memset(&addr_entry, 0, sizeof(addr_entry));
+               memcpy(&addr_entry, crypto->address, ETH_ALEN);
+               addr_entry.cipher = crypto->cipher;
+
+               reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
+               rt73usb_register_multiwrite(rt2x00dev, reg,
+                                           &addr_entry, sizeof(addr_entry));
+
+               /*
+                * Enable pairwise lookup table for given BSS idx,
+                * without this received frames will not be decrypted
+                * by the hardware.
+                */
+               rt73usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+               reg |= (1 << crypto->bssidx);
+               rt73usb_register_write(rt2x00dev, SEC_CSR4, reg);
+
+               /*
+                * 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;
+       }
+
+       /*
+        * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
+        * a particular key is valid. Because using the FIELD32()
+        * defines directly will cause a lot of overhead we use
+        * a calculation to determine the correct bit directly.
+        */
+       if (key->hw_key_idx < 32) {
+               mask = 1 << key->hw_key_idx;
+
+               rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt73usb_register_write(rt2x00dev, SEC_CSR2, reg);
+       } else {
+               mask = 1 << (key->hw_key_idx - 32);
+
+               rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+               if (crypto->cmd == SET_KEY)
+                       reg |= mask;
+               else if (crypto->cmd == DISABLE_KEY)
+                       reg &= ~mask;
+               rt73usb_register_write(rt2x00dev, SEC_CSR3, reg);
+       }
+
+       return 0;
+}
+
 static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
                                 const unsigned int filter_flags)
 {
@@ -1265,8 +1478,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 * TX descriptor initialization
 */
 static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-                                   struct sk_buff *skb,
-                                   struct txentry_desc *txdesc)
+                                 struct sk_buff *skb,
+                                 struct txentry_desc *txdesc)
 {
       struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
       __le32 *txd = skbdesc->desc;
@@ -1280,7 +1493,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
       rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
       rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
       rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
-       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_HW_SEQUENCE,
                          test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
       rt2x00_desc_write(txd, 1, word);
@@ -1292,6 +1505,11 @@ static void rt73usb_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);
+               _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+       }
+
       rt2x00_desc_read(txd, 5, &word);
       rt2x00_set_field32(&word, TXD_W5_TX_POWER,
                          TXPOWER_TO_DEV(rt2x00dev->tx_power));
@@ -1313,12 +1531,16 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
       rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
       rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
                          test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
+       rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
+                          test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
+                          test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
+       rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
       rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT,
                          skb->len - skbdesc->desc_len);
       rt2x00_set_field32(&word, TXD_W0_BURST2,
                          test_bit(ENTRY_TXD_BURST, &txdesc->flags));
-       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
+       rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
       rt2x00_desc_write(txd, 0, word);
 }
 
@@ -1468,6 +1690,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
 static void rt73usb_fill_rxdone(struct queue_entry *entry,
                               struct rxdone_entry_desc *rxdesc)
 {
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
       __le32 *rxd = (__le32 *)entry->skb->data;
       u32 word0;
@@ -1489,6 +1712,38 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
       if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
               rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
 
+       if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+               rxdesc->cipher =
+                   rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG);
+               rxdesc->cipher_status =
+                   rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR);
+       }
+
+       if (rxdesc->cipher != CIPHER_NONE) {
+               _rt2x00_desc_read(rxd, 2, &rxdesc->iv);
+               _rt2x00_desc_read(rxd, 3, &rxdesc->eiv);
+               _rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+
+               /*
+                * 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;
+
+               /*
+                * FIXME: Legacy driver indicates that the frame does
+                * contain the Michael Mic. Unfortunately, in rt2x00
+                * the MIC seems to be missing completely...
+                */
+               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,
@@ -1496,7 +1751,7 @@ static void rt73usb_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 = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
+       rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1);
       rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 
       if (rt2x00_get_field32(word0, RXD_W0_OFDM))
@@ -1938,6 +2193,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        */
       __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
       __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+       __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 
       /*
        * Set the rssi offset.
@@ -1997,6 +2253,7 @@ static const struct ieee80211_ops rt73usb_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,
       .set_retry_limit        = rt73usb_set_retry_limit,
       .bss_info_changed       = rt2x00mac_bss_info_changed,
@@ -2024,6 +2281,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
       .get_tx_data_len        = rt73usb_get_tx_data_len,
       .kick_tx_queue          = rt73usb_kick_tx_queue,
       .fill_rxdone            = rt73usb_fill_rxdone,
+       .config_shared_key      = rt73usb_config_shared_key,
+       .config_pairwise_key    = rt73usb_config_pairwise_key,
       .config_filter          = rt73usb_config_filter,
       .config_intf            = rt73usb_config_intf,
       .config_erp             = rt73usb_config_erp,
drivers/net/wireless/rt2x00/rt73usb.h +19 -3
index 1484935..91e04d3 100644
@@ -92,6 +92,16 @@
 #define PAIRWISE_KEY_TABLE_BASE                0x1200
 #define PAIRWISE_TA_TABLE_BASE         0x1a00
 
+#define SHARED_KEY_ENTRY(__idx) \
+       ( SHARED_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+       ( PAIRWISE_KEY_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_key_entry)) )
+#define PAIRWISE_TA_ENTRY(__idx) \
+       ( PAIRWISE_TA_TABLE_BASE + \
+               ((__idx) * sizeof(struct hw_pairwise_ta_entry)) )
+
 struct hw_key_entry {
       u8 key[16];
       u8 tx_mic[8];
@@ -100,7 +110,8 @@ struct hw_key_entry {
 
 struct hw_pairwise_ta_entry {
       u8 address[6];
-       u8 reserved[2];
+       u8 cipher;
+       u8 reserved;
 } __attribute__ ((packed));
 
 /*
@@ -563,6 +574,10 @@ struct hw_pairwise_ta_entry {
 * SEC_CSR4: Pairwise key table lookup control.
 */
 #define SEC_CSR4                       0x30b0
+#define SEC_CSR4_ENABLE_BSS0           FIELD32(0x00000001)
+#define SEC_CSR4_ENABLE_BSS1           FIELD32(0x00000002)
+#define SEC_CSR4_ENABLE_BSS2           FIELD32(0x00000004)
+#define SEC_CSR4_ENABLE_BSS3           FIELD32(0x00000008)
 
 /*
 * SEC_CSR5: shared key table security mode register.
@@ -1010,8 +1025,10 @@ struct hw_pairwise_ta_entry {
 
 /*
 * Word4
+ * ICV: Received ICV of originally encrypted.
+ * NOTE: This is a guess, the official definition is "reserved"
 */
-#define RXD_W4_RESERVED                        FIELD32(0xffffffff)
+#define RXD_W4_ICV                     FIELD32(0xffffffff)
 
 /*
 * the above 20-byte is called RXINFO and will be DMAed to MAC RX block
--

1.5.6.1

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

We need modparams for disabling HW crypto support if it misbehaves.

Signature · 1 line
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
#7 lore raw

Re: [PATCH 3/5] rt2x00: Implement HW encryption (rt73usb)

Quoted 1 line · On Monday 04 August 2008, Stefanik G=E1bor wrote:

On Mon, Aug 4, 2008 at 4:38 PM, Ivo van Doorn <[email protected]> wro=

te:

Quoted 2 lines
Quoted 2 lines

rt73usb supports hardware encryption.
rt73usb supports up to 4 shared keys and up to 64 pairwise keys.

<...>

Quoted 1 line

We need modparams for disabling HW crypto support if it misbehaves.

Hmm, I'm not that big fan of module parameters, but perhaps there shoul= d
indeed be some toggle possibility. Well, I'll add that in a few days.

Ivo
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles= s" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw
In reply to Ivo van Doorn
Quoted 5 lines · Ivo van Doorn

Hi John,

Only 5 patches, but they do bump rt2x00 to a new version: 2.2.0 This series will add HW crypto support to rt2x00, by default it has been enabled for rt61pci and rt73usb.

Seems to work well on my rt61pci card!

In fact, it reports a higher link quality (and maintains a higher bitrate) than the version in current wireless-testing. The quality report also fluctuates less than previously. This is consistent over a few hours of testing with streaming PCM audio.

I do get a lockdep warning when bringing up the device, however.

=============================================
[ INFO: possible recursive locking detected ] 2.6.27-rc1-rt2-wl #1
---------------------------------------------
rt61pci/4405 is trying to acquire lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

but task is already holding lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

other info that might help us debug this:
3 locks held by rt61pci/4405:
#0: ((name)){--..}, at: [<ffffffff80250741>] run_workqueue+0xa1/0x230 #1: (&(&local->scan_work)->work){--..}, at: [<ffffffff80250741>]

run_workqueue+0xa1/0x230
 #2:  (_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

stack backtrace:

Pid: 4405, comm: rt61pci Not tainted 2.6.27-rc1-rt2-wl #1

Call Trace:
 [<ffffffff802657ac>] __lock_acquire+0xb1c/0x12d0
 [<ffffffff8024939e>] ? __mod_timer+0xbe/0xe0
 [<ffffffff80265fb9>] lock_acquire+0x59/0x80
 [<ffffffffa014cc52>] ? ieee80211_scan_completed+0x172/0x320 [mac80211]
 [<ffffffff8055e5d4>] _spin_lock+0x34/0x50
 [<ffffffffa014cc52>] ieee80211_scan_completed+0x172/0x320 [mac80211]
 [<ffffffffa014d0bb>] ieee80211_sta_scan_work+0x8b/0x210 [mac80211]
 [<ffffffffa014d030>] ? ieee80211_sta_scan_work+0x0/0x210 [mac80211]
 [<ffffffffa014d030>] ? ieee80211_sta_scan_work+0x0/0x210 [mac80211]
 [<ffffffff8025078b>] run_workqueue+0xeb/0x230
 [<ffffffff80250977>] worker_thread+0xa7/0x120
 [<ffffffff80254f30>] ? autoremove_wake_function+0x0/0x40
 [<ffffffff802508d0>] ? worker_thread+0x0/0x120
 [<ffffffff80254b89>] kthread+0x49/0x80
 [<ffffffff8020d5b9>] child_rip+0xa/0x11
 [<ffffffff8020cbc3>] ? restore_args+0x0/0x30
 [<ffffffff80254b40>] ? kthread+0x0/0x80
 [<ffffffff8020d5af>] ? child_rip+0x0/0x11
Signature · 1 line
Will Dyson
#9 lore raw
Quoted 24 lines · Will Dyson
Quoted 5 lines · Ivo van Doorn

Hi John,

Only 5 patches, but they do bump rt2x00 to a new version: 2.2.0 This series will add HW crypto support to rt2x00, by default it has been enabled for rt61pci and rt73usb.

Seems to work well on my rt61pci card!

In fact, it reports a higher link quality (and maintains a higher bitrate) than the version in current wireless-testing. The quality report also fluctuates less than previously. This is consistent over a few hours of testing with streaming PCM audio.

I do get a lockdep warning when bringing up the device, however.

=============================================
[ INFO: possible recursive locking detected ] 2.6.27-rc1-rt2-wl #1
---------------------------------------------
rt61pci/4405 is trying to acquire lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

Quoted 4 lines

but task is already holding lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

I get that same lockdep warning when using the mainline kernel with b43. It doesn't seem to cause any problems.

Larry

#10 lore raw
Quoted 25 lines · Larry Finger
Quoted 24 lines · Will Dyson
Quoted 5 lines · Ivo van Doorn

Hi John,

Only 5 patches, but they do bump rt2x00 to a new version: 2.2.0 This series will add HW crypto support to rt2x00, by default it has been enabled for rt61pci and rt73usb.

Seems to work well on my rt61pci card!

In fact, it reports a higher link quality (and maintains a higher bitrate) than the version in current wireless-testing. The quality report also fluctuates less than previously. This is consistent over a few hours of testing with streaming PCM audio.

I do get a lockdep warning when bringing up the device, however.

=============================================
[ INFO: possible recursive locking detected ] 2.6.27-rc1-rt2-wl #1
---------------------------------------------
rt61pci/4405 is trying to acquire lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

Quoted 7 lines
Quoted 4 lines

but task is already holding lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

I get that same lockdep warning when using the mainline kernel with b43. It doesn't seem to cause any problems.

Sounds like a mac80211 bug then, can't find something obvious at first glance, but perhaps Johannes has an idea?

Ivo

maintainer
#11 lore raw
Quoted 13 lines · Ivo van Doorn
Quoted 13 lines
Quoted 12 lines

=============================================
[ INFO: possible recursive locking detected ] 2.6.27-rc1-rt2-wl #1
---------------------------------------------
rt61pci/4405 is trying to acquire lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

but task is already holding lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

Quoted 5 lines
Quoted 2 lines

I get that same lockdep warning when using the mainline kernel with b43. It doesn't seem to cause any problems.

Sounds like a mac80211 bug then, can't find something obvious at first glance, but perhaps Johannes has an idea?

I ignore everything with the TX lock in it because those have been wrongly annotated in a bunch of versions, including -rc1 afaik.

johannes

#12 lore raw
Quoted 15 lines · Johannes Berg
Quoted 13 lines · Ivo van Doorn
Quoted 13 lines
Quoted 12 lines

=============================================
[ INFO: possible recursive locking detected ] 2.6.27-rc1-rt2-wl #1
---------------------------------------------
rt61pci/4405 is trying to acquire lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

but task is already holding lock:
(_xmit_IEEE80211#2){-...}, at: [<ffffffffa014cc52>]
ieee80211_scan_completed+0x172/0x320 [mac80211]

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

I get that same lockdep warning when using the mainline kernel with b43. It doesn't seem to cause any problems.

Sounds like a mac80211 bug then, can't find something obvious at first glance, but perhaps Johannes has an idea?

I ignore everything with the TX lock in it because those have been wrongly annotated in a bunch of versions, including -rc1 afaik.

Heh ok. :)

Ivo