Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] net: rfkill: Check the return value of regulator_enable()
From: Fabio Estevam @ 2013-08-17 21:36 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Fabio Estevam

From: Fabio Estevam <fabio.estevam@freescale.com>

Fix the following build warning:

net/rfkill/rfkill-regulator.c:43:20: warning: ignoring return value of 'regulator_enable', declared with attribute warn_unused_result [-Wunused-result]

Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
---
 net/rfkill/rfkill-regulator.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/rfkill/rfkill-regulator.c b/net/rfkill/rfkill-regulator.c
index d11ac79..0aa922c 100644
--- a/net/rfkill/rfkill-regulator.c
+++ b/net/rfkill/rfkill-regulator.c
@@ -30,6 +30,7 @@ struct rfkill_regulator_data {
 static int rfkill_regulator_set_block(void *data, bool blocked)
 {
 	struct rfkill_regulator_data *rfkill_data = data;
+	int ret;
 
 	pr_debug("%s: blocked: %d\n", __func__, blocked);
 
@@ -40,7 +41,9 @@ static int rfkill_regulator_set_block(void *data, bool blocked)
 		}
 	} else {
 		if (!rfkill_data->reg_enabled) {
-			regulator_enable(rfkill_data->vcc);
+			ret = regulator_enable(rfkill_data->vcc);
+			if (ret)
+				return ret;
 			rfkill_data->reg_enabled = true;
 		}
 	}
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 6/6] rt2x00: rt2800lib: fix beacon generation on RT3593
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

On the RT3593 chipset, the beacon registers are located
in the high 8KB part of the shared memory.

The high part of the shared memory is only accessible
if it is explicitly selected. Add a helper function
in order to be able to control the SHR_MSEL bit in
the PBF_SYS_CTRL register. Also add a few more helper
functions and use those to select the correct part of
the shared memory before and after accessing the beacon
registers.

The base addresses of the beacon registers are also
different from the actually used values, so fix the
'rt2800_hw_beacon_base' function to return the correct
values.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800.h    |    3 ++
 drivers/net/wireless/rt2x00/rt2800lib.c |   47 +++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 48018a5..67498b0 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -572,6 +572,7 @@
 #define PBF_SYS_CTRL			0x0400
 #define PBF_SYS_CTRL_READY		FIELD32(0x00000080)
 #define PBF_SYS_CTRL_HOST_RAM_WRITE	FIELD32(0x00010000)
+#define PBF_SYS_CTRL_SHR_MSEL		FIELD32(0x00080000)
 
 /*
  * HOST-MCU shared memory
@@ -2024,6 +2025,8 @@ struct mac_iveiv_entry {
 	  (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
 	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
 
+#define HW_BEACON_BASE_HIGH(__index)	(0x4000 + (__index) * 512)
+
 #define BEACON_BASE_TO_OFFSET(_base)	(((_base) - 0x4000) / 64)
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index d223308..3c2843b 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -84,6 +84,42 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
 	return false;
 }
 
+static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev,
+					    bool high)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+	u32 reg;
+
+	lockdep_assert_held(&drv_data->shared_mem_mutex);
+
+	if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev)))
+		return;
+
+	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+	rt2x00_set_field32(&reg, PBF_SYS_CTRL_SHR_MSEL, high);
+	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+}
+
+static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return true;
+
+	return false;
+}
+
+static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2800_beacon_uses_high_mem(rt2x00dev))
+		rt2800_shared_mem_select(rt2x00dev, true);
+}
+
+static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev)
+{
+	if (rt2800_beacon_uses_high_mem(rt2x00dev))
+		rt2800_shared_mem_select(rt2x00dev, false);
+}
+
 static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
 			     const unsigned int word, const u8 value)
 {
@@ -951,6 +987,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
 					  unsigned int index)
 {
+	if (rt2x00_rt(rt2x00dev, RT3593))
+		return HW_BEACON_BASE_HIGH(index);
+
 	return HW_BEACON_BASE(index);
 }
 
@@ -1015,8 +1054,12 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 
 	rt2800_shared_mem_lock(rt2x00dev);
+
+	rt2800_select_beacon_mem(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
+	rt2800_deselect_beacon_mem(rt2x00dev);
+
 	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
@@ -1044,6 +1087,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 
 	rt2800_shared_mem_lock(rt2x00dev);
 
+	rt2800_select_beacon_mem(rt2x00dev);
+
 	/*
 	 * For the Beacon base registers we only need to clear
 	 * the whole TXWI which (when set to 0) will invalidate
@@ -1052,6 +1097,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 
+	rt2800_deselect_beacon_mem(rt2x00dev);
+
 	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH 5/6] rt2x00: rt2800lib: don't hardcode beacon offsets
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

The values written into the BCN_OFFSET[01] registers are
hardcoded in the rt2800_init_register function.

Add a macro and a helper function to derive these values
directly from the base address of a given beacon, and use
the new function instead of the hardcoded numbers.

The patch contains no functional changes. The programmed
register values are the same before and after the patch.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800.h    |    2 ++
 drivers/net/wireless/rt2x00/rt2800lib.c |   30 ++++++++++++++++++++++--------
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 426129a..48018a5 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2024,6 +2024,8 @@ struct mac_iveiv_entry {
 	  (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
 	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
 
+#define BEACON_BASE_TO_OFFSET(_base)	(((_base) - 0x4000) / 64)
+
 /*
  * BBP registers.
  * The wordsize of the BBP is 8 bits.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b44eccf..d223308 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -954,6 +954,12 @@ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
 	return HW_BEACON_BASE(index);
 }
 
+static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev,
+					  unsigned int index)
+{
+	return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));
+}
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -4505,17 +4511,25 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		return ret;
 
 	rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */
-	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0,
+			   rt2800_get_beacon_offset(rt2x00dev, 0));
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1,
+			   rt2800_get_beacon_offset(rt2x00dev, 1));
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2,
+			   rt2800_get_beacon_offset(rt2x00dev, 2));
+	rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3,
+			   rt2800_get_beacon_offset(rt2x00dev, 3));
 	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
 
 	rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */
-	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4,
+			   rt2800_get_beacon_offset(rt2x00dev, 4));
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5,
+			   rt2800_get_beacon_offset(rt2x00dev, 5));
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6,
+			   rt2800_get_beacon_offset(rt2x00dev, 6));
+	rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7,
+			   rt2800_get_beacon_offset(rt2x00dev, 7));
 	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
 
 	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
-- 
1.7.10

^ permalink raw reply related

* [PATCH 4/6] rt2x00: rt2800lib: add rt2800_hw_beacon_base helper
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

The HW_BEACON_BASE() macro returns the base address
of a given beacon, however the returned values are
not usable on all chipsets. On devices which have
selectable shared memory parts, some beacon may be
located in the high part of the shared memory.

Instead of extending the already complicated macro,
add a new helper function and use that to get the
base address of a given beacon.

Te helper function will be extended in a subsequent
patch to handle different chipsets' requirements,
the actual patch contains no functional changes.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index ee7eede..b44eccf 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -948,6 +948,12 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
+static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev,
+					  unsigned int index)
+{
+	return HW_BEACON_BASE(index);
+}
+
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
@@ -1000,7 +1006,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 		return;
 	}
 
-	beacon_base = HW_BEACON_BASE(entry->entry_idx);
+	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx);
 
 	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
@@ -1028,7 +1034,7 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 	const int txwi_desc_size = rt2x00dev->bcn->winfo_size;
 	unsigned int beacon_base;
 
-	beacon_base = HW_BEACON_BASE(index);
+	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);
 
 	rt2800_shared_mem_lock(rt2x00dev);
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH 3/6] rt2x00: rt2800: serialize shared memory access
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

The shared memory of the rt2800 devices is accessible
through the register offset range between 0x4000 and
0x8000. The size of this range is 16KB only and on
devices which have more than 16KB of shared memory either
the low or the high part of the memory is accessible at a
time.

Serialize all accesses to the shared memory by a mutex,
in order to avoid concurrent use of that.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   50 +++++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2800lib.h |   18 +++++++++++
 drivers/net/wireless/rt2x00/rt2800pci.c |   10 +++++++
 drivers/net/wireless/rt2x00/rt2800usb.c |    5 ++++
 4 files changed, 83 insertions(+)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 2d409e0..ee7eede 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -445,6 +445,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00_is_soc(rt2x00dev))
 		return;
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	mutex_lock(&rt2x00dev->csr_mutex);
 
 	/*
@@ -464,6 +465,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 	}
 
 	mutex_unlock(&rt2x00dev->csr_mutex);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2800_mcu_request);
 
@@ -699,10 +701,16 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	/*
 	 * Initialize firmware.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
+
 	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
+
 		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 	}
 	msleep(1);
@@ -993,8 +1001,11 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	}
 
 	beacon_base = HW_BEACON_BASE(entry->entry_idx);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
 	 * Enable beaconing again.
@@ -1019,6 +1030,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 
 	beacon_base = HW_BEACON_BASE(index);
 
+	rt2800_shared_mem_lock(rt2x00dev);
+
 	/*
 	 * For the Beacon base registers we only need to clear
 	 * the whole TXWI which (when set to 0) will invalidate
@@ -1026,6 +1039,8 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
 	 */
 	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 void rt2800_clear_beacon(struct queue_entry *entry)
@@ -1209,7 +1224,9 @@ static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid)
 {
 	u32 offset;
 	offset = MAC_WCID_ATTR_ENTRY(wcid);
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, offset, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
@@ -1222,11 +1239,13 @@ static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev,
 	 * The BSS Idx numbers is split in a main value of 3 bits,
 	 * and a extended field for adding one additional bit to the value.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_read(rt2x00dev, offset, &reg);
 	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7));
 	rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT,
 			   (bssidx & 0x8) >> 3);
 	rt2800_register_write(rt2x00dev, offset, reg);
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
@@ -1239,6 +1258,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 
 	offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	if (crypto->cmd == SET_KEY) {
 		rt2800_register_read(rt2x00dev, offset, &reg);
 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
@@ -1263,6 +1283,7 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0);
 		rt2800_register_write(rt2x00dev, offset, reg);
 	}
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
 
@@ -1272,8 +1293,11 @@ static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev,
 	    (crypto->cipher == CIPHER_AES))
 		iveiv_entry.iv[3] |= 0x20;
 	iveiv_entry.iv[3] |= key->keyidx << 6;
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiwrite(rt2x00dev, offset,
 				      &iveiv_entry, sizeof(iveiv_entry));
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
@@ -1296,8 +1320,11 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 		       sizeof(key_entry.rx_mic));
 
 		offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_multiwrite(rt2x00dev, offset,
 					      &key_entry, sizeof(key_entry));
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -1312,10 +1339,12 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 
 	offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_read(rt2x00dev, offset, &reg);
 	rt2x00_set_field32(&reg, field,
 			   (crypto->cmd == SET_KEY) * crypto->cipher);
 	rt2800_register_write(rt2x00dev, offset, reg);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
 	 * Update WCID information
@@ -1385,8 +1414,11 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 		       sizeof(key_entry.rx_mic));
 
 		offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_multiwrite(rt2x00dev, offset,
 					      &key_entry, sizeof(key_entry));
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -4816,14 +4848,19 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * ASIC will keep garbage value after boot, clear encryption keys.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	for (i = 0; i < 4; i++)
 		rt2800_register_write(rt2x00dev,
 					 SHARED_KEY_MODE_ENTRY(i), 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	for (i = 0; i < 256; i++) {
 		rt2800_config_wcid(rt2x00dev, NULL, i);
 		rt2800_delete_wcid_attr(rt2x00dev, i);
+
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
 	}
 
 	/*
@@ -4949,8 +4986,10 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
 	 * BBP was enabled after firmware was loaded,
 	 * but we need to reactivate it now.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 	msleep(1);
 
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
@@ -6634,10 +6673,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Send signal to firmware during boot time.
 	 */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
+
 	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
+		rt2800_shared_mem_unlock(rt2x00dev);
+
 		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
 	}
 	msleep(1);
@@ -7701,6 +7746,8 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	int retval;
 	u32 reg;
 
+	mutex_init(&drv_data->shared_mem_mutex);
+
 	retval = rt2800_probe_rt(rt2x00dev);
 	if (retval)
 		return retval;
@@ -7785,8 +7832,11 @@ void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
 	u32 offset;
 
 	offset = MAC_IVEIV_ENTRY(hw_key_idx);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2800_register_multiread(rt2x00dev, offset,
 				      &iveiv_entry, sizeof(iveiv_entry));
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
 	memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index f89d413..f3f4404 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -37,6 +37,8 @@ struct rt2800_drv_data {
 	unsigned int tbtt_tick;
 
 	unsigned long rt2800_flags;
+
+	struct mutex shared_mem_mutex;
 };
 
 struct rt2800_ops {
@@ -76,6 +78,22 @@ static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
 	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
 }
 
+static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	if (rt2800_has_high_shared_mem(rt2x00dev))
+		mutex_lock(&drv_data->shared_mem_mutex);
+}
+
+static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	if (rt2800_has_high_shared_mem(rt2x00dev))
+		mutex_unlock(&drv_data->shared_mem_mutex);
+}
+
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 					const unsigned int offset,
 					u32 *value)
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index f8f2abb..b14ddf6 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -71,6 +71,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 	if (rt2x00_is_soc(rt2x00dev))
 		return;
 
+	rt2800_shared_mem_lock(rt2x00dev);
+
 	for (i = 0; i < 200; i++) {
 		rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
 
@@ -88,6 +90,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+
+	rt2800_shared_mem_unlock(rt2x00dev);
 }
 
 #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
@@ -325,8 +329,10 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
 	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	return 0;
 }
@@ -547,8 +553,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
 		return retval;
 
 	/* After resume MCU_BOOT_SIGNAL will trash these. */
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02);
 	rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF);
@@ -576,10 +584,12 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 				   0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP);
 	} else if (state == STATE_SLEEP) {
+		rt2800_shared_mem_lock(rt2x00dev);
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
 					  0xffffffff);
 		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID,
 					  0xffffffff);
+		rt2800_shared_mem_unlock(rt2x00dev);
 		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP,
 				   0xff, 0x01);
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 338034e..4ff38b8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -259,8 +259,10 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 	rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
 				      data + offset, length);
 
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	/*
 	 * Send firmware request to device to load firmware,
@@ -275,7 +277,10 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 	}
 
 	msleep(10);
+
+	rt2800_shared_mem_lock(rt2x00dev);
 	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2800_shared_mem_unlock(rt2x00dev);
 
 	return 0;
 }
-- 
1.7.10

^ permalink raw reply related

* [PATCH 2/6] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

Some chipsets have more than 16KB of shared memory.
Introduce a new rt2800 specific flag to indicate that
and add a helper function which helps to check the
presence of the new flag.

Also enable the new flag for the RT3593 chipset which
has 24KB of shared memory. The flag can also be used
for other chipsets, but none of those has been tested
yet.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    9 +++++++++
 drivers/net/wireless/rt2x00/rt2800lib.h |   13 +++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index aa6b6b0..2d409e0 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -7697,6 +7697,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev)
 
 int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 	int retval;
 	u32 reg;
 
@@ -7704,6 +7705,14 @@ int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (retval)
 		return retval;
 
+	switch (rt2x00dev->chip.rt) {
+	case RT3071:
+	case RT3593:
+	case RT5592:
+		__set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+		break;
+	}
+
 	/*
 	 * Allocate eeprom data.
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 9b3e8ef..f89d413 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -22,6 +22,10 @@
 #ifndef RT2800LIB_H
 #define RT2800LIB_H
 
+enum rt2800_flag {
+	RT2800_HAS_HIGH_SHARED_MEM,
+};
+
 /* RT2800 driver data structure */
 struct rt2800_drv_data {
 	u8 calibration_bw20;
@@ -31,6 +35,8 @@ struct rt2800_drv_data {
 	u8 txmixer_gain_24g;
 	u8 txmixer_gain_5g;
 	unsigned int tbtt_tick;
+
+	unsigned long rt2800_flags;
 };
 
 struct rt2800_ops {
@@ -63,6 +69,13 @@ struct rt2800_ops {
 	__le32 *(*drv_get_txwi)(struct queue_entry *entry);
 };
 
+static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+	return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags);
+}
+
 static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 					const unsigned int offset,
 					u32 *value)
-- 
1.7.10

^ permalink raw reply related

* [PATCH 1/6] rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376762167-24583-1-git-send-email-juhosg@openwrt.org>

The rt2800_drv_data structure contains driver specific
information. Move the declaration into the rt2800lib.h
header which is a more logical place for it. Also fix
the comment style to avoid checkpatch warning.

The patch contains no functional changes, it is in
preparation for the next patch.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/rt2x00/rt2800.h    |   13 -------------
 drivers/net/wireless/rt2x00/rt2800lib.h |   11 +++++++++++
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index e25e5bf..426129a 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2956,17 +2956,4 @@ enum rt2800_eeprom_word {
  */
 #define BCN_TBTT_OFFSET 64
 
-/*
- * RT2800 driver data structure
- */
-struct rt2800_drv_data {
-	u8 calibration_bw20;
-	u8 calibration_bw40;
-	u8 bbp25;
-	u8 bbp26;
-	u8 txmixer_gain_24g;
-	u8 txmixer_gain_5g;
-	unsigned int tbtt_tick;
-};
-
 #endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index a94ba44..9b3e8ef 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -22,6 +22,17 @@
 #ifndef RT2800LIB_H
 #define RT2800LIB_H
 
+/* RT2800 driver data structure */
+struct rt2800_drv_data {
+	u8 calibration_bw20;
+	u8 calibration_bw40;
+	u8 bbp25;
+	u8 bbp26;
+	u8 txmixer_gain_24g;
+	u8 txmixer_gain_5g;
+	unsigned int tbtt_tick;
+};
+
 struct rt2800_ops {
 	void (*register_read)(struct rt2x00_dev *rt2x00dev,
 			      const unsigned int offset, u32 *value);
-- 
1.7.10

^ permalink raw reply related

* [PATCH 0/6] rt2x00: fix beaconing on RT3593
From: Gabor Juhos @ 2013-08-17 17:56 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos

Gabor Juhos (6):
  rt2x00: rt2800lib: move rt2800_drv_data declaration into rt2800lib.h
  rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag
  rt2x00: rt2800: serialize shared memory access
  rt2x00: rt2800lib: add rt2800_hw_beacon_base helper
  rt2x00: rt2800lib: don't hardcode beacon offsets
  rt2x00: rt2800lib: fix beacon generation on RT3593

 drivers/net/wireless/rt2x00/rt2800.h    |   18 ++--
 drivers/net/wireless/rt2x00/rt2800lib.c |  146 ++++++++++++++++++++++++++++---
 drivers/net/wireless/rt2x00/rt2800lib.h |   42 +++++++++
 drivers/net/wireless/rt2x00/rt2800pci.c |   10 +++
 drivers/net/wireless/rt2x00/rt2800usb.c |    5 ++
 5 files changed, 198 insertions(+), 23 deletions(-)

--
1.7.10

^ permalink raw reply

* [PATCH v1 36/49] wireless: libertas_tf: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, Ming Lei, John W. Linville,
	libertas-dev, linux-wireless, netdev
In-Reply-To: <1376756714-25479-1-git-send-email-ming.lei@canonical.com>

Complete() will be run with interrupt enabled, so change to
spin_lock_irqsave().

Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: libertas-dev@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/wireless/libertas_tf/if_usb.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c
index d576dd6..0e9e972 100644
--- a/drivers/net/wireless/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/libertas_tf/if_usb.c
@@ -610,6 +610,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 				      struct if_usb_card *cardp,
 				      struct lbtf_private *priv)
 {
+	unsigned long flags;
+
 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
 		lbtf_deb_usbd(&cardp->udev->dev,
 			     "The receive buffer is too large\n");
@@ -619,12 +621,12 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 
 	BUG_ON(!in_interrupt());
 
-	spin_lock(&priv->driver_lock);
+	spin_lock_irqsave(&priv->driver_lock, flags);
 	memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
 	       recvlength - MESSAGE_HEADER_LEN);
 	kfree_skb(skb);
 	lbtf_cmd_response_rx(priv);
-	spin_unlock(&priv->driver_lock);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
 }
 
 /**
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v1 35/49] wireless: libertas: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, Ming Lei, John W. Linville,
	libertas-dev, linux-wireless, netdev
In-Reply-To: <1376756714-25479-1-git-send-email-ming.lei@canonical.com>

Complete() will be run with interrupt enabled, so change to
spin_lock_irqsave().

Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: libertas-dev@lists.infradead.org
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/wireless/libertas/if_usb.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 2798077..f6a8396 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -626,6 +626,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 				      struct lbs_private *priv)
 {
 	u8 i;
+	unsigned long flags;
 
 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
 		lbs_deb_usbd(&cardp->udev->dev,
@@ -636,7 +637,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 
 	BUG_ON(!in_interrupt());
 
-	spin_lock(&priv->driver_lock);
+	spin_lock_irqsave(&priv->driver_lock, flags);
 
 	i = (priv->resp_idx == 0) ? 1 : 0;
 	BUG_ON(priv->resp_len[i]);
@@ -646,7 +647,7 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 	kfree_skb(skb);
 	lbs_notify_command_response(priv, i);
 
-	spin_unlock(&priv->driver_lock);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 	lbs_deb_usbd(&cardp->udev->dev,
 		    "Wake up main thread to handle cmd response\n");
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v1 34/49] wireless: ath: carl9170: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, Ming Lei,
	Christian Lamparter, John W. Linville, linux-wireless, netdev
In-Reply-To: <1376756714-25479-1-git-send-email-ming.lei@canonical.com>

Complete() will be run with interrupt enabled, so change to
spin_lock_irqsave().

Cc: Christian Lamparter <chunkeey@googlemail.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/wireless/ath/carl9170/rx.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 4684dd9..61f62a6 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -129,6 +129,7 @@ static int carl9170_check_sequence(struct ar9170 *ar, unsigned int seq)
 
 static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
 {
+	unsigned long flags;
 	/*
 	 * Some commands may have a variable response length
 	 * and we cannot predict the correct length in advance.
@@ -148,7 +149,7 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
 		carl9170_restart(ar, CARL9170_RR_INVALID_RSP);
 	}
 
-	spin_lock(&ar->cmd_lock);
+	spin_lock_irqsave(&ar->cmd_lock, flags);
 	if (ar->readbuf) {
 		if (len >= 4)
 			memcpy(ar->readbuf, buffer + 4, len - 4);
@@ -156,7 +157,7 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
 		ar->readbuf = NULL;
 	}
 	complete(&ar->cmd_wait);
-	spin_unlock(&ar->cmd_lock);
+	spin_unlock_irqrestore(&ar->cmd_lock, flags);
 }
 
 void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v1 33/49] wireless: zd1211rw: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, Ming Lei, Daniel Drake,
	Ulrich Kunitz, John W. Linville, linux-wireless, netdev
In-Reply-To: <1376756714-25479-1-git-send-email-ming.lei@canonical.com>

Complete() will be run with interrupt enabled, so change to
spin_lock_irqsave().

Cc: Daniel Drake <dsd@gentoo.org>
Cc: Ulrich Kunitz <kune@deine-taler.de>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/wireless/zd1211rw/zd_usb.c |   21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 7ef0b4a..8169ee0 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -372,14 +372,15 @@ static inline void handle_regs_int_override(struct urb *urb)
 {
 	struct zd_usb *usb = urb->context;
 	struct zd_usb_interrupt *intr = &usb->intr;
+	unsigned long flags;
 
-	spin_lock(&intr->lock);
+	spin_lock_irqsave(&intr->lock, flags);
 	if (atomic_read(&intr->read_regs_enabled)) {
 		atomic_set(&intr->read_regs_enabled, 0);
 		intr->read_regs_int_overridden = 1;
 		complete(&intr->read_regs.completion);
 	}
-	spin_unlock(&intr->lock);
+	spin_unlock_irqrestore(&intr->lock, flags);
 }
 
 static inline void handle_regs_int(struct urb *urb)
@@ -388,9 +389,10 @@ static inline void handle_regs_int(struct urb *urb)
 	struct zd_usb_interrupt *intr = &usb->intr;
 	int len;
 	u16 int_num;
+	unsigned long flags;
 
 	ZD_ASSERT(in_interrupt());
-	spin_lock(&intr->lock);
+	spin_lock_irqsave(&intr->lock, flags);
 
 	int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
 	if (int_num == CR_INTERRUPT) {
@@ -426,7 +428,7 @@ static inline void handle_regs_int(struct urb *urb)
 	}
 
 out:
-	spin_unlock(&intr->lock);
+	spin_unlock_irqrestore(&intr->lock, flags);
 
 	/* CR_INTERRUPT might override read_reg too. */
 	if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
@@ -666,6 +668,7 @@ static void rx_urb_complete(struct urb *urb)
 	struct zd_usb_rx *rx;
 	const u8 *buffer;
 	unsigned int length;
+	unsigned long flags;
 
 	switch (urb->status) {
 	case 0:
@@ -694,14 +697,14 @@ static void rx_urb_complete(struct urb *urb)
 		/* If there is an old first fragment, we don't care. */
 		dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
 		ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment));
-		spin_lock(&rx->lock);
+		spin_lock_irqsave(&rx->lock, flags);
 		memcpy(rx->fragment, buffer, length);
 		rx->fragment_length = length;
-		spin_unlock(&rx->lock);
+		spin_unlock_irqrestore(&rx->lock, flags);
 		goto resubmit;
 	}
 
-	spin_lock(&rx->lock);
+	spin_lock_irqsave(&rx->lock, flags);
 	if (rx->fragment_length > 0) {
 		/* We are on a second fragment, we believe */
 		ZD_ASSERT(length + rx->fragment_length <=
@@ -711,9 +714,9 @@ static void rx_urb_complete(struct urb *urb)
 		handle_rx_packet(usb, rx->fragment,
 			         rx->fragment_length + length);
 		rx->fragment_length = 0;
-		spin_unlock(&rx->lock);
+		spin_unlock_irqrestore(&rx->lock, flags);
 	} else {
-		spin_unlock(&rx->lock);
+		spin_unlock_irqrestore(&rx->lock, flags);
 		handle_rx_packet(usb, buffer, length);
 	}
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v1 32/49] wireless: ath9k: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, Ming Lei, Luis R. Rodriguez,
	John W. Linville, linux-wireless, netdev
In-Reply-To: <1376756714-25479-1-git-send-email-ming.lei@canonical.com>

Complete() will be run with interrupt enabled, so change to
spin_lock_irqsave().

Cc: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
 drivers/net/wireless/ath/ath9k/hif_usb.c      |   29 ++++++++++++++-----------
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c |    9 ++++----
 drivers/net/wireless/ath/ath9k/wmi.c          |   11 +++++-----
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 6d5d716..5efc1f0 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -136,6 +136,7 @@ static void hif_usb_mgmt_cb(struct urb *urb)
 	struct cmd_buf *cmd = (struct cmd_buf *)urb->context;
 	struct hif_device_usb *hif_dev;
 	bool txok = true;
+	unsigned long flags;
 
 	if (!cmd || !cmd->skb || !cmd->hif_dev)
 		return;
@@ -155,14 +156,14 @@ static void hif_usb_mgmt_cb(struct urb *urb)
 		 * If the URBs are being flushed, no need to complete
 		 * this packet.
 		 */
-		spin_lock(&hif_dev->tx.tx_lock);
+		spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 		if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
-			spin_unlock(&hif_dev->tx.tx_lock);
+			spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 			dev_kfree_skb_any(cmd->skb);
 			kfree(cmd);
 			return;
 		}
-		spin_unlock(&hif_dev->tx.tx_lock);
+		spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 		break;
 	default:
@@ -253,6 +254,7 @@ static void hif_usb_tx_cb(struct urb *urb)
 	struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
 	struct hif_device_usb *hif_dev;
 	bool txok = true;
+	unsigned long flags;
 
 	if (!tx_buf || !tx_buf->hif_dev)
 		return;
@@ -272,13 +274,13 @@ static void hif_usb_tx_cb(struct urb *urb)
 		 * If the URBs are being flushed, no need to add this
 		 * URB to the free list.
 		 */
-		spin_lock(&hif_dev->tx.tx_lock);
+		spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 		if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) {
-			spin_unlock(&hif_dev->tx.tx_lock);
+			spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 			ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
 			return;
 		}
-		spin_unlock(&hif_dev->tx.tx_lock);
+		spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 		break;
 	default:
@@ -293,13 +295,13 @@ static void hif_usb_tx_cb(struct urb *urb)
 	__skb_queue_head_init(&tx_buf->skb_queue);
 
 	/* Add this TX buffer to the free list */
-	spin_lock(&hif_dev->tx.tx_lock);
+	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
 	hif_dev->tx.tx_buf_cnt++;
 	if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
 		__hif_usb_tx(hif_dev); /* Check for pending SKBs */
 	TX_STAT_INC(buf_completed);
-	spin_unlock(&hif_dev->tx.tx_lock);
+	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 }
 
 /* TX lock has to be taken */
@@ -530,8 +532,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 	int rx_remain_len, rx_pkt_len;
 	u16 pool_index = 0;
 	u8 *ptr;
+	unsigned long flags;
 
-	spin_lock(&hif_dev->rx_lock);
+	spin_lock_irqsave(&hif_dev->rx_lock, flags);
 
 	rx_remain_len = hif_dev->rx_remain_len;
 	rx_pkt_len = hif_dev->rx_transfer_len;
@@ -559,7 +562,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 		}
 	}
 
-	spin_unlock(&hif_dev->rx_lock);
+	spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
 
 	while (index < len) {
 		u16 pkt_len;
@@ -585,7 +588,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 		index = index + 4 + pkt_len + pad_len;
 
 		if (index > MAX_RX_BUF_SIZE) {
-			spin_lock(&hif_dev->rx_lock);
+			spin_lock_irqsave(&hif_dev->rx_lock, flags);
 			hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
 			hif_dev->rx_transfer_len =
 				MAX_RX_BUF_SIZE - chk_idx - 4;
@@ -595,7 +598,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 			if (!nskb) {
 				dev_err(&hif_dev->udev->dev,
 					"ath9k_htc: RX memory allocation error\n");
-				spin_unlock(&hif_dev->rx_lock);
+				spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
 				goto err;
 			}
 			skb_reserve(nskb, 32);
@@ -606,7 +609,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 
 			/* Record the buffer pointer */
 			hif_dev->remain_skb = nskb;
-			spin_unlock(&hif_dev->rx_lock);
+			spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
 		} else {
 			nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
 			if (!nskb) {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index e602c95..a6f34f8 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -1156,25 +1156,26 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
+	unsigned long flags;
 
-	spin_lock(&priv->rx.rxbuflock);
+	spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 		if (!tmp_buf->in_process) {
 			rxbuf = tmp_buf;
 			break;
 		}
 	}
-	spin_unlock(&priv->rx.rxbuflock);
+	spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
 
 	if (rxbuf == NULL) {
 		ath_dbg(common, ANY, "No free RX buffer\n");
 		goto err;
 	}
 
-	spin_lock(&priv->rx.rxbuflock);
+	spin_lock_irqsave(&priv->rx.rxbuflock, flags);
 	rxbuf->skb = skb;
 	rxbuf->in_process = true;
-	spin_unlock(&priv->rx.rxbuflock);
+	spin_unlock_irqrestore(&priv->rx.rxbuflock, flags);
 
 	tasklet_schedule(&priv->rx_tasklet);
 	return;
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 65c8894..101b771 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -207,6 +207,7 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
 	struct wmi *wmi = (struct wmi *) priv;
 	struct wmi_cmd_hdr *hdr;
 	u16 cmd_id;
+	unsigned long flags;
 
 	if (unlikely(wmi->stopped))
 		goto free_skb;
@@ -215,20 +216,20 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
 	cmd_id = be16_to_cpu(hdr->command_id);
 
 	if (cmd_id & 0x1000) {
-		spin_lock(&wmi->wmi_lock);
+		spin_lock_irqsave(&wmi->wmi_lock, flags);
 		__skb_queue_tail(&wmi->wmi_event_queue, skb);
-		spin_unlock(&wmi->wmi_lock);
+		spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 		tasklet_schedule(&wmi->wmi_event_tasklet);
 		return;
 	}
 
 	/* Check if there has been a timeout. */
-	spin_lock(&wmi->wmi_lock);
+	spin_lock_irqsave(&wmi->wmi_lock, flags);
 	if (cmd_id != wmi->last_cmd_id) {
-		spin_unlock(&wmi->wmi_lock);
+		spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 		goto free_skb;
 	}
-	spin_unlock(&wmi->wmi_lock);
+	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 
 	/* WMI command response */
 	ath9k_wmi_rsp_callback(wmi, skb);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v1 00/49] USB: prepare for enabling irq in complete()
From: Ming Lei @ 2013-08-17 16:24 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, Oliver Neukum, Alan Stern, linux-input,
	linux-bluetooth, netdev, linux-wireless, linux-media, alsa-devel

Hi,

As we are going to run URB->complete() in tasklet context[1][2], and
hard interrupt may be enabled when running URB completion handler[3],
so we might need to disable interrupt when acquiring one lock in
the completion handler for the below reasons:

- URB->complete() holds a subsystem wide lock which may be acquired
in another hard irq context, and the subsystem wide lock is acquired
by spin_lock()/read_lock()/write_lock() in complete()

- URB->complete() holds a private lock with spin_lock()/read_lock()/write_lock()
but driver may export APIs to make other drivers acquire the same private
lock in its interrupt handler.

For the sake of safety and making the change simple, this patch set
converts all spin_lock()/read_lock()/write_lock() in completion handler
path into their irqsave version mechanically.

But if you are sure the above two cases do not happen in your driver,
please let me know and I can drop the unnecessary change.

Also if you find some conversions are missed, also please let me know so
that I can add it in the next round.


[1], USB: URB documentation: claim complete() will be run with IRQs enabled
https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=85721d45261c4be684730c7509a59daa6cda30d8

[2], USB: HCD: support giveback of URB in tasklet context
https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=94dfd7edfd5c9b605caf7b562de7a813d216e011

[3], http://marc.info/?l=linux-usb&m=137286330626363&w=2

V1:
	- rename patchset title
	- add missed changes on 'usb_skeleon and usb sg lib'
	- remove several sound usb drivers which have been done via sound tree
	- some patch style fix
	- replace snd_pcm_stream_lock with snd_pcm_stream_lock_irqsave for related
	a/v drivers

Cc: linux-input@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org
Cc: linux-media@vger.kernel.org
Cc: alsa-devel@alsa-project.org

 drivers/bluetooth/bfusb.c                     |   12 ++++----
 drivers/bluetooth/btusb.c                     |    5 ++--
 drivers/hid/usbhid/hid-core.c                 |    5 ++--
 drivers/input/misc/cm109.c                    |   10 ++++---
 drivers/isdn/hardware/mISDN/hfcsusb.c         |   36 ++++++++++++-----------
 drivers/media/dvb-core/dvb_demux.c            |   17 +++++++----
 drivers/media/usb/cx231xx/cx231xx-audio.c     |   10 ++++---
 drivers/media/usb/cx231xx/cx231xx-core.c      |   10 ++++---
 drivers/media/usb/cx231xx/cx231xx-vbi.c       |    5 ++--
 drivers/media/usb/em28xx/em28xx-audio.c       |    5 ++--
 drivers/media/usb/em28xx/em28xx-core.c        |    5 ++--
 drivers/media/usb/sn9c102/sn9c102_core.c      |    7 +++--
 drivers/media/usb/tlg2300/pd-alsa.c           |    5 ++--
 drivers/media/usb/tlg2300/pd-video.c          |    5 ++--
 drivers/media/usb/tm6000/tm6000-video.c       |    5 ++--
 drivers/net/usb/cdc-phonet.c                  |    5 ++--
 drivers/net/usb/hso.c                         |   38 ++++++++++++++-----------
 drivers/net/usb/kaweth.c                      |    7 +++--
 drivers/net/usb/rtl8150.c                     |    5 ++--
 drivers/net/wireless/ath/ath9k/hif_usb.c      |   29 ++++++++++---------
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c |    9 +++---
 drivers/net/wireless/ath/ath9k/wmi.c          |   11 +++----
 drivers/net/wireless/ath/carl9170/rx.c        |    5 ++--
 drivers/net/wireless/libertas/if_usb.c        |    5 ++--
 drivers/net/wireless/libertas_tf/if_usb.c     |    6 ++--
 drivers/net/wireless/zd1211rw/zd_usb.c        |   21 ++++++++------
 drivers/staging/bcm/InterfaceRx.c             |    5 ++--
 drivers/staging/btmtk_usb/btmtk_usb.c         |    5 ++--
 drivers/staging/ced1401/usb1401.c             |   35 ++++++++++++-----------
 drivers/staging/vt6656/usbpipe.c              |    9 +++---
 drivers/usb/class/cdc-wdm.c                   |   16 +++++++----
 drivers/usb/class/usblp.c                     |   10 ++++---
 drivers/usb/core/devio.c                      |    5 ++--
 drivers/usb/core/message.c                    |    5 ++--
 drivers/usb/misc/adutux.c                     |   10 ++++---
 drivers/usb/misc/iowarrior.c                  |    5 ++--
 drivers/usb/misc/ldusb.c                      |    7 +++--
 drivers/usb/misc/legousbtower.c               |    6 ++--
 drivers/usb/misc/usbtest.c                    |   10 ++++---
 drivers/usb/misc/uss720.c                     |    7 ++++-
 drivers/usb/serial/cyberjack.c                |   15 ++++++----
 drivers/usb/serial/digi_acceleport.c          |   23 ++++++++-------
 drivers/usb/serial/io_edgeport.c              |   14 +++++----
 drivers/usb/serial/io_ti.c                    |    5 ++--
 drivers/usb/serial/mos7720.c                  |    5 ++--
 drivers/usb/serial/mos7840.c                  |    5 ++--
 drivers/usb/serial/quatech2.c                 |    5 ++--
 drivers/usb/serial/sierra.c                   |    9 +++---
 drivers/usb/serial/symbolserial.c             |    5 ++--
 drivers/usb/serial/ti_usb_3410_5052.c         |    9 +++---
 drivers/usb/serial/usb_wwan.c                 |    5 ++--
 drivers/usb/usb-skeleton.c                    |   11 ++++---
 sound/usb/caiaq/audio.c                       |    5 ++--
 sound/usb/midi.c                              |    5 ++--
 54 files changed, 318 insertions(+), 221 deletions(-)


Thanks,
--
Ming Lei


^ permalink raw reply

* Re: [PATCH 1/1] Delete duplicate code. Use of the variable instead call a function
From: Sergey K @ 2013-08-17 15:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <1376741797-25505-2-git-send-email-perplexus@ya.ru>

Sergey K <perplexus@...> writes:

> 
> ---
>  net/mac80211/tx.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
> index 098ae85..79db7f3 100644
> --- a/net/mac80211/tx.c
> +++ b/net/mac80211/tx.c
>  <at>  <at>  -1769,8 +1769,6  <at>  <at>  netdev_tx_t 
ieee80211_subif_start_xmit(struct sk_buff *skb,
>  			memcpy(hdr.addr3, skb->data, ETH_ALEN);
>  			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
>  			hdrlen = 30;
> -			authorized = test_sta_flag(sta, 
WLAN_STA_AUTHORIZED);
> -			wme_sta = test_sta_flag(sta, WLAN_STA_WME);
>  		}
>  		ap_sdata = container_of(sdata->bss, struct 
ieee80211_sub_if_data,
>  					u.ap);
>  <at>  <at>  -1979,7 +1977,7  <at>  <at>  netdev_tx_t 
ieee80211_subif_start_xmit(struct sk_buff *skb,
>  	 * EAPOL frames from the local station.
>  	 */
>  	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
> -		     !is_multicast_ether_addr(hdr.addr1) && !authorized &&
> +		     !multicast && !authorized &&
>  		     (cpu_to_be16(ethertype) != sdata-
>control_port_protocol ||
>  		      !ether_addr_equal(sdata->vif.addr, skb->data + 
ETH_ALEN)))) {
>  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG


We need to delete authorized and wme_sta flags, because these flags are set 
below:

1956         multicast = is_multicast_ether_addr(hdr.addr1);
1957         if (!multicast) {
1958                 sta = sta_info_get(sdata, hdr.addr1);
1959                 if (sta) {
1960                         authorized = test_sta_flag(sta, 
WLAN_STA_AUTHORIZED);
1961                         wme_sta = test_sta_flag(sta, WLAN_STA_WME);
1962                 }
1963         }



^ permalink raw reply

* [PATCH 1/1] Delete duplicate code. Use of the variable instead call a function
From: Sergey K @ 2013-08-17 12:16 UTC (permalink / raw)
  To: linux-wireless; +Cc: Sergey K
In-Reply-To: <1376741797-25505-1-git-send-email-perplexus@ya.ru>

---
 net/mac80211/tx.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 098ae85..79db7f3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1769,8 +1769,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
 			hdrlen = 30;
-			authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
-			wme_sta = test_sta_flag(sta, WLAN_STA_WME);
 		}
 		ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
 					u.ap);
@@ -1979,7 +1977,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	 * EAPOL frames from the local station.
 	 */
 	if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
-		     !is_multicast_ether_addr(hdr.addr1) && !authorized &&
+		     !multicast && !authorized &&
 		     (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
 		      !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- 
1.8.1.5


^ permalink raw reply related

* [PATCH 0/1] *** mac80211: delete duplicate code ***
From: Sergey K @ 2013-08-17 12:16 UTC (permalink / raw)
  To: linux-wireless; +Cc: Sergey K

*** BLURB HERE ***

Sergey K (1):
  Delete duplicate code. Use of the variable instead call a function

 net/mac80211/tx.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

-- 
1.8.1.5


^ permalink raw reply

* [PATCH v2 6/6] rt2x00: rt2800lib: adjust frequency offset for RF3053
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

Along with other chipsets, the Ralink driver uses the
frequency adjustment code for RF3053 as well. Remove
the bogus place-holder comment from the RF3053 specific
channel configuration function and call the frequency
adjustment function instead

Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.

Reference:
  RT3593_ChipSwitchChannel function in chips/rt3593.c

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 1b81fc9..aa6b6b0 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2360,7 +2360,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 	}
 	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
 
-	/* TODO: frequency calibration? */
+	rt2800_adjust_freq_offset(rt2x00dev);
 
 	if (conf_is_ht40(conf)) {
 		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40,
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 5/6] rt2x00: rt2800lib: move rt2800_adjust_freq_offset function
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

Move the rt2800_adjust_freq_offset function before
the channel configuration functions to make it usable
from those without a forward declaration.

The patch contains no functional changes.

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   73 ++++++++++++++++---------------
 1 file changed, 37 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 623ad9d..1b81fc9 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1875,6 +1875,43 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 	rt2x00dev->lna_gain = lna_gain;
 }
 
+#define FREQ_OFFSET_BOUND	0x5f
+
+static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
+{
+	u8 freq_offset, prev_freq_offset;
+	u8 rfcsr, prev_rfcsr;
+
+	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
+	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
+
+	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	prev_rfcsr = rfcsr;
+
+	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
+	if (rfcsr == prev_rfcsr)
+		return;
+
+	if (rt2x00_is_usb(rt2x00dev)) {
+		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
+				   freq_offset, prev_rfcsr);
+		return;
+	}
+
+	prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
+	while (prev_freq_offset != freq_offset) {
+		if (prev_freq_offset < freq_offset)
+			prev_freq_offset++;
+		else
+			prev_freq_offset--;
+
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
+		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+		usleep_range(1000, 1500);
+	}
+}
+
 static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
 					 struct ieee80211_conf *conf,
 					 struct rf_channel *rf,
@@ -2492,42 +2529,6 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 
 #define POWER_BOUND		0x27
 #define POWER_BOUND_5G		0x2b
-#define FREQ_OFFSET_BOUND	0x5f
-
-static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
-{
-	u8 freq_offset, prev_freq_offset;
-	u8 rfcsr, prev_rfcsr;
-
-	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
-	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
-
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	prev_rfcsr = rfcsr;
-
-	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
-	if (rfcsr == prev_rfcsr)
-		return;
-
-	if (rt2x00_is_usb(rt2x00dev)) {
-		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
-				   freq_offset, prev_rfcsr);
-		return;
-	}
-
-	prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
-	while (prev_freq_offset != freq_offset) {
-		if (prev_freq_offset < freq_offset)
-			prev_freq_offset++;
-		else
-			prev_freq_offset--;
-
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
-		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
-
-		usleep_range(1000, 1500);
-	}
-}
 
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
 					 struct ieee80211_conf *conf,
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 4/6] rt2x00: rt2800lib: use step-by-step frequency offset adjustment on MMIO devices
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

According to the DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver, the RFCSR17 register can't be programmed in
one step on devices which are using the frequency
offset adjustment code.

Update the code to use step-by-step adjustment.

Reference:
  RT30xxWriteRFRegister function in common/rt_rf.c

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1:
  - new patch
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index bebc56f..623ad9d 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2496,7 +2496,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 
 static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
 {
-	u8 freq_offset;
+	u8 freq_offset, prev_freq_offset;
 	u8 rfcsr, prev_rfcsr;
 
 	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
@@ -2509,11 +2509,24 @@ static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
 	if (rfcsr == prev_rfcsr)
 		return;
 
-	if (rt2x00_is_usb(rt2x00dev))
+	if (rt2x00_is_usb(rt2x00dev)) {
 		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
 				   freq_offset, prev_rfcsr);
-	else
+		return;
+	}
+
+	prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE);
+	while (prev_freq_offset != freq_offset) {
+		if (prev_freq_offset < freq_offset)
+			prev_freq_offset++;
+		else
+			prev_freq_offset--;
+
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset);
 		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+		usleep_range(1000, 1500);
+	}
 }
 
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 3/6] rt2x00: rt2800lib: use a MCU command for frequency adjustment on USB devices
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

According to the Ralink driver, there is an MCU
command which can be used to send the frequency
offset value directly to the USB device without
going through the RFCSR writing sequence.

Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.

Reference:
  RTMPAdjustFrequencyOffset function in common/rt_rf.c

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1:
  - add a MCU_FREQ_OFFSET constant and use that instead
    of a hardcoded number
---
 drivers/net/wireless/rt2x00/rt2800.h    |    1 +
 drivers/net/wireless/rt2x00/rt2800lib.c |    6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 6e69b96..e25e5bf 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2794,6 +2794,7 @@ enum rt2800_eeprom_word {
 #define MCU_RADAR			0x60
 #define MCU_BOOT_SIGNAL			0x72
 #define MCU_ANT_SELECT			0X73
+#define MCU_FREQ_OFFSET			0x74
 #define MCU_BBP_SIGNAL			0x80
 #define MCU_POWER_SAVE			0x83
 #define MCU_BAND_SELECT		0x91
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 3407ac9..bebc56f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2509,7 +2509,11 @@ static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
 	if (rfcsr == prev_rfcsr)
 		return;
 
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	if (rt2x00_is_usb(rt2x00dev))
+		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff,
+				   freq_offset, prev_rfcsr);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 }
 
 static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 1/6] rt2x00: rt2800lib: fix frequency offset boundary calculation
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

The current code in the 'rt2800_adjust_freq_offset'
function limits the device specific frequency offset
value to FREQ_BOUND but ignores the fact that the
uppermost bit is not part of the frequency offset
value. As the result, the driver always uses the
FREQ_BOUND value if the uppermost bit is set.

Update the code to use the correct source value
for calculating the boundary.

Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.

Reference:
  RTMPAdjustFrequencyOffset function in common/rt_rf.c

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 2f64034..de27277 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2496,13 +2496,14 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 
 static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
 {
+	u8 freq_offset;
 	u8 rfcsr;
 
+	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
+	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
+
 	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND)
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND);
-	else
-		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
 	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 }
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 2/6] rt2x00: rt2800lib: optimize frequency offset adjustment
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos
In-Reply-To: <1376741373-10032-1-git-send-email-juhosg@openwrt.org>

Don't write the new value into the register if it is
the same as the old value to avoid unncessary USB bus
traffic with USB devices. The change also saves a few
cycle on MMIO based devices.

Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629
driver.

Reference:
  RTMPAdjustFrequencyOffset function in common/rt_rf.c

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
Changes since v1: ---
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index de27277..3407ac9 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2497,13 +2497,18 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev)
 {
 	u8 freq_offset;
-	u8 rfcsr;
+	u8 rfcsr, prev_rfcsr;
 
 	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE);
 	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND);
 
 	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	prev_rfcsr = rfcsr;
+
 	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset);
+	if (rfcsr == prev_rfcsr)
+		return;
+
 	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 }
 
-- 
1.7.10

^ permalink raw reply related

* [PATCH v2 0/6] rt2x00: rt2800lib: frequency offset adjustment fixes
From: Gabor Juhos @ 2013-08-17 12:09 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Gabor Juhos

The patch-set contain small fixes for the frequency adjustment
code of the rt2800 driver.

Gabor Juhos (6):
  rt2x00: rt2800lib: fix frequency offset boundary calculation
  rt2x00: rt2800lib: optimize frequency offset adjustment
  rt2x00: rt2800lib: use a MCU command for frequency adjustment on USB
    devices
  rt2x00: rt2800lib: use step-by-step frequency offset adjustment on
    MMIO devices
  rt2x00: rt2800lib: move rt2800_adjust_freq_offset function
  rt2x00: rt2800lib: adjust frequency offset for RF3053

 drivers/net/wireless/rt2x00/rt2800.h    |    1 +
 drivers/net/wireless/rt2x00/rt2800lib.c |   52 ++++++++++++++++++++++---------
 2 files changed, 39 insertions(+), 14 deletions(-)

--
1.7.10

^ permalink raw reply

* Re: [PATCH 0/5] rt2x00: rt2800lib: frequency offset adjustment fixes
From: Gabor Juhos @ 2013-08-17  9:50 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <1376685498-5167-1-git-send-email-juhosg@openwrt.org>

2013.08.16. 22:38 keltezéssel, Gabor Juhos írta:
> The patch-set contain small fixes for the frequency adjustment 
> code of the rt2800 driver.
> 
> Gabor Juhos (5):
>   rt2x00: rt2800lib: fix frequency offset boundary calculation
>   rt2x00: rt2800lib: optimize frequency offset adjustment
>   rt2x00: rt2800lib: use a MCU command for frequency adjustment on USB
>     devices
>   rt2x00: rt2800lib: move rt2800_adjust_freq_offset function
>   rt2x00: rt2800lib: adjust frequency offset for RF3053
> 
>  drivers/net/wireless/rt2x00/rt2800lib.c |   38 +++++++++++++++++++------------
>  1 file changed, 24 insertions(+), 14 deletions(-)
> 

John,

Please ignore this set. I will send a slightly improved version.

-Gabor

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox