Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 5/6] staging: vt6656: rxtx s_vFillRTSHead create union of vnt_rts*/vnt_cts* structures.
From: Malcolm Priestley @ 2013-08-26 10:17 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Only one of vnt_rts*/vnt_cts* structures are accessed at any one time.

Join these structures in to a single union.

These will eventually form the tail structure of vnt_tx_buffer and
include structures vnt_tx_datahead*

Structures in s_vFillCTSHead will join in next patch series.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 25 ++++++++-----------------
 drivers/staging/vt6656/rxtx.h | 12 ++++++++++++
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index a45cc9f..0785431 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -720,48 +720,39 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
 {
+	union vnt_tx_data_head *head = pvRTS;
 
-    if (pvRTS == NULL)
-    	return;
+	if (!head)
+		return;
 
     // Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account.
     //       Otherwise, we need to modified codes for them.
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
         if (byFBOption == AUTO_FB_NONE) {
-		struct vnt_rts_g *pBuf = (struct vnt_rts_g *)pvRTS;
-
-		vnt_rxtx_rts_g_head(pDevice, pBuf,
+		vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
         }
         else {
-		struct vnt_rts_g_fb *pBuf = (struct vnt_rts_g_fb *)pvRTS;
-
-		vnt_rxtx_rts_g_fb_head(pDevice, pBuf,
+		vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
         } // if (byFBOption == AUTO_FB_NONE)
     }
     else if (byPktType == PK_TYPE_11A) {
         if (byFBOption == AUTO_FB_NONE) {
-		struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
-
-		vnt_rxtx_rts_ab_head(pDevice, pBuf,
+		vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
         }
         else {
-		struct vnt_rts_a_fb *pBuf = (struct vnt_rts_a_fb *)pvRTS;
-
-		vnt_rxtx_rts_a_fb_head(pDevice, pBuf,
+		vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
         }
     }
     else if (byPktType == PK_TYPE_11B) {
-	struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
-
-	vnt_rxtx_rts_ab_head(pDevice, pBuf,
+	vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
 			psEthHeader, byPktType, cbFrameLength,
 			bNeedAck, wCurrentRate, byFBOption);
     }
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index ad62052..4bbee1c 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -168,6 +168,18 @@ struct vnt_cts_fb {
 	u16 reserved2;
 } __packed;
 
+union vnt_tx_data_head {
+	/* rts g */
+	struct vnt_rts_g rts_g;
+	struct vnt_rts_g_fb rts_g_fb;
+	/* rts a/b */
+	struct vnt_rts_ab rts_ab;
+	struct vnt_rts_a_fb rts_a_fb;
+	/* cts g */
+	struct vnt_cts cts_g;
+	struct vnt_cts_fb cts_g_fb;
+};
+
 struct vnt_tx_buffer {
 	u8 byType;
 	u8 byPKTNO;
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 4/6] staging: vt6656: rxtx.c s_vFillRTSHead Parse out struct vnt_rts_a_fb to new function.
From: Malcolm Priestley @ 2013-08-26 10:12 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Parse out vnt_rts_a_fb code to new function vnt_rxtx_rts_a_fb_head.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 54 +++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index ce8018e..a45cc9f 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -692,11 +692,34 @@ static int vnt_rxtx_rts_ab_head(struct vnt_private *priv,
 	return 0;
 }
 
+static int vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
+	struct vnt_rts_a_fb *buf, struct ethhdr *eth_hdr,
+	u8 pkt_type, u32 frame_len, int need_ack,
+	u16 current_rate, u8 fb_option)
+{
+	u16 rts_frame_len = 20;
+
+	BBvCalculateParameter(priv, rts_frame_len,
+		priv->byTopOFDMBasicRate, pkt_type, &buf->a);
+
+	buf->wDuration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+
+	buf->wRTSDuration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+
+	buf->wRTSDuration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+
+	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
+
+	return 0;
+}
+
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
 {
-	u32 uRTSFrameLen = 20;
 
     if (pvRTS == NULL)
     	return;
@@ -729,33 +752,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         }
         else {
 		struct vnt_rts_a_fb *pBuf = (struct vnt_rts_a_fb *)pvRTS;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
-            //Get Duration
-		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
-			cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
-		pBuf->wRTSDuration_f0 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_AA_F0, cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->wRTSDuration_f1 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_AA_F1, cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->data.duration = pBuf->wDuration;
-		/* Get RTS Frame body */
-		pBuf->data.frame_control = TYPE_CTL_RTS;
-
-		if (pDevice->eOPMode == OP_MODE_ADHOC ||
-				pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ra, psEthHeader->h_dest, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ra, pDevice->abyBSSID, ETH_ALEN);
 
-		if (pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ta, pDevice->abyBSSID, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ta, psEthHeader->h_source, ETH_ALEN);
+		vnt_rxtx_rts_a_fb_head(pDevice, pBuf,
+				psEthHeader, byPktType, cbFrameLength,
+				bNeedAck, wCurrentRate, byFBOption);
         }
     }
     else if (byPktType == PK_TYPE_11B) {
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 3/6] staging: vt6656: rxtx.c s_vFillRTSHead Parse out struct vnt_rts_ab to new function.
From: Malcolm Priestley @ 2013-08-26 10:09 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Parse out vnt_rts_ab code to new function vnt_rxtx_rts_ab_head.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 65 ++++++++++++++++---------------------------
 1 file changed, 24 insertions(+), 41 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 5cfdfaf..ce8018e 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -674,6 +674,24 @@ static int vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
 	return 0;
 }
 
+static int vnt_rxtx_rts_ab_head(struct vnt_private *priv,
+	struct vnt_rts_ab *buf, struct ethhdr *eth_hdr,
+	u8 pkt_type, u32 frame_len, int need_ack,
+	u16 current_rate, u8 fb_option)
+{
+	u16 rts_frame_len = 20;
+
+	BBvCalculateParameter(priv, rts_frame_len,
+		priv->byTopOFDMBasicRate, pkt_type, &buf->ab);
+
+	buf->wDuration = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+
+	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
+
+	return 0;
+}
+
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
@@ -704,27 +722,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
     else if (byPktType == PK_TYPE_11A) {
         if (byFBOption == AUTO_FB_NONE) {
 		struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->ab);
-            //Get Duration
-		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
-			cbFrameLength, byPktType, wCurrentRate,
-				bNeedAck, byFBOption);
-		pBuf->data.duration = pBuf->wDuration;
-		/* Get RTS Frame body */
-		pBuf->data.frame_control = TYPE_CTL_RTS;
-
-		if (pDevice->eOPMode == OP_MODE_ADHOC ||
-				pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ra, psEthHeader->h_dest, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ra, pDevice->abyBSSID, ETH_ALEN);
 
-		if (pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ta, pDevice->abyBSSID, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ta, psEthHeader->h_source, ETH_ALEN);
+		vnt_rxtx_rts_ab_head(pDevice, pBuf,
+				psEthHeader, byPktType, cbFrameLength,
+				bNeedAck, wCurrentRate, byFBOption);
         }
         else {
 		struct vnt_rts_a_fb *pBuf = (struct vnt_rts_a_fb *)pvRTS;
@@ -759,28 +760,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
     }
     else if (byPktType == PK_TYPE_11B) {
 	struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
-        //Get SignalField,ServiceField,Length
-	BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate,
-		PK_TYPE_11B, &pBuf->ab);
-        //Get Duration
-	pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
-		cbFrameLength, byPktType, wCurrentRate,
-		bNeedAck, byFBOption);
-
-	pBuf->data.duration = pBuf->wDuration;
-	/* Get RTS Frame body */
-	pBuf->data.frame_control = TYPE_CTL_RTS;
-
-	if (pDevice->eOPMode == OP_MODE_ADHOC ||
-			pDevice->eOPMode == OP_MODE_AP)
-		memcpy(pBuf->data.ra, psEthHeader->h_dest, ETH_ALEN);
-	else
-		memcpy(pBuf->data.ra, pDevice->abyBSSID, ETH_ALEN);
 
-	if (pDevice->eOPMode == OP_MODE_AP)
-		memcpy(pBuf->data.ta, pDevice->abyBSSID, ETH_ALEN);
-	else
-		memcpy(pBuf->data.ta, psEthHeader->h_source, ETH_ALEN);
+	vnt_rxtx_rts_ab_head(pDevice, pBuf,
+			psEthHeader, byPktType, cbFrameLength,
+			bNeedAck, wCurrentRate, byFBOption);
     }
 }
 
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 2/6] staging: vt6656: rxtx.c s_vFillRTSHead Parse out struct vnt_rts_g_fb to new function.
From: Malcolm Priestley @ 2013-08-26 10:07 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Parse out vnt_rts_g_fb code to new function vnt_rxtx_rts_g_fb_head.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 78 +++++++++++++++++++++----------------------
 1 file changed, 38 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 57af55b..5cfdfaf 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -639,6 +639,41 @@ static int vnt_rxtx_rts_g_head(struct vnt_private *priv,
 	return 0;
 }
 
+static int vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
+	struct vnt_rts_g_fb *buf, struct ethhdr *eth_hdr,
+	u8 pkt_type, u32 frame_len, int need_ack,
+	u16 current_rate, u8 fb_option)
+{
+	u16 rts_frame_len = 20;
+
+	BBvCalculateParameter(priv, rts_frame_len, priv->byTopCCKBasicRate,
+		PK_TYPE_11B, &buf->b);
+	BBvCalculateParameter(priv, rts_frame_len,
+		priv->byTopOFDMBasicRate, pkt_type, &buf->a);
+
+
+	buf->wDuration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
+		PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
+	buf->wDuration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+	buf->wDuration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+
+
+	buf->wRTSDuration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+	buf->wRTSDuration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+	buf->wRTSDuration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+	buf->wRTSDuration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
+		frame_len, pkt_type, current_rate, need_ack, fb_option);
+
+	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
+
+	return 0;
+}
+
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
@@ -660,47 +695,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         }
         else {
 		struct vnt_rts_g_fb *pBuf = (struct vnt_rts_g_fb *)pvRTS;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
-            //Get Duration
-		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
-			cbFrameLength, PK_TYPE_11B,
-			pDevice->byTopCCKBasicRate, bNeedAck, byFBOption);
-		pBuf->wDuration_aa = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
-			cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
-			cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->wRTSDuration_ba_f0 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
-		pBuf->wRTSDuration_aa_f0 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_AA_F0, cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->wRTSDuration_ba_f1 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
-		pBuf->wRTSDuration_aa_f1 = s_uGetRTSCTSDuration(pDevice,
-			RTSDUR_AA_F1, cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
-		pBuf->data.duration = pBuf->wDuration_aa;
-		/*Get RTS Frame body*/
-		pBuf->data.frame_control = TYPE_CTL_RTS;
-
-		if (pDevice->eOPMode == OP_MODE_ADHOC ||
-				pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ra, psEthHeader->h_dest, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ra, pDevice->abyBSSID, ETH_ALEN);
 
-		if (pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ta, pDevice->abyBSSID, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ta, psEthHeader->h_source, ETH_ALEN);
+		vnt_rxtx_rts_g_fb_head(pDevice, pBuf,
+				psEthHeader, byPktType, cbFrameLength,
+				bNeedAck, wCurrentRate, byFBOption);
         } // if (byFBOption == AUTO_FB_NONE)
     }
     else if (byPktType == PK_TYPE_11A) {
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH 1/6] staging: vt6656: rxtx.c s_vFillRTSHead Parse out struct vnt_rts_g to new functions.
From: Malcolm Priestley @ 2013-08-26 10:04 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Parse out vnt_rts_g code to new function vnt_rxtx_rts_g_head.

Also create a new common calling function vnt_fill_ieee80211_rts
to fill the ieee80211_rts structure.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 75 +++++++++++++++++++++++++++----------------
 1 file changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index dd2bfc9..57af55b 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -595,6 +595,50 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
     return 0;
 }
 
+static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
+	struct ieee80211_rts *rts, struct ethhdr *eth_hdr,
+		u16 duration)
+{
+	rts->duration = duration;
+	rts->frame_control = TYPE_CTL_RTS;
+
+	if (priv->eOPMode == OP_MODE_ADHOC || priv->eOPMode == OP_MODE_AP)
+		memcpy(rts->ra, eth_hdr->h_dest, ETH_ALEN);
+	else
+		memcpy(rts->ra, priv->abyBSSID, ETH_ALEN);
+
+	if (priv->eOPMode == OP_MODE_AP)
+		memcpy(rts->ta, priv->abyBSSID, ETH_ALEN);
+	else
+		memcpy(rts->ta, eth_hdr->h_source, ETH_ALEN);
+
+	return 0;
+}
+
+static int vnt_rxtx_rts_g_head(struct vnt_private *priv,
+	struct vnt_rts_g *buf, struct ethhdr *eth_hdr,
+	u8 pkt_type, u32 frame_len, int need_ack,
+	u16 current_rate, u8 fb_option)
+{
+	u16 rts_frame_len = 20;
+
+	BBvCalculateParameter(priv, rts_frame_len, priv->byTopCCKBasicRate,
+		PK_TYPE_11B, &buf->b);
+	BBvCalculateParameter(priv, rts_frame_len,
+		priv->byTopOFDMBasicRate, pkt_type, &buf->a);
+
+	buf->wDuration_bb = s_uGetRTSCTSDuration(priv, RTSDUR_BB, frame_len,
+		PK_TYPE_11B, priv->byTopCCKBasicRate, need_ack, fb_option);
+	buf->wDuration_aa = s_uGetRTSCTSDuration(priv, RTSDUR_AA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+	buf->wDuration_ba = s_uGetRTSCTSDuration(priv, RTSDUR_BA, frame_len,
+		pkt_type, current_rate, need_ack, fb_option);
+
+	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
+
+	return 0;
+}
+
 static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	void *pvRTS, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
@@ -609,35 +653,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
         if (byFBOption == AUTO_FB_NONE) {
 		struct vnt_rts_g *pBuf = (struct vnt_rts_g *)pvRTS;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
-		BBvCalculateParameter(pDevice, uRTSFrameLen,
-			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
-            //Get Duration
-		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
-			cbFrameLength, PK_TYPE_11B,
-			pDevice->byTopCCKBasicRate, bNeedAck, byFBOption);
-		pBuf->wDuration_aa = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
-			cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
-			cbFrameLength, byPktType,
-			wCurrentRate, bNeedAck, byFBOption);
-		pBuf->data.duration = pBuf->wDuration_aa;
-		/*Get RTS Frame body */
-		pBuf->data.frame_control = TYPE_CTL_RTS;
 
-		if (pDevice->eOPMode == OP_MODE_ADHOC ||
-				pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ra, psEthHeader->h_dest, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ra, pDevice->abyBSSID, ETH_ALEN);
-
-		if (pDevice->eOPMode == OP_MODE_AP)
-			memcpy(pBuf->data.ta, pDevice->abyBSSID, ETH_ALEN);
-		else
-			memcpy(pBuf->data.ta, psEthHeader->h_source, ETH_ALEN);
+		vnt_rxtx_rts_g_head(pDevice, pBuf,
+				psEthHeader, byPktType, cbFrameLength,
+				bNeedAck, wCurrentRate, byFBOption);
         }
         else {
 		struct vnt_rts_g_fb *pBuf = (struct vnt_rts_g_fb *)pvRTS;
-- 
1.8.1.2


^ permalink raw reply related

* Re: [PATCH v2] iwlwifi: mvm: make debugfs write() operations write up to count bytes
From: Johannes Berg @ 2013-08-26  8:57 UTC (permalink / raw)
  To: Djalal Harouni
  Cc: Intel Linux Wireless, John W. Linville, Emmanuel Grumbach,
	linux-wireless, linux-kernel
In-Reply-To: <1377351353-18588-1-git-send-email-tixxdz@opendz.org>

On Sat, 2013-08-24 at 14:35 +0100, Djalal Harouni wrote:
> Some debugfs write() operations of the MVM Firmware will ignore the
> count argument, and will copy more bytes than what was specified.
> Fix this by getting the right count of bytes.
> 
> This will honor restrictions put on the number of bytes to write and
> avoid strcmp() calls on garbage data.

Applied, thanks.

johannes


^ permalink raw reply

* [PATCH v2 4/4] ath10k: fix issues on non-preemptible systems
From: Michal Kazior @ 2013-08-26  8:53 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1377507205-5386-1-git-send-email-michal.kazior@tieto.com>

Workers may not call into a sleepable function
(e.g. mutex_lock). Since ath10k workers can run
for a very long time it is necessary to explicitly
allow process rescheduling in case there's no
preemption.

This fixes some issues with system freezes, hangs,
watchdogs being triggered, userspace being
unresponsive on slow host machines under heavy
load.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/htc.c    |    4 ++++
 drivers/net/wireless/ath/ath10k/htt_rx.c |    4 ++++
 drivers/net/wireless/ath/ath10k/wmi.c    |    4 ++++
 3 files changed, 12 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 7d445d3..99f1dbd 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -237,6 +237,10 @@ static void ath10k_htc_send_work(struct work_struct *work)
 		ret = ath10k_htc_issue_skb(htc, ep, skb, credits);
 		if (ret == -ENOSR)
 			break;
+
+#ifndef CONFIG_PREEMPT
+		cond_resched();
+#endif
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6cf4d95..80ea398 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1229,6 +1229,10 @@ static void ath10k_htt_rx_work(struct work_struct *work)
 			break;
 
 		ath10k_htt_rx_process_skb(htt->ar, skb);
+
+#ifndef CONFIG_PREEMPT
+		cond_resched();
+#endif
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 32fd5e7..f36f0be 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1155,6 +1155,10 @@ static void ath10k_wmi_event_work(struct work_struct *work)
 			break;
 
 		ath10k_wmi_event_process(ar, skb);
+
+#ifndef CONFIG_PREEMPT
+		cond_resched();
+#endif
 	}
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 3/4] ath10k: move htt rx processing to worker
From: Michal Kazior @ 2013-08-26  8:53 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1377507205-5386-1-git-send-email-michal.kazior@tieto.com>

This improves rx performance by a significant
value (280mbps -> 350mbps UDP) on AP135.

Note: it is not safe to move HTT tx completion
handling to a worker yet as it must be serialized
against HTC tx completions.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
v2:
 * use ieee80211_rx_ni()

 drivers/net/wireless/ath/ath10k/core.h   |    4 ++-
 drivers/net/wireless/ath/ath10k/htt.h    |    3 ++
 drivers/net/wireless/ath/ath10k/htt_rx.c |   54 ++++++++++++++++++++++++++----
 drivers/net/wireless/ath/ath10k/txrx.c   |    2 +-
 4 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 17694ec..b5f8df0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -42,8 +42,10 @@
 
 #define ATH10K_NUM_HTC_TX_WORKERS ATH10K_HTC_EP_COUNT
 #define ATH10K_NUM_WMI_RX_WORKERS 1
+#define ATH10K_NUM_HTT_RX_WORKERS 1
 #define ATH10K_MAX_NUM_PARALLEL_WORKERS (ATH10K_NUM_HTC_TX_WORKERS + \
-					 ATH10K_NUM_WMI_RX_WORKERS)
+					 ATH10K_NUM_WMI_RX_WORKERS + \
+					 ATH10K_NUM_HTT_RX_WORKERS)
 
 /* Antenna noise floor */
 #define ATH10K_DEFAULT_NOISE_FLOOR -95
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 26c78a9..8abbf2c 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1268,6 +1268,9 @@ struct ath10k_htt {
 	/* set if host-fw communication goes haywire
 	 * used to avoid further failures */
 	bool rx_confused;
+
+	struct work_struct rx_work;
+	struct sk_buff_head rx_queue;
 };
 
 #define RX_HTT_HDR_STATUS_LEN 64
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 9bb0ae89..6cf4d95 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -40,6 +40,10 @@
 /* when under memory pressure rx ring refill may fail and needs a retry */
 #define HTT_RX_RING_REFILL_RETRY_MS 50
 
+
+static void ath10k_htt_rx_work(struct work_struct *work);
+
+
 static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt)
 {
 	int size;
@@ -211,6 +215,8 @@ void ath10k_htt_rx_detach(struct ath10k_htt *htt)
 {
 	int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld;
 
+	skb_queue_purge(&htt->rx_queue);
+	cancel_work_sync(&htt->rx_work);
 	del_timer_sync(&htt->rx_ring.refill_retry_timer);
 
 	while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) {
@@ -501,6 +507,9 @@ int ath10k_htt_rx_attach(struct ath10k_htt *htt)
 	if (__ath10k_htt_rx_ring_fill_n(htt, htt->rx_ring.fill_level))
 		goto err_fill_ring;
 
+	INIT_WORK(&htt->rx_work, ath10k_htt_rx_work);
+	skb_queue_head_init(&htt->rx_queue);
+
 	ath10k_dbg(ATH10K_DBG_HTT, "HTT RX ring size: %d, fill_level: %d\n",
 		   htt->rx_ring.size, htt->rx_ring.fill_level);
 	return 0;
@@ -1083,17 +1092,11 @@ end:
 	}
 }
 
-void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_htt_rx_process_skb(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
 	struct htt_resp *resp = (struct htt_resp *)skb->data;
 
-	/* confirm alignment */
-	if (!IS_ALIGNED((unsigned long)skb->data, 4))
-		ath10k_warn("unaligned htt message, expect trouble\n");
-
-	ath10k_dbg(ATH10K_DBG_HTT, "HTT RX, msg_type: 0x%0X\n",
-		   resp->hdr.msg_type);
 	switch (resp->hdr.msg_type) {
 	case HTT_T2H_MSG_TYPE_VERSION_CONF: {
 		htt->target_version_major = resp->ver_resp.major;
@@ -1214,3 +1217,40 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 	/* Free the indication buffer */
 	dev_kfree_skb_any(skb);
 }
+
+static void ath10k_htt_rx_work(struct work_struct *work)
+{
+	struct ath10k_htt *htt = container_of(work, struct ath10k_htt, rx_work);
+	struct sk_buff *skb;
+
+	for (;;) {
+		skb = skb_dequeue(&htt->rx_queue);
+		if (!skb)
+			break;
+
+		ath10k_htt_rx_process_skb(htt->ar, skb);
+	}
+}
+
+void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
+{
+	struct ath10k_htt *htt = &ar->htt;
+	struct htt_resp *resp = (struct htt_resp *)skb->data;
+
+	/* confirm alignment */
+	if (!IS_ALIGNED((unsigned long)skb->data, 4))
+		ath10k_warn("unaligned htt message, expect trouble\n");
+
+	ath10k_dbg(ATH10K_DBG_HTT, "HTT RX, msg_type: 0x%0X\n",
+		   resp->hdr.msg_type);
+	switch (resp->hdr.msg_type) {
+	case HTT_T2H_MSG_TYPE_RX_FRAG_IND:
+	case HTT_T2H_MSG_TYPE_RX_IND:
+		skb_queue_tail(&htt->rx_queue, skb);
+		queue_work(ar->workqueue, &htt->rx_work);
+		break;
+	default:
+		ath10k_htt_rx_process_skb(ar, skb);
+		break;
+	}
+}
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index ce7e304..dd87e6f 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -297,7 +297,7 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
 		   status->band);
 
 	spin_lock_bh(&ar->txrx_lock);
-	ieee80211_rx(ar->hw, info->skb);
+	ieee80211_rx_ni(ar->hw, info->skb);
 	spin_unlock_bh(&ar->txrx_lock);
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 1/4] ath10k: synchronize tx/rx reporting to mac80211
From: Michal Kazior @ 2013-08-26  8:53 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1377507205-5386-1-git-send-email-michal.kazior@tieto.com>

According to mac80211 docs tx and rx reporting
routines must not run concurrently unless they are
_irqsafe variants.

This doesn't fix any visible bug but is apparently
the right thing to do as per the documentation.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |    1 +
 drivers/net/wireless/ath/ath10k/core.h |    3 +++
 drivers/net/wireless/ath/ath10k/txrx.c |    4 ++++
 3 files changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 04c132e..b43e8ad 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -526,6 +526,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 
 	mutex_init(&ar->conf_mutex);
 	spin_lock_init(&ar->data_lock);
+	spin_lock_init(&ar->txrx_lock);
 
 	INIT_LIST_HEAD(&ar->peers);
 	init_waitqueue_head(&ar->peer_mapping_wq);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index ab05c4c..0469a2e 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -392,6 +392,9 @@ struct ath10k {
 	u32 survey_last_cycle_count;
 	struct survey_info survey[ATH10K_NUM_CHANS];
 
+	/* synchronized tx/rx reporting to mac80211 */
+	spinlock_t txrx_lock;
+
 #ifdef CONFIG_ATH10K_DEBUGFS
 	struct ath10k_debug debug;
 #endif
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 68b6fae..ce7e304 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -88,7 +88,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc)
 	if (ATH10K_SKB_CB(txdesc)->htt.no_ack)
 		info->flags &= ~IEEE80211_TX_STAT_ACK;
 
+	spin_lock_bh(&htt->ar->txrx_lock);
 	ieee80211_tx_status(htt->ar->hw, msdu);
+	spin_unlock_bh(&htt->ar->txrx_lock);
 	/* we do not own the msdu anymore */
 
 exit:
@@ -294,7 +296,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
 		   status->freq,
 		   status->band);
 
+	spin_lock_bh(&ar->txrx_lock);
 	ieee80211_rx(ar->hw, info->skb);
+	spin_unlock_bh(&ar->txrx_lock);
 }
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 2/4] ath10k: make the workqueue multithreaded
From: Michal Kazior @ 2013-08-26  8:53 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1377507205-5386-1-git-send-email-michal.kazior@tieto.com>

TX work for a HTC endpoint can run for long
periods of time, especially on slower host
machines when under heavy load.

This patch prevents one endpoint starving another
one by allowing each endpoint worker to be
processed in parallel.

This is safe since none of ar->workqueue users
depend on sequential execution.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.c |    4 +++-
 drivers/net/wireless/ath/ath10k/core.h |    5 +++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index b43e8ad..348a0fd 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -520,7 +520,9 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 
 	setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
 
-	ar->workqueue = create_singlethread_workqueue("ath10k_wq");
+	ar->workqueue = alloc_workqueue("ath10k_wq",
+					WQ_UNBOUND | WQ_MEM_RECLAIM,
+					ATH10K_MAX_NUM_PARALLEL_WORKERS);
 	if (!ar->workqueue)
 		goto err_wq;
 
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 0469a2e..17694ec 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -40,6 +40,11 @@
 #define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
 #define ATH10K_NUM_CHANS 38
 
+#define ATH10K_NUM_HTC_TX_WORKERS ATH10K_HTC_EP_COUNT
+#define ATH10K_NUM_WMI_RX_WORKERS 1
+#define ATH10K_MAX_NUM_PARALLEL_WORKERS (ATH10K_NUM_HTC_TX_WORKERS + \
+					 ATH10K_NUM_WMI_RX_WORKERS)
+
 /* Antenna noise floor */
 #define ATH10K_DEFAULT_NOISE_FLOOR -95
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v2 0/4] ath10k: fixes
From: Michal Kazior @ 2013-08-26  8:53 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior
In-Reply-To: <1377066854-13981-1-git-send-email-michal.kazior@tieto.com>

Hi,

This patchset addresses some throughput/stability
issues.

v2:
 * add new patch
 * fix WARNING due to wrong ieee80211_rx() usage


Pozdrawiam / Best regards,
Michal Kazior.


Michal Kazior (4):
  ath10k: synchronize tx/rx reporting to mac80211
  ath10k: make the workqueue multithreaded
  ath10k: move htt rx processing to worker
  ath10k: fix issues on non-preemptible systems

 drivers/net/wireless/ath/ath10k/core.c   |    5 ++-
 drivers/net/wireless/ath/ath10k/core.h   |   10 ++++++
 drivers/net/wireless/ath/ath10k/htc.c    |    4 +++
 drivers/net/wireless/ath/ath10k/htt.h    |    3 ++
 drivers/net/wireless/ath/ath10k/htt_rx.c |   58 ++++++++++++++++++++++++++----
 drivers/net/wireless/ath/ath10k/txrx.c   |    6 +++-
 drivers/net/wireless/ath/ath10k/wmi.c    |    4 +++
 7 files changed, 81 insertions(+), 9 deletions(-)

-- 
1.7.9.5


^ permalink raw reply

* [PATCH] ath9k: Fix DEBUG_FS dependency for ath9k
From: Sujith Manoharan @ 2013-08-26  7:53 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

Reported-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index c91bc61..7944c25 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -56,7 +56,7 @@ config ATH9K_AHB
 
 config ATH9K_DEBUGFS
 	bool "Atheros ath9k debugging"
-	depends on ATH9K
+	depends on ATH9K && DEBUG_FS
 	select MAC80211_DEBUGFS
 	select RELAY
 	---help---
-- 
1.8.3.4


^ permalink raw reply related

* Re: [PATCH] mac80211_hwsim: fix error return code in init_mac80211_hwsim()
From: Johannes Berg @ 2013-08-26  7:37 UTC (permalink / raw)
  To: Wei Yongjun; +Cc: linville, yongjun_wei, linux-wireless
In-Reply-To: <CAPgLHd-GQuhYuKXBj6FVjtpGYWZYVwuGR-Sj3w19JSMcTm1JLg@mail.gmail.com>

On Mon, 2013-08-26 at 15:32 +0800, Wei Yongjun wrote:
> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
> 
> Fix to return -ENOMEM in the netdev alloc error handling
> case instead of 0, as done elsewhere in this function.

Makes sense, applied.

johannes


^ permalink raw reply

* [PATCH] mac80211: fix change_interface queue assignments
From: Johannes Berg @ 2013-08-26  7:35 UTC (permalink / raw)
  To: linux-wireless; +Cc: Jouni Malinen, Johannes Berg

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

Jouni reported that with mac80211_hwsim, multicast TX was causing
crashes due to invalid vif->cab_queue assignment. It turns out that
this is caused by change_interface() getting invoked and not having
the vif->type/vif->p2p assigned correctly before calling the queue
check (ieee80211_check_queues). Fix this by passing the 'external'
interface type to the function and adjusting it accordingly.

While at it, also fix the error path in change_interface, it wasn't
correctly resetting to the external type but using the internal one
instead.

Fortunately this affects on hwsim because all other drivers set the
vif->type/vif->p2p variables when changing iftype. This shouldn't
be needed, but almost all implementations actually do it for their
own internal handling.

Reported-by: Jouni Malinen <j@w1.fi>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/iface.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7ca534b..fcecd63 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -308,12 +308,13 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
 	return 0;
 }
 
-static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
+static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
+				  enum nl80211_iftype iftype)
 {
 	int n_queues = sdata->local->hw.queues;
 	int i;
 
-	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) {
+	if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
 		for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 			if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
 					 IEEE80211_INVAL_HW_QUEUE))
@@ -324,8 +325,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
 		}
 	}
 
-	if ((sdata->vif.type != NL80211_IFTYPE_AP &&
-	     sdata->vif.type != NL80211_IFTYPE_MESH_POINT) ||
+	if ((iftype != NL80211_IFTYPE_AP &&
+	     iftype != NL80211_IFTYPE_P2P_GO &&
+	     iftype != NL80211_IFTYPE_MESH_POINT) ||
 	    !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) {
 		sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
 		return 0;
@@ -408,7 +410,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 		return ret;
 	}
 
-	ret = ieee80211_check_queues(sdata);
+	ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
 	if (ret) {
 		kfree(sdata);
 		return ret;
@@ -592,7 +594,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 			res = drv_add_interface(local, sdata);
 			if (res)
 				goto err_stop;
-			res = ieee80211_check_queues(sdata);
+			res = ieee80211_check_queues(sdata,
+				ieee80211_vif_type_p2p(&sdata->vif));
 			if (res)
 				goto err_del_interface;
 		}
@@ -1389,14 +1392,14 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
 
 	ret = drv_change_interface(local, sdata, internal_type, p2p);
 	if (ret)
-		type = sdata->vif.type;
+		type = ieee80211_vif_type_p2p(&sdata->vif);
 
 	/*
 	 * Ignore return value here, there's not much we can do since
 	 * the driver changed the interface type internally already.
 	 * The warnings will hopefully make driver authors fix it :-)
 	 */
-	ieee80211_check_queues(sdata);
+	ieee80211_check_queues(sdata, type);
 
 	ieee80211_setup_sdata(sdata, type);
 
-- 
1.8.4.rc3


^ permalink raw reply related

* [PATCH] mac80211_hwsim: fix error return code in init_mac80211_hwsim()
From: Wei Yongjun @ 2013-08-26  7:32 UTC (permalink / raw)
  To: linville; +Cc: yongjun_wei, linux-wireless

From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>

Fix to return -ENOMEM in the netdev alloc error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
 drivers/net/wireless/mac80211_hwsim.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index cb34c78..9e0ebee 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2525,8 +2525,10 @@ static int __init init_mac80211_hwsim(void)
 	}
 
 	hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup);
-	if (hwsim_mon == NULL)
+	if (hwsim_mon == NULL) {
+		err = -ENOMEM;
 		goto failed;
+	}
 
 	rtnl_lock();
 


^ permalink raw reply related

* [PATCH] zd1201: fix error return code
From: Wei Yongjun @ 2013-08-26  7:32 UTC (permalink / raw)
  To: linville; +Cc: yongjun_wei, linux-wireless

From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>

Fix to return -ENOMEM in the memory alloc error handling
case instead of 0, as done elsewhere in this function.

Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
---
 drivers/net/wireless/zd1201.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 4941f20..73aa738 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -75,8 +75,10 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw)
         len = fw_entry->size;
 
 	buf = kmalloc(1024, GFP_ATOMIC);
-	if (!buf)
+	if (!buf) {
+		err = -ENOMEM;
 		goto exit;
+	}
 	
 	while (len > 0) {
 		int translen = (len > 1024) ? 1024 : len;
@@ -1762,8 +1764,10 @@ static int zd1201_probe(struct usb_interface *interface,
 	zd->endp_out2 = 2;
 	zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!zd->rx_urb || !zd->tx_urb)
+	if (!zd->rx_urb || !zd->tx_urb) {
+		err = -ENOMEM;
 		goto err_zd;
+	}
 
 	mdelay(100);
 	err = zd1201_drvr_start(zd);


^ permalink raw reply related

* Re: [PATCH v2 13/16] wcn36xx: add wcn36xx.h
From: Eugene Krasnikov @ 2013-08-26  7:23 UTC (permalink / raw)
  To: Joe Perches; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377298929.2816.15.camel@joe-AO722>

Since wcn36xx soon will become a part of ath family and all ath
drivers are using printk i thought it's reasonable to use common
approach everywhere:) May be in future all ath debug functions will be
united into one debug framework and the same code will be used
everywhere.

2013/8/24 Joe Perches <joe@perches.com>:
> On Fri, 2013-08-23 at 10:58 +0200, Eugene Krasnikov wrote:
>> Adding wcn36xx.h
> []
>> +#define wcn36xx_err(fmt, arg...)                             \
>> +     printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg);
>> +
>> +#define wcn36xx_warn(fmt, arg...)                            \
>> +     printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg)
>> +
>> +#define wcn36xx_info(fmt, arg...)            \
>> +     printk(KERN_INFO pr_fmt(fmt), ##arg)
>> +
>
> I these would be better using:
>
> #define wcn36xx_err(fmt, ...)                                   \
>         pr_err("ERROR " fmt, ##__VA_ARGS__)
>
> etc...
>
>> +#define wcn36xx_dbg(mask, fmt, arg...) do {                  \
>> +     if (debug_mask & mask)                                  \
>> +             printk(KERN_DEBUG pr_fmt(fmt), ##arg);  \
>> +} while (0)
>
> And maybe this one using pr_debug so dynamic_debug
> can work too.
>
>



-- 
Best regards,
Eugene

^ permalink raw reply

* [PATCH] mwifiex: add missing endian conversions
From: Tobias Waldekranz @ 2013-08-26  7:18 UTC (permalink / raw)
  To: linux-wireless

Fixes multiple locations where a little endian host is assumed during
ser/des of messages sent to/received from the chip.

Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
---
 drivers/net/wireless/mwifiex/11n_aggr.c    | 2 +-
 drivers/net/wireless/mwifiex/main.h        | 2 +-
 drivers/net/wireless/mwifiex/sdio.c        | 6 +++---
 drivers/net/wireless/mwifiex/sta_cmdresp.c | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index a78e065..b53c73c 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -69,7 +69,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
 	memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset);
 
 	/* Copy SNAP header */
-	snap.snap_type = *(u16 *) ((u8 *)skb_src->data + dt_offset);
+	snap.snap_type = le16_to_cpu(*(__le16 *) ((u8 *)skb_src->data + dt_offset));
 	dt_offset += sizeof(u16);
 
 	memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr));
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 4ef67fc..7797512 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1014,7 +1014,7 @@ mwifiex_netdev_get_priv(struct net_device *dev)
  */
 static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb)
 {
-	return (*(u32 *)skb->data == PKT_TYPE_MGMT);
+	return (le32_to_cpu(*(__le32 *)skb->data) == PKT_TYPE_MGMT);
 }
 
 int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 139c958..27fdbe2 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -963,7 +963,7 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter,
 
 	case MWIFIEX_TYPE_EVENT:
 		dev_dbg(adapter->dev, "info: --- Rx: Event ---\n");
-		adapter->event_cause = *(u32 *) skb->data;
+		adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data);
 
 		if ((skb->len > 0) && (skb->len  < MAX_EVENT_SIZE))
 			memcpy(adapter->event_body,
@@ -1088,8 +1088,8 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter,
 		for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) {
 
 			/* get curr PKT len & type */
-			pkt_len = *(u16 *) &curr_ptr[0];
-			pkt_type = *(u16 *) &curr_ptr[2];
+			pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]);
+			pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]);
 
 			/* copy pkt to deaggr buf */
 			skb_deaggr = card->mpa_rx.skb_arr[pind];
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 9f990e1..f12468a8 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -280,7 +280,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
 
 	tlv_buf = ((u8 *)rate_cfg) +
 			sizeof(struct host_cmd_ds_tx_rate_cfg);
-	tlv_buf_len = *(u16 *) (tlv_buf + sizeof(u16));
+	tlv_buf_len = le16_to_cpu(*(__le16 *) (tlv_buf + sizeof(u16)));
 
 	while (tlv_buf && tlv_buf_len > 0) {
 		tlv = (*tlv_buf);
-- 
1.8.3


^ permalink raw reply related

* [PATCH] ath9k: Fix TX poll work locking
From: Sujith Manoharan @ 2013-08-26  6:17 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

There is no need to call ath_txq_unlock_complete() in the
TX poll routine - frame completion is not done here,
so use ath_txq_unlock().

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/link.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index fff5d3c..2f831db 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -41,7 +41,7 @@ void ath_tx_complete_poll_work(struct work_struct *work)
 				txq->axq_tx_inprogress = true;
 			}
 		}
-		ath_txq_unlock_complete(sc, txq);
+		ath_txq_unlock(sc, txq);
 	}
 
 	if (needreset) {
-- 
1.8.3.4


^ permalink raw reply related

* Re: [PATCH] mac80211: implement STA CSA for drivers using channel contexts
From: Arik Nemtsov @ 2013-08-25 13:14 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1377266513.14021.37.camel@jlt4.sipsolutions.net>

On Fri, Aug 23, 2013 at 5:01 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Fri, 2013-08-16 at 23:09 +0300, Arik Nemtsov wrote:
>
>> > Well, it can't. If you look carefully then the old chan_switch op
>> > behaviour is to let the driver switch, not switch in software
>> > afterwards.
>>
>> The right thing for chan_switch drivers would be not to call hw_config()..
>
> chan_switch? or chanctx?

both. the hw_config(channel) is meaningless for chanctx drivers. The
legacy code for op_chan_switch drivers didn't call hw_config() as
well, assuming they'd already get notified internally by their op.

>> The TI driver implements the chan_switch op and uses channel contexts.
>
> Huh, ok, that was a combination I didn't think was going to exist, since
> the chanswitch API doesn't really tell you what channel context etc.
> OTOH, it does give you the vif so you have the chanctx implicitly.

Yep, it's good enough. The driver gets the chandef from the vif.

>
>> Note that with the above, the channel_contexts + software chan-switch
>> drivers will still need the kind of code that I wrote. So it would
>> just lead to replicated code. Or maybe you meant something else?
>
> We have too many possibilities I guess ... I think for MVM I want the
> disconnect, not the channel context change in software. You're taking
> that possibility away, hence my suggestion of a new hardware flag for it
> or so.

I was thinking it's equivalent to to AP case - currently mac80211 is
the dictator and simply changes the chandef once the lower drv
completes the switch.

Anyway IMHO the simplest approach to handle all the legacy stuff +
chanctx it to keep the current patch as is, and add a mac80211 HW flag
to support it, keeping the deauth option as default.
That's what I think you're suggesting?

>
>> Also, where would you put csa_active = true (if at all) for a STA
>> interface? Unlike AP, the trigger here is mac80211 code. So putting it
>> there seemed appropriate.
>
> Yeah, I was really just trying to say that current chanctx drivers need
> not really expect a chanctx to change channel unless they implement CSA,
> but that currently means AP-CSA - basically what I just said above with
> taking away the possibility of doing the deauth instead.

Let's keep the csa_active as I've used it, and just do a deauth when
the csa-support HW flag is not given?

Arik

^ permalink raw reply

* [PATCH] ath9k: Fix ASPM workaround usage
From: Sujith Manoharan @ 2013-08-25 11:00 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

The PCIE Workaround register (AR_WA/0x4004) is used to handle
various hardware quirks. For AR9002 chips, AR_WA_D3_L1_DISABLE
is used to prevent the HW from automatically entering L1 state
when D3 is enforced.

AR_WA_D3_L1_DISABLE has to be enabled for a few AR9280 based
cards, mark them based on their PCI subdevice/subvendor IDs
and enforce it in ar9002_hw_configpcipowersave().

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/ar9002_hw.c | 29 +++++++------------
 drivers/net/wireless/ath/ath9k/ar9003_hw.c |  7 +----
 drivers/net/wireless/ath/ath9k/ath9k.h     |  1 +
 drivers/net/wireless/ath/ath9k/hw.c        |  1 -
 drivers/net/wireless/ath/ath9k/init.c      |  5 ++++
 drivers/net/wireless/ath/ath9k/pci.c       | 46 ++++++++++++++++++++++++++++++
 6 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 8dc2d08..fb61b08 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -269,13 +269,12 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
 				val |= AR_WA_D3_L1_DISABLE;
 		} else {
-			if (((AR_SREV_9285(ah) ||
-			      AR_SREV_9271(ah) ||
-			      AR_SREV_9287(ah)) &&
-			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
-			    (AR_SREV_9280(ah) &&
-			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
-				val |= AR_WA_D3_L1_DISABLE;
+			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
+				if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
+					val |= AR_WA_D3_L1_DISABLE;
+			} else if (AR_SREV_9280(ah)) {
+				if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
+					val |= AR_WA_D3_L1_DISABLE;
 			}
 		}
 
@@ -297,24 +296,18 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 	} else {
 		if (ah->config.pcie_waen) {
 			val = ah->config.pcie_waen;
-			if (!power_off)
-				val &= (~AR_WA_D3_L1_DISABLE);
+			val &= (~AR_WA_D3_L1_DISABLE);
 		} else {
-			if (AR_SREV_9285(ah) ||
-			    AR_SREV_9271(ah) ||
-			    AR_SREV_9287(ah)) {
+			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
 				val = AR9285_WA_DEFAULT;
-				if (!power_off)
-					val &= (~AR_WA_D3_L1_DISABLE);
-			}
-			else if (AR_SREV_9280(ah)) {
+				val &= (~AR_WA_D3_L1_DISABLE);
+			} else if (AR_SREV_9280(ah)) {
 				/*
 				 * For AR9280 chips, bit 22 of 0x4004
 				 * needs to be set.
 				 */
 				val = AR9280_WA_DEFAULT;
-				if (!power_off)
-					val &= (~AR_WA_D3_L1_DISABLE);
+				val &= (~AR_WA_D3_L1_DISABLE);
 			} else {
 				val = AR_WA_DEFAULT;
 			}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 582cddd..608bb48 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -763,12 +763,7 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
 	if (!power_off /* !restore */) {
 		/* set bit 19 to allow forcing of pcie core into L1 state */
 		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
-
-		/* Several PCIe massages to ensure proper behaviour */
-		if (ah->config.pcie_waen)
-			REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
-		else
-			REG_WRITE(ah, AR_WA, ah->WARegVal);
+		REG_WRITE(ah, AR_WA, ah->WARegVal);
 	}
 
 	/*
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 8519e75..2ee35f6 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -631,6 +631,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
 #define ATH9K_PCI_CUS217     0x0004
 #define ATH9K_PCI_WOW        0x0008
 #define ATH9K_PCI_BT_ANT_DIV 0x0010
+#define ATH9K_PCI_D3_L1_WAR  0x0020
 
 /*
  * Default cache line size, in bytes.
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index b3a6891..2670bf6 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -450,7 +450,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
 	ah->config.ack_6mb = 0x0;
 	ah->config.cwm_ignore_extcca = 0;
 	ah->config.pcie_clock_req = 0;
-	ah->config.pcie_waen = 0;
 	ah->config.analog_shiftreg = 1;
 
 	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index b897183..9a1f349 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -551,6 +551,11 @@ static void ath9k_init_platform(struct ath_softc *sc)
 		pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV;
 		ath_info(common, "Set BT/WLAN RX diversity capability\n");
 	}
+
+	if (sc->driver_data & ATH9K_PCI_D3_L1_WAR) {
+		ah->config.pcie_waen = 0x0040473b;
+		ath_info(common, "Enable WAR for ASPM D3/L1\n");
+	}
 }
 
 static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index e7996a6..d089a7c 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -30,6 +30,52 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
 	{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 	{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
 
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 PCI_VENDOR_ID_AZWAVE,
+			 0x1C71),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 PCI_VENDOR_ID_FOXCONN,
+			 0xE01F),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x11AD, /* LITEON */
+			 0x6632),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x11AD, /* LITEON */
+			 0x6642),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 PCI_VENDOR_ID_QMI,
+			 0x0306),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x185F, /* WNC */
+			 0x309D),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x10CF, /* Fujitsu */
+			 0x147C),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x10CF, /* Fujitsu */
+			 0x147D),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+			 0x002A,
+			 0x10CF, /* Fujitsu */
+			 0x1536),
+	  .driver_data = ATH9K_PCI_D3_L1_WAR },
+
 	/* AR9285 card for Asus */
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
 			 0x002B,
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH] ath5k: debugfs: NULL-terminate strings
From: Djalal Harouni @ 2013-08-25 10:50 UTC (permalink / raw)
  To: Jiri Slaby, Nick Kossifidis, John W. Linville, linux-wireless,
	linux-kernel
  Cc: Djalal Harouni

Avoid processing garbage data by NULL terminating the strings.

Signed-off-by: Djalal Harouni <tixxdz@opendz.org>
---
Patch compile tested only.

 drivers/net/wireless/ath/ath5k/debug.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 9d00dab..b8d031a 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -245,9 +245,11 @@ static ssize_t write_file_beacon(struct file *file,
 	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	if (strncmp(buf, "disable", 7) == 0) {
 		AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
 		pr_info("debugfs disable beacons\n");
@@ -345,9 +347,11 @@ static ssize_t write_file_debug(struct file *file,
 	unsigned int i;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
 		if (strncmp(buf, dbg_info[i].name,
 					strlen(dbg_info[i].name)) == 0) {
@@ -448,9 +452,11 @@ static ssize_t write_file_antenna(struct file *file,
 	unsigned int i;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	if (strncmp(buf, "diversity", 9) == 0) {
 		ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
 		pr_info("debug: enable diversity\n");
@@ -619,9 +625,11 @@ static ssize_t write_file_frameerrors(struct file *file,
 	struct ath5k_statistics *st = &ah->stats;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	if (strncmp(buf, "clear", 5) == 0) {
 		st->rxerr_crc = 0;
 		st->rxerr_phy = 0;
@@ -766,9 +774,11 @@ static ssize_t write_file_ani(struct file *file,
 	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	if (strncmp(buf, "sens-low", 8) == 0) {
 		ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
 	} else if (strncmp(buf, "sens-high", 9) == 0) {
@@ -862,9 +872,11 @@ static ssize_t write_file_queue(struct file *file,
 	struct ath5k_hw *ah = file->private_data;
 	char buf[20];
 
-	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+	count = min_t(size_t, count, sizeof(buf) - 1);
+	if (copy_from_user(buf, userbuf, count))
 		return -EFAULT;
 
+	buf[count] = '\0';
 	if (strncmp(buf, "start", 5) == 0)
 		ieee80211_wake_queues(ah->hw);
 	else if (strncmp(buf, "stop", 4) == 0)
-- 
1.7.11.7


^ permalink raw reply related

* [PATCH] ath9k: Fix ASPM for AR9462
From: Sujith Manoharan @ 2013-08-25  9:13 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

If the L1 entrance latency is not calibrated properly
in the EEPROM in WB222 boards, there could be problems
in connectivity. Check and correct the calibrated value
if it doesn't match the optimal value for WB222, 4us.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/ar9003_hw.c | 14 ++++++++++++++
 drivers/net/wireless/ath/ath9k/hw.h        |  1 +
 drivers/net/wireless/ath/ath9k/pci.c       | 16 ++++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 738aa7e..582cddd 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -745,6 +745,20 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
 					 bool power_off)
 {
+	/*
+	 * Increase L1 Entry Latency. Some WB222 boards don't have
+	 * this change in eeprom/OTP.
+	 *
+	 */
+	if (AR_SREV_9462(ah)) {
+		u32 val = ah->config.aspm_l1_fix;
+		if ((val & 0xff000000) == 0x17000000) {
+			val &= 0x00ffffff;
+			val |= 0x27000000;
+			REG_WRITE(ah, 0x570c, val);
+		}
+	}
+
 	/* Nothing to do on restore for 11N */
 	if (!power_off /* !restore */) {
 		/* set bit 19 to allow forcing of pcie core into L1 state */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index fa543a6..69a907b 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -311,6 +311,7 @@ struct ath9k_ops_config {
 	u16 ani_poll_interval; /* ANI poll interval in ms */
 
 	/* Platform specific config */
+	u32 aspm_l1_fix;
 	u32 xlna_gpio;
 	u32 ant_ctrl_comm2g_switch_enable;
 	bool xatten_margin_cfg;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 3280798..e7996a6 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -314,6 +314,22 @@ static void ath_pci_aspm_init(struct ath_common *common)
 		return;
 	}
 
+	/*
+	 * 0x70c - Ack Frequency Register.
+	 *
+	 * Bits 27:29 - DEFAULT_L1_ENTRANCE_LATENCY.
+	 *
+	 * 000 : 1 us
+	 * 001 : 2 us
+	 * 010 : 4 us
+	 * 011 : 8 us
+	 * 100 : 16 us
+	 * 101 : 32 us
+	 * 110/111 : 64 us
+	 */
+	if (AR_SREV_9462(ah))
+		pci_read_config_dword(pdev, 0x70c, &ah->config.aspm_l1_fix);
+
 	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
 	if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
 		ah->aspm_enabled = true;
-- 
1.8.3.4


^ permalink raw reply related

* RE: [Ilw] Re: iwlwifi micorcode errors and hardware resets problems
From: Grumbach, Emmanuel @ 2013-08-25  8:21 UTC (permalink / raw)
  To: Luca Coelho, Stanislaw Gruszka
  Cc: ilw@linux.intel.com, linux-wireless@vger.kernel.org
In-Reply-To: <1377345177.5589.3.camel@porter.coelho.fi>

PiBPbiBGcmksIDIwMTMtMDgtMjMgYXQgMTE6MDggKzAyMDAsIFN0YW5pc2xhdyBHcnVzemthIHdy
b3RlOg0KPiA+IFdlIGhhdmUgdGhvc2UgYnVnIHJlcG9ydHMgb24gUkggYnVnemlsbGEsIGFuZCB2
YXJpb3VzIG90aGVyIGl3bHdpZmkNCj4gPiBwcm9ibGVtcywgYnV0IHRob3NlIGhhdmUgc29tZSBj
b21tb24gc2NlbmFyaW86DQo+ID4NCj4gPiBodHRwczovL2J1Z3ppbGxhLnJlZGhhdC5jb20vc2hv
d19idWcuY2dpP2lkPTk3OTg3Mw0KPiA+IGh0dHBzOi8vYnVnemlsbGEucmVkaGF0LmNvbS9zaG93
X2J1Zy5jZ2k/aWQ9OTkwNTM2DQo+ID4gaHR0cHM6Ly9idWd6aWxsYS5yZWRoYXQuY29tL3Nob3df
YnVnLmNnaT9pZD05OTQzMjINCj4gPiBodHRwczovL2J1Z3ppbGxhLnJlZGhhdC5jb20vc2hvd19i
dWcuY2dpP2lkPTk5NjUwMg0KPiA+IGh0dHBzOi8vYnVnemlsbGEucmVkaGF0LmNvbS9zaG93X2J1
Zy5jZ2k/aWQ9OTY5NjEwDQo+ID4gaHR0cHM6Ly9idWd6aWxsYS5yZWRoYXQuY29tL3Nob3dfYnVn
LmNnaT9pZD05OTkwNTMNCj4gPg0KPiA+IEZpcnN0IHRoZXJlIGlzIE1pY3JvY29kZSBlcnJvciBv
ciBvdGhlciBmaXJtd2FyZSBwcm9ibGVtLCB3aGF0IG1ha2Ugd2UNCj4gPiBkbyBpd2xfdHJhbnNf
c3RvcF9kZXZpY2UoKSB3aGljaCBzZXQgdHJhbnMtPnN0YXRlIHRvIElXTF9UUkFOU19OT19GVy4N
Cj4gPiBJZiBtYWM4MDIxMSBoYXMgc29tZSBwZW5kaW5nIHdvcmtzL3RpbWVycyBpLmUuIGllZWU4
MDIxMV9zdGFfd29yaygpLA0KPiA+IGl0IGNhbGxzIGRydiBhbmQgd2UgdHJpZ2dlciBvbiBvZiB0
aG9zZSB3YXJuaW5ncw0KPiA+DQo+ID4gICAgICAgICBXQVJOX09OQ0UodHJhbnMtPnN0YXRlICE9
IElXTF9UUkFOU19GV19BTElWRSwNCj4gPiAgICAgICAgICAgICAgICAgICAiJXMgYmFkIHN0YXRl
ID0gJWQiLCBfX2Z1bmNfXywgdHJhbnMtPnN0YXRlKTsNCj4gPg0KPiA+IG9uIHNvbWUgdHJhbnMg
b3BlcmF0aW9uLg0KPiA+DQo+ID4gSSB0aGluayB0aGlzIGNhbiBiZSBmaXhlZCBieSBmaXJzdCBk
byBxdWllc2NlIG9uIG1hYzgwMjExIChmb3IgZXhhbXBsZQ0KPiA+IGJ5IGllZWU4MDIxMV9zdGFf
cXVpZXNjZSgpIHByb2NlZHVyZSwgd2hpY2ggSSByZW1vdmVkIGJ1dCBjYW4gYmUgYWRkZWQNCj4g
PiBiYWNrKSBhbmQgdGhlbiBkbyBpd2xhZ25fcHJlcGFyZV9yZXN0YXJ0KCkgJiBpZWVlODAyMTFf
cmVzdGFydF9odygpLg0KPiA+DQo+ID4gVGhvdWdoIEknbSBub3Qgc3VyZSBpZiBpdCdzIHdvcnRo
IHRvIGRvIHRoaXMgc2luY2UgdGhvc2Ugd2FybmluZ3MgYXJlDQo+ID4gaW5kaWNhdG9yIGZvciBt
YWxmdW5jdGlvbmluZyBpd2x3aWZpIGZpcm13YXJlIChvciBkcml2ZXIgbm90IGNvcnJlY3RseQ0K
PiA+IGNvbW11bmljYXRpbmcgd2l0aCBmaXJtd2FyZSksIHdoaWNoIHdpbGwgYmUgdW5ub3RpY2Vk
IGlmIG5vdCByZXBvcnRlZA0KPiA+IGF1dG9tYXRpY2FsbHkgYnkgdG9vbCBsaWtlIEFCUlQuIEJ1
dCBwZXJoYXBzIHdlIGNvdWxkIGFkZCBXQVJOX09OQ0Ugb24NCj4gPiBNaWNyb2NvZGUgZXJyb3Ig
Y29uZGl0aW9uID8NCj4gDQo+IEkgdGhpbmsgdGhhdCwgaWYgdGhlIHF1aWVzY2UgcmVhbGx5IGhl
bHBzIHdpdGggdGhpcywgd2Ugc2hvdWxkIGRvIGl0Lg0KPiBUaGlzIFdBUk4gaXMgYSBzaWRlLWVm
ZmVjdCBvZiB0aGUgcHJvYmxlbSBhbmQgbm90IHRoZSBwcm9ibGVtIGl0c2VsZi4NCj4gSWYgeW91
IHdhbnQgdG8gY2F0Y2ggdGhlIEZXIHByb2JsZW0sIHRoZXJlIHNob3VsZCBiZSBhIFdBUk4gZWxz
ZXdoZXJlLg0KPiANCj4gSSdtIG5vdCBzYXlpbmcgdGhhdCB0aGlzIFdBUk4gc2hvdWxkIGJlIHJl
bW92ZWQgYW5kIEkgYWxzbyB0aGluayBpdCdzIGEgZ29vZA0KPiBpZGVhIHRvIGNoYW5nZSBpdCB0
byBXQVJOX09OX09OQ0UoKS4gIEkganVzdCB0aGluayB0aGF0LCBpZiB0aGVyZSdzIGFueXRoaW5n
DQo+IHRoZSBkcml2ZXIgY2FuIGRvIHRvIGtlZXAgdGhpbmdzIHJ1bm5pbmcgbmljZWx5LCB3ZSBz
aG91bGQgZG8gaXQuDQo+IA0KPiBJbiBhbnkgY2FzZSwgSSdsbCBsZWF2ZSB0aGlzIGZvciBKb2hh
bm5lcywgRW1tYW51ZWwgb3Igc29tZSBvZiB0aGUgb3RoZXIgZ3V5cw0KPiB3aXRoIG1vcmUgZXhw
ZXJpZW5jZSBpbiBpd2x3aWZpIHRvIGNvbW1lbnQuIDspDQoNCllvdSBnb3QgbXkgQUNLIGhlcmUu
IFdlIGhhdmUgc29tZSBpc3N1ZXMgd2l0aCBmaXJtd2FyZS4gT2J2aW91c2x5LiBCdXQgbW9zdCBv
ZiB0aGUgaXNzdWVzIGFyZSB2ZXJ5IGhhcmQgdG8gZGVidWcuIE1vc3Qgb2YgdGhlbSBJIGFtIHNl
ZWluZyBhcmUgbW9yZSBsaWtlIHRoZSBmaXJtd2FyZSBnZXR0aW5nIHN0dWNrIGV0Yy4uLiAgQWZ0
ZXIgYWxsIHRoaXMgaXMgd2h5IHdlIGhhdmUgYSByZXN0YXJ0IGZsb3csIGZvciB0aGVzZSBpc3N1
ZXMgdGhhdCBkb24ndCBoYXBwZW4gZnJlcXVlbnRseSBidXQgYXJlIHNvbHZhYmxlIGJ5IGEgcmVz
ZXQuIFNpbmNlIHdlIHN0aWxsIHdhbnQgdG8ga25vdyB3aGVuIHRoaXMga2luZCBvZiB0aGluZ3Mg
aGFwcGVuLCBhZGRpbmcgYSBXQVJOX09OX09OQ0Ugc291bmRzIGdvb2QuDQo=

^ permalink raw reply

* mac80211 kernel panic due to invalid cab_queue value with hwsim
From: Jouni Malinen @ 2013-08-24 16:00 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

Something is cab_queue handling is broken (and has been broken for a
while) in mac80211. At least mac80211_hwsim shows this, but I guess it
could happen with some other drivers, too. The error shows up as
group-addressed Data frames from a P2P GO not being transmitted if
CONFIG_MAC80211_VERBOSE_DEBUG is defined and kernel panic if that is not
defined. ieee80211_tx_h_multicast_ps_buf() can assign
IEEE80211_INVAL_HW_QUEUE (0xff) into info->hw_queue in some cases and
that results in the issues in ieee80211_tx_frags where q >=
local->hw.queues check is done only with verbose debugging enabled. If
that check is not there, kernel panic shows up at least in
skb_queue_splice_tail_init() when that invalid hw_queue 0xff value is
used to index the local->pending array.

I'm not sure where cab_queue should be cleared to avoid this, but for
now, I'm using following workaround to avoid the symptoms:


diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 098ae85..41655a4 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -413,8 +413,13 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
 	if (ieee80211_has_order(hdr->frame_control))
 		return TX_CONTINUE;
 
-	if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
-		info->hw_queue = tx->sdata->vif.cab_queue;
+	if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) {
+		if (tx->sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE) {
+			printk(KERN_DEBUG "%s:trying to assign invalid cab_queue for skb %p vif.type=%d\n",
+			       __func__, tx->skb, tx->sdata->vif.type);
+		} else
+			info->hw_queue = tx->sdata->vif.cab_queue;
+	}
 
 	/* no stations in PS mode */
 	if (!atomic_read(&ps->num_sta_ps))

-- 
Jouni Malinen                                            PGP id EFC895FA

^ 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