2015-04-21 21:33:27

by Malcolm Priestley

[permalink] [raw]
Subject: [PATCH 1/3] staging: vt6655: vnt_tx_packet Correct TX order of OWNED_BY_NIC

The state of m_td0TD0.f1Owner should change after the buff_addr
has been filled otherwise the device grabs the buffer too early.

m_td0TD0.f1Owner is protected by memory barriers on both sides
of change.

iTDUsed is best incremented after MACvTransmit.

It appears that f1Owner actually polls to do the memory transfer.

A back port patch will be needed for v3.19

Signed-off-by: Malcolm Priestley <[email protected]>
Cc: <[email protected]> # v4.0+
---
drivers/staging/vt6655/device_main.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index c5f8233..ed90b6f 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1201,14 +1201,6 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
if (dma_idx == TYPE_AC0DMA)
head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;

- priv->iTDUsed[dma_idx]++;
-
- /* Take ownership */
- wmb();
- head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
-
- /* get Next */
- wmb();
priv->apCurrTD[dma_idx] = head_td->next;

spin_unlock_irqrestore(&priv->lock, flags);
@@ -1229,11 +1221,18 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)

head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);

+ /* Poll Transmit the adapter */
+ wmb();
+ head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
+ wmb(); /* second memory barrier */
+
if (head_td->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
MACvTransmitAC0(priv->PortOffset);
else
MACvTransmit0(priv->PortOffset);

+ priv->iTDUsed[dma_idx]++;
+
spin_unlock_irqrestore(&priv->lock, flags);

return 0;
--
2.1.4



2015-04-21 21:33:28

by Malcolm Priestley

[permalink] [raw]
Subject: [PATCH 2/3] staging: vt6655: CARDbUpdateTSF bss timestamp correct tsf counter value.

The TSF counter is not set correctly.

Use sync_tsf for last beacon value and get tsf local value.

Remove qwLocalTSF variable and call CARDbGetCurrentTSF.

Signed-off-by: Malcolm Priestley <[email protected]>
---
drivers/staging/vt6655/card.c | 10 +++++++---
drivers/staging/vt6655/card.h | 2 +-
drivers/staging/vt6655/device_main.c | 2 +-
3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index 1cdcf49..e00c060 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -362,12 +362,16 @@ bool CARDbSetPhyParameter(struct vnt_private *pDevice, u8 bb_type)
* Return Value: none
*/
bool CARDbUpdateTSF(struct vnt_private *pDevice, unsigned char byRxRate,
- u64 qwBSSTimestamp, u64 qwLocalTSF)
+ u64 qwBSSTimestamp)
{
+ u64 local_tsf;
u64 qwTSFOffset = 0;

- if (qwBSSTimestamp != qwLocalTSF) {
- qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF);
+ CARDbGetCurrentTSF(pDevice, &local_tsf);
+
+ if (qwBSSTimestamp != local_tsf) {
+ qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp,
+ local_tsf);
/* adjust TSF, HW's TSF add TSF Offset reg */
VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST, (u32)qwTSFOffset);
VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST + 4, (u32)(qwTSFOffset >> 32));
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
index 2dfc419..16cca49 100644
--- a/drivers/staging/vt6655/card.h
+++ b/drivers/staging/vt6655/card.h
@@ -83,7 +83,7 @@ bool CARDbRadioPowerOff(struct vnt_private *);
bool CARDbRadioPowerOn(struct vnt_private *);
bool CARDbSetPhyParameter(struct vnt_private *, u8);
bool CARDbUpdateTSF(struct vnt_private *, unsigned char byRxRate,
- u64 qwBSSTimestamp, u64 qwLocalTSF);
+ u64 qwBSSTimestamp);
bool CARDbSetBeaconPeriod(struct vnt_private *, unsigned short wBeaconInterval);

#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index ed90b6f..26a6f67 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1473,7 +1473,7 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) {
if (conf->assoc) {
CARDbUpdateTSF(priv, conf->beacon_rate->hw_value,
- conf->sync_device_ts, conf->sync_tsf);
+ conf->sync_tsf);

CARDbSetBeaconPeriod(priv, conf->beacon_int);

--
2.1.4


2015-04-21 21:33:30

by Malcolm Priestley

[permalink] [raw]
Subject: [PATCH 3/3] staging: vt6655: lock MACvWriteBSSIDAddress.

This function selects page 1 and cause intermittent problems on
interrupt handler.

lock call with spin_lock_irqsave.

Signed-off-by: Malcolm Priestley <[email protected]>
Cc: <[email protected]> # v3.19+
---
drivers/staging/vt6655/device_main.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 26a6f67..8f96cc9 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1412,9 +1412,16 @@ static void vnt_bss_info_changed(struct ieee80211_hw *hw,

priv->current_aid = conf->aid;

- if (changed & BSS_CHANGED_BSSID)
+ if (changed & BSS_CHANGED_BSSID) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid);

+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
if (changed & BSS_CHANGED_BASIC_RATES) {
priv->basic_rates = conf->basic_rates;

--
2.1.4