Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: mac80211:  3.9.0+:  Invalid WDS/flush state and non-connecting station.
From: Ben Greear @ 2013-05-08 16:18 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <5182D078.4020605@candelatech.com>

On 05/02/2013 01:45 PM, Ben Greear wrote:
> On 05/02/2013 01:24 PM, Johannes Berg wrote:
>> On Thu, 2013-05-02 at 12:50 -0700, Ben Greear wrote:
>>> Kernel is hacked 3.9.0+
>>
>> Clearly :)
>>
>>> I've been seeing this problem for a while (and posted about it previously).  The problem
>>> is that a station appears to associate fine, but never actually 'connects'.  This problem
>>> is not easy to reproduce...
>>
>> It would be useful to know what you added ... the message you point to
>> (invalid wds/flush whatever) doesn't exist upstream.
>
> Gobs of stuff, as usual.  Thought I had that WDS thing pushed upstream,
> but I guess not.

Ok, I reproduced this with yet more debugging printouts in the kernel.

The symptom is this:

The sme_state is SME_CONNECTED, so it bails out below before sending the
'connected' message to user-space.

void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                                const u8 *req_ie, size_t req_ie_len,
                                const u8 *resp_ie, size_t resp_ie_len,
                                u16 status, bool wextev,
                                struct cfg80211_bss *bss)
{
         struct wireless_dev *wdev = dev->ieee80211_ptr;
         const u8 *country_ie;
#ifdef CONFIG_CFG80211_WEXT
         union iwreq_data wrqu;
#endif

         ASSERT_WDEV_LOCK(wdev);

         printk("connect_result: %s: type: %i  sme_state: %i\n",
                dev->name, (int)(wdev->iftype), (int)(wdev->sme_state));

         if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
                     wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
                 return;

         if (wdev->sme_state != CFG80211_SME_CONNECTING)
                 return;

>
> http://dmz2.candelatech.com/git/gitweb.cgi?p=linux-3.9.dev.y/.git;a=summary
>
> That message comes from:
>
>      /*
>       * Remove all stations associated with this interface.
>       *
>       * This must be done before calling ops->remove_interface()
>       * because otherwise we can later invoke ops->sta_notify()
>       * whenever the STAs are removed, and that invalidates driver
>       * assumptions about always getting a vif pointer that is valid
>       * (because if we remove a STA after ops->remove_interface()
>       * the driver will have removed the vif info already!)
>       *
>       * This is relevant only in WDS mode, in all other modes we've
>       * already removed all stations when disconnecting or similar,
>       * so warn otherwise.
>       *
>       * We call sta_info_flush_cleanup() later, to combine RCU waits.
>       */
>      flushed = sta_info_flush_defer(sdata);
>      if ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
>          (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)) {
>          sdata_info(sdata,
>                 "Invalid WDS/flush state, type: %i  WDS: %i  flushed: %i\n",
>                 sdata->vif.type, NL80211_IFTYPE_WDS, flushed);
>          WARN_ON_ONCE(1);
>      }
>
> I notice __cfg80211_connect_result checks the wdev state, so I added some
> printouts there to see if it is bailing due to some funny state, but will
> probably be a while before I reproduce it again and know for sure.
>
> Thanks,
> Ben
>
>
>>
>> johannes
>>
>
>


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: [ath9k-devel] [PATCH RFC] ath9k: collect statistics about Rx-Dup and Rx-STBC packets
From: Ben Greear @ 2013-05-08 16:07 UTC (permalink / raw)
  To: Sujith Manoharan
  Cc: Felix Fietkau, Oleksij Rempel, ath9k-devel, linux-wireless
In-Reply-To: <20873.58246.410990.985421@gargle.gargle.HOWL>

On 05/07/2013 10:32 PM, Sujith Manoharan wrote:
> Felix Fietkau wrote:
>> The problem I have with the current stats is they're just an arbitrary
>> collection of random stuff that is probably useless for 99% of all
>> users. In many cases the way the stats are collected also makes the data
>> completely meaningless (e.g. because the source/destination address is
>> not taken into account).
>>
>> Why care about the number of packets on the air that were sent with a
>> specific rate flag? Why care about the number of beacons on the air
>> (with no filter on a set of APs or anything)? Or what about the number
>> of fragments received? To me it just looks like an incoherent set of
>> useless facts.
>
> Yes, having per-station statistics would be useful, mainly for RX and TX. Right
> now, all the counters are global and there is no way to find out how a
> particular station is performing, especially in AP mode. Since mac80211 gives us
> proper debugfs hooks for station addition/deletion, relevant stuff can be moved
> there.
>
> The 'recv' file used to be just for HW errors (DESC, CRC etc.), now it has various
> counters that should probably be node-specific.
>
> The 'xmit' file can be trimmed and information can be maintained per-station.
> This will be really useful in AP mode - especially for diagnosing aggregation, QoS, PS etc.

I think it's good to keep global counters too..otherwise it is going to be
a lot of work to gather per NIC stats, and since you would have to read for each
station, your stats might not be quite as atomic as they used to be.

But, I'm fine with adding per-station counters on top of the global
stats.

Thanks,
Ben

>
> Other than these two files, the rest are simple.
>
> Sujith
>


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: Linux driver for Realtek RTL8723AU devices with USB ID 0bda:1724 such as found in Lenovo IdeaPad Yoga 13
From: Larry Finger @ 2013-05-08 16:06 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: linux-wireless, LKML, netdev, Dan Williams, 'George0505',
	Joon Ro, Greg KH
In-Reply-To: <5189B939.4010905@zytor.com>

On 05/07/2013 09:32 PM, H. Peter Anvin wrote:
>
> So I can verify that this driver works against 3.8.11 (not against
> current -linus because of a build failure), and yes, there is Bluetooth
> in this device.  In fact, it seems to work better than some in-tree
> drivers I have seen in the past.
>
> However, I'm confused as to the above and what it implies for the
> purpose of the staging tree.  Wasn't the whole point of the staging tree
> to have a working-but-ugly driver upstream and have the work to clean it
> up happen in the mainline tree instead of off somewhere.

Yes, but even staging has some standards. For example, they frown on inclusion 
of firmware in a massive data block in a file in the driver - it should be in a 
separate file the /lib/firmware/ tree. In addition, the mainline 
drivers/net/wireless/ tree is only available to devices that use mac80211 for 
the software-based MAC layer. That conversion is a serious effort that may never 
be done, thus the 8723au driver may never leave staging.

What are the details of the build failure on the mainline tree? It builds fine 
here. One possibility is that your source tree has a leftover copy of 
include/linux/version.h that contains a stale coded value of the kernel version. 
I just pushed a Makefile fix that causes the compiler to look in the new 
location for version.h first. If that doesn't work, please post the error.

Larry



^ permalink raw reply

* Re: Fun with QoS in AP mode.
From: Ben Greear @ 2013-05-08 15:15 UTC (permalink / raw)
  To: Sujith Manoharan; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <20873.56643.216380.594657@gargle.gargle.HOWL>

On 05/07/2013 10:06 PM, Sujith Manoharan wrote:
> Ben Greear wrote:
>> We were doing some testing with ToS/QoS in some VOIP streams today.
>>
>> The mappings on the station machine work fine, but on the AP, the packets
>> always go to the BE queue.  Both systems are 3.9.0+ ath9k, recent hostapd,
>> supplicant, etc.
>
> Is the AP running ath9k ?

Yes, both AP and Station machine are ath9k, 3.9.0+, etc....

Basically identicaly hardware and software loads..just one is acting as AP
and one as station(s) in this scenario.

Ben

>
> Sujith
>


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply

* Re: Linux summit this year ?
From: John W. Linville @ 2013-05-08 15:09 UTC (permalink / raw)
  To: Seth Forshee
  Cc: Johannes Berg, Marcel Holtmann, Larry Finger, Matt Chen, joeyli,
	linux-wireless
In-Reply-To: <20130507174445.GB2073@tuxdriver.com>

On Tue, May 07, 2013 at 01:44:45PM -0400, John W. Linville wrote:
> On Tue, May 07, 2013 at 11:42:36AM -0500, Seth Forshee wrote:
> > On Fri, May 03, 2013 at 10:49:47AM -0400, John W. Linville wrote:
> > > On Fri, May 03, 2013 at 10:11:10AM +0200, Johannes Berg wrote:
> > > > On Thu, 2013-05-02 at 15:43 -0400, John W. Linville wrote:
> > > > 
> > > > > "I'm confirming that we got the space you needed for the Wireless Summit in
> > > > > New Orleans.
> > > > 
> > > > > Does that sound alright to everyone?  
> > > > 
> > > > Sounds good to me. If it overlaps LPC, which one are people going to
> > > > have to register for (if not going to both anyway)?
> > > 
> > > I would presume that if you want to got to LPC sessions then you
> > > would have to register for LPC.  Generally we have required Wireless
> > > Summit attendees to register for LinuxCon, and I presume that would
> > > be required this time (so both LinuxCon and LPC if you want the
> > > LPC sessions).
> > 
> > Why require LinuxCon registration rather than LPC? I'd assume most
> > wireless summit attendees are more interested in plumbers than LinuxCon.
> > Could the summit just require registration at one or the other?
> 
> Well, I can ask.  But the fact is that LPC and LCNA are separate
> events with separate events with separate budgets and expenses,
> separate organizers, etc.
> 
> Anyway, I'll let you know what the event folks say...

Angela says:

"Yes, they can either register for LPC or LinuxCon/CloudOpen."

Hth!

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: Wifi signal level differences
From: nick @ 2013-05-08 14:42 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-wireless
In-Reply-To: <1368023384.1664.10.camel@dcbw.foobar.com>


Hi Dan,
Thanks for the prompt reply.

The Fedora 12 Linux PC (X86) is running with kernel 2.6.31.5 .
And, the embedded device is 2.6.32.16 .


Thanks for the info on where the calculation is actually done. I can look in the mac80211 code to see if there is a difference.


Regards

Nick







^ permalink raw reply

* Re: Wifi signal level differences
From: Dan Williams @ 2013-05-08 14:29 UTC (permalink / raw)
  To: nick; +Cc: linux-wireless
In-Reply-To: <7566504.38231368021104217.JavaMail.www@wwinf3714>

On Wed, 2013-05-08 at 15:51 +0200, nick@nhthomas.freeserve.co.uk wrote:
> Hi,
> 
> I have an Atheros ath6kl_usb based wifi dongle.
> I am using it with an embedded project.
> 
> The driver code can be built for either X86 or sh4 hardware - so I can also use the same USB wifi dongle on my Fedora 12 Linux PC or plugged in to the embedded device.
> It's working fine in both situations.
> 
> But, I notice that the signal level reported in /proc/net/wireless is slightly different between the two units.
> Note, I am using the same physical Atheros wifi dongle, and moving it from one device to the other to this test.
> 
> I notice that when using the X86 PC I see a signal level of -61, which is marginally better than the -66 I see in the embedded device.
> 
> I know that this isn't an exact science - but using a short USB extension lead I can orientate the wifi dongle to be in the same place and orientation when plugged in to either device.
> So, I would expect the wifi signal strength to be reported the same !?
> 
> I know there are many differences between my Fedora 12 PC, and the embedded STLinux project - not least that the driver is compiled using different compilers.
> 
> But, I was wondering what else could explain the difference in signal levels between the two?
> 
> Also, which part of the driver code is responsible for reading/calculating the signal level value?

What kernel versions is each system running?  The kernel's mac80211
stack is what calculates the actual dBm/RSSI value based on information
given from the dongle firmware.  And the calculations may change in
different kernel versions.  Second make sure you compare the firmware
versions that you have on the two systems to see if they are different;
it's also possible that different firmware versions calculate signal
strength differently.

In the end though, the difference between -61 and -66 isn't worth
worrying about, since in the same location without moving the signal
level can change by that much from one second to the next.

Dan


^ permalink raw reply

* Wifi signal level differences
From: nick @ 2013-05-08 13:51 UTC (permalink / raw)
  To: linux-wireless

Hi,

I have an Atheros ath6kl_usb based wifi dongle.
I am using it with an embedded project.

The driver code can be built for either X86 or sh4 hardware - so I can also use the same USB wifi dongle on my Fedora 12 Linux PC or plugged in to the embedded device.
It's working fine in both situations.

But, I notice that the signal level reported in /proc/net/wireless is slightly different between the two units.
Note, I am using the same physical Atheros wifi dongle, and moving it from one device to the other to this test.

I notice that when using the X86 PC I see a signal level of -61, which is marginally better than the -66 I see in the embedded device.

I know that this isn't an exact science - but using a short USB extension lead I can orientate the wifi dongle to be in the same place and orientation when plugged in to either device.
So, I would expect the wifi signal strength to be reported the same !?

I know there are many differences between my Fedora 12 PC, and the embedded STLinux project - not least that the driver is compiled using different compilers.

But, I was wondering what else could explain the difference in signal levels between the two?

Also, which part of the driver code is responsible for reading/calculating the signal level value?


Regards

Nick

^ permalink raw reply

* [PATCH v2] wireless: move crypto constants to ieee80211.h
From: Johannes Berg @ 2013-05-08 13:34 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

mac80211 and the Intel drivers all define crypto
constants, move them to ieee80211.h instead.

Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlegacy/commands.h    |  8 ----
 drivers/net/wireless/iwlwifi/dvm/commands.h |  8 ----
 drivers/net/wireless/iwlwifi/pcie/tx.c      |  6 +--
 include/linux/ieee80211.h                   |  9 ++++
 net/mac80211/aes_ccm.c                      |  6 +--
 net/mac80211/key.c                          | 24 +++++-----
 net/mac80211/key.h                          | 15 +------
 net/mac80211/rx.c                           | 12 ++---
 net/mac80211/wep.c                          | 48 ++++++++++----------
 net/mac80211/wpa.c                          | 68 +++++++++++++++--------------
 10 files changed, 96 insertions(+), 108 deletions(-)

diff --git a/drivers/net/wireless/iwlegacy/commands.h b/drivers/net/wireless/iwlegacy/commands.h
index 3b6c994..0484215 100644
--- a/drivers/net/wireless/iwlegacy/commands.h
+++ b/drivers/net/wireless/iwlegacy/commands.h
@@ -1348,14 +1348,6 @@ struct il_rx_mpdu_res_start {
 #define TX_CMD_SEC_KEY128	0x08
 
 /*
- * security overhead sizes
- */
-#define WEP_IV_LEN 4
-#define WEP_ICV_LEN 4
-#define CCMP_MIC_LEN 8
-#define TKIP_ICV_LEN 4
-
-/*
  * C_TX = 0x1c (command)
  */
 
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 95ca026..174b0f1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -1225,14 +1225,6 @@ struct iwl_rx_mpdu_res_start {
 #define TX_CMD_SEC_KEY128	0x08
 
 /*
- * security overhead sizes
- */
-#define WEP_IV_LEN 4
-#define WEP_ICV_LEN 4
-#define CCMP_MIC_LEN 8
-#define TKIP_ICV_LEN 4
-
-/*
  * REPLY_TX = 0x1c (command)
  */
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index d97c1fa..aea024f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
 
 	switch (sec_ctl & TX_CMD_SEC_MSK) {
 	case TX_CMD_SEC_CCM:
-		len += CCMP_MIC_LEN;
+		len += IEEE80211_CCMP_MIC_LEN;
 		break;
 	case TX_CMD_SEC_TKIP:
-		len += TKIP_ICV_LEN;
+		len += IEEE80211_TKIP_ICV_LEN;
 		break;
 	case TX_CMD_SEC_WEP:
-		len += WEP_IV_LEN + WEP_ICV_LEN;
+		len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;
 		break;
 	}
 
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 06b0ed0..d826e5a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1829,6 +1829,15 @@ enum ieee80211_key_len {
 	WLAN_KEY_LEN_AES_CMAC = 16,
 };
 
+#define IEEE80211_WEP_IV_LEN		4
+#define IEEE80211_WEP_ICV_LEN		4
+#define IEEE80211_CCMP_HDR_LEN		8
+#define IEEE80211_CCMP_MIC_LEN		8
+#define IEEE80211_CCMP_PN_LEN		6
+#define IEEE80211_TKIP_IV_LEN		8
+#define IEEE80211_TKIP_ICV_LEN		4
+#define IEEE80211_CMAC_PN_LEN		6
+
 /* Public action codes */
 enum ieee80211_pub_actioncode {
 	WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 0785e95..be7614b9 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 			*cpos++ = *pos++ ^ e[i];
 	}
 
-	for (i = 0; i < CCMP_MIC_LEN; i++)
+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
 		mic[i] = b[i] ^ s_0[i];
 }
 
@@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
 		crypto_cipher_encrypt_one(tfm, a, a);
 	}
 
-	for (i = 0; i < CCMP_MIC_LEN; i++) {
+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
 		if ((mic[i] ^ s_0[i]) != a[i])
 			return -1;
 	}
@@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
 
 	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
 	if (!IS_ERR(tfm))
-		crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
+		crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
 
 	return tfm;
 }
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 67059b8..e39cc91 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 	switch (cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		key->conf.iv_len = WEP_IV_LEN;
-		key->conf.icv_len = WEP_ICV_LEN;
+		key->conf.iv_len = IEEE80211_WEP_IV_LEN;
+		key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
-		key->conf.iv_len = TKIP_IV_LEN;
-		key->conf.icv_len = TKIP_ICV_LEN;
+		key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
+		key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
 		if (seq) {
 			for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
 				key->u.tkip.rx[i].iv32 =
@@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 		spin_lock_init(&key->u.tkip.txlock);
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
-		key->conf.iv_len = CCMP_HDR_LEN;
-		key->conf.icv_len = CCMP_MIC_LEN;
+		key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
+		key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
 		if (seq) {
 			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
-				for (j = 0; j < CCMP_PN_LEN; j++)
+				for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
 					key->u.ccmp.rx_pn[i][j] =
-						seq[CCMP_PN_LEN - j - 1];
+						seq[IEEE80211_CCMP_PN_LEN - j - 1];
 		}
 		/*
 		 * Initialize AES key state here as an optimization so that
@@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 		key->conf.iv_len = 0;
 		key->conf.icv_len = sizeof(struct ieee80211_mmie);
 		if (seq)
-			for (j = 0; j < CMAC_PN_LEN; j++)
+			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
 				key->u.aes_cmac.rx_pn[j] =
-					seq[CMAC_PN_LEN - j - 1];
+					seq[IEEE80211_CMAC_PN_LEN - j - 1];
 		/*
 		 * Initialize AES key state here as an optimization so that
 		 * it does not need to be initialized for every packet.
@@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
 			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
 		else
 			pn = key->u.ccmp.rx_pn[tid];
-		memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
+		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
 		if (WARN_ON(tid != 0))
 			return;
 		pn = key->u.aes_cmac.rx_pn;
-		memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
+		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
 		break;
 	}
 }
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index e8de3e6..036d57e 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -19,17 +19,6 @@
 #define NUM_DEFAULT_KEYS 4
 #define NUM_DEFAULT_MGMT_KEYS 2
 
-#define WEP_IV_LEN		4
-#define WEP_ICV_LEN		4
-#define ALG_CCMP_KEY_LEN	16
-#define CCMP_HDR_LEN		8
-#define CCMP_MIC_LEN		8
-#define CCMP_TK_LEN		16
-#define CCMP_PN_LEN		6
-#define TKIP_IV_LEN		8
-#define TKIP_ICV_LEN		4
-#define CMAC_PN_LEN		6
-
 struct ieee80211_local;
 struct ieee80211_sub_if_data;
 struct sta_info;
@@ -93,13 +82,13 @@ struct ieee80211_key {
 			 * frames and the last counter is used with Robust
 			 * Management frames.
 			 */
-			u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN];
+			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCCMPReplays */
 		} ccmp;
 		struct {
 			atomic64_t tx_pn;
-			u8 rx_pn[CMAC_PN_LEN];
+			u8 rx_pn[IEEE80211_CMAC_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCMACReplays */
 			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 22e412b..6e2c8c5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1622,7 +1622,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 			entry->ccmp = 1;
 			memcpy(entry->last_pn,
 			       rx->key->u.ccmp.rx_pn[queue],
-			       CCMP_PN_LEN);
+			       IEEE80211_CCMP_PN_LEN);
 		}
 		return RX_QUEUED;
 	}
@@ -1641,21 +1641,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 	 * (IEEE 802.11i, 8.3.3.4.5) */
 	if (entry->ccmp) {
 		int i;
-		u8 pn[CCMP_PN_LEN], *rpn;
+		u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
 		int queue;
 		if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
 			return RX_DROP_UNUSABLE;
-		memcpy(pn, entry->last_pn, CCMP_PN_LEN);
-		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
 			pn[i]++;
 			if (pn[i])
 				break;
 		}
 		queue = rx->security_idx;
 		rpn = rx->key->u.ccmp.rx_pn[queue];
-		if (memcmp(pn, rpn, CCMP_PN_LEN))
+		if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
 			return RX_DROP_UNUSABLE;
-		memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
 	}
 
 	skb_pull(rx->skb, ieee80211_hdrlen(fc));
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index c04d401..6ee2b58 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -28,7 +28,7 @@
 int ieee80211_wep_init(struct ieee80211_local *local)
 {
 	/* start WEP IV from a random value */
-	get_random_bytes(&local->wep_iv, WEP_IV_LEN);
+	get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
 
 	local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(local->wep_tx_tfm)) {
@@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
 
 	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
-	if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN ||
-		    skb_headroom(skb) < WEP_IV_LEN))
+	if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN ||
+		    skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
 		return NULL;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	newhdr = skb_push(skb, WEP_IV_LEN);
-	memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
+	newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
+	memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
 
 	/* the HW only needs room for the IV, but not the actual IV */
 	if (info->control.hw_key &&
 	    (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
 		return newhdr + hdrlen;
 
-	skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_WEP_IV_LEN);
 	ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
 	return newhdr + hdrlen;
 }
@@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
 	unsigned int hdrlen;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, WEP_IV_LEN);
+	memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_WEP_IV_LEN);
 }
 
 
@@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
 	put_unaligned(icv, (__le32 *)(data + data_len));
 
 	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + WEP_ICV_LEN; i++)
+	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
 		crypto_cipher_encrypt_one(tfm, data + i, data + i);
 
 	return 0;
@@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 	if (!iv)
 		return -1;
 
-	len = skb->len - (iv + WEP_IV_LEN - skb->data);
+	len = skb->len - (iv + IEEE80211_WEP_IV_LEN - skb->data);
 
 	/* Prepend 24-bit IV to RC4 key */
 	memcpy(rc4key, iv, 3);
@@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 	memcpy(rc4key + 3, key, keylen);
 
 	/* Add room for ICV */
-	skb_put(skb, WEP_ICV_LEN);
+	skb_put(skb, IEEE80211_WEP_ICV_LEN);
 
 	return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
-					  iv + WEP_IV_LEN, len);
+					  iv + IEEE80211_WEP_IV_LEN, len);
 }
 
 
@@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
 		return -1;
 
 	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + WEP_ICV_LEN; i++)
+	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
 		crypto_cipher_decrypt_one(tfm, data + i, data + i);
 
 	crc = cpu_to_le32(~crc32_le(~0, data, data_len));
-	if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
+	if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
 		/* ICV mismatch */
 		return -1;
 
@@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
 		return -1;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN)
+	if (skb->len < hdrlen + IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN)
 		return -1;
 
-	len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN;
+	len = skb->len - hdrlen - IEEE80211_WEP_IV_LEN - IEEE80211_WEP_ICV_LEN;
 
 	keyidx = skb->data[hdrlen + 3] >> 6;
 
@@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
 	memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
 
 	if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
-				       skb->data + hdrlen + WEP_IV_LEN,
-				       len))
+				       skb->data + hdrlen +
+				       IEEE80211_WEP_IV_LEN, len))
 		ret = -1;
 
 	/* Trim ICV */
-	skb_trim(skb, skb->len - WEP_ICV_LEN);
+	skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN);
 
 	/* Remove IV */
-	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, WEP_IV_LEN);
+	memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_WEP_IV_LEN);
 
 	return ret;
 }
@@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
 			return RX_DROP_UNUSABLE;
 	} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
-		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
+		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
+					    IEEE80211_WEP_IV_LEN))
 			return RX_DROP_UNUSABLE;
 		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
 			rx->sta->wep_weak_iv_count++;
 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
 		/* remove ICV */
-		if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
+		if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
 			return RX_DROP_UNUSABLE;
 	}
 
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index c7c6d64..c9edfcb 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 
 	tail = MICHAEL_MIC_LEN;
 	if (!info->control.hw_key)
-		tail += TKIP_ICV_LEN;
+		tail += IEEE80211_TKIP_ICV_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < TKIP_IV_LEN))
+		    skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
 		return TX_DROP;
 
 	key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
@@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		tail = 0;
 	else
-		tail = TKIP_ICV_LEN;
+		tail = IEEE80211_TKIP_ICV_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < TKIP_IV_LEN))
+		    skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
 		return -1;
 
-	pos = skb_push(skb, TKIP_IV_LEN);
-	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
-	skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN);
+	pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
+	memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_TKIP_IV_LEN);
 	pos += hdrlen;
 
 	/* the HW only needs room for the IV, but not the actual IV */
@@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 		return 0;
 
 	/* Add room for ICV */
-	skb_put(skb, TKIP_ICV_LEN);
+	skb_put(skb, IEEE80211_TKIP_ICV_LEN);
 
 	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
 					   key, skb, pos, len);
@@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 		return RX_DROP_UNUSABLE;
 
 	/* Trim ICV */
-	skb_trim(skb, skb->len - TKIP_ICV_LEN);
+	skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);
 
 	/* Remove IV */
-	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, TKIP_IV_LEN);
+	memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_TKIP_IV_LEN);
 
 	return RX_CONTINUE;
 }
@@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 	else
 		qos_tid = 0;
 
-	data_len = skb->len - hdrlen - CCMP_HDR_LEN;
+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
 	if (encrypted)
-		data_len -= CCMP_MIC_LEN;
+		data_len -= IEEE80211_CCMP_MIC_LEN;
 
 	/* First block, b_0 */
 	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
@@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 	 */
 	b_0[1] = qos_tid | (mgmt << 4);
 	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
-	memcpy(&b_0[8], pn, CCMP_PN_LEN);
+	memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
 	/* l(m) */
 	put_unaligned_be16(data_len, &b_0[14]);
 
@@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		tail = 0;
 	else
-		tail = CCMP_MIC_LEN;
+		tail = IEEE80211_CCMP_MIC_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < CCMP_HDR_LEN))
+		    skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
 		return -1;
 
-	pos = skb_push(skb, CCMP_HDR_LEN);
-	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
-	skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN);
+	pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
+	memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_CCMP_HDR_LEN);
 
 	/* the HW only needs room for the IV, but not the actual IV */
 	if (info->control.hw_key &&
@@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		return 0;
 
-	pos += CCMP_HDR_LEN;
+	pos += IEEE80211_CCMP_HDR_LEN;
 	ccmp_special_blocks(skb, pn, scratch, 0);
 	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
-				  pos, skb_put(skb, CCMP_MIC_LEN));
+				  pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
 
 	return 0;
 }
@@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_key *key = rx->key;
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-	u8 pn[CCMP_PN_LEN];
+	u8 pn[IEEE80211_CCMP_PN_LEN];
 	int data_len;
 	int queue;
 
@@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 	    !ieee80211_is_robust_mgmt_frame(hdr))
 		return RX_CONTINUE;
 
-	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
+		   IEEE80211_CCMP_MIC_LEN;
 	if (!rx->sta || data_len < 0)
 		return RX_DROP_UNUSABLE;
 
 	if (status->flag & RX_FLAG_DECRYPTED) {
-		if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
+		if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
 			return RX_DROP_UNUSABLE;
 	} else {
 		if (skb_linearize(rx->skb))
@@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 	queue = rx->security_idx;
 
-	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
+	if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) {
 		key->u.ccmp.replays++;
 		return RX_DROP_UNUSABLE;
 	}
@@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 		if (ieee80211_aes_ccm_decrypt(
 			    key->u.ccmp.tfm, scratch,
-			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
-			    skb->data + skb->len - CCMP_MIC_LEN,
-			    skb->data + hdrlen + CCMP_HDR_LEN))
+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+			    data_len,
+			    skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
 			return RX_DROP_UNUSABLE;
 	}
 
-	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
+	memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
 
 	/* Remove CCMP header and MIC */
-	if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
+	if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN))
 		return RX_DROP_UNUSABLE;
-	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
-	skb_pull(skb, CCMP_HDR_LEN);
+	memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
 
 	return RX_CONTINUE;
 }
-- 
1.8.0


^ permalink raw reply related

* [PATCH] wireless: move crypto constants to ieee80211.h
From: Johannes Berg @ 2013-05-08 13:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

mac80211 and the Intel drivers both define crypto
constants, move them to ieee80211.h instead.

Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/dvm/commands.h |  8 ----
 drivers/net/wireless/iwlwifi/pcie/tx.c      |  6 +--
 include/linux/ieee80211.h                   |  9 ++++
 net/mac80211/aes_ccm.c                      |  6 +--
 net/mac80211/key.c                          | 24 +++++-----
 net/mac80211/key.h                          | 15 +------
 net/mac80211/rx.c                           | 12 ++---
 net/mac80211/wep.c                          | 48 ++++++++++----------
 net/mac80211/wpa.c                          | 68 +++++++++++++++--------------
 9 files changed, 96 insertions(+), 100 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 95ca026..174b0f1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -1225,14 +1225,6 @@ struct iwl_rx_mpdu_res_start {
 #define TX_CMD_SEC_KEY128	0x08
 
 /*
- * security overhead sizes
- */
-#define WEP_IV_LEN 4
-#define WEP_ICV_LEN 4
-#define CCMP_MIC_LEN 8
-#define TKIP_ICV_LEN 4
-
-/*
  * REPLY_TX = 0x1c (command)
  */
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index d97c1fa..aea024f 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
 
 	switch (sec_ctl & TX_CMD_SEC_MSK) {
 	case TX_CMD_SEC_CCM:
-		len += CCMP_MIC_LEN;
+		len += IEEE80211_CCMP_MIC_LEN;
 		break;
 	case TX_CMD_SEC_TKIP:
-		len += TKIP_ICV_LEN;
+		len += IEEE80211_TKIP_ICV_LEN;
 		break;
 	case TX_CMD_SEC_WEP:
-		len += WEP_IV_LEN + WEP_ICV_LEN;
+		len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;
 		break;
 	}
 
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 06b0ed0..d826e5a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1829,6 +1829,15 @@ enum ieee80211_key_len {
 	WLAN_KEY_LEN_AES_CMAC = 16,
 };
 
+#define IEEE80211_WEP_IV_LEN		4
+#define IEEE80211_WEP_ICV_LEN		4
+#define IEEE80211_CCMP_HDR_LEN		8
+#define IEEE80211_CCMP_MIC_LEN		8
+#define IEEE80211_CCMP_PN_LEN		6
+#define IEEE80211_TKIP_IV_LEN		8
+#define IEEE80211_TKIP_ICV_LEN		4
+#define IEEE80211_CMAC_PN_LEN		6
+
 /* Public action codes */
 enum ieee80211_pub_actioncode {
 	WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 0785e95..be7614b9 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
 			*cpos++ = *pos++ ^ e[i];
 	}
 
-	for (i = 0; i < CCMP_MIC_LEN; i++)
+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
 		mic[i] = b[i] ^ s_0[i];
 }
 
@@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
 		crypto_cipher_encrypt_one(tfm, a, a);
 	}
 
-	for (i = 0; i < CCMP_MIC_LEN; i++) {
+	for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
 		if ((mic[i] ^ s_0[i]) != a[i])
 			return -1;
 	}
@@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
 
 	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
 	if (!IS_ERR(tfm))
-		crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);
+		crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
 
 	return tfm;
 }
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 67059b8..e39cc91 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 	switch (cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 	case WLAN_CIPHER_SUITE_WEP104:
-		key->conf.iv_len = WEP_IV_LEN;
-		key->conf.icv_len = WEP_ICV_LEN;
+		key->conf.iv_len = IEEE80211_WEP_IV_LEN;
+		key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
-		key->conf.iv_len = TKIP_IV_LEN;
-		key->conf.icv_len = TKIP_ICV_LEN;
+		key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
+		key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
 		if (seq) {
 			for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
 				key->u.tkip.rx[i].iv32 =
@@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 		spin_lock_init(&key->u.tkip.txlock);
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
-		key->conf.iv_len = CCMP_HDR_LEN;
-		key->conf.icv_len = CCMP_MIC_LEN;
+		key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
+		key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
 		if (seq) {
 			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
-				for (j = 0; j < CCMP_PN_LEN; j++)
+				for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
 					key->u.ccmp.rx_pn[i][j] =
-						seq[CCMP_PN_LEN - j - 1];
+						seq[IEEE80211_CCMP_PN_LEN - j - 1];
 		}
 		/*
 		 * Initialize AES key state here as an optimization so that
@@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
 		key->conf.iv_len = 0;
 		key->conf.icv_len = sizeof(struct ieee80211_mmie);
 		if (seq)
-			for (j = 0; j < CMAC_PN_LEN; j++)
+			for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
 				key->u.aes_cmac.rx_pn[j] =
-					seq[CMAC_PN_LEN - j - 1];
+					seq[IEEE80211_CMAC_PN_LEN - j - 1];
 		/*
 		 * Initialize AES key state here as an optimization so that
 		 * it does not need to be initialized for every packet.
@@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
 			pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
 		else
 			pn = key->u.ccmp.rx_pn[tid];
-		memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);
+		memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
 		if (WARN_ON(tid != 0))
 			return;
 		pn = key->u.aes_cmac.rx_pn;
-		memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);
+		memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
 		break;
 	}
 }
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index e8de3e6..036d57e 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -19,17 +19,6 @@
 #define NUM_DEFAULT_KEYS 4
 #define NUM_DEFAULT_MGMT_KEYS 2
 
-#define WEP_IV_LEN		4
-#define WEP_ICV_LEN		4
-#define ALG_CCMP_KEY_LEN	16
-#define CCMP_HDR_LEN		8
-#define CCMP_MIC_LEN		8
-#define CCMP_TK_LEN		16
-#define CCMP_PN_LEN		6
-#define TKIP_IV_LEN		8
-#define TKIP_ICV_LEN		4
-#define CMAC_PN_LEN		6
-
 struct ieee80211_local;
 struct ieee80211_sub_if_data;
 struct sta_info;
@@ -93,13 +82,13 @@ struct ieee80211_key {
 			 * frames and the last counter is used with Robust
 			 * Management frames.
 			 */
-			u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN];
+			u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCCMPReplays */
 		} ccmp;
 		struct {
 			atomic64_t tx_pn;
-			u8 rx_pn[CMAC_PN_LEN];
+			u8 rx_pn[IEEE80211_CMAC_PN_LEN];
 			struct crypto_cipher *tfm;
 			u32 replays; /* dot11RSNAStatsCMACReplays */
 			u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 22e412b..6e2c8c5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1622,7 +1622,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 			entry->ccmp = 1;
 			memcpy(entry->last_pn,
 			       rx->key->u.ccmp.rx_pn[queue],
-			       CCMP_PN_LEN);
+			       IEEE80211_CCMP_PN_LEN);
 		}
 		return RX_QUEUED;
 	}
@@ -1641,21 +1641,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 	 * (IEEE 802.11i, 8.3.3.4.5) */
 	if (entry->ccmp) {
 		int i;
-		u8 pn[CCMP_PN_LEN], *rpn;
+		u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
 		int queue;
 		if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
 			return RX_DROP_UNUSABLE;
-		memcpy(pn, entry->last_pn, CCMP_PN_LEN);
-		for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
+		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
 			pn[i]++;
 			if (pn[i])
 				break;
 		}
 		queue = rx->security_idx;
 		rpn = rx->key->u.ccmp.rx_pn[queue];
-		if (memcmp(pn, rpn, CCMP_PN_LEN))
+		if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
 			return RX_DROP_UNUSABLE;
-		memcpy(entry->last_pn, pn, CCMP_PN_LEN);
+		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
 	}
 
 	skb_pull(rx->skb, ieee80211_hdrlen(fc));
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index c04d401..6ee2b58 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -28,7 +28,7 @@
 int ieee80211_wep_init(struct ieee80211_local *local)
 {
 	/* start WEP IV from a random value */
-	get_random_bytes(&local->wep_iv, WEP_IV_LEN);
+	get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
 
 	local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(local->wep_tx_tfm)) {
@@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
 
 	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 
-	if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN ||
-		    skb_headroom(skb) < WEP_IV_LEN))
+	if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN ||
+		    skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
 		return NULL;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	newhdr = skb_push(skb, WEP_IV_LEN);
-	memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen);
+	newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
+	memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
 
 	/* the HW only needs room for the IV, but not the actual IV */
 	if (info->control.hw_key &&
 	    (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
 		return newhdr + hdrlen;
 
-	skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_WEP_IV_LEN);
 	ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
 	return newhdr + hdrlen;
 }
@@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
 	unsigned int hdrlen;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, WEP_IV_LEN);
+	memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_WEP_IV_LEN);
 }
 
 
@@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
 	put_unaligned(icv, (__le32 *)(data + data_len));
 
 	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + WEP_ICV_LEN; i++)
+	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
 		crypto_cipher_encrypt_one(tfm, data + i, data + i);
 
 	return 0;
@@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 	if (!iv)
 		return -1;
 
-	len = skb->len - (iv + WEP_IV_LEN - skb->data);
+	len = skb->len - (iv + IEEE80211_WEP_IV_LEN - skb->data);
 
 	/* Prepend 24-bit IV to RC4 key */
 	memcpy(rc4key, iv, 3);
@@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
 	memcpy(rc4key + 3, key, keylen);
 
 	/* Add room for ICV */
-	skb_put(skb, WEP_ICV_LEN);
+	skb_put(skb, IEEE80211_WEP_ICV_LEN);
 
 	return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
-					  iv + WEP_IV_LEN, len);
+					  iv + IEEE80211_WEP_IV_LEN, len);
 }
 
 
@@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
 		return -1;
 
 	crypto_cipher_setkey(tfm, rc4key, klen);
-	for (i = 0; i < data_len + WEP_ICV_LEN; i++)
+	for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
 		crypto_cipher_decrypt_one(tfm, data + i, data + i);
 
 	crc = cpu_to_le32(~crc32_le(~0, data, data_len));
-	if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0)
+	if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
 		/* ICV mismatch */
 		return -1;
 
@@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
 		return -1;
 
 	hdrlen = ieee80211_hdrlen(hdr->frame_control);
-	if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN)
+	if (skb->len < hdrlen + IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN)
 		return -1;
 
-	len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN;
+	len = skb->len - hdrlen - IEEE80211_WEP_IV_LEN - IEEE80211_WEP_ICV_LEN;
 
 	keyidx = skb->data[hdrlen + 3] >> 6;
 
@@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
 	memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
 
 	if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
-				       skb->data + hdrlen + WEP_IV_LEN,
-				       len))
+				       skb->data + hdrlen +
+				       IEEE80211_WEP_IV_LEN, len))
 		ret = -1;
 
 	/* Trim ICV */
-	skb_trim(skb, skb->len - WEP_ICV_LEN);
+	skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN);
 
 	/* Remove IV */
-	memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, WEP_IV_LEN);
+	memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_WEP_IV_LEN);
 
 	return ret;
 }
@@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
 		if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
 			return RX_DROP_UNUSABLE;
 	} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
-		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN))
+		if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
+					    IEEE80211_WEP_IV_LEN))
 			return RX_DROP_UNUSABLE;
 		if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
 			rx->sta->wep_weak_iv_count++;
 		ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
 		/* remove ICV */
-		if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN))
+		if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
 			return RX_DROP_UNUSABLE;
 	}
 
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index c7c6d64..c9edfcb 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 
 	tail = MICHAEL_MIC_LEN;
 	if (!info->control.hw_key)
-		tail += TKIP_ICV_LEN;
+		tail += IEEE80211_TKIP_ICV_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < TKIP_IV_LEN))
+		    skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
 		return TX_DROP;
 
 	key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
@@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		tail = 0;
 	else
-		tail = TKIP_ICV_LEN;
+		tail = IEEE80211_TKIP_ICV_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < TKIP_IV_LEN))
+		    skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
 		return -1;
 
-	pos = skb_push(skb, TKIP_IV_LEN);
-	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
-	skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN);
+	pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
+	memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_TKIP_IV_LEN);
 	pos += hdrlen;
 
 	/* the HW only needs room for the IV, but not the actual IV */
@@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 		return 0;
 
 	/* Add room for ICV */
-	skb_put(skb, TKIP_ICV_LEN);
+	skb_put(skb, IEEE80211_TKIP_ICV_LEN);
 
 	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
 					   key, skb, pos, len);
@@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 		return RX_DROP_UNUSABLE;
 
 	/* Trim ICV */
-	skb_trim(skb, skb->len - TKIP_ICV_LEN);
+	skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);
 
 	/* Remove IV */
-	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
-	skb_pull(skb, TKIP_IV_LEN);
+	memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_TKIP_IV_LEN);
 
 	return RX_CONTINUE;
 }
@@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 	else
 		qos_tid = 0;
 
-	data_len = skb->len - hdrlen - CCMP_HDR_LEN;
+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
 	if (encrypted)
-		data_len -= CCMP_MIC_LEN;
+		data_len -= IEEE80211_CCMP_MIC_LEN;
 
 	/* First block, b_0 */
 	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
@@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
 	 */
 	b_0[1] = qos_tid | (mgmt << 4);
 	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
-	memcpy(&b_0[8], pn, CCMP_PN_LEN);
+	memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
 	/* l(m) */
 	put_unaligned_be16(data_len, &b_0[14]);
 
@@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		tail = 0;
 	else
-		tail = CCMP_MIC_LEN;
+		tail = IEEE80211_CCMP_MIC_LEN;
 
 	if (WARN_ON(skb_tailroom(skb) < tail ||
-		    skb_headroom(skb) < CCMP_HDR_LEN))
+		    skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
 		return -1;
 
-	pos = skb_push(skb, CCMP_HDR_LEN);
-	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
-	skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN);
+	pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
+	memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
+	skb_set_network_header(skb, skb_network_offset(skb) +
+				    IEEE80211_CCMP_HDR_LEN);
 
 	/* the HW only needs room for the IV, but not the actual IV */
 	if (info->control.hw_key &&
@@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 	if (info->control.hw_key)
 		return 0;
 
-	pos += CCMP_HDR_LEN;
+	pos += IEEE80211_CCMP_HDR_LEN;
 	ccmp_special_blocks(skb, pn, scratch, 0);
 	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
-				  pos, skb_put(skb, CCMP_MIC_LEN));
+				  pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
 
 	return 0;
 }
@@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 	struct ieee80211_key *key = rx->key;
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-	u8 pn[CCMP_PN_LEN];
+	u8 pn[IEEE80211_CCMP_PN_LEN];
 	int data_len;
 	int queue;
 
@@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 	    !ieee80211_is_robust_mgmt_frame(hdr))
 		return RX_CONTINUE;
 
-	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
+	data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
+		   IEEE80211_CCMP_MIC_LEN;
 	if (!rx->sta || data_len < 0)
 		return RX_DROP_UNUSABLE;
 
 	if (status->flag & RX_FLAG_DECRYPTED) {
-		if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN))
+		if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
 			return RX_DROP_UNUSABLE;
 	} else {
 		if (skb_linearize(rx->skb))
@@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 	queue = rx->security_idx;
 
-	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
+	if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) {
 		key->u.ccmp.replays++;
 		return RX_DROP_UNUSABLE;
 	}
@@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 		if (ieee80211_aes_ccm_decrypt(
 			    key->u.ccmp.tfm, scratch,
-			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
-			    skb->data + skb->len - CCMP_MIC_LEN,
-			    skb->data + hdrlen + CCMP_HDR_LEN))
+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+			    data_len,
+			    skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
+			    skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
 			return RX_DROP_UNUSABLE;
 	}
 
-	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
+	memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
 
 	/* Remove CCMP header and MIC */
-	if (pskb_trim(skb, skb->len - CCMP_MIC_LEN))
+	if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN))
 		return RX_DROP_UNUSABLE;
-	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
-	skb_pull(skb, CCMP_HDR_LEN);
+	memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
+	skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
 
 	return RX_CONTINUE;
 }
-- 
1.8.0


^ permalink raw reply related

* Re: Linux summit this year ?
From: Seth Forshee @ 2013-05-08 13:20 UTC (permalink / raw)
  To: John W. Linville
  Cc: Johannes Berg, Marcel Holtmann, Larry Finger, Matt Chen, joeyli,
	linux-wireless
In-Reply-To: <20130507174445.GB2073@tuxdriver.com>

On Tue, May 07, 2013 at 01:44:45PM -0400, John W. Linville wrote:
> On Tue, May 07, 2013 at 11:42:36AM -0500, Seth Forshee wrote:
> > On Fri, May 03, 2013 at 10:49:47AM -0400, John W. Linville wrote:
> > > On Fri, May 03, 2013 at 10:11:10AM +0200, Johannes Berg wrote:
> > > > On Thu, 2013-05-02 at 15:43 -0400, John W. Linville wrote:
> > > > 
> > > > > "I'm confirming that we got the space you needed for the Wireless Summit in
> > > > > New Orleans.
> > > > 
> > > > > Does that sound alright to everyone?  
> > > > 
> > > > Sounds good to me. If it overlaps LPC, which one are people going to
> > > > have to register for (if not going to both anyway)?
> > > 
> > > I would presume that if you want to got to LPC sessions then you
> > > would have to register for LPC.  Generally we have required Wireless
> > > Summit attendees to register for LinuxCon, and I presume that would
> > > be required this time (so both LinuxCon and LPC if you want the
> > > LPC sessions).
> > 
> > Why require LinuxCon registration rather than LPC? I'd assume most
> > wireless summit attendees are more interested in plumbers than LinuxCon.
> > Could the summit just require registration at one or the other?
> 
> Well, I can ask.  But the fact is that LPC and LCNA are separate
> events with separate events with separate budgets and expenses,
> separate organizers, etc.
> 
> Anyway, I'll let you know what the event folks say...

It's not really a big deal for me, I just thought it a bit odd since the
audiences for wireless summit and LPC probably have more overlap. The
reasons you and Marcel gave make sense.

Thanks,
Seth

^ permalink raw reply

* Re: Linux summit this year ?
From: John W. Linville @ 2013-05-07 17:44 UTC (permalink / raw)
  To: Seth Forshee
  Cc: Johannes Berg, Marcel Holtmann, Larry Finger, Matt Chen, joeyli,
	linux-wireless
In-Reply-To: <20130507164236.GD32496@thinkpad-t410>

On Tue, May 07, 2013 at 11:42:36AM -0500, Seth Forshee wrote:
> On Fri, May 03, 2013 at 10:49:47AM -0400, John W. Linville wrote:
> > On Fri, May 03, 2013 at 10:11:10AM +0200, Johannes Berg wrote:
> > > On Thu, 2013-05-02 at 15:43 -0400, John W. Linville wrote:
> > > 
> > > > "I'm confirming that we got the space you needed for the Wireless Summit in
> > > > New Orleans.
> > > 
> > > > Does that sound alright to everyone?  
> > > 
> > > Sounds good to me. If it overlaps LPC, which one are people going to
> > > have to register for (if not going to both anyway)?
> > 
> > I would presume that if you want to got to LPC sessions then you
> > would have to register for LPC.  Generally we have required Wireless
> > Summit attendees to register for LinuxCon, and I presume that would
> > be required this time (so both LinuxCon and LPC if you want the
> > LPC sessions).
> 
> Why require LinuxCon registration rather than LPC? I'd assume most
> wireless summit attendees are more interested in plumbers than LinuxCon.
> Could the summit just require registration at one or the other?

Well, I can ask.  But the fact is that LPC and LCNA are separate
events with separate events with separate budgets and expenses,
separate organizers, etc.

Anyway, I'll let you know what the event folks say...

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* atheros AR5B22, using ath9k, can't switch between inscure and WEP/WPA
From: Wally @ 2013-05-08 12:25 UTC (permalink / raw)
  To: linux-wireless

Hi, guys:
    Recently I got a atheros mini-PCIE wifi module AR5B22, so I download
the latest version of compat-driver(compat-drivers-2013-03-28.tar.gz),
and build it for armel on my arm board, it works great but with one
little problem:

If I connect to an inscure AP then change to a WEP/WPA AP, I can't
connect the inscure one again, I have to run "modprobe -r ath9k;
modprobe ath9k" to connect the inscure AP.

    I think this may be a bug in the ath9k driver, I also search this
bug on web but without an answer, so I send this letter for help.

    Any advice would be grateful, thanks.

Wally 



^ permalink raw reply

* Re: [PATCH 1/3] wil6210: TCP/UDP checksum offloading support
From: Vladimir Kondratiev @ 2013-05-08 12:06 UTC (permalink / raw)
  To: wilocity.git; +Cc: linux-wireless, wil6210, Erez Kirshenbaum
In-Reply-To: <1368001971-11551-1-git-send-email-wilocity.git@gmail.com>

On Wednesday, May 08, 2013 11:32:51 AM wilocity.git@gmail.com wrote:
> From: Erez Kirshenbaum <erezk@wilocity.com>
> 
> Add TCP/UDP checksum hardware offloading, configure hw and set the corresponding offloading bits in the
> DMA descriptors.
> 
> Signed-off-by: Erez Kirshenbaum <erezk@wilocity.com>
> Signed-off-by: Wilocity Git <wilocity.git@gmail.com>

Please run your patches through 'checkpatch.pl --strict' and fix reported problems

> ---
>  drivers/net/wireless/ath/wil6210/netdev.c | 24 ++++++++++
>  drivers/net/wireless/ath/wil6210/txrx.c   | 77 +++++++++++++++++++++++++++++--
>  drivers/net/wireless/ath/wil6210/txrx.h   | 28 +++++++++--
>  drivers/net/wireless/ath/wil6210/wmi.c    |  8 ++++
>  4 files changed, 130 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
> index 098a8ec..4f2a61f 100644
> --- a/drivers/net/wireless/ath/wil6210/netdev.c
> +++ b/drivers/net/wireless/ath/wil6210/netdev.c
> @@ -32,12 +32,34 @@ static int wil_stop(struct net_device *ndev)
>  	return wil_down(wil);
>  }
>  
> +static netdev_features_t wil_fix_features(struct net_device *netdev,
> +			netdev_features_t features)
> +{
> +	return features;
> +}
> +
> +static int wil_set_features(struct net_device *netdev,
> +			netdev_features_t features)
> +{
> +	struct wil6210_priv *wil = ndev_to_wil(netdev);
> +	netdev_features_t changed = features ^ netdev->features;
> +
> +	wil_info(wil, "wil_set_features: %x\n", (unsigned int)features);
> +	if (changed & NETIF_F_HW_CSUM)
> +		wil_info(wil, "Tx checksum offloading changed\n");
> +	else if (changed & NETIF_F_RXCSUM)
> +		wil_info(wil, "Rx checksum offloading changed\n");
> +	return 0;
> +}
> +
>  static const struct net_device_ops wil_netdev_ops = {
>  	.ndo_open		= wil_open,
>  	.ndo_stop		= wil_stop,
>  	.ndo_start_xmit		= wil_start_xmit,
>  	.ndo_set_mac_address	= eth_mac_addr,
>  	.ndo_validate_addr	= eth_validate_addr,
> +	.ndo_fix_features	= wil_fix_features,
> +	.ndo_set_features	= wil_set_features,
>  };

2 methods above are not needed, remove

>  
>  void *wil_if_alloc(struct device *dev, void __iomem *csr)
> @@ -78,6 +100,8 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
>  
>  	ndev->netdev_ops = &wil_netdev_ops;
>  	ndev->ieee80211_ptr = wdev;
> +	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
> +	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
>  	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
>  	wdev->netdev = ndev;
>  
> diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
> index 7970245..3f44a6c 100644
> --- a/drivers/net/wireless/ath/wil6210/txrx.c
> +++ b/drivers/net/wireless/ath/wil6210/txrx.c
> @@ -18,6 +18,9 @@
>  #include <net/ieee80211_radiotap.h>
>  #include <linux/if_arp.h>
>  #include <linux/moduleparam.h>
> +#include <linux/ip.h>
> +#include <linux/ipv6.h>
> +#include <net/ipv6.h>
>  
>  #include "wil6210.h"
>  #include "wmi.h"
> @@ -391,7 +394,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
>  		 */
>  		wil_swap_ethaddr(skb->data);
>  	}
> -
> +	/* Check checksum-offload status */
> +	if (ndev->features & NETIF_F_RXCSUM) {
> +		if (d->dma.status & RX_DMA_STATUS_L4_IDENT) {

This code access Rx descriptor in the non-cached memory, this is time consuming.
Need to access cached copy through 'd1'
Also, to reduce identation, combine 2 'if' statement into one.

> +			/* L4 protocol identified, csum calculated */
> +			if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0)

Same note for non-cached memory as above

> +				skb->ip_summed = CHECKSUM_UNNECESSARY;
> +			else
> +				wil_err(wil, "Incorrect checksum reported\n");

If this error detected, does it mean packet still usable?

What is exact meaning of this error:
- HW did not calculated checksum for some reason, or
- checksum calculated but do not match

> +		}
> +	}
>  	return skb;
>  }
>  
> @@ -605,9 +617,7 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
>  {
>  	d->dma.addr_low = lower_32_bits(pa);
>  	d->dma.addr_high = (u16)upper_32_bits(pa);
> -	d->dma.ip_length = 0;
> -	/* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/
> -	d->dma.b11 = 0/*14 | BIT(7)*/;
> +	d->dma.offload_cfg = 0;
>  	d->dma.error = 0;
>  	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
>  	d->dma.length = len;
> @@ -630,6 +640,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
>  			struct sk_buff *skb)
>  {
>  	struct device *dev = wil_to_dev(wil);
> +	struct net_device *ndev = wil_to_ndev(wil);
>  	volatile struct vring_tx_desc *d;
>  	u32 swhead = vring->swhead;
>  	int avail = wil_vring_avail_tx(vring);
> @@ -638,6 +649,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
>  	int vring_index = vring - wil->vring_tx;
>  	uint i = swhead;
>  	dma_addr_t pa;
> +	int is_ip4 = 0, is_ip6 = 0, is_tcp = 0, is_udp = 0;
> +
>  
>  	wil_dbg_txrx(wil, "%s()\n", __func__);
>  
> @@ -665,6 +678,62 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
>  		return -EINVAL;
>  	/* 1-st segment */
>  	wil_tx_desc_map(d, pa, skb_headlen(skb));

Please make separate function like wil_tx_csum from code below

Also, consider optimising calculations and return ASAP like:

bool is_ip6 = false;
switch(skb->protocol) {
case htons(ETH_P_IP):
	break;
case htons(ETH_P_IPV6):
	is_ip6 = true;
	break;
default:
	return;
}
> +	/*
> +	 * Process offloading
> +	 */
> +	if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
> +		(ndev->features & NETIF_F_HW_CSUM))  {
> +		if (skb->protocol == htons(ETH_P_IP)) {
> +			is_ip4 = 1;
> +		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
> +			is_tcp = 1;
> +		else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
> +			is_udp = 1;
> +		} else if (skb->protocol == htons(ETH_P_IPV6)) {
> +			unsigned int offset = 0;
> +			int ipv6hdr =  ipv6_find_hdr(skb,
> +						&offset, -1, NULL, NULL);
> +			is_ip6 = 1;
> +			if (ipv6hdr == NEXTHDR_TCP)
> +				is_tcp = 1;
> +			else if (ipv6hdr == NEXTHDR_UDP)
> +				is_udp = 1;
> +		}
> +	}
> +
> +
> +	if (is_ip4 || is_ip6) {
> +		if (is_ip4)
> +			d->dma.offload_cfg |=
> +				BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
> +		d->dma.offload_cfg |=
> +			(skb_network_header_len(skb) &
> +			DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK);
> +		d->dma.offload_cfg |=
> +			(0x0e << DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS);
> +		if (is_tcp || is_udp) {
> +			/* Enable TCP/UDP checksum */

Do one need to do anything if it is neither TCP nor UDP?

> +			d->dma.d0 |=
> +				BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
> +			/* Calculate pseudo-header */
> +			d->dma.d0 |=
> +			   BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
> +			if (is_tcp)  {
> +				d->dma.d0 |=
> +					(2 << DMA_CFG_DESC_TX_0_L4_TYPE_POS);
> +			/* L4 header len: TCP header length */
> +				d->dma.d0 |=
> +					(tcp_hdrlen(skb) &
> +					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
> +			} else  {
> +				/* L4 header len: UDP header length */
> +				d->dma.d0 |=
> +					(sizeof(struct udphdr) &
> +					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
> +			}
> +		}
> +	}
> +
>  	d->mac.d[2] |= ((nr_frags + 1) <<
>  		       MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
>  	/* middle segments */
> diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
> index adef12f..da22a93 100644
> --- a/drivers/net/wireless/ath/wil6210/txrx.h
> +++ b/drivers/net/wireless/ath/wil6210/txrx.h
> @@ -209,7 +209,21 @@ struct vring_tx_mac {
>  
>  #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30
>  #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2
> -#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000
> +#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 /* L4 type: 0-UDP, 2-TCP */
> +
> +/* TX DMA Dword 2 */
> +/* Offload bits in offload_cfg field */
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_POS 0
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_LEN 8
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK 0x00FF /* IP hdr len */
> +
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS 8
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_LEN 7
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_MSK 0x7F00 /* MAC hdr len */
> +
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS 15
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_LEN 1
> +#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_MSK 0x8000 /* 1-IPv4, 0-IPv6 */
>  
>  
>  #define TX_DMA_STATUS_DU         BIT(0)
> @@ -218,8 +232,7 @@ struct vring_tx_dma {
>  	u32 d0;
>  	u32 addr_low;
>  	u16 addr_high;
> -	u8  ip_length;
> -	u8  b11;       /* 0..6: mac_length; 7:ip_version */
> +	u16 offload_cfg;

If 2 bytes above combined to u16, proper endian conversions need to be used.
Alternatively, you may keep 2 u8 fields, renaming 2-nd one to offload_cfg,
and adjust bit numbers.

>  	u8  error;     /* 0..2: err; 3..7: reserved; */
>  	u8  status;    /* 0: used; 1..7; reserved */
>  	u16 length;
> @@ -309,8 +322,17 @@ struct vring_rx_mac {
>  
>  #define RX_DMA_D0_CMD_DMA_IT     BIT(10)
>  
> +/* Error field, offload bits */
> +#define RX_DMA_ERROR_L3_ERR   BIT(4)
> +#define RX_DMA_ERROR_L4_ERR   BIT(5)
> +
> +
> +/* Status field */
>  #define RX_DMA_STATUS_DU         BIT(0)
>  #define RX_DMA_STATUS_ERROR      BIT(2)
> +
> +#define RX_DMA_STATUS_L3_IDENT   BIT(4)
> +#define RX_DMA_STATUS_L4_IDENT   BIT(5)

These 2 bits are not used. Shouldn't it be checked on Rx?

>  #define RX_DMA_STATUS_PHY_INFO   BIT(6)
>  
>  struct vring_rx_dma {
> diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
> index 45b04e3..dc0aa8a 100644
> --- a/drivers/net/wireless/ath/wil6210/wmi.c
> +++ b/drivers/net/wireless/ath/wil6210/wmi.c
> @@ -932,6 +932,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
>  		struct wmi_cfg_rx_chain_done_event evt;
>  	} __packed evt;
>  	int rc;
> +	u8 csum_enabled = 0;
> +
> +	/* Initialize offload. Linux always calculates IP checksum */
> +	cmd.l3_l4_ctrl |= (0 << L3_L4_CTRL_IPV4_CHECKSUM_EN_POS);

Why do one need IP checksum enable if NETIF_F_RXCSUM disabled?

> +	/* Enable/disable TCP/UDP checksum */
> +	if (ndev->features & NETIF_F_RXCSUM)
> +		csum_enabled = 1;
> +	cmd.l3_l4_ctrl |= (csum_enabled << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);

Fragment above will be better like (no need to introduce csum_enabled):

	if (ndev->features & NETIF_F_RXCSUM)
		cmd.l3_l4_ctrl |= BIT(L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);


>  
>  	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
>  		struct ieee80211_channel *ch = wdev->preset_chandef.chan;
> 

Thanks, Vladimir

^ permalink raw reply

* [PATCH v2] wl18xx: use locally administered MAC address if not available from fuse
From: Luciano Coelho @ 2013-05-08  9:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: coelho, arik, eliad

In some R&D chips, the device may be left untrimmed and with the MAC
address missing from fuse ROM.  In order to support those devices,
apply a random locally administered MAC address instead.

Signed-off-by: Luciano Coelho <coelho@ti.com>
---

In v2:

* use eth_random_addr() to generate the locally assigned address,
  instead of hardcoding it. (thanks Johannes)

 drivers/net/wireless/ti/wl18xx/main.c |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ae85ae4..7aa0eb8 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/ip.h>
 #include <linux/firmware.h>
+#include <linux/etherdevice.h>
 
 #include "../wlcore/wlcore.h"
 #include "../wlcore/debug.h"
@@ -1318,6 +1319,16 @@ static int wl18xx_get_mac(struct wl1271 *wl)
 		((mac1 & 0xff000000) >> 24);
 	wl->fuse_nic_addr = (mac1 & 0xffffff);
 
+	if (!wl->fuse_oui_addr && !wl->fuse_nic_addr) {
+		u8 mac[ETH_ALEN];
+
+		eth_random_addr(mac);
+
+		wl->fuse_oui_addr = (mac[0] << 16) + (mac[1] << 8) + mac[2];
+		wl->fuse_nic_addr = (mac[3] << 16) + (mac[4] << 8) + mac[5];
+		wl1271_warning("MAC address from fuse not available, using random locally administered addresses.");
+	}
+
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
 
 out:
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 3/3] Wi6210: Added TSO support
From: wilocity.git @ 2013-05-08  8:35 UTC (permalink / raw)
  To: qca_vkondrat; +Cc: linux-wireless, wil6210, Wilocity Git

From: Erez Kirshenbaum <erezk@wilocitycom>

Added TCP offloading support in TX. The 1st descriptor holds the TCP/IP header used as a pattern
for all packets. Large send data is assigned to descriptors, each chain has MPDU size. The header
descriptor does not have a valid DU value so we ignore it in tx_complete. Due to hardware design
the first data descriptor has increased number of descriptors which compensates the header descriptor.

Signed-off-by: Erez Kirshenbaum <erezk@wilocitycom>
Signed-off-by: Wilocity Git <wilocity.git@gmail.com>
---
 drivers/net/wireless/ath/wil6210/netdev.c  |   3 +-
 drivers/net/wireless/ath/wil6210/txrx.c    | 248 +++++++++++++++++++++++++++--
 drivers/net/wireless/ath/wil6210/wil6210.h |   2 +-
 3 files changed, 241 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index b294729..8449b78 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -100,7 +100,8 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
 
 	ndev->netdev_ops = &wil_netdev_ops;
 	ndev->ieee80211_ptr = wdev;
-	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG;
+	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
+		NETIF_F_SG | NETIF_F_TSO;
 	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 5076abd..b81ff5d 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -647,8 +647,16 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
 	return 0;
 }
 
-static void wil_tx_desc_offload_setup(struct vring_tx_desc *d,
-				struct sk_buff *skb)
+/**
+ * Sets the descriptor @d up for csum and/or TSO offloaing. The corresponding
+ * @skb is used to obtain the protocol and headers length.
+ * @tso_desc_type is a descriptor type for TSO: -1 - no TSO send,
+ * 0 - a header, 1 - first data, 2 - middle, 3 - last descriptor.
+ * Returns the protocol: 0 - not TCP, 1 - TCPv4, 2 - TCPv6.
+ * Note, if d==NULL, the function only returns the protocol result.
+ */
+static int wil_tx_desc_offload_setup(struct vring_tx_desc *d,
+				struct sk_buff *skb, int tso_desc_type)
 {
 	int is_ip4 = 0, is_ip6 = 0, is_tcp = 0, is_udp = 0;
 
@@ -670,7 +678,7 @@ static void wil_tx_desc_offload_setup(struct vring_tx_desc *d,
 			is_udp = 1;
 	}
 
-	if (is_ip4 || is_ip6) {
+	if (d && (is_ip4 || is_ip6)) {
 		if (is_ip4)
 			d->dma.offload_cfg |=
 				BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
@@ -693,6 +701,19 @@ static void wil_tx_desc_offload_setup(struct vring_tx_desc *d,
 				d->dma.d0 |=
 					(tcp_hdrlen(skb) &
 					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+				if (tso_desc_type != -1) {
+					/* Setup TSO: the bit and desc type */
+					d->dma.d0 |=
+				       (BIT(DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS))
+				       | (tso_desc_type <<
+				    DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS);
+					if (is_ip4)
+						d->dma.d0 |=
+				BIT(DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS);
+					d->mac.d[2] |= (1 << /* Descs count */
+				MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
+
+				}
 			} else  {
 				/* L4 header len: UDP header length */
 				d->dma.d0 |=
@@ -701,6 +722,213 @@ static void wil_tx_desc_offload_setup(struct vring_tx_desc *d,
 			}
 		}
 	}
+	return is_tcp ? (is_ip4 ? 1 : 2) : 0;
+}
+
+static inline void wil_tx_last_desc(struct vring_tx_desc *d, int vring_index)
+{
+	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS)
+		| BIT(9) /* BUG: undocumented bit */
+		| BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS)
+		| (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
+}
+
+static inline void wil_set_tx_desc_count(struct vring_tx_desc *d, int cnt)
+{
+	d->mac.d[2] &= ~(MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK);
+	d->mac.d[2] |= (cnt << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
+}
+
+
+static int wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
+		struct sk_buff *skb)
+{
+	struct device *dev = wil_to_dev(wil);
+	struct vring_tx_desc *d;
+	struct vring_tx_desc *hdrdesc, *firstdata = NULL;
+	struct wil_skb_cb *skbcb = (struct wil_skb_cb *)skb->cb;
+	u32 swhead = vring->swhead;
+	u32 swtail = vring->swtail;
+	int used = (vring->size + swhead - swtail) % vring->size;
+	int avail = vring->size - used - 1;
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	int min_desc_required = (nr_frags*3)+1;	/* Min required descriptors */
+	int mss = skb_shinfo(skb)->gso_size;	/* payload size w/o headers */
+	int f, len, hdrlen;
+	int vring_index = vring - wil->vring_tx;
+	int i = swhead;
+	int descs_used = 1;	/* Tx descs used. At least 1 with the header */
+	dma_addr_t pa;
+	const struct skb_frag_struct *frag;
+	int tcp_ver = 0;
+	struct vring_tx_desc *sg_desc = NULL;
+	int sg_desc_cnt = 0;
+	int rem_data = 0;
+	int lenmss;
+	int compensate_hdr_desc = 1;
+
+	if (avail < min_desc_required) {
+		/*
+		 A typical page 4K is 3-4 payloads, we assume each fragment
+		 is a full payload, that's how min_desc_required has been
+		 calculated. In real we might need more or less descriptors,
+		 this is the initial check only.
+		*/
+		wil_err(wil, "Tx ring full. Need %d descriptors\n",
+			min_desc_required);
+		netif_tx_stop_all_queues(wil_to_ndev(wil));
+		return -ENOMEM;
+	}
+
+	tcp_ver = wil_tx_desc_offload_setup(NULL, skb, 0);
+	if (tcp_ver == 0) {
+		wil_err(wil, "TSO requires TCP protocol\n");
+		return -EINVAL;
+	}
+	hdrlen = 0x0e +	/* MAC header len */
+		(int)skb_network_header_len(skb) +	/* IP header len */
+		tcp_hdrlen(skb);		/* TCP header len */
+
+	if (tcp_ver == 1) {
+		/* TCP v4, zero out the IP length and IPv4 checksum fields
+		as required by the offloading doc
+		*/
+		ip_hdr(skb)->tot_len = 0;
+		ip_hdr(skb)->check = 0;
+	} else {
+		/* TCP v6, zero out the payload length */
+		ipv6_hdr(skb)->payload_len = 0;
+	}
+
+	/* FIXME FW can accept only unicast frames for the peer */
+	memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);
+
+	d = (struct vring_tx_desc *)&(vring->va[i].tx);
+	pa = dma_map_single(dev, skb->data, hdrlen, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, pa))) {
+		wil_err(wil, "DMA map error\n");
+		goto err_exit;
+	}
+	wil_tx_desc_map((struct vring_tx_desc *)d, pa, hdrlen);
+	hdrdesc = d;
+	wil_tx_desc_offload_setup(d, skb, 0);
+	wil_tx_last_desc(d, vring_index);
+
+	vring->ctx[i] = skb_get(skb);
+	skbcb->sngl_mapped = i;
+	skbcb->nodma_desc = i;	/* TSO header desc makes no DMA complete */
+
+
+	len = skb_headlen(skb) - hdrlen;
+	rem_data = mss;
+	if (len > 0) {
+		/* There is some data besides the headers, use a different
+		descriptor
+		*/
+		i = (swhead + 1) % vring->size;
+		d = (struct vring_tx_desc *)&(vring->va[i].tx);
+		pa = dma_map_single(dev, skb->data+hdrlen, len,
+				DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(dev, pa)))
+				goto dma_error;
+		wil_tx_desc_map((struct vring_tx_desc *)d, pa, len);
+		firstdata = d;	/* 1st data descriptor */
+		wil_tx_desc_offload_setup(d, skb, 1);
+		skbcb->sngl_mapped = i;
+		vring->ctx[i] = skb_get(skb);
+		descs_used++;
+		sg_desc = d;
+		sg_desc_cnt = 1;
+		rem_data = mss - len;
+
+	}
+	/* Data segments. split each fragment to chunks with mss size */
+	for (f = 0; f < nr_frags; f++)  {
+		frag = &skb_shinfo(skb)->frags[f];
+		len = frag->size;
+		while (len > 0)  {
+			if (rem_data == 0) {
+				/* got full mss descs chain. Complete the
+				previous descriptor
+				*/
+				wil_tx_last_desc(d, vring_index);
+				if (sg_desc)
+					wil_set_tx_desc_count(sg_desc,
+							sg_desc_cnt +
+							compensate_hdr_desc);
+				sg_desc = NULL;
+				sg_desc_cnt = 0;
+				rem_data = mss;
+				compensate_hdr_desc = 0;
+			} else {
+				if (descs_used == avail)  {
+					wil_err(wil,
+					"Tx: ring overflow TSO\n");
+					netif_tx_stop_all_queues(
+							wil_to_ndev(wil));
+					goto dma_error;
+				}
+				lenmss = len > rem_data ? rem_data : len;
+				i = (swhead + descs_used) % vring->size;
+				pa = skb_frag_dma_map(dev, frag,
+						(frag->size - len),
+						lenmss, DMA_TO_DEVICE);
+				if (unlikely(dma_mapping_error(dev, pa)))
+					goto dma_error;
+				d = (struct vring_tx_desc *)&(vring->va[i].tx);
+				wil_tx_desc_map((struct vring_tx_desc *)d,
+						pa, lenmss);
+				if (sg_desc == NULL)
+					sg_desc = d;
+
+				if (firstdata)  {
+					/* middle desc */
+					wil_tx_desc_offload_setup(d, skb, 2);
+				} else {
+					/* 1st data desc */
+					wil_tx_desc_offload_setup(d, skb, 1);
+					firstdata = d;
+				}
+				vring->ctx[i] = skb_get(skb);
+				descs_used++;
+				sg_desc_cnt++;
+				len -= lenmss;
+				rem_data -= lenmss;
+			}
+		}
+	}
+	wil_tx_last_desc(d, vring_index);
+	if (sg_desc)
+		wil_set_tx_desc_count(sg_desc, sg_desc_cnt +
+					compensate_hdr_desc);
+
+	/* Last data descriptor */
+	d->dma.d0 |= (3 << DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS);
+	/* Fill the number of descriptors */
+	wil_set_tx_desc_count(hdrdesc, descs_used);
+
+	/* advance swhead */
+	wil_vring_advance_head(vring, descs_used);
+	iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
+	return 0;
+
+ dma_error:
+	wil_err(wil, "DMA map page error\n");
+	while (descs_used > 0) {
+		i = (swhead + descs_used) % vring->size;
+		d = (struct vring_tx_desc *)&(vring->va[i].tx);
+		d->dma.status = TX_DMA_STATUS_DU;
+		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+		if (i > skbcb->sngl_mapped)
+			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+		else
+			dma_unmap_single(dev, pa, d->dma.length,
+					DMA_TO_DEVICE);
+		descs_used--;
+		dev_kfree_skb_any(skb);	/* Decrease skb reference count */
+	}
+err_exit:
+	return -EINVAL;
 }
 
 static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
@@ -753,7 +981,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	 */
 	if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
 		(ndev->features & NETIF_F_HW_CSUM))
-		wil_tx_desc_offload_setup((struct vring_tx_desc *)d, skb);
+		wil_tx_desc_offload_setup((struct vring_tx_desc *)d, skb, -1);
 
 
 
@@ -776,15 +1004,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
 			(ndev->features & NETIF_F_HW_CSUM))
 			wil_tx_desc_offload_setup((struct vring_tx_desc *)d,
-						skb);
+						skb, -1);
 		/* Keep reference to skb till all the fragments are done */
 		vring->ctx[i] = skb_get(skb);
 	}
 	/* for the last seg only */
-	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
-	d->dma.d0 |= BIT(9); /* BUG: undocumented bit */
-	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
-	d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
+	wil_tx_last_desc((struct vring_tx_desc *)d, vring_index);
 
 	wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
 			  (const void *)d, sizeof(*d), false);
@@ -843,7 +1068,10 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 			goto drop;
 		}
 		/* set up vring entry */
-		rc = wil_tx_vring(wil, vring, skb);
+		if (skb_is_gso(skb))
+			rc = wil_tx_vring_tso(wil, vring, skb);
+		else
+			rc = wil_tx_vring(wil, vring, skb);
 	}
 	switch (rc) {
 	case 0:
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 8f76ecd..6884c45 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -35,7 +35,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
 #define WIL6210_MEM_SIZE (2*1024*1024UL)
 
 #define WIL6210_RX_RING_SIZE (128)
-#define WIL6210_TX_RING_SIZE (128)
+#define WIL6210_TX_RING_SIZE (512)
 #define WIL6210_MAX_TX_RINGS (24)
 
 /* Hardware definitions begin */
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH 2/3] wil6210: Add scatter gather support
From: wilocity.git @ 2013-05-08  8:34 UTC (permalink / raw)
  To: qca_vkondrat; +Cc: linux-wireless, wil6210, Wilocity Git

From: Erez Kirshenbaum <erezk@wilocitycom>

Add scatter gather support in TX flow, each SKB may provide multiple fragments to be handled
by more then one DMA descriptor. tx_complete is able to release multiple descriptors by
checking the DU bit of the sent descriptors till the last descriptor "done" (with DU bit set).

Signed-off-by: Erez Kirshenbaum <erezk@wilocitycom>
Signed-off-by: Wilocity Git <wilocity.git@gmail.com>
---
 drivers/net/wireless/ath/wil6210/netdev.c |   4 +-
 drivers/net/wireless/ath/wil6210/txrx.c   | 206 ++++++++++++++++++------------
 2 files changed, 129 insertions(+), 81 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 4f2a61f..b294729 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -100,8 +100,8 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
 
 	ndev->netdev_ops = &wil_netdev_ops;
 	ndev->ieee80211_ptr = wdev;
-	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
-	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG;
+	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
 
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 3f44a6c..5076abd 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -26,6 +26,14 @@
 #include "wmi.h"
 #include "txrx.h"
 
+struct  wil_skb_cb {
+	int sngl_mapped;	/* Last desc. index, single_mapped skb data */
+	int nodma_desc;		/* Header desc. index with no DMA completion
+				happens in some modes, e.g. in TSO
+				*/
+};
+
+
 static bool rtap_include_phy_info;
 module_param(rtap_include_phy_info, bool, S_IRUGO);
 MODULE_PARM_DESC(rtap_include_phy_info,
@@ -107,6 +115,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
 {
 	struct device *dev = wil_to_dev(wil);
 	size_t sz = vring->size * sizeof(vring->va[0]);
+	struct wil_skb_cb *skbcb;
 
 	while (!wil_vring_is_empty(vring)) {
 		if (tx) {
@@ -116,13 +125,15 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
 					((u64)d->dma.addr_high << 32);
 			struct sk_buff *skb = vring->ctx[vring->swtail];
 			if (skb) {
-				dma_unmap_single(dev, pa, d->dma.length,
-						 DMA_TO_DEVICE);
+				skbcb = (struct wil_skb_cb *)skb->cb;
+				if (vring->swtail <= skbcb->sngl_mapped)
+					dma_unmap_single(dev, pa,
+						d->dma.length, DMA_TO_DEVICE);
+				else
+					dma_unmap_page(dev, pa,
+						d->dma.length, DMA_TO_DEVICE);
 				dev_kfree_skb_any(skb);
 				vring->ctx[vring->swtail] = NULL;
-			} else {
-				dma_unmap_page(dev, pa, d->dma.length,
-					       DMA_TO_DEVICE);
 			}
 			vring->swtail = wil_vring_next_tail(vring);
 		} else { /* rx */
@@ -636,12 +647,69 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
 	return 0;
 }
 
+static void wil_tx_desc_offload_setup(struct vring_tx_desc *d,
+				struct sk_buff *skb)
+{
+	int is_ip4 = 0, is_ip6 = 0, is_tcp = 0, is_udp = 0;
+
+
+	if (skb->protocol == htons(ETH_P_IP)) {
+		is_ip4 = 1;
+	if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+		is_tcp = 1;
+	else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+		is_udp = 1;
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		unsigned int offset = 0;
+		int ipv6hdr =  ipv6_find_hdr(skb,
+					&offset, -1, NULL, NULL);
+		is_ip6 = 1;
+		if (ipv6hdr == NEXTHDR_TCP)
+			is_tcp = 1;
+		else if (ipv6hdr == NEXTHDR_UDP)
+			is_udp = 1;
+	}
+
+	if (is_ip4 || is_ip6) {
+		if (is_ip4)
+			d->dma.offload_cfg |=
+				BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
+		d->dma.offload_cfg |=
+			(skb_network_header_len(skb) &
+			DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK);
+		d->dma.offload_cfg |=
+			(0x0e << DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS);
+		if (is_tcp || is_udp) {
+			/* Enable TCP/UDP checksum */
+			d->dma.d0 |=
+				BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
+			/* Calculate pseudo-header */
+			d->dma.d0 |=
+			   BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
+			if (is_tcp)  {
+				d->dma.d0 |=
+					(2 << DMA_CFG_DESC_TX_0_L4_TYPE_POS);
+			/* L4 header len: TCP header length */
+				d->dma.d0 |=
+					(tcp_hdrlen(skb) &
+					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+			} else  {
+				/* L4 header len: UDP header length */
+				d->dma.d0 |=
+					(sizeof(struct udphdr) &
+					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+			}
+		}
+	}
+}
+
 static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 			struct sk_buff *skb)
 {
 	struct device *dev = wil_to_dev(wil);
 	struct net_device *ndev = wil_to_ndev(wil);
 	volatile struct vring_tx_desc *d;
+	struct wil_skb_cb *skbcb = (struct wil_skb_cb *)skb->cb;
 	u32 swhead = vring->swhead;
 	int avail = wil_vring_avail_tx(vring);
 	int nr_frags = skb_shinfo(skb)->nr_frags;
@@ -649,7 +717,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	int vring_index = vring - wil->vring_tx;
 	uint i = swhead;
 	dma_addr_t pa;
-	int is_ip4 = 0, is_ip6 = 0, is_tcp = 0, is_udp = 0;
+
 
 
 	wil_dbg_txrx(wil, "%s()\n", __func__);
@@ -662,6 +730,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		return -ENOMEM;
 	}
 	d = &(vring->va[i].tx);
+	skbcb->sngl_mapped = i;
+	skbcb->nodma_desc = -1;
 
 	/* FIXME FW can accept only unicast frames for the peer */
 	memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);
@@ -682,60 +752,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	 * Process offloading
 	 */
 	if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
-		(ndev->features & NETIF_F_HW_CSUM))  {
-		if (skb->protocol == htons(ETH_P_IP)) {
-			is_ip4 = 1;
-		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-			is_tcp = 1;
-		else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
-			is_udp = 1;
-		} else if (skb->protocol == htons(ETH_P_IPV6)) {
-			unsigned int offset = 0;
-			int ipv6hdr =  ipv6_find_hdr(skb,
-						&offset, -1, NULL, NULL);
-			is_ip6 = 1;
-			if (ipv6hdr == NEXTHDR_TCP)
-				is_tcp = 1;
-			else if (ipv6hdr == NEXTHDR_UDP)
-				is_udp = 1;
-		}
-	}
+		(ndev->features & NETIF_F_HW_CSUM))
+		wil_tx_desc_offload_setup((struct vring_tx_desc *)d, skb);
 
 
-	if (is_ip4 || is_ip6) {
-		if (is_ip4)
-			d->dma.offload_cfg |=
-				BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
-		d->dma.offload_cfg |=
-			(skb_network_header_len(skb) &
-			DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK);
-		d->dma.offload_cfg |=
-			(0x0e << DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS);
-		if (is_tcp || is_udp) {
-			/* Enable TCP/UDP checksum */
-			d->dma.d0 |=
-				BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
-			/* Calculate pseudo-header */
-			d->dma.d0 |=
-			   BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
-			if (is_tcp)  {
-				d->dma.d0 |=
-					(2 << DMA_CFG_DESC_TX_0_L4_TYPE_POS);
-			/* L4 header len: TCP header length */
-				d->dma.d0 |=
-					(tcp_hdrlen(skb) &
-					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
-			} else  {
-				/* L4 header len: UDP header length */
-				d->dma.d0 |=
-					(sizeof(struct udphdr) &
-					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
-			}
-		}
-	}
 
 	d->mac.d[2] |= ((nr_frags + 1) <<
 		       MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
+	/* Keep reference to skb till the fragments and skb_data are done */
+	vring->ctx[i] = skb_get(skb);
 	/* middle segments */
 	for (f = 0; f < nr_frags; f++) {
 		const struct skb_frag_struct *frag =
@@ -748,7 +773,12 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		if (unlikely(dma_mapping_error(dev, pa)))
 			goto dma_error;
 		wil_tx_desc_map(d, pa, len);
-		vring->ctx[i] = NULL;
+		if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
+			(ndev->features & NETIF_F_HW_CSUM))
+			wil_tx_desc_offload_setup((struct vring_tx_desc *)d,
+						skb);
+		/* Keep reference to skb till all the fragments are done */
+		vring->ctx[i] = skb_get(skb);
 	}
 	/* for the last seg only */
 	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
@@ -763,25 +793,21 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	wil_vring_advance_head(vring, nr_frags + 1);
 	wil_dbg_txrx(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
 	iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
-	/* hold reference to skb
-	 * to prevent skb release before accounting
-	 * in case of immediate "tx done"
-	 */
-	vring->ctx[i] = skb_get(skb);
 
 	return 0;
  dma_error:
 	/* unmap what we have mapped */
 	/* Note: increment @f to operate with positive index */
 	for (f++; f > 0; f--) {
-		i = (swhead + f) % vring->size;
+		i = (swhead + f - 1) % vring->size;
 		d = &(vring->va[i].tx);
 		d->dma.status = TX_DMA_STATUS_DU;
 		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
-		if (vring->ctx[i])
+		if (i <= skbcb->sngl_mapped)
 			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
 		else
 			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);	/* Decrease skb reference count */
 	}
 
 	return -EINVAL;
@@ -847,7 +873,9 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 	struct net_device *ndev = wil_to_ndev(wil);
 	struct device *dev = wil_to_dev(wil);
 	struct vring *vring = &wil->vring_tx[ringid];
-
+	struct wil_skb_cb *skbcb;
+	int swtail, swtail_to_rel;
+	int nodma_comp;
 	if (!vring->va) {
 		wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid);
 		return;
@@ -855,17 +883,22 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 
 	wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
 
-	while (!wil_vring_is_empty(vring)) {
-		volatile struct vring_tx_desc *d1 =
-					      &vring->va[vring->swtail].tx;
-		struct vring_tx_desc dd, *d = &dd;
-		dma_addr_t pa;
-		struct sk_buff *skb;
+	swtail_to_rel = vring->swtail;
 
-		dd = *d1;
+	for (swtail = vring->swtail; swtail != vring->swhead;
+		swtail = (swtail + 1) % vring->size) {
+		struct vring_tx_desc *d = (struct vring_tx_desc *)
+			&vring->va[swtail].tx;
+		if (d->dma.status & TX_DMA_STATUS_DU)
+			swtail_to_rel = swtail;
+	}
 
-		if (!(d->dma.status & TX_DMA_STATUS_DU))
-			break;
+	for (swtail = vring->swtail; swtail != swtail_to_rel;
+		swtail = (swtail + 1) % vring->size) {
+		struct vring_tx_desc *d = (struct vring_tx_desc *)
+			&vring->va[swtail].tx;
+		dma_addr_t pa;
+		struct sk_buff *skb;
 
 		wil_dbg_txrx(wil,
 			     "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
@@ -875,7 +908,9 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 				  (const void *)d, sizeof(*d), false);
 
 		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
-		skb = vring->ctx[vring->swtail];
+		nodma_comp = false;
+		skbcb = NULL;
+		skb = vring->ctx[swtail];
 		if (skb) {
 			if (d->dma.error == 0) {
 				ndev->stats.tx_packets++;
@@ -884,18 +919,31 @@ void wil_tx_complete(struct wil6210_priv *wil, int ringid)
 				ndev->stats.tx_errors++;
 			}
 
-			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			skbcb = (struct wil_skb_cb *)skb->cb;
+			if (swtail == skbcb->nodma_desc)
+				nodma_comp = true;
+		}
+		if ((!nodma_comp) && (d->dma.d0 &
+			BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS)))
+			if ((!(d->dma.status & TX_DMA_STATUS_DU)))
+				break;
+
+		if (skbcb) {
+			if (swtail <= skbcb->sngl_mapped)
+				dma_unmap_single(dev, pa, d->dma.length,
+						DMA_TO_DEVICE);
+			else
+				dma_unmap_page(dev, pa, d->dma.length,
+						DMA_TO_DEVICE);
 			dev_kfree_skb_any(skb);
-			vring->ctx[vring->swtail] = NULL;
-		} else {
-			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
 		}
+		vring->ctx[swtail] = NULL;
 		d->dma.addr_low = 0;
 		d->dma.addr_high = 0;
 		d->dma.length = 0;
 		d->dma.status = TX_DMA_STATUS_DU;
-		vring->swtail = wil_vring_next_tail(vring);
 	}
+	vring->swtail = swtail;
 	if (wil_vring_avail_tx(vring) > vring->size/4)
 		netif_tx_wake_all_queues(wil_to_ndev(wil));
 }
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH 1/3] wil6210: TCP/UDP checksum offloading support
From: wilocity.git @ 2013-05-08  8:32 UTC (permalink / raw)
  To: qca_vkondrat; +Cc: linux-wireless, wil6210, Erez Kirshenbaum, Wilocity Git

From: Erez Kirshenbaum <erezk@wilocity.com>

Add TCP/UDP checksum hardware offloading, configure hw and set the corresponding offloading bits in the
DMA descriptors.

Signed-off-by: Erez Kirshenbaum <erezk@wilocity.com>
Signed-off-by: Wilocity Git <wilocity.git@gmail.com>
---
 drivers/net/wireless/ath/wil6210/netdev.c | 24 ++++++++++
 drivers/net/wireless/ath/wil6210/txrx.c   | 77 +++++++++++++++++++++++++++++--
 drivers/net/wireless/ath/wil6210/txrx.h   | 28 +++++++++--
 drivers/net/wireless/ath/wil6210/wmi.c    |  8 ++++
 4 files changed, 130 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 098a8ec..4f2a61f 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -32,12 +32,34 @@ static int wil_stop(struct net_device *ndev)
 	return wil_down(wil);
 }
 
+static netdev_features_t wil_fix_features(struct net_device *netdev,
+			netdev_features_t features)
+{
+	return features;
+}
+
+static int wil_set_features(struct net_device *netdev,
+			netdev_features_t features)
+{
+	struct wil6210_priv *wil = ndev_to_wil(netdev);
+	netdev_features_t changed = features ^ netdev->features;
+
+	wil_info(wil, "wil_set_features: %x\n", (unsigned int)features);
+	if (changed & NETIF_F_HW_CSUM)
+		wil_info(wil, "Tx checksum offloading changed\n");
+	else if (changed & NETIF_F_RXCSUM)
+		wil_info(wil, "Rx checksum offloading changed\n");
+	return 0;
+}
+
 static const struct net_device_ops wil_netdev_ops = {
 	.ndo_open		= wil_open,
 	.ndo_stop		= wil_stop,
 	.ndo_start_xmit		= wil_start_xmit,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_fix_features	= wil_fix_features,
+	.ndo_set_features	= wil_set_features,
 };
 
 void *wil_if_alloc(struct device *dev, void __iomem *csr)
@@ -78,6 +100,8 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
 
 	ndev->netdev_ops = &wil_netdev_ops;
 	ndev->ieee80211_ptr = wdev;
+	ndev->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	ndev->features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
 	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
 	wdev->netdev = ndev;
 
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 7970245..3f44a6c 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -18,6 +18,9 @@
 #include <net/ieee80211_radiotap.h>
 #include <linux/if_arp.h>
 #include <linux/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
 
 #include "wil6210.h"
 #include "wmi.h"
@@ -391,7 +394,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 		 */
 		wil_swap_ethaddr(skb->data);
 	}
-
+	/* Check checksum-offload status */
+	if (ndev->features & NETIF_F_RXCSUM) {
+		if (d->dma.status & RX_DMA_STATUS_L4_IDENT) {
+			/* L4 protocol identified, csum calculated */
+			if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0)
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+			else
+				wil_err(wil, "Incorrect checksum reported\n");
+		}
+	}
 	return skb;
 }
 
@@ -605,9 +617,7 @@ static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
 {
 	d->dma.addr_low = lower_32_bits(pa);
 	d->dma.addr_high = (u16)upper_32_bits(pa);
-	d->dma.ip_length = 0;
-	/* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/
-	d->dma.b11 = 0/*14 | BIT(7)*/;
+	d->dma.offload_cfg = 0;
 	d->dma.error = 0;
 	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
 	d->dma.length = len;
@@ -630,6 +640,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 			struct sk_buff *skb)
 {
 	struct device *dev = wil_to_dev(wil);
+	struct net_device *ndev = wil_to_ndev(wil);
 	volatile struct vring_tx_desc *d;
 	u32 swhead = vring->swhead;
 	int avail = wil_vring_avail_tx(vring);
@@ -638,6 +649,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	int vring_index = vring - wil->vring_tx;
 	uint i = swhead;
 	dma_addr_t pa;
+	int is_ip4 = 0, is_ip6 = 0, is_tcp = 0, is_udp = 0;
+
 
 	wil_dbg_txrx(wil, "%s()\n", __func__);
 
@@ -665,6 +678,62 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 		return -EINVAL;
 	/* 1-st segment */
 	wil_tx_desc_map(d, pa, skb_headlen(skb));
+	/*
+	 * Process offloading
+	 */
+	if ((skb->ip_summed == CHECKSUM_PARTIAL) &&
+		(ndev->features & NETIF_F_HW_CSUM))  {
+		if (skb->protocol == htons(ETH_P_IP)) {
+			is_ip4 = 1;
+		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+			is_tcp = 1;
+		else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+			is_udp = 1;
+		} else if (skb->protocol == htons(ETH_P_IPV6)) {
+			unsigned int offset = 0;
+			int ipv6hdr =  ipv6_find_hdr(skb,
+						&offset, -1, NULL, NULL);
+			is_ip6 = 1;
+			if (ipv6hdr == NEXTHDR_TCP)
+				is_tcp = 1;
+			else if (ipv6hdr == NEXTHDR_UDP)
+				is_udp = 1;
+		}
+	}
+
+
+	if (is_ip4 || is_ip6) {
+		if (is_ip4)
+			d->dma.offload_cfg |=
+				BIT(DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS);
+		d->dma.offload_cfg |=
+			(skb_network_header_len(skb) &
+			DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK);
+		d->dma.offload_cfg |=
+			(0x0e << DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS);
+		if (is_tcp || is_udp) {
+			/* Enable TCP/UDP checksum */
+			d->dma.d0 |=
+				BIT(DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS);
+			/* Calculate pseudo-header */
+			d->dma.d0 |=
+			   BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS);
+			if (is_tcp)  {
+				d->dma.d0 |=
+					(2 << DMA_CFG_DESC_TX_0_L4_TYPE_POS);
+			/* L4 header len: TCP header length */
+				d->dma.d0 |=
+					(tcp_hdrlen(skb) &
+					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+			} else  {
+				/* L4 header len: UDP header length */
+				d->dma.d0 |=
+					(sizeof(struct udphdr) &
+					DMA_CFG_DESC_TX_0_L4_LENGTH_MSK);
+			}
+		}
+	}
+
 	d->mac.d[2] |= ((nr_frags + 1) <<
 		       MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
 	/* middle segments */
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index adef12f..da22a93 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -209,7 +209,21 @@ struct vring_tx_mac {
 
 #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30
 #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2
-#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000
+#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 /* L4 type: 0-UDP, 2-TCP */
+
+/* TX DMA Dword 2 */
+/* Offload bits in offload_cfg field */
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_POS 0
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_LEN 8
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_IP_LEN_MSK 0x00FF /* IP hdr len */
+
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_POS 8
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_LEN 7
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_MAC_LEN_MSK 0x7F00 /* MAC hdr len */
+
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_POS 15
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_LEN 1
+#define DMA_CFG_DESC_TX_OFFLOAD_CFG_L3T_IPV4_MSK 0x8000 /* 1-IPv4, 0-IPv6 */
 
 
 #define TX_DMA_STATUS_DU         BIT(0)
@@ -218,8 +232,7 @@ struct vring_tx_dma {
 	u32 d0;
 	u32 addr_low;
 	u16 addr_high;
-	u8  ip_length;
-	u8  b11;       /* 0..6: mac_length; 7:ip_version */
+	u16 offload_cfg;
 	u8  error;     /* 0..2: err; 3..7: reserved; */
 	u8  status;    /* 0: used; 1..7; reserved */
 	u16 length;
@@ -309,8 +322,17 @@ struct vring_rx_mac {
 
 #define RX_DMA_D0_CMD_DMA_IT     BIT(10)
 
+/* Error field, offload bits */
+#define RX_DMA_ERROR_L3_ERR   BIT(4)
+#define RX_DMA_ERROR_L4_ERR   BIT(5)
+
+
+/* Status field */
 #define RX_DMA_STATUS_DU         BIT(0)
 #define RX_DMA_STATUS_ERROR      BIT(2)
+
+#define RX_DMA_STATUS_L3_IDENT   BIT(4)
+#define RX_DMA_STATUS_L4_IDENT   BIT(5)
 #define RX_DMA_STATUS_PHY_INFO   BIT(6)
 
 struct vring_rx_dma {
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 45b04e3..dc0aa8a 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -932,6 +932,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 		struct wmi_cfg_rx_chain_done_event evt;
 	} __packed evt;
 	int rc;
+	u8 csum_enabled = 0;
+
+	/* Initialize offload. Linux always calculates IP checksum */
+	cmd.l3_l4_ctrl |= (0 << L3_L4_CTRL_IPV4_CHECKSUM_EN_POS);
+	/* Enable/disable TCP/UDP checksum */
+	if (ndev->features & NETIF_F_RXCSUM)
+		csum_enabled = 1;
+	cmd.l3_l4_ctrl |= (csum_enabled << L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS);
 
 	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
 		struct ieee80211_channel *ch = wdev->preset_chandef.chan;
-- 
1.7.11.7


^ permalink raw reply related

* Re: [PATCH] mac80211: refine ieee80211_rx() context requirement
From: Johannes Berg @ 2013-05-08  8:57 UTC (permalink / raw)
  To: Wei.Yang; +Cc: linux-wireless, wei.wyang
In-Reply-To: <518A112F.3070903@windriver.com>

On Wed, 2013-05-08 at 16:47 +0800, wyang1 wrote:
> On 05/08/2013 04:37 PM, Johannes Berg wrote:
> > On Wed, 2013-05-08 at 10:36 +0200, Johannes Berg wrote:
> >> On Wed, 2013-05-08 at 16:31 +0800, Wei.Yang@windriver.com wrote:
> >>> From: Wei Yang <Wei.Yang@windriver.com>
> >>>
> >>> In case of RT kernel, the return value of softirq_count() always
> >>> equal to 0, we need to use in_serving_softirq to decide whether
> >>> the current context is in softirq context.
> >>> -	WARN_ON_ONCE(softirq_count() == 0);
> >>> +	WARN_ON_ONCE(!in_serving_softirq());
> >> As I understand the code, I don't believe this change to be correct. The
> >> function can happily run with softirqs disabled (e.g.
> >> local_bh_disable()), for example by being called via ieee80211_rx_ni().
> >> As I understand in_serving_softirq(), it checks that it's actually
> >> inside handling a softirq, no?
> > Arguably, it should be
> > 	WARN_ON_ONCE(!in_softirq());
> >
> > but that's equivalent:
> 
> Yeah, but the softirq is threaded in rt kernel, the softirq_count always 
> return 0. The warning should always happen with rt kernel.

So maybe then the RT kernel defines in_softirq() appropriately and you
should submit a patch to change to using that? I find it hard to believe
that the RT kernel breaks _all_ the softirq APIs, but hey, I know
nothing about RT :-)

johannes


^ permalink raw reply

* Re: [PATCH] mac80211: refine ieee80211_rx() context requirement
From: wyang1 @ 2013-05-08  8:47 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, wei.wyang
In-Reply-To: <1368002236.8279.15.camel@jlt4.sipsolutions.net>

On 05/08/2013 04:37 PM, Johannes Berg wrote:
> On Wed, 2013-05-08 at 10:36 +0200, Johannes Berg wrote:
>> On Wed, 2013-05-08 at 16:31 +0800, Wei.Yang@windriver.com wrote:
>>> From: Wei Yang <Wei.Yang@windriver.com>
>>>
>>> In case of RT kernel, the return value of softirq_count() always
>>> equal to 0, we need to use in_serving_softirq to decide whether
>>> the current context is in softirq context.
>>> -	WARN_ON_ONCE(softirq_count() == 0);
>>> +	WARN_ON_ONCE(!in_serving_softirq());
>> As I understand the code, I don't believe this change to be correct. The
>> function can happily run with softirqs disabled (e.g.
>> local_bh_disable()), for example by being called via ieee80211_rx_ni().
>> As I understand in_serving_softirq(), it checks that it's actually
>> inside handling a softirq, no?
> Arguably, it should be
> 	WARN_ON_ONCE(!in_softirq());
>
> but that's equivalent:

Yeah, but the softirq is threaded in rt kernel, the softirq_count always 
return 0. The warning should always happen with rt kernel.

Wei
>
> include/linux/hardirq.h
>
>   * in_softirq - Are we currently processing softirq or have bh disabled?
>
>   #define in_softirq()           (softirq_count())
>
> johannes
>
>
>


^ permalink raw reply

* [PATCH] wl18xx: use locally administered MAC address if not available from fuse
From: Luciano Coelho @ 2013-05-08  8:44 UTC (permalink / raw)
  To: linux-wireless; +Cc: coelho

In some R&D chips, the device may be left untrimmed and with the MAC
address missing from fuse ROM.  In order to support those devices,
apply a locally administered MAC address instead and generate print
out a message to warn the user.

Based on the original patch by Victor Goldenshtein.

Signed-off-by: Luciano Coelho <coelho@ti.com>
---
 drivers/net/wireless/ti/wl18xx/main.c   |    6 ++++++
 drivers/net/wireless/ti/wl18xx/wl18xx.h |    9 +++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index ae85ae4..e296f34 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1318,6 +1318,12 @@ static int wl18xx_get_mac(struct wl1271 *wl)
 		((mac1 & 0xff000000) >> 24);
 	wl->fuse_nic_addr = (mac1 & 0xffffff);
 
+	if (!wl->fuse_oui_addr && !wl->fuse_nic_addr) {
+		wl->fuse_oui_addr = WL18XX_DEFAULT_LOCAL_OUI;
+		wl->fuse_nic_addr = WL18XX_DEFAULT_LOCAL_NIC;
+		wl1271_warning("MAC address from fuse ROM not available, using locally administered addresses.");
+	}
+
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
 
 out:
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index 9204e07..e76bfc7 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -42,6 +42,15 @@
 
 #define WL18XX_RX_BA_MAX_SESSIONS 5
 
+/*
+ * Locally administered MAC address to be used when unavailable in
+ * fuse ROM.  This is TI's 08:00:28 OUI with the locally administered
+ * bit set.  Note that this is actually the assigned BDADDR, the WLAN
+ * MAC addresses are generated incrementally from this one.
+ */
+#define WL18XX_DEFAULT_LOCAL_OUI	(0x0a0028)
+#define WL18XX_DEFAULT_LOCAL_NIC	(0x000000)
+
 struct wl18xx_priv {
 	/* buffer for sending commands to FW */
 	u8 cmd_buf[WL18XX_CMD_MAX_SIZE];
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH] mac80211: refine ieee80211_rx() context requirement
From: wyang1 @ 2013-05-08  8:44 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, wei.wyang
In-Reply-To: <1368002161.8279.14.camel@jlt4.sipsolutions.net>

On 05/08/2013 04:36 PM, Johannes Berg wrote:
> On Wed, 2013-05-08 at 16:31 +0800, Wei.Yang@windriver.com wrote:
>> From: Wei Yang <Wei.Yang@windriver.com>
>>
>> In case of RT kernel, the return value of softirq_count() always
>> equal to 0, we need to use in_serving_softirq to decide whether
>> the current context is in softirq context.
>> -	WARN_ON_ONCE(softirq_count() == 0);
>> +	WARN_ON_ONCE(!in_serving_softirq());
> As I understand the code, I don't believe this change to be correct. The
> function can happily run with softirqs disabled (e.g.
> local_bh_disable()), for example by being called via ieee80211_rx_ni().
> As I understand in_serving_softirq(), it checks that it's actually
> inside handling a softirq, no?

Yes, I am not an expert on wireless, so I am not sure whether 
ieee80211_rx will be called with softirqs disabled.
Just as you said, if it can run with softirqs diabled, the fix is not 
correct. sorry for it.

Thanks
Wei
>
> johannes
>
>
>


^ permalink raw reply

* Re: [PATCH] mac80211: refine ieee80211_rx() context requirement
From: Johannes Berg @ 2013-05-08  8:37 UTC (permalink / raw)
  To: Wei.Yang; +Cc: linux-wireless, wei.wyang
In-Reply-To: <1368002161.8279.14.camel@jlt4.sipsolutions.net>

On Wed, 2013-05-08 at 10:36 +0200, Johannes Berg wrote:
> On Wed, 2013-05-08 at 16:31 +0800, Wei.Yang@windriver.com wrote:
> > From: Wei Yang <Wei.Yang@windriver.com>
> > 
> > In case of RT kernel, the return value of softirq_count() always
> > equal to 0, we need to use in_serving_softirq to decide whether
> > the current context is in softirq context.
> 
> > -	WARN_ON_ONCE(softirq_count() == 0);
> > +	WARN_ON_ONCE(!in_serving_softirq());
> 
> As I understand the code, I don't believe this change to be correct. The
> function can happily run with softirqs disabled (e.g.
> local_bh_disable()), for example by being called via ieee80211_rx_ni().
> As I understand in_serving_softirq(), it checks that it's actually
> inside handling a softirq, no?

Arguably, it should be
	WARN_ON_ONCE(!in_softirq());

but that's equivalent:

include/linux/hardirq.h

 * in_softirq - Are we currently processing softirq or have bh disabled?

 #define in_softirq()           (softirq_count())

johannes


^ permalink raw reply

* Re: [PATCH] mac80211: refine ieee80211_rx() context requirement
From: Johannes Berg @ 2013-05-08  8:36 UTC (permalink / raw)
  To: Wei.Yang; +Cc: linux-wireless, wei.wyang
In-Reply-To: <1368001892-18068-1-git-send-email-Wei.Yang@windriver.com>

On Wed, 2013-05-08 at 16:31 +0800, Wei.Yang@windriver.com wrote:
> From: Wei Yang <Wei.Yang@windriver.com>
> 
> In case of RT kernel, the return value of softirq_count() always
> equal to 0, we need to use in_serving_softirq to decide whether
> the current context is in softirq context.

> -	WARN_ON_ONCE(softirq_count() == 0);
> +	WARN_ON_ONCE(!in_serving_softirq());

As I understand the code, I don't believe this change to be correct. The
function can happily run with softirqs disabled (e.g.
local_bh_disable()), for example by being called via ieee80211_rx_ni().
As I understand in_serving_softirq(), it checks that it's actually
inside handling a softirq, no?

johannes


^ permalink raw reply

* [PATCH] mac80211: refine ieee80211_rx() context requirement
From: Wei.Yang @ 2013-05-08  8:31 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, wei.wyang

From: Wei Yang <Wei.Yang@windriver.com>

In case of RT kernel, the return value of softirq_count() always
equal to 0, we need to use in_serving_softirq to decide whether
the current context is in softirq context.

Signed-off-by: Wei Yang <Wei.Yang@windriver.com>
---
 net/mac80211/rx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c6844ad..80fac46 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3226,7 +3226,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
-	WARN_ON_ONCE(softirq_count() == 0);
+	WARN_ON_ONCE(!in_serving_softirq());
 
 	if (WARN_ON(status->band >= IEEE80211_NUM_BANDS))
 		goto drop;
-- 
1.7.9.5


^ permalink raw reply related


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