svn commit: r282999 - head/sys/dev/iwn

Adrian Chadd adrian at FreeBSD.org
Sat May 16 05:59:26 UTC 2015


Author: adrian
Date: Sat May 16 05:59:25 2015
New Revision: 282999
URL: https://svnweb.freebsd.org/changeset/base/282999

Log:
  Various iwn(4) fixes.
  
  * simplify channel logic for determining RF gain setting in scan setup
  * don't set TX timer on error
  * free node references for unsent frames on device stop
  * set maxfrags to IWN_MAX_SCATTER-1 (first segment is used by TX command)
  * add missing IWN_UNLOCK() from interrupt path when the hardware
    disappears.
  * pass control frames to host
  * nitems() instead of local macro
  
  Tested:
  
  * Intel 5100, STA mode
  
  PR:		kern/196264
  Submitted by:	Andriy Voskoboinyk <s3erios at gmail.com>

Modified:
  head/sys/dev/iwn/if_iwn.c

Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c	Sat May 16 05:43:20 2015	(r282998)
+++ head/sys/dev/iwn/if_iwn.c	Sat May 16 05:59:25 2015	(r282999)
@@ -1875,7 +1875,7 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, 
 		    &paddr, BUS_DMA_NOWAIT);
 		if (error != 0 && error != EFBIG) {
 			device_printf(sc->sc_dev,
-			    "%s: can't not map mbuf, error %d\n", __func__,
+			    "%s: can't map mbuf, error %d\n", __func__,
 			    error);
 			goto fail;
 		}
@@ -2036,6 +2036,10 @@ iwn_reset_tx_ring(struct iwn_softc *sc, 
 			m_freem(data->m);
 			data->m = NULL;
 		}
+		if (data->ni != NULL) {
+			ieee80211_free_node(data->ni);
+			data->ni = NULL;
+		}
 	}
 	/* Clear TX descriptors. */
 	memset(ring->desc, 0, ring->desc_dma.size);
@@ -2969,7 +2973,7 @@ iwn_rx_done(struct iwn_softc *sc, struct
 		return;
 	}
 	/* Discard frames that are too short. */
-	if (len < sizeof (*wh)) {
+	if (len < sizeof (struct ieee80211_frame_ack)) {
 		DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n",
 		    __func__, len);
 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
@@ -3021,7 +3025,10 @@ iwn_rx_done(struct iwn_softc *sc, struct
 
 	/* Grab a reference to the source node. */
 	wh = mtod(m, struct ieee80211_frame *);
-	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+	if (len >= sizeof(struct ieee80211_frame_min))
+		ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+	else
+		ni = NULL;
 	nf = (ni != NULL && ni->ni_vap->iv_state == IEEE80211_S_RUN &&
 	    (ic->ic_flags & IEEE80211_F_SCAN) == 0) ? sc->noise : -95;
 
@@ -4047,8 +4054,10 @@ iwn_intr(void *arg)
 		r2 = 0;	/* Unused. */
 	} else {
 		r1 = IWN_READ(sc, IWN_INT);
-		if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
+		if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0) {
+			IWN_UNLOCK(sc);
 			return;	/* Hardware gone! */
+		}
 		r2 = IWN_READ(sc, IWN_FH_INT);
 	}
 
@@ -4519,7 +4528,7 @@ iwn_tx_data(struct iwn_softc *sc, struct
 			return error;
 		}
 		/* Too many DMA segments, linearize mbuf. */
-		m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER);
+		m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER - 1);
 		if (m1 == NULL) {
 			device_printf(sc->sc_dev,
 			    "%s: could not defrag mbuf\n", __func__);
@@ -4725,7 +4734,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 			return error;
 		}
 		/* Too many DMA segments, linearize mbuf. */
-		m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER);
+		m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER - 1);
 		if (m1 == NULL) {
 			device_printf(sc->sc_dev,
 			    "%s: could not defrag mbuf\n", __func__);
@@ -4825,8 +4834,8 @@ iwn_raw_xmit(struct ieee80211_node *ni, 
 		/* NB: m is reclaimed on tx failure */
 		ieee80211_free_node(ni);
 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-	}
-	sc->sc_tx_timer = 5;
+	} else
+		sc->sc_tx_timer = 5;
 
 	IWN_UNLOCK(sc);
 
@@ -4872,9 +4881,8 @@ iwn_start_locked(struct ifnet *ifp)
 		if (iwn_tx_data(sc, m, ni) != 0) {
 			ieee80211_free_node(ni);
 			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-			continue;
-		}
-		sc->sc_tx_timer = 5;
+		} else
+			sc->sc_tx_timer = 5;
 	}
 
 	DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__);
@@ -4950,7 +4958,6 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd,
 		IWN_LOCK(sc);
 		memset(&sc->last_stat, 0, sizeof(struct iwn_stats));
 		IWN_UNLOCK(sc);
-		error = 0;
 		break;
 	default:
 		error = EINVAL;
@@ -6818,16 +6825,10 @@ iwn_scan(struct iwn_softc *sc, struct ie
 	chan->active = htole16(dwell_active);
 	chan->passive = htole16(dwell_passive);
 
-	if (IEEE80211_IS_CHAN_5GHZ(c) &&
-	    !(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
-		chan->rf_gain = 0x3b;
-	} else if (IEEE80211_IS_CHAN_5GHZ(c)) {
+	if (IEEE80211_IS_CHAN_5GHZ(c))
 		chan->rf_gain = 0x3b;
-	} else if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
-		chan->rf_gain = 0x28;
-	} else {
+	else
 		chan->rf_gain = 0x28;
-	}
 
 	DPRINTF(sc, IWN_DEBUG_STATE,
 	    "%s: chan %u flags 0x%x rf_gain 0x%x "
@@ -8809,7 +8810,6 @@ iwn_hw_reset(void *arg0, int pending)
 }
 #ifdef	IWN_DEBUG
 #define	IWN_DESC(x) case x:	return #x
-#define	COUNTOF(array) (sizeof(array) / sizeof(array[0]))
 
 /*
  * Translate CSR code to string
@@ -8880,7 +8880,7 @@ iwn_debug_register(struct iwn_softc *sc)
 	DPRINTF(sc, IWN_DEBUG_REGISTER,
 	    "CSR values: (2nd byte of IWN_INT_COALESCING is IWN_INT_PERIODIC)%s",
 	    "\n");
-	for (i = 0; i <  COUNTOF(csr_tbl); i++){
+	for (i = 0; i <  nitems(csr_tbl); i++){
 		DPRINTF(sc, IWN_DEBUG_REGISTER,"  %10s: 0x%08x ",
 			iwn_get_csr_string(csr_tbl[i]), IWN_READ(sc, csr_tbl[i]));
 		if ((i+1) % 3 == 0)


More information about the svn-src-all mailing list