Skip to contentSkip to conversation

staging: vt6655: vnt_tx_packet Correct TX order of OWNED_BY_NIC

PATCH New Malcolm Priestley 1 participant 3 messages Apr 21, 2015 Staging

lore
Share & tools
lore
#0 lore raw

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

---
 drivers/staging/vt6655/device_main.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
drivers/staging/vt6655/device_main.c +7 -8
index c5f8233..ed90b6f 100644
@@ -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;
Signature · 1 line
2.1.4
#1 lore raw

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.

---
 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(-)
drivers/staging/vt6655/card.c +7 -3
index 1cdcf49..e00c060 100644
@@ -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));
drivers/staging/vt6655/card.h +1 -1
index 2dfc419..16cca49 100644
@@ -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__ */
drivers/staging/vt6655/device_main.c +1 -1
index ed90b6f..26a6f67 100644
@@ -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);
 
Signature · 1 line
2.1.4
#2 lore raw

PATCH 3/3 staging: vt6655: lock MACvWriteBSSIDAddress.

In reply to Malcolm Priestley

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

lock call with spin_lock_irqsave.

---
 drivers/staging/vt6655/device_main.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/staging/vt6655/device_main.c +8 -1
index 26a6f67..8f96cc9 100644
@@ -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;
 
Signature · 1 line
2.1.4