* Re: [PATCH 1/2] ath10k: Fix bug in max. VHT A-MPDU size
From: Kalle Valo @ 2013-10-01 16:27 UTC (permalink / raw)
To: Michal Kazior; +Cc: ath10k, Sujith Manoharan, linux-wireless
In-Reply-To: <1380292567-2363-2-git-send-email-michal.kazior@tieto.com>
Michal Kazior <michal.kazior@tieto.com> writes:
> From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
>
> For VHT peers, the maximum A-MPDU size has to be calculated
> from the VHT capabilities element and not the HT-cap. The formula
> is the same, but a higher value is used in VHT, allowing larger
> aggregates to be transmitted.
>
> Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
This kills the TCP TX throughput with D-Link DIR-865L (ath10k x86 as the
client) from ~350 Mbps to ~120 Mbps. Sujith mentioned private there's a
workaround for this, this patch should have that.
--
Kalle Valo
^ permalink raw reply
* RE: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-10-01 16:23 UTC (permalink / raw)
To: Johan Hedberg
Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development,
Gustavo F. Padovan, linux-wireless@vger.kernel.org Wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <20131001111309.GA19641@x220.p-661hnu-f1>
Hi Johan,
> Hi Marcel & Bing,
>
> On Thu, Sep 26, 2013, Marcel Holtmann wrote:
> > >> You're right that we're missing the clearing of the HCI_SETUP flag
> > >> for such a scenario. Could you try the attached patch. It should
> > >> fix the
> > >
> > > We have tested your patch. Yes, it fixes the problem. Thanks!
> >
> > then lets get a proper version with full commit message explaining the
> > issue merged upstream. As I said, this is a real bug we need to fix.
>
> I've just sent a new patch set titled "[PATCH 0/2] Bluetooth: Fix
> hci_dev_open race condition". Bing, could you please test this with your
> original setup so we ensure that the issue is still properly handled.
We tested this new patch set with our original setup and the issue is not seen.
Thanks,
Bing
^ permalink raw reply
* [PATCH 8/8] staging: vt6656: rxtx.c remove dead code s_uFillDataHead/pvTxDataHd.
From: Malcolm Priestley @ 2013-10-01 15:07 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
uFillDataHead in is now dead so remove and pvTxDataHd.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 42 +++---------------------------------------
1 file changed, 3 insertions(+), 39 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index d094a6a..8df94ff 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -103,10 +103,6 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
- u32 uDMAIdx, int bNeedAck, u8 byFBOption);
-
static void s_vGenerateMACHeader(struct vnt_private *pDevice,
u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader,
int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx);
@@ -583,32 +579,6 @@ static u16 vnt_rxtx_datahead_ab(struct vnt_private *priv, u8 pkt_type,
return buf->wDuration;
}
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
- u32 uDMAIdx, int bNeedAck, u8 byFBOption)
-{
-
- if (pTxDataHead == NULL) {
- return 0;
- }
-
- if (byPktType == PK_TYPE_11A) {
- struct vnt_tx_datahead_ab *pBuf =
- (struct vnt_tx_datahead_ab *)pTxDataHead;
-
- return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
- pBuf, cbFrameLength, bNeedAck);
- }
- else if (byPktType == PK_TYPE_11B) {
- struct vnt_tx_datahead_ab *pBuf =
- (struct vnt_tx_datahead_ab *)pTxDataHead;
-
- return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
- pBuf, cbFrameLength, bNeedAck);
- }
- return 0;
-}
-
static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
struct ieee80211_rts *rts, struct ethhdr *eth_hdr,
u16 duration)
@@ -1026,14 +996,13 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
u32 uDuration;
u32 cbHeaderLength = 0, uPadding = 0;
struct vnt_mic_hdr *pMICHDR;
- void *pvTxDataHd;
u8 byFBOption = AUTO_FB_NONE, byFragType;
u16 wTxBufSize;
u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
u32 *pdwMIC_L, *pdwMIC_R;
int bSoftWEP = false;
- pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = NULL;
if (bNeedEncryption && pTransmitKey->pvKeyTable) {
if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
@@ -1797,7 +1766,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
struct vnt_tx_fifo_head *pTxBufHead;
u8 byPktType;
u8 *pbyTxBufferAddr;
- void *pvTxDataHd;
u32 uDuration, cbReqCount;
struct ieee80211_hdr *pMACHeader;
u32 cbHeaderSize, cbFrameBodySize;
@@ -1823,7 +1791,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
u32 cbExtSuppRate = 0;
struct vnt_usb_send_context *pContext;
- pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = NULL;
if(skb->len <= WLAN_HDR_ADDR3_LEN) {
cbFrameBodySize = 0;
@@ -2006,11 +1974,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
pTX_Buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
- //Fill DataHead
- uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
- cbFrameSize, TYPE_TXDMA0, bNeedACK, AUTO_FB_NONE);
-
- pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
+ pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 7/8] staging: vt6656: rxtx.c add no rts struct vnt_tx_datahead_ab
From: Malcolm Priestley @ 2013-10-01 15:03 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Add no rts/cts vnt_tx_datahead_ab to union vnt_tx_data_head.
The need_mic now applies to all modes of packet type PK_TYPE_11B.
and return vnt_rxtx_datahead_ab in s_vGenerateTxParameter
This removes pvTxDataHd pointer assignment and calls to s_uFillDataHead.
Since pvTxDataHd is now null a small vendor hack to vDMA0_tx_80211/csMgmt_xmit
to do with Disassociation-packet is also changed correct head position.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 44 +++++++++++++++++--------------------------
drivers/staging/vt6656/rxtx.h | 1 +
2 files changed, 18 insertions(+), 27 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 0a77092..d094a6a 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -964,6 +964,13 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
}
}
else if (byPktType == PK_TYPE_11B) {
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
if (need_rts) {
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
@@ -973,13 +980,6 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
- if (need_mic) {
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
- } else {
- head = &tx_buffer->tx_head.tx_ab.tx.head;
- }
-
/* Fill RTS */
return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
@@ -988,11 +988,11 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
- if (need_mic)
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
-
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
+ &head->data_head_ab, cbFrameSize, bNeedACK);
}
}
//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
@@ -1186,8 +1186,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
cbMICHDR + sizeof(struct vnt_rts_ab);
}
else if (bRTS == false) { //RTS_needless, no MICHDR
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
}
@@ -1220,10 +1218,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
tx_buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
- //Fill DataHead
- if (pvTxDataHd)
- uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate,
- pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, byFBOption);
+
// Generate TX MAC Header
s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
byFragType, uDMAIdx, 0);
@@ -1456,7 +1451,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
struct ieee80211_hdr *pMACHeader;
struct ethhdr sEthHeader;
u8 byPktType, *pbyTxBufferAddr;
- void *pvTxDataHd;
struct vnt_mic_hdr *pMICHDR = NULL;
u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
int bNeedACK, bIsPSPOLL = false;
@@ -1593,8 +1587,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
sizeof(struct vnt_cts);
}
else { // 802.11a/b packet
- pvTxDataHd = (struct vnt_tx_datahead_ab *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
sizeof(struct vnt_tx_datahead_ab);
}
@@ -1615,10 +1607,6 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
pTX_Buffer, &pMICHDR, 0,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
- //Fill DataHead
- uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
- cbFrameSize, TYPE_TXDMA0, bNeedACK, AUTO_FB_NONE);
-
pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
@@ -1688,7 +1676,9 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
data_head->wDuration_b =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
} else {
- ((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+ struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+ tx_ab.tx.head.data_head_ab;
+ data_head->wDuration =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
}
}
@@ -1997,8 +1987,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
}
else {//802.11a/b packet
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
sizeof(struct vnt_tx_datahead_ab);
}
@@ -2137,7 +2125,9 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
data_head->wDuration_b =
cpu_to_le16(p80211Header->sA2.wDurationID);
} else {
- ((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+ struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+ tx_ab.tx.head.data_head_ab;
+ data_head->wDuration =
cpu_to_le16(p80211Header->sA2.wDurationID);
}
}
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index d905b97..eecbe89 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -186,6 +186,7 @@ union vnt_tx_data_head {
struct vnt_cts_fb cts_g_fb;
/* no rts/cts */
struct vnt_tx_datahead_a_fb data_head_a_fb;
+ struct vnt_tx_datahead_ab data_head_ab;
};
struct vnt_tx_mic_hdr {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 6/8] staging: vt6656: rxtx.c parse out vnt_rxtx_datahead_ab
From: Malcolm Priestley @ 2013-10-01 15:00 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Parse struct vnt_tx_datahead_ab from s_uFillDataHead and
move to struct vnt_rts_ab structure returning duration down
functions.
Both are returned in s_uFillDataHead at this stage as pvTxDataHd
is only null in s_bPacketToWirelessUsb.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 53 +++++++++++++++++++++----------------------
drivers/staging/vt6656/rxtx.h | 1 +
2 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 1d02724..0a77092 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -569,6 +569,20 @@ static u16 vnt_rxtx_datahead_a_fb(struct vnt_private *priv, u8 pkt_type,
return buf->wDuration;
}
+static u16 vnt_rxtx_datahead_ab(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_ab *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->ab);
+ /* Get Duration and TimeStampOff */
+ buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+ return buf->wDuration;
+}
+
static u32 s_uFillDataHead(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
u32 uDMAIdx, int bNeedAck, u8 byFBOption)
@@ -581,28 +595,16 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
if (byPktType == PK_TYPE_11A) {
struct vnt_tx_datahead_ab *pBuf =
(struct vnt_tx_datahead_ab *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->ab);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
+
+ return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
+ pBuf, cbFrameLength, bNeedAck);
}
else if (byPktType == PK_TYPE_11B) {
struct vnt_tx_datahead_ab *pBuf =
(struct vnt_tx_datahead_ab *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->ab);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
+
+ return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate,
+ pBuf, cbFrameLength, bNeedAck);
}
return 0;
}
@@ -703,7 +705,8 @@ static u16 vnt_rxtx_rts_ab_head(struct vnt_private *priv,
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
- return 0;
+ return vnt_rxtx_datahead_ab(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
static u16 vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
@@ -764,7 +767,7 @@ static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
break;
}
case PK_TYPE_11B:
- vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
+ return vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
}
@@ -947,7 +950,7 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
cbFrameSize, wCurrentRate, bNeedACK);
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
} else {
//Fill RsvTime
@@ -978,7 +981,7 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
}
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else { //RTS_needless, non PCF mode
@@ -1179,12 +1182,8 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
else {//802.11a/b packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
- sizeof(struct vnt_rts_ab));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_ab) +
- sizeof(struct vnt_tx_datahead_ab);
+ cbMICHDR + sizeof(struct vnt_rts_ab);
}
else if (bRTS == false) { //RTS_needless, no MICHDR
pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index d8f25d1..d905b97 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -140,6 +140,7 @@ struct vnt_rts_ab {
u16 wDuration;
u16 wReserved;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_ab data_head;
} __packed;
struct vnt_rts_a_fb {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 5/8] staging: vt6656: rxtx.c add no rts struct vnt_tx_datahead_a_fb
From: Malcolm Priestley @ 2013-10-01 14:58 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Add no rts/cts vnt_tx_datahead_a_fb to union vnt_tx_data_head.
The need_mic now applies to all modes of packet type PK_TYPE_11A.
and return vnt_rxtx_datahead_a_fb in s_vGenerateTxParameter
This removes pvTxDataHd pointer assignment.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 30 ++++++++++--------------------
drivers/staging/vt6656/rxtx.h | 2 ++
2 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index b2c4786..1d02724 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -579,13 +579,6 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
}
if (byPktType == PK_TYPE_11A) {
- if (byFBOption != AUTO_FB_NONE) {
- struct vnt_tx_datahead_a_fb *pBuf =
- (struct vnt_tx_datahead_a_fb *)pTxDataHead;
-
- return vnt_rxtx_datahead_a_fb(pDevice, byPktType, wCurrentRate,
- pBuf, cbFrameLength, bNeedAck);
- } else {
struct vnt_tx_datahead_ab *pBuf =
(struct vnt_tx_datahead_ab *)pTxDataHead;
//Get SignalField,ServiceField,Length
@@ -597,7 +590,6 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
wCurrentRate);
return (pBuf->wDuration);
- }
}
else if (byPktType == PK_TYPE_11B) {
struct vnt_tx_datahead_ab *pBuf =
@@ -938,6 +930,13 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
}
}
else if (byPktType == PK_TYPE_11A) {
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
if (need_rts) {
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
@@ -947,13 +946,6 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
cbFrameSize, wCurrentRate, bNeedACK);
- if (need_mic) {
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
- } else {
- head = &tx_buffer->tx_head.tx_ab.tx.head;
- }
-
/* Fill RTS */
s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
@@ -961,11 +953,11 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
//Fill RsvTime
struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
- if (need_mic)
- *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
-
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ return vnt_rxtx_datahead_a_fb(pDevice, byPktType, wCurrentRate,
+ &head->data_head_a_fb, cbFrameSize, bNeedACK);
}
}
else if (byPktType == PK_TYPE_11B) {
@@ -1207,8 +1199,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
cbMICHDR + sizeof(struct vnt_rts_a_fb);
}
else if (bRTS == false) { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
}
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 3fd8507..d8f25d1 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -183,6 +183,8 @@ union vnt_tx_data_head {
/* cts g */
struct vnt_cts cts_g;
struct vnt_cts_fb cts_g_fb;
+ /* no rts/cts */
+ struct vnt_tx_datahead_a_fb data_head_a_fb;
};
struct vnt_tx_mic_hdr {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 4/8] staging: vt6656: rxtx.c parse out struct vnt_tx_datahead_a_fb
From: Malcolm Priestley @ 2013-10-01 14:56 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Parse struct vnt_tx_datahead_a_fb from s_uFillDataHead and
move to struct vnt_rts_a_fb structure returning duration down
functions.
This removes pvTxDataHd pointer assignment.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 49 ++++++++++++++++++++++++-------------------
drivers/staging/vt6656/rxtx.h | 1 +
2 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index a56a49a..b2c4786 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -552,6 +552,23 @@ static u16 vnt_rxtx_datahead_g_fb(struct vnt_private *priv, u8 pkt_type,
return buf->wDuration_a;
}
+static u16 vnt_rxtx_datahead_a_fb(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_a_fb *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+ /* Get Duration and TimeStampOff */
+ buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wDuration_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+ return buf->wDuration;
+}
+
static u32 s_uFillDataHead(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
u32 uDMAIdx, int bNeedAck, u8 byFBOption)
@@ -565,19 +582,9 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
if (byFBOption != AUTO_FB_NONE) {
struct vnt_tx_datahead_a_fb *pBuf =
(struct vnt_tx_datahead_a_fb *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- //Get Duration and TimeStampOff
- pBuf->wDuration = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_f0 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_f1 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- return (pBuf->wDuration);
+
+ return vnt_rxtx_datahead_a_fb(pDevice, byPktType, wCurrentRate,
+ pBuf, cbFrameLength, bNeedAck);
} else {
struct vnt_tx_datahead_ab *pBuf =
(struct vnt_tx_datahead_ab *)pTxDataHead;
@@ -728,7 +735,8 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
- return 0;
+ return vnt_rxtx_datahead_a_fb(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
@@ -758,7 +766,7 @@ static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
break;
case PK_TYPE_11A:
if (byFBOption) {
- vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
+ return vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
break;
@@ -1195,12 +1203,8 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
- sizeof(struct vnt_rts_a_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_a_fb) +
- sizeof(struct vnt_tx_datahead_a_fb);
+ cbMICHDR + sizeof(struct vnt_rts_a_fb);
}
else if (bRTS == false) { //RTS_needless
pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
@@ -1228,8 +1232,9 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
tx_buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
//Fill DataHead
- uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
- cbFrameSize, uDMAIdx, bNeedACK, byFBOption);
+ if (pvTxDataHd)
+ uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate,
+ pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, byFBOption);
// Generate TX MAC Header
s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
byFragType, uDMAIdx, 0);
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 0a022cf..3fd8507 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -149,6 +149,7 @@ struct vnt_rts_a_fb {
u16 wRTSDuration_f0;
u16 wRTSDuration_f1;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_a_fb data_head;
} __packed;
/* CTS buffer header */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 3/8] staging: vt6656: rxtx.c Parse struct vnt_tx_datahead_g_fb
From: Malcolm Priestley @ 2013-10-01 14:54 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Parse struct vnt_tx_datahead_g_fb from s_uFillDataHead and
move to struct vnt_rts_g_fb/struct vnt_cts_fb structure returning
duration down functions.
This removes pvTxDataHd pointer assignment.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 74 +++++++++++++++++++------------------------
drivers/staging/vt6656/rxtx.h | 2 ++
2 files changed, 35 insertions(+), 41 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 58a9d8a..a56a49a 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -528,6 +528,30 @@ static u16 vnt_rxtx_datahead_g(struct vnt_private *priv, u8 pkt_type, u16 rate,
return buf->wDuration_a;
}
+static u16 vnt_rxtx_datahead_g_fb(struct vnt_private *priv, u8 pkt_type,
+ u16 rate, struct vnt_tx_datahead_g_fb *buf,
+ u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+
+ BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+ PK_TYPE_11B, &buf->b);
+
+ /* Get Duration and TimeStamp */
+ buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
+
+ buf->wDuration_a_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_a_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+ buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+ buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+ priv->byTopCCKBasicRate);
+
+ return buf->wDuration_a;
+}
+
static u32 s_uFillDataHead(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
u32 uDMAIdx, int bNeedAck, u8 byFBOption)
@@ -537,35 +561,7 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
return 0;
}
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption == AUTO_FB_NONE) {
- ;
- } else {
- // Auto Fallback
- struct vnt_tx_datahead_g_fb *pBuf =
- (struct vnt_tx_datahead_g_fb *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- BBvCalculateParameter(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
- //Get Duration and TimeStamp
- pBuf->wDuration_a = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_b = s_uGetDataDuration(pDevice,
- PK_TYPE_11B, bNeedAck);
- pBuf->wDuration_a_f0 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_a_f1 = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wTimeStampOff_a = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
- pDevice->byTopCCKBasicRate);
- return (pBuf->wDuration_a);
- } //if (byFBOption == AUTO_FB_NONE)
- }
- else if (byPktType == PK_TYPE_11A) {
+ if (byPktType == PK_TYPE_11A) {
if (byFBOption != AUTO_FB_NONE) {
struct vnt_tx_datahead_a_fb *pBuf =
(struct vnt_tx_datahead_a_fb *)pTxDataHead;
@@ -689,7 +685,8 @@ static u16 vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
- return 0;
+ return vnt_rxtx_datahead_g_fb(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
static u16 vnt_rxtx_rts_ab_head(struct vnt_private *priv,
@@ -755,7 +752,7 @@ static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
else
- vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
+ return vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
break;
@@ -805,6 +802,9 @@ static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
pBuf->data.duration = pBuf->wDuration_ba;
pBuf->data.frame_control = TYPE_CTL_CTS;
memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+ return vnt_rxtx_datahead_g_fb(pDevice, byPktType, wCurrentRate,
+ &pBuf->data_head, cbFrameLength, bNeedAck);
} else {
struct vnt_cts *pBuf = &head->cts_g;
/* Get SignalField,ServiceField,Length */
@@ -1167,20 +1167,12 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb) +
- sizeof(struct vnt_tx_datahead_g_fb);
+ cbMICHDR + sizeof(struct vnt_rts_g_fb);
}
else if (bRTS == false) { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb) +
- sizeof(struct vnt_tx_datahead_g_fb);
+ cbMICHDR + sizeof(struct vnt_cts_fb);
}
} // Auto Fall Back
}
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index ea20e94..0a022cf 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -132,6 +132,7 @@ struct vnt_rts_g_fb {
u16 wRTSDuration_ba_f1;
u16 wRTSDuration_aa_f1;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_g_fb data_head;
} __packed;
struct vnt_rts_ab {
@@ -168,6 +169,7 @@ struct vnt_cts_fb {
u16 wCTSDuration_ba_f1;
struct ieee80211_cts data;
u16 reserved2;
+ struct vnt_tx_datahead_g_fb data_head;
} __packed;
union vnt_tx_data_head {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 2/8] staging: vt6656: rxtx.c Parse struct vnt_tx_datahead_g
From: Malcolm Priestley @ 2013-10-01 14:52 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
Parse struct vnt_tx_datahead_g from s_uFillDataHead and
move to struct vnt_rts_g/struct vnt_cts structure.
This removes pvTxDataHd pointer assignment.
The duration_id(uDuration) field is now returned in s_vGenerateTxParameter.
The return of s_uFillDataHead temporary or'ed to retain functionality of
other functions and is removed at the end of this patch series.
Since pvTxDataHd is now null a small vendor hack to vDMA0_tx_80211/csMgmt_xmit
to do with Disassociation-packet is also changed correct head position.
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 107 ++++++++++++++++++++----------------------
drivers/staging/vt6656/rxtx.h | 2 +
2 files changed, 54 insertions(+), 55 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index ff40255..58a9d8a 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -509,6 +509,25 @@ static u16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType,
return cpu_to_le16((u16)uDurTime);
}
+static u16 vnt_rxtx_datahead_g(struct vnt_private *priv, u8 pkt_type, u16 rate,
+ struct vnt_tx_datahead_g *buf, u32 frame_len, int need_ack)
+{
+ /* Get SignalField,ServiceField,Length */
+ BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+ BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+ PK_TYPE_11B, &buf->b);
+
+ /* Get Duration and TimeStamp */
+ buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+ buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
+
+ buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+ buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+ priv->byTopCCKBasicRate);
+
+ return buf->wDuration_a;
+}
+
static u32 s_uFillDataHead(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
u32 uDMAIdx, int bNeedAck, u8 byFBOption)
@@ -520,24 +539,7 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
if (byFBOption == AUTO_FB_NONE) {
- struct vnt_tx_datahead_g *pBuf =
- (struct vnt_tx_datahead_g *)pTxDataHead;
- //Get SignalField,ServiceField,Length
- BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &pBuf->a);
- BBvCalculateParameter(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
- //Get Duration and TimeStamp
- pBuf->wDuration_a = s_uGetDataDuration(pDevice,
- byPktType, bNeedAck);
- pBuf->wDuration_b = s_uGetDataDuration(pDevice,
- PK_TYPE_11B, bNeedAck);
-
- pBuf->wTimeStampOff_a = vnt_time_stamp_off(pDevice,
- wCurrentRate);
- pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
- pDevice->byTopCCKBasicRate);
- return (pBuf->wDuration_a);
+ ;
} else {
// Auto Fallback
struct vnt_tx_datahead_g_fb *pBuf =
@@ -651,7 +653,8 @@ static u16 vnt_rxtx_rts_g_head(struct vnt_private *priv,
vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
- return 0;
+ return vnt_rxtx_datahead_g(priv, pkt_type, current_rate,
+ &buf->data_head, frame_len, need_ack);
}
static u16 vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
@@ -748,7 +751,7 @@ static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
case PK_TYPE_11GB:
case PK_TYPE_11GA:
if (byFBOption == AUTO_FB_NONE)
- vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
+ return vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
else
@@ -815,6 +818,9 @@ static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
pBuf->data.duration = pBuf->wDuration_ba;
pBuf->data.frame_control = TYPE_CTL_CTS;
memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+ return vnt_rxtx_datahead_g(pDevice, byPktType, wCurrentRate,
+ &pBuf->data_head, cbFrameLength, bNeedAck);
}
return 0;
@@ -896,7 +902,7 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
}
/* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+ return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else {//RTS_needless, PCF mode
@@ -919,7 +925,7 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
}
/* Fill CTS */
- s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
+ return s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
cbFrameSize, bNeedACK, wCurrentRate, byFBOption);
}
}
@@ -1151,20 +1157,12 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g) +
- sizeof(struct vnt_tx_datahead_g);
+ cbMICHDR + sizeof(struct vnt_rts_g);
}
else { //RTS_needless
- pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts));
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts) +
- sizeof(struct vnt_tx_datahead_g);
+ cbMICHDR + sizeof(struct vnt_cts);
}
} else {
// Auto Fall Back
@@ -1233,13 +1231,13 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
//uDMAIdx = TYPE_AC0DMA;
//pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
- //Fill FIFO,RrvTime,RTS,and CTS
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
- tx_buffer, &pMICHDR, cbMICHDR,
- cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
+ /* Fill FIFO, RrvTime, RTS and CTS */
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ tx_buffer, &pMICHDR, cbMICHDR,
+ cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
//Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
- byFBOption);
+ uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
+ cbFrameSize, uDMAIdx, bNeedACK, byFBOption);
// Generate TX MAC Header
s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
byFragType, uDMAIdx, 0);
@@ -1605,10 +1603,8 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
//Set RrvTime/RTS/CTS Buffer
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
- pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + sizeof(struct vnt_cts));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+ sizeof(struct vnt_cts);
}
else { // 802.11a/b packet
pvTxDataHd = (struct vnt_tx_datahead_ab *) (pbyTxBufferAddr +
@@ -1629,13 +1625,13 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
/* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
pTX_Buffer, &pMICHDR, 0,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
//Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
- AUTO_FB_NONE);
+ uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
+ cbFrameSize, TYPE_TXDMA0, bNeedACK, AUTO_FB_NONE);
pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
@@ -1699,9 +1695,11 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
// in the same place of other packet's Duration-field).
// And it will cause Cisco-AP to issue Disassociation-packet
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+ struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+ tx_cts.tx.head.cts_g.data_head;
+ data_head->wDuration_a =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+ data_head->wDuration_b =
cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
} else {
((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
@@ -2008,11 +2006,8 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
- pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
- wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
- sizeof(struct vnt_cts));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
- sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+ sizeof(struct vnt_cts);
}
else {//802.11a/b packet
@@ -2033,13 +2028,13 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
/* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+ uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
pTX_Buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
//Fill DataHead
- uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
- AUTO_FB_NONE);
+ uDuration |= s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd,
+ cbFrameSize, TYPE_TXDMA0, bNeedACK, AUTO_FB_NONE);
pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
@@ -2149,9 +2144,11 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
// in the same place of other packet's Duration-field).
// And it will cause Cisco-AP to issue Disassociation-packet
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+ struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+ tx_cts.tx.head.cts_g.data_head;
+ data_head->wDuration_a =
cpu_to_le16(p80211Header->sA2.wDurationID);
- ((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+ data_head->wDuration_b =
cpu_to_le16(p80211Header->sA2.wDurationID);
} else {
((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index bbda9a3..ea20e94 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -117,6 +117,7 @@ struct vnt_rts_g {
u16 wDuration_bb;
u16 wReserved;
struct ieee80211_rts data;
+ struct vnt_tx_datahead_g data_head;
} __packed;
struct vnt_rts_g_fb {
@@ -156,6 +157,7 @@ struct vnt_cts {
u16 wReserved;
struct ieee80211_cts data;
u16 reserved2;
+ struct vnt_tx_datahead_g data_head;
} __packed;
struct vnt_cts_fb {
--
1.8.3.2
^ permalink raw reply related
* [PATCH 1/8] staging: vt6656: rxtx.c change tx functions to return u16
From: Malcolm Priestley @ 2013-10-01 14:50 UTC (permalink / raw)
To: gregkh; +Cc: linux-wireless
s_vGenerateTxParameter, s_vFillCTSHead, s_vFillRTSHead, vnt_rxtx_rts* functions
to return u16
Initially this is the duration_id field for ieee80211_hdr
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
drivers/staging/vt6656/rxtx.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 791144a..ff40255 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -98,7 +98,7 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
static void *s_vGetFreeContext(struct vnt_private *pDevice);
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
@@ -124,11 +124,11 @@ static unsigned int s_uGetTxRsvTime(struct vnt_private *pDevice, u8 byPktType,
static u16 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice, u8 byRTSRsvType,
u8 byPktType, u32 cbFrameLength, u16 wCurrentRate);
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
int bNeedAck, u16 wCurrentRate, u8 byFBOption);
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption);
@@ -630,7 +630,7 @@ static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
return 0;
}
-static int vnt_rxtx_rts_g_head(struct vnt_private *priv,
+static u16 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)
@@ -654,7 +654,7 @@ 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,
+static u16 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)
@@ -689,7 +689,7 @@ 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,
+static u16 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)
@@ -707,7 +707,7 @@ 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,
+static u16 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)
@@ -731,13 +731,13 @@ static int vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
return 0;
}
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
{
if (!head)
- return;
+ return 0;
/* Note: So far RTSHead doesn't appear in ATIM
* & Beacom DMA, so we don't need to take them
@@ -768,16 +768,18 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
psEthHeader, byPktType, cbFrameLength,
bNeedAck, wCurrentRate, byFBOption);
}
+
+ return 0;
}
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
int bNeedAck, u16 wCurrentRate, u8 byFBOption)
{
u32 uCTSFrameLen = 14;
if (!head)
- return;
+ return 0;
if (byFBOption != AUTO_FB_NONE) {
/* Auto Fall back */
@@ -814,6 +816,8 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
pBuf->data.frame_control = TYPE_CTL_CTS;
memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
}
+
+ return 0;
}
/*+
@@ -839,7 +843,7 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
*
-*/
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts)
@@ -862,7 +866,7 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
}
if (!pFifoHead)
- return;
+ return 0;
if (pDevice->bLongHeader)
cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
@@ -983,6 +987,8 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
}
}
//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
+
+ return 0;
}
/*
u8 * pbyBuffer,//point to pTxBufHead
--
1.8.3.2
^ permalink raw reply related
* [PATCH] mac80211: implement SMPS for AP
From: Emmanuel Grumbach @ 2013-10-01 13:45 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach
When the driver requests to move to STATIC or DYNAMIC SMPS,
we send an action frame to each associated station and
reconfigure the channel context / driver.
Of course, non-MIMO stations are ignored.
The beacon isn't updated. The association response will
include the original capabilities. Stations that associate
while in non-OFF SMPS mode will get an action frame right
after association to inform them about our current state.
Note that we wait until the end of the EAPOL. Sending an
action frame before the EAPOL is finished can be an issue
for a few clients. Clients aren't likely to send EAPOL
frames in MIMO anyway.
When the SMPS configuration gets more permissive (e.g.
STATIC -> OFF), we don't wake up stations that are asleep
We remember that they don't know about the change and send
the action frame when they wake up.
When the SMPS configuration gets more restrictive (e.g.
OFF -> STATIC), we set the TIM bit for every sleeping STA.
uAPSD stations might send MIMO until they poll the action
frame, but this is for a short period of time.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
This patch was sent long ago. I fixed VLAN handling
---
net/mac80211/cfg.c | 108 +++++++++++++++++++++++++++++++++++++++--
net/mac80211/debugfs_netdev.c | 25 ++++++----
net/mac80211/ht.c | 41 ++++++++++++----
net/mac80211/ieee80211_i.h | 15 ++++--
net/mac80211/iface.c | 2 +
net/mac80211/mlme.c | 2 +-
net/mac80211/sta_info.c | 72 +++++++++++++++++++++++++++
net/mac80211/sta_info.h | 5 ++
net/mac80211/status.c | 31 +++++++-----
net/mac80211/util.c | 25 ++++++++++
10 files changed, 288 insertions(+), 38 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index befb23f..2720373 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1059,6 +1059,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
/* abort any running channel switch */
sdata->vif.csa_active = false;
cancel_work_sync(&sdata->csa_finalize_work);
+ cancel_work_sync(&sdata->u.ap.request_smps_work);
/* turn off carrier for this interface and dependent VLANs */
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -1553,6 +1554,20 @@ static int ieee80211_change_station(struct wiphy *wiphy,
mutex_unlock(&local->sta_mtx);
+ if ((sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+ sta->known_smps_mode != sta->sdata->bss->req_smps &&
+ test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
+ sta_info_tx_streams(sta) != 1) {
+ ht_dbg(sta->sdata,
+ "%pM just authorized and MIMO capable - update SMPS\n",
+ sta->sta.addr);
+ ieee80211_send_smps_action(sta->sdata,
+ sta->sdata->bss->req_smps,
+ sta->sta.addr,
+ sta->sdata->vif.bss_conf.bssid);
+ }
+
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
ieee80211_recalc_ps(local, -1);
@@ -2337,8 +2352,92 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
}
#endif
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps_mode)
+int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_smps_mode smps_mode)
+{
+ struct sta_info *sta;
+ enum ieee80211_smps_mode old_req;
+ int i;
+
+ if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
+ return -EINVAL;
+
+ if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+ return 0;
+
+ old_req = sdata->u.ap.req_smps;
+ sdata->u.ap.req_smps = smps_mode;
+
+ /* AUTOMATIC doesn't mean much for AP - don't allow it */
+ if (old_req == smps_mode ||
+ smps_mode == IEEE80211_SMPS_AUTOMATIC)
+ return 0;
+
+ /* If no associated stations, there's no need to do anything */
+ if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
+ sdata->smps_mode = smps_mode;
+ ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
+ return 0;
+ }
+
+ ht_dbg(sdata,
+ "SMSP %d requested in AP mode, sending Action frame to %d stations\n",
+ smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
+
+ mutex_lock(&sdata->local->sta_mtx);
+ for (i = 0; i < STA_HASH_SIZE; i++) {
+ for (sta = rcu_dereference_protected(sdata->local->sta_hash[i],
+ lockdep_is_held(&sdata->local->sta_mtx));
+ sta;
+ sta = rcu_dereference_protected(sta->hnext,
+ lockdep_is_held(&sdata->local->sta_mtx))) {
+ /*
+ * Only stations associated to our AP and
+ * associated VLANs
+ */
+ if (sta->sdata->bss != &sdata->u.ap)
+ continue;
+
+ /* This station doesn't support MIMO - skip it */
+ if (sta_info_tx_streams(sta) == 1)
+ continue;
+
+ /*
+ * Don't wake up a STA just to send the action frame
+ * unless we are getting more restrictive.
+ */
+ if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
+ !ieee80211_smps_is_restrictive(sta->known_smps_mode,
+ smps_mode)) {
+ ht_dbg(sdata,
+ "Won't send SMPS to sleeping STA %pM\n",
+ sta->sta.addr);
+ continue;
+ }
+
+ /*
+ * If the STA is not authorized, wait until it gets
+ * authorized and the action frame will be sent then.
+ */
+ if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ continue;
+
+ ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
+ ieee80211_send_smps_action(sdata, smps_mode,
+ sta->sta.addr,
+ sdata->vif.bss_conf.bssid);
+ }
+ }
+ mutex_unlock(&sdata->local->sta_mtx);
+
+ sdata->smps_mode = smps_mode;
+ ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
+
+ return 0;
+}
+
+int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_smps_mode smps_mode)
{
const u8 *ap;
enum ieee80211_smps_mode old_req;
@@ -2346,6 +2445,9 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
lockdep_assert_held(&sdata->wdev.mtx);
+ if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
+ return -EINVAL;
+
old_req = sdata->u.mgd.req_smps;
sdata->u.mgd.req_smps = smps_mode;
@@ -2402,7 +2504,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
/* no change, but if automatic follow powersave */
sdata_lock(sdata);
- __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
+ __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps);
sdata_unlock(sdata);
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ebde2fb..46ba3fb 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -227,12 +227,15 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
target_mode == IEEE80211_SMPS_DYNAMIC)
return -EINVAL;
- /* supported only on managed interfaces for now */
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
+ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_AP)
return -EOPNOTSUPP;
sdata_lock(sdata);
- err = __ieee80211_request_smps(sdata, smps_mode);
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ err = __ieee80211_request_smps_mgd(sdata, smps_mode);
+ else
+ err = __ieee80211_request_smps_ap(sdata, smps_mode);
sdata_unlock(sdata);
return err;
@@ -248,12 +251,15 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
char *buf, int buflen)
{
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- return snprintf(buf, buflen, "request: %s\nused: %s\n",
- smps_modes[sdata->u.mgd.req_smps],
- smps_modes[sdata->smps_mode]);
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ return snprintf(buf, buflen, "request: %s\nused: %s\n",
+ smps_modes[sdata->u.mgd.req_smps],
+ smps_modes[sdata->smps_mode]);
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
+ return snprintf(buf, buflen, "request: %s\nused: %s\n",
+ smps_modes[sdata->u.ap.req_smps],
+ smps_modes[sdata->smps_mode]);
+ return -EINVAL;
}
static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
@@ -566,6 +572,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(num_mcast_sta);
+ DEBUGFS_ADD_MODE(smps, 0600);
DEBUGFS_ADD(num_sta_ps);
DEBUGFS_ADD(dtim_count);
DEBUGFS_ADD(num_buffered_multicast);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 529bf58..9a8be8f 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -448,14 +448,25 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
return 0;
}
-void ieee80211_request_smps_work(struct work_struct *work)
+void ieee80211_request_smps_mgd_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
container_of(work, struct ieee80211_sub_if_data,
u.mgd.request_smps_work);
sdata_lock(sdata);
- __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
+ __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.driver_smps_mode);
+ sdata_unlock(sdata);
+}
+
+void ieee80211_request_smps_ap_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data,
+ u.ap.request_smps_work);
+
+ sdata_lock(sdata);
+ __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
sdata_unlock(sdata);
}
@@ -464,19 +475,29 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+ if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_AP))
return;
if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
smps_mode = IEEE80211_SMPS_AUTOMATIC;
- if (sdata->u.mgd.driver_smps_mode == smps_mode)
- return;
-
- sdata->u.mgd.driver_smps_mode = smps_mode;
-
- ieee80211_queue_work(&sdata->local->hw,
- &sdata->u.mgd.request_smps_work);
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.driver_smps_mode == smps_mode)
+ return;
+ sdata->u.mgd.driver_smps_mode = smps_mode;
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->u.mgd.request_smps_work);
+ } else {
+ /* AUTOMATIC is meaningless in AP mode */
+ if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC))
+ return;
+ if (sdata->u.ap.driver_smps_mode == smps_mode)
+ return;
+ sdata->u.ap.driver_smps_mode = smps_mode;
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->u.ap.request_smps_work);
+ }
}
/* this might change ... don't want non-open drivers using it */
EXPORT_SYMBOL_GPL(ieee80211_request_smps);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d604e16..09ebb73 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -262,6 +262,10 @@ struct ieee80211_if_ap {
struct ps_data ps;
atomic_t num_mcast_sta; /* number of stations receiving multicast */
+ enum ieee80211_smps_mode req_smps, /* requested smps mode */
+ driver_smps_mode; /* smps mode request */
+
+ struct work_struct request_smps_work;
};
struct ieee80211_if_wds {
@@ -1436,7 +1440,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode smps, const u8 *da,
const u8 *bssid);
-void ieee80211_request_smps_work(struct work_struct *work);
+void ieee80211_request_smps_ap_work(struct work_struct *work);
+void ieee80211_request_smps_mgd_work(struct work_struct *work);
+bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
+ enum ieee80211_smps_mode smps_mode_new);
void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
u16 initiator, u16 reason, bool stop);
@@ -1631,8 +1638,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems,
enum ieee80211_band band, u32 *basic_rates);
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
- enum ieee80211_smps_mode smps_mode);
+int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_smps_mode smps_mode);
+int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_smps_mode smps_mode);
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e1e484d..68016ef 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1304,6 +1304,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_AP:
skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
INIT_LIST_HEAD(&sdata->u.ap.vlans);
+ INIT_WORK(&sdata->u.ap.request_smps_work,
+ ieee80211_request_smps_ap_work);
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
case NL80211_IFTYPE_P2P_CLIENT:
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ed84af6..fb140f2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3697,7 +3697,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ieee80211_beacon_connection_loss_work);
INIT_WORK(&ifmgd->csa_connection_drop_work,
ieee80211_csa_connection_drop_work);
- INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
+ INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
setup_timer(&ifmgd->timer, ieee80211_sta_timer,
(unsigned long) sdata);
setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 9c97237..a6cd1e5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -385,6 +385,30 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
sta->sta.smps_mode = IEEE80211_SMPS_OFF;
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ struct ieee80211_supported_band *sband =
+ local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
+ u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
+ /*
+ * Assume that hostapd advertises our caps in the beacon and
+ * this is the known_smps_mode for a station that just assciated
+ */
+ switch (smps) {
+ case WLAN_HT_SMPS_CONTROL_DISABLED:
+ sta->known_smps_mode = IEEE80211_SMPS_OFF;
+ break;
+ case WLAN_HT_SMPS_CONTROL_STATIC:
+ sta->known_smps_mode = IEEE80211_SMPS_STATIC;
+ break;
+ case WLAN_HT_SMPS_CONTROL_DYNAMIC:
+ sta->known_smps_mode = IEEE80211_SMPS_DYNAMIC;
+ break;
+ default:
+ WARN_ON(1);
+ }
+ }
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
@@ -1069,6 +1093,19 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
+ /* This station just woke up and isn't aware of our SMPS state */
+ if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
+ sdata->smps_mode) &&
+ sta->known_smps_mode != sdata->bss->req_smps &&
+ sta_info_tx_streams(sta) != 1) {
+ ht_dbg(sdata,
+ "%pM just woke up and MIMO capable - update SMPS\n",
+ sta->sta.addr);
+ ieee80211_send_smps_action(sdata, sdata->bss->req_smps,
+ sta->sta.addr,
+ sdata->vif.bss_conf.bssid);
+ }
+
local->total_ps_buffered -= buffered;
sta_info_recalc_tim(sta);
@@ -1520,3 +1557,38 @@ int sta_info_move_state(struct sta_info *sta,
return 0;
}
+
+u8 sta_info_tx_streams(struct sta_info *sta)
+{
+ struct ieee80211_sta_ht_cap *ht_cap = &sta->sta.ht_cap;
+ u8 rx_streams;
+
+ if (!sta->sta.ht_cap.ht_supported)
+ return 1;
+
+ if (sta->sta.vht_cap.vht_supported) {
+ int i;
+ u16 tx_mcs_map =
+ le16_to_cpu(sta->sta.vht_cap.vht_mcs.tx_mcs_map);
+
+ for (i = 7; i <= 0; i--)
+ if ((tx_mcs_map & (0x3 << (i * 2))) !=
+ IEEE80211_VHT_MCS_NOT_SUPPORTED)
+ return i + 1;
+ }
+
+ if (ht_cap->mcs.rx_mask[3])
+ rx_streams = 4;
+ else if (ht_cap->mcs.rx_mask[2])
+ rx_streams = 3;
+ else if (ht_cap->mcs.rx_mask[1])
+ rx_streams = 2;
+ else
+ rx_streams = 1;
+
+ if (!(ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_RX_DIFF))
+ return rx_streams;
+
+ return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+ >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9013969..390d249 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -301,6 +301,8 @@ struct sta_ampdu_mlme {
* @chains: chains ever used for RX from this station
* @chain_signal_last: last signal (per chain)
* @chain_signal_avg: signal average (per chain)
+ * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
+ * AP only.
*/
struct sta_info {
/* General information, mostly static */
@@ -411,6 +413,8 @@ struct sta_info {
unsigned int lost_packets;
unsigned int beacon_loss_count;
+ enum ieee80211_smps_mode known_smps_mode;
+
/* keep last! */
struct ieee80211_sta sta;
};
@@ -613,6 +617,7 @@ void sta_set_rate_info_rx(struct sta_info *sta,
struct rate_info *rinfo);
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
+u8 sta_info_tx_streams(struct sta_info *sta);
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 368837f..1ced74c 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -191,29 +191,36 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_HT &&
mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS &&
- sdata->vif.type == NL80211_IFTYPE_STATION &&
ieee80211_sdata_running(sdata)) {
- /*
- * This update looks racy, but isn't -- if we come
- * here we've definitely got a station that we're
- * talking to, and on a managed interface that can
- * only be the AP. And the only other place updating
- * this variable in managed mode is before association.
- */
+ enum ieee80211_smps_mode smps_mode;
+
switch (mgmt->u.action.u.ht_smps.smps_control) {
case WLAN_HT_SMPS_CONTROL_DYNAMIC:
- sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
+ smps_mode = IEEE80211_SMPS_DYNAMIC;
break;
case WLAN_HT_SMPS_CONTROL_STATIC:
- sdata->smps_mode = IEEE80211_SMPS_STATIC;
+ smps_mode = IEEE80211_SMPS_STATIC;
break;
case WLAN_HT_SMPS_CONTROL_DISABLED:
default: /* shouldn't happen since we don't send that */
- sdata->smps_mode = IEEE80211_SMPS_OFF;
+ smps_mode = IEEE80211_SMPS_OFF;
break;
}
- ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ /*
+ * This update looks racy, but isn't -- if we come
+ * here we've definitely got a station that we're
+ * talking to, and on a managed interface that can
+ * only be the AP. And the only other place updating
+ * this variable in managed mode is before association.
+ */
+ sdata->smps_mode = smps_mode;
+ ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
+ } else if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+ sta->known_smps_mode = smps_mode;
+ }
}
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 75a1685..47aca3b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2292,3 +2292,28 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)
ieee80211_queue_work(hw, &local->radar_detected_work);
}
EXPORT_SYMBOL(ieee80211_radar_detected);
+
+/*
+ * Returns true if smps_mode_new is strictly more restrictive than
+ * smps_mode_old.
+ */
+bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
+ enum ieee80211_smps_mode smps_mode_new)
+{
+ if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC ||
+ smps_mode_new == IEEE80211_SMPS_AUTOMATIC))
+ return false;
+
+ switch (smps_mode_old) {
+ case IEEE80211_SMPS_STATIC:
+ return false;
+ case IEEE80211_SMPS_DYNAMIC:
+ return smps_mode_new == IEEE80211_SMPS_STATIC;
+ case IEEE80211_SMPS_OFF:
+ return smps_mode_new != IEEE80211_SMPS_OFF;
+ default:
+ WARN_ON(1);
+ }
+
+ return false;
+}
--
1.7.10.4
^ permalink raw reply related
* Re: [PATCH 3.12] mac80211: fix a tx power handling regression
From: Johannes Berg @ 2013-10-01 12:32 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <52495798.1030408@openwrt.org>
On Mon, 2013-09-30 at 12:51 +0200, Felix Fietkau wrote:
> > Not sure I see why? It's an absolute value after we do the calculations
> > in that interface that has the TPC.
> Maybe we need to rework this somehow, but in the mean time, this patch
> fixes a serious regression that I've been looking into for a while now.
> I haven't worked out the exact conditions that trigger this yet, but
> often when an AP VLAN gets destroyed and recreated, or when a new
> temporary interface is brought up and then down again, the tx power for
> *all* interfaces gets reset to the lowest possible level.
I think we just need to skip VLANs in the loop instead, they don't
really matter here. Can you try that? Using the max would effectively
ignore them since they might always have 0 for bss_conf.txpower.
johannes
^ permalink raw reply
* Re: [wireless-regdb] [PATCH] regulatory: enable channels 52-64 and 100-144 for world roaming
From: Johannes Berg @ 2013-10-01 12:15 UTC (permalink / raw)
To: linux-wireless; +Cc: bzhao, wireless-regdb, mcgrof
In-Reply-To: <1368738412-7740-1-git-send-email-johannes@sipsolutions.net>
On Thu, 2013-05-16 at 23:06 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> If allowed in a country, these channels typically require DFS
> so mark them as such. Channel 144 is a bit special, it's coming
> into use now to allow more VHT 80 channels, but world roaming
> with passive scanning is acceptable anyway. It seems fairly
> unlikely that it'll be used as the control channel for a VHT
> AP, but it needs to be present to allow a full VHT connection
> to an AP that uses it as one of the secondary channels.
>
> Also enable VHT 160 on these channels, and also for channels
> 36-48 to be able to use VHT 160 there.
So many months later ... I'm merging this now.
johannes
^ permalink raw reply
* Re: [PATCH] iw: use nl80211 for phy_lookup function
From: Johannes Berg @ 2013-10-01 11:53 UTC (permalink / raw)
To: Javier Lopez; +Cc: linux-wireless
In-Reply-To: <1380534243-4766-1-git-send-email-jlopex@cozybit.com>
On Mon, 2013-09-30 at 11:44 +0200, Javier Lopez wrote:
> Original implementation uses sysfs to get dev index from
> dev name. Due the changes on netns and sysfs iw is broken
> if using multiple network namespaces. iw works properly
> if using it from the main namespace, but it won't work if
> using from the new namespace.
>
> Kernel commit 3ff195b0, "sysfs: Implement sysfs tagged
> directory support" patch, added a filtering mechanism
> to sysfs, allowing sysfs directories to look different
> depending on the context where they are being observed.
>
> When an interface is moved to another namespace, the
> interface dissapears from sysfs structure. In order
> to recover access to the directory a solution is to
> remount sysfs from the correct context. This will force
> the user to remount sysfs before using iw from a
> different namespace.
>
> To avoid this issue we can use nl80211 (using
> NL80211_CMD_GET_WIPHY command) this returns the list of
> phys, then process the list, find the device and return
> the device index.
This seems a bit workaround-ish/hack-ish to me. Why would a remount be
necessary? Can't sysfs look at the process tags when determining the
access? Should we maybe do something in our sysfs code in the kernel for
this?
johannes
^ permalink raw reply
* Re: [PATCH 2/2] mac80211: implement support for configuring antenna gain
From: Johannes Berg @ 2013-10-01 11:50 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless
In-Reply-To: <524AAE97.5020708@openwrt.org>
On Tue, 2013-10-01 at 13:14 +0200, Felix Fietkau wrote:
> On 2013-10-01 1:05 PM, Johannes Berg wrote:
> > On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
> >> Report the maximum allowable extra antenna gain to the driver to allow
> >> it to reduce the tx power even further based on internal data
> >
> > I don't quite understand the maximum thing here - what's a user to do
> > who has an antenna that goes over? Is that then intended to not be
> > supported? That seems odd. A very high gain antenna might just result in
> > signal distortions, but what's the reason for limiting it this way?
> Very high gain antennas are useful for long distance links.
> The signal is not distorted, but focused directionally, which can easily
> make it exceed regulatory EIRP limits, unless tx power is reduced
> appropriately.
Sure.
> If the user explicitly configures the gain of the directional antenna
> using this patch, mac80211 will reduce the maximum allowed tx power
> setting to stay within the legal limit.
I understand. I don't understand the pieces about "max_antenna_gain".
johannes
^ permalink raw reply
* Re: [PATCH 0/5] Add Mesh Channel Switch Support
From: Johannes Berg @ 2013-10-01 11:31 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
On Fri, 2013-09-13 at 16:36 -0700, Chun-Yeow Yeoh wrote:
> These patches are reviewed and commented by Bob Copeland and Thomas
> Pedersen. Any further comments are welcomed.
Sorry for the long delay, I posted some more comments. Can't really
comment on how good this is etc. since I'm not familiar with mesh :)
johannes
^ permalink raw reply
* Re: [PATCH 5/5] mac80211: process mesh channel switching using beacon
From: Johannes Berg @ 2013-10-01 11:30 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-6-git-send-email-yeohchunyeow@cozybit.com>
On Fri, 2013-09-13 at 16:36 -0700, Chun-Yeow Yeoh wrote:
> err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
> ifibss->chandef.chan->band,
> sta_flags, ifibss->bssid,
> - ¶ms.count, &mode,
> + ¶ms.count, &mode, &ttl,
> ¶ms.chandef);
I think it'd be worth doing some refactoring here to have an output
struct ... the parameters to this function are getting unreal. :)
> + if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef,
> + IEEE80211_CHAN_DISABLED)) {
> + sdata_info(sdata,
> + "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
> + sdata->vif.addr,
> + params.chandef.chan->center_freq,
> + params.chandef.width,
> + params.chandef.center_freq1,
> + params.chandef.center_freq2);
> + }
Seems like you should *do* something here, like return false?
johannes
^ permalink raw reply
* Re: [PATCH 4/5] {nl,cfg,mac}80211: finalizing mesh channel switching
From: Johannes Berg @ 2013-10-01 11:27 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-5-git-send-email-yeohchunyeow@cozybit.com>
On Fri, 2013-09-13 at 16:36 -0700, Chun-Yeow Yeoh wrote:
> Finalizing the requried procedures for channel switching completion and
typo: required
> also adding the function for updating the beacon and probe response frames
> with CSA and MCSP elements. Once the channel switching is completed, the
> CSA and MCSP elements are removed from the beacon or probe response frames
> as defined in the IEEE Std 802.11-2012 section 10.9.8.4.3.
I'd prefer you rewrote this to be more active ... this seems rather
observer style :)
> +int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
> +{
> + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
> + int ret = 0;
> +
> + /* Remove the CSA and MCSP elements from the beacon */
> + kfree(ifmsh->csa_settings);
> + ifmsh->csa_settings = NULL;
> + ret = ieee80211_mesh_rebuild_beacon(sdata);
> + if (ret)
> + return -EINVAL;
This seems totally racy with what I pointed out in the other patch ...
> + /* Reset the TTL value and Initiator flag */
> + ifmsh->chsw_init = false;
> + ifmsh->chsw_ttl = 0;
> +
> + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
> +
> + mcsa_dbg(sdata, "complete switching to center freq %d MHz",
> + sdata->vif.bss_conf.chandef.chan->center_freq);
> + return ret;
return 0
> + tmp_csa_settings = kmalloc(sizeof(struct cfg80211_csa_settings),
> + GFP_ATOMIC);
> + if (!tmp_csa_settings) {
> + mcsa_dbg(sdata, "could not allocate memory for csa beaconing");
You should never print a message for memory allocation failures, they
already give very verbose output.
> + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
> + return ret;
return 0
johannes
^ permalink raw reply
* Re: [PATCH 3/5] mac80211: adding the CSA and MCSP elements in mesh beaconing
From: Johannes Berg @ 2013-10-01 11:25 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-4-git-send-email-yeohchunyeow@cozybit.com>
Subject should probably just say "add", not "adding".
Should this patch be before the other one so userspace can't trigger an
invalid CSA thing inbetween the two patches?
> + if (ifmsh->csa_settings) {
> + *pos++ = ieee80211_frequency_to_channel(
> + ifmsh->csa_settings->chandef.chan->center_freq);
Why is that csa_settings access not racy?
johannes
^ permalink raw reply
* Re: [PATCH 2/5] {nl,cfg,mac}80211: enable the triggering of CSA frame in mesh
From: Johannes Berg @ 2013-10-01 11:24 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-3-git-send-email-yeohchunyeow@cozybit.com>
On Fri, 2013-09-13 at 16:36 -0700, Chun-Yeow Yeoh wrote:
> + skb = dev_alloc_skb(local->tx_headroom + hdr_len +
> + 5 + /* channel switch announcement element */
> + 3 + /* secondary channel offset element */
> + 8); /* mesh channel switch parameters element */
> + if (!skb)
> + return -1;
please fix that to -ENOMEM while at it
> +}
> +
Please no blank line at EOF
johannes
^ permalink raw reply
* Re: [PATCH 1/5] mac80211: process the CSA frame for mesh accordingly
From: Johannes Berg @ 2013-10-01 11:21 UTC (permalink / raw)
To: Chun-Yeow Yeoh; +Cc: linux-wireless, linville, devel, distro11s
In-Reply-To: <1379115372-28426-2-git-send-email-yeohchunyeow@cozybit.com>
On Fri, 2013-09-13 at 16:36 -0700, Chun-Yeow Yeoh wrote:
> + skb = dev_alloc_skb(local->tx_headroom + len);
> + if (!skb)
> + return -1;
-ENOMEM ?
> + skb_reserve(skb, local->tx_headroom);
> + mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len);
> +
> + /* offset_ttl is based on whether the secondary channel
> + * offset is available or not. Substract 1 from the mesh TTL
> + * and disable the initiator flag before forwarding.
> + */
> + offset_ttl = (len < 42) ? 7 : 10;
> + *(pos + offset_ttl) -= 1;
> + *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
That's somewhat ugly, is there no better way to express that? Maybe with
different structs or something? I guess I can live with it, just asking
though.
> + /* forward or re-broadcast the CSA frame */
> + if (fwd_csa) {
> + if (mesh_fwd_csa_frame(sdata, mgmt, len) < 0)
> + mcsa_dbg(sdata, "Failed to forward the CSA frame");
> + }
> +
> + /* block the Tx only after fowarding the CSA frame if required */
typo: forwarding
> + block_tx = !!(elems.mesh_chansw_params_ie->mesh_flags
> + & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT);
No need for !! with bool variables
johannes
^ permalink raw reply
* Re: [PATCH 2/2] mac80211: implement support for configuring antenna gain
From: Felix Fietkau @ 2013-10-01 11:14 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1380625512.14430.19.camel@jlt4.sipsolutions.net>
On 2013-10-01 1:05 PM, Johannes Berg wrote:
> On Fri, 2013-09-06 at 15:06 +0200, Felix Fietkau wrote:
>> Report the maximum allowable extra antenna gain to the driver to allow
>> it to reduce the tx power even further based on internal data
>
> I don't quite understand the maximum thing here - what's a user to do
> who has an antenna that goes over? Is that then intended to not be
> supported? That seems odd. A very high gain antenna might just result in
> signal distortions, but what's the reason for limiting it this way?
Very high gain antennas are useful for long distance links.
The signal is not distorted, but focused directionally, which can easily
make it exceed regulatory EIRP limits, unless tx power is reduced
appropriately.
If the user explicitly configures the gain of the directional antenna
using this patch, mac80211 will reduce the maximum allowed tx power
setting to stay within the legal limit.
- Felix
^ permalink raw reply
* Re: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Johan Hedberg @ 2013-10-01 11:13 UTC (permalink / raw)
To: Bing Zhao
Cc: Marcel Holtmann, linux-bluetooth@vger.kernel.org development,
Gustavo F. Padovan, linux-wireless@vger.kernel.org Wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <B3090D30-6F81-4E12-8F58-E650F77BB72E@holtmann.org>
Hi Marcel & Bing,
On Thu, Sep 26, 2013, Marcel Holtmann wrote:
> >> You're right that we're missing the clearing of the HCI_SETUP flag for
> >> such a scenario. Could you try the attached patch. It should fix the
> >
> > We have tested your patch. Yes, it fixes the problem. Thanks!
>
> then lets get a proper version with full commit message explaining the
> issue merged upstream. As I said, this is a real bug we need to fix.
I've just sent a new patch set titled "[PATCH 0/2] Bluetooth: Fix
hci_dev_open race condition". Bing, could you please test this with your
original setup so we ensure that the issue is still properly handled.
Johan
^ permalink raw reply
* Re: [PATCH 2/4] nl80211/cfg80211: enable DFS for IBSS mode
From: Johannes Berg @ 2013-10-01 11:09 UTC (permalink / raw)
To: Simon Wunderlich; +Cc: linux-wireless, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1378230201-25446-3-git-send-email-siwu@hrz.tu-chemnitz.de>
On Tue, 2013-09-03 at 19:43 +0200, Simon Wunderlich wrote:
> To use DFS in IBSS mode, userspace is required to react to radar events.
> It can inform nl80211 that it is capable of doing so by adding a
> NL80211_ATTR_CONTROL_PORT_DFS attribute when joining the IBSS.
I don't like that name, it makes no sense. This has nothing to do with
the port control (802.1X-style) at all.
> If this attribute is supplied, DFS channels may be used if the driver
> supports it. Support will be checked even if a channel without DFS will
> be joined, as the channel might change later due to scan activity or
> channel switch announcements.
You also really should document *what* is required of userspace here.
You're kinda saying this needs to be implemented, but not saying what
needs to be done. I can't even tell - what does it really have to do?
Don't you implement most of it in patches 3 and 4 anyway in the kernel?
johannes
^ permalink raw reply
* Re: [PATCH 1/4] nl80211: allow CAC only if no operation is going on
From: Johannes Berg @ 2013-10-01 11:06 UTC (permalink / raw)
To: Simon Wunderlich; +Cc: linux-wireless, Mathias Kretschmer, Simon Wunderlich
In-Reply-To: <1378230201-25446-2-git-send-email-siwu@hrz.tu-chemnitz.de>
On Tue, 2013-09-03 at 19:43 +0200, Simon Wunderlich wrote:
> A CAC should fail if it is triggered while the interface is already
> running.
Applied, though this is a bit questionable - it forces every driver
implementing this to have the same carrier semantics as mac80211. That
might very well be a good thing, but those semantics aren't really
documented.
johannes
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox