Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Feb 2015 17:45:54 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278764 - head/sys/dev/wpi
Message-ID:  <201502141745.t1EHjs3a079624@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sat Feb 14 17:45:53 2015
New Revision: 278764
URL: https://svnweb.freebsd.org/changeset/base/278764

Log:
  More fixes to wpi(4), again not by me! Woo!
  
  - Use IEEE80211_F_DATAPAD;
  - (c->ic_flags & IEEE80211_CHAN_PASSIVE) -> IEEE80211_IS_CHAN_PASSIVE(c);
  - Convert ackfailcnt to int (there is dereference to *(int *) in ieee80211_ratectl_tx_complete());
  - Fix & move cleanup to the end in wpi_rx_done();
  - Add missed lock in wpi_update_beacon();
  - Try to fix powersave.
  
  PR:		kern/197143
  Submitted by:	 Andriy Voskoboinyk <s3erios@gmail.com>

Modified:
  head/sys/dev/wpi/if_wpi.c
  head/sys/dev/wpi/if_wpireg.h

Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c	Sat Feb 14 17:44:24 2015	(r278763)
+++ head/sys/dev/wpi/if_wpi.c	Sat Feb 14 17:45:53 2015	(r278764)
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
  *
  * A similar thing happens with the tx rings. The difference is the firmware
  * stop processing buffers once the queue is full and until confirmation
- * of a successful transmition (tx_intr) has occurred.
+ * of a successful transmition (tx_done) has occurred.
  *
  * The command ring operates in the same manner as the tx queues.
  *
@@ -447,6 +447,8 @@ wpi_attach(device_t dev)
 	ic->ic_cryptocaps =
 		  IEEE80211_CRYPTO_AES_CCM;
 
+	ic->ic_flags |= IEEE80211_F_DATAPAD;
+
 	/*
 	 * Read in the eeprom and also setup the channels for
 	 * net80211. We don't set the rates as net80211 does this for us
@@ -1378,8 +1380,7 @@ wpi_read_eeprom_band(struct wpi_softc *s
 		    "adding chan %d (%dMHz) flags=0x%x maxpwr=%d passive=%d,"
 		    " offset %d\n", chan, c->ic_freq,
 		    channels[i].flags, sc->maxpwr[chan],
-		    (c->ic_flags & IEEE80211_CHAN_PASSIVE) != 0,
-		    ic->ic_nchans);
+		    IEEE80211_IS_CHAN_PASSIVE(c), ic->ic_nchans);
 	}
 }
 
@@ -1695,8 +1696,7 @@ wpi_rx_done(struct wpi_softc *sc, struct
 
 	if (stat->len > WPI_STAT_MAXLEN) {
 		device_printf(sc->sc_dev, "invalid RX statistic header\n");
-		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-		return;
+		goto fail1;
 	}
 
 	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
@@ -1714,23 +1714,20 @@ wpi_rx_done(struct wpi_softc *sc, struct
 	if ((flags & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
 		DPRINTF(sc, WPI_DEBUG_RECV, "%s: RX flags error %x\n",
 		    __func__, flags);
-		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-		return;
+		goto fail1;
 	}
 	/* Discard frames that are too short. */
 	if (len < sizeof (*wh)) {
 		DPRINTF(sc, WPI_DEBUG_RECV, "%s: frame too short: %d\n",
 		    __func__, len);
-		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-		return;
+		goto fail1;
 	}
 
 	m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
 	if (m1 == NULL) {
 		DPRINTF(sc, WPI_DEBUG_ANY, "%s: no mbuf to restock ring\n",
 		    __func__);
-		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-		return;
+		goto fail1;
 	}
 	bus_dmamap_unload(ring->data_dmat, data->map);
 
@@ -1752,8 +1749,7 @@ wpi_rx_done(struct wpi_softc *sc, struct
 		ring->desc[ring->cur] = htole32(paddr);
 		bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
 		    BUS_DMASYNC_PREWRITE);
-		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-		return;
+		goto fail1;
 	}
 
 	m = data->m;
@@ -1777,18 +1773,14 @@ wpi_rx_done(struct wpi_softc *sc, struct
 	if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
 	    !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
 	    cip != NULL && cip->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
-		if ((flags & WPI_RX_CIPHER_MASK) != WPI_RX_CIPHER_CCMP) {
-			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-			m_freem(m);
-			return;
-		}
+		if ((flags & WPI_RX_CIPHER_MASK) != WPI_RX_CIPHER_CCMP)
+			goto fail2;
+
 		/* Check whether decryption was successful or not. */
 		if ((flags & WPI_RX_DECRYPT_MASK) != WPI_RX_DECRYPT_OK) {
 			DPRINTF(sc, WPI_DEBUG_RECV,
 			    "CCMP decryption failed 0x%x\n", flags);
-			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-			m_freem(m);
-			return;
+			goto fail2;
 		}
 		m->m_flags |= M_WEP;
 	}
@@ -1817,6 +1809,13 @@ wpi_rx_done(struct wpi_softc *sc, struct
 		(void)ieee80211_input_all(ic, m, stat->rssi, -WPI_RSSI_OFFSET);
 
 	WPI_LOCK(sc);
+
+	return;
+
+fail2:	ieee80211_free_node(ni);
+	m_freem(m);
+
+fail1:	if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
 }
 
 static void
@@ -1836,6 +1835,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
 	struct mbuf *m;
 	struct ieee80211_node *ni;
 	struct ieee80211vap *vap;
+	int ackfailcnt = stat->ackfailcnt;
 	int status = le32toh(stat->status);
 
 	KASSERT(data->ni != NULL, ("no node"));
@@ -1844,7 +1844,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
 
 	DPRINTF(sc, WPI_DEBUG_XMIT, "%s: "
 	    "qid %d idx %d retries %d btkillcnt %d rate %x duration %d "
-	    "status %x\n", __func__, desc->qid, desc->idx, stat->ackfailcnt,
+	    "status %x\n", __func__, desc->qid, desc->idx, ackfailcnt,
 	    stat->btkillcnt, stat->rate, le32toh(stat->duration), status);
 
 	/* Unmap and free mbuf. */
@@ -1861,11 +1861,11 @@ wpi_tx_done(struct wpi_softc *sc, struct
 	if ((status & 0xff) != 1) {
 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		ieee80211_ratectl_tx_complete(vap, ni,
-		    IEEE80211_RATECTL_TX_FAILURE, &stat->ackfailcnt, NULL);
+		    IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
 	} else {
 		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
 		ieee80211_ratectl_tx_complete(vap, ni,
-		    IEEE80211_RATECTL_TX_SUCCESS, &stat->ackfailcnt, NULL);
+		    IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
 	}
 
 	ieee80211_tx_complete(ni, m, (status & 0xff) != 1);
@@ -1931,10 +1931,7 @@ wpi_notif_intr(struct wpi_softc *sc)
 	hw = le32toh(sc->shared->next);
 	hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
 
-	if (sc->rxq.cur == hw)
-		return;
-
-	do {
+	while (sc->rxq.cur != hw) {
 		sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
 
 		struct wpi_rx_data *data = &sc->rxq.data[sc->rxq.cur];
@@ -2020,10 +2017,10 @@ wpi_notif_intr(struct wpi_softc *sc)
                             BUS_DMASYNC_POSTREAD);
 
 			uint32_t *status = (uint32_t *)(desc + 1);
-#ifdef WPI_DEBUG
+
 			DPRINTF(sc, WPI_DEBUG_STATE, "state changed to %x\n",
 			    le32toh(*status));
-#endif
+
 			if (le32toh(*status) & 1) {
 				ieee80211_runtask(ic, &sc->sc_radiooff_task);
 				return;
@@ -2061,7 +2058,7 @@ wpi_notif_intr(struct wpi_softc *sc)
 			break;
 		}
 		}
-	} while (sc->rxq.cur != hw);
+	}
 
 	/* Tell the firmware what we have processed. */
 	wpi_update_rx_ring(sc);
@@ -2081,15 +2078,15 @@ wpi_wakeup_intr(struct wpi_softc *sc)
 
 	/* Wakeup RX and TX rings. */
 	if (sc->rxq.update) {
-		wpi_update_rx_ring(sc);
 		sc->rxq.update = 0;
+		wpi_update_rx_ring(sc);
 	}
 	for (qid = 0; qid < WPI_NTXQUEUES; qid++) {
 		struct wpi_tx_ring *ring = &sc->txq[qid];
 
 		if (ring->update) {
-			wpi_update_tx_ring(sc, ring);
 			ring->update = 0;
+			wpi_update_tx_ring(sc, ring);
 		}
 	}
 
@@ -2227,6 +2224,8 @@ done:
 static int
 wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
 {
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ieee80211_frame *wh;
 	struct wpi_tx_cmd *cmd;
 	struct wpi_tx_data *data;
@@ -2234,23 +2233,16 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 	struct wpi_tx_ring *ring;
 	struct mbuf *m1;
 	bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER];
-	u_int hdrlen;
-	int error, i, nsegs, pad, totlen;
+	int error, i, hdrspace, nsegs, totlen;
 
 	WPI_LOCK_ASSERT(sc);
 
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
 
 	wh = mtod(buf->m, struct ieee80211_frame *);
-	hdrlen = ieee80211_anyhdrsize(wh);
+	hdrspace = ieee80211_anyhdrspace(ic, wh);
 	totlen = buf->m->m_pkthdr.len;
 
-	if (hdrlen & 3) {
-		/* First segment length must be a multiple of 4. */
-		pad = 4 - (hdrlen & 3);
-	} else
-		pad = 0;
-
 	ring = &sc->txq[buf->ac];
 	desc = &ring->desc[ring->cur];
 	data = &ring->data[ring->cur];
@@ -2265,8 +2257,8 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 	memcpy(cmd->data, buf->data, buf->size);
 
 	/* Save and trim IEEE802.11 header. */
-	memcpy((uint8_t *)(cmd->data + buf->size), wh, hdrlen);
-	m_adj(buf->m, hdrlen);
+	memcpy((uint8_t *)(cmd->data + buf->size), wh, hdrspace);
+	m_adj(buf->m, hdrspace);
 
 	error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, buf->m,
 	    segs, &nsegs, BUS_DMA_NOWAIT);
@@ -2304,10 +2296,10 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 	    __func__, ring->qid, ring->cur, totlen, nsegs);
 
 	/* Fill TX descriptor. */
-	desc->nsegs = WPI_PAD32(totlen + pad) << 4 | (1 + nsegs);
+	desc->nsegs = WPI_PAD32(totlen) << 4 | (1 + nsegs);
 	/* First DMA segment is used by the TX command. */
 	desc->segs[0].addr = htole32(data->cmd_paddr);
-	desc->segs[0].len  = htole32(4 + buf->size + hdrlen + pad);
+	desc->segs[0].len  = htole32(4 + buf->size + hdrspace);
 	/* Other DMA segments are for data payload. */
 	seg = &segs[0];
 	for (i = 1; i <= nsegs; i++) {
@@ -2353,9 +2345,10 @@ wpi_tx_data(struct wpi_softc *sc, struct
 	uint32_t flags;
 	uint16_t qos;
 	uint8_t tid, type;
-	int ac, error, rate, ismcast, totlen;
+	int ac, error, rate, ismcast, hdrlen, totlen;
 
 	wh = mtod(m, struct ieee80211_frame *);
+	hdrlen = ieee80211_anyhdrsize(wh);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
 
@@ -2399,12 +2392,12 @@ wpi_tx_data(struct wpi_softc *sc, struct
 		/* 802.11 header may have moved. */
 		wh = mtod(m, struct ieee80211_frame *);
 	}
-	totlen = m->m_pkthdr.len;
+	totlen = m->m_pkthdr.len - (hdrlen & 3);
 
 	if (ieee80211_radiotap_active_vap(vap)) {
 		struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
 
-		tap->wt_flags = 0;
+		tap->wt_flags = IEEE80211_RADIOTAP_F_DATAPAD;
 		tap->wt_rate = rate;
 		if (k != NULL)
 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
@@ -2420,6 +2413,9 @@ wpi_tx_data(struct wpi_softc *sc, struct
 			flags |= WPI_TX_NEED_ACK;
 	}
 
+	if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)
+		flags |= WPI_TX_MORE_FRAG;	/* Cannot happen yet. */
+
 	/* Check if frame must be protected using RTS/CTS or CTS-to-self. */
 	if (!ismcast) {
 		/* NB: Group frames are sent using CCK in 802.11b/g. */
@@ -2518,11 +2514,12 @@ wpi_tx_data_raw(struct wpi_softc *sc, st
 	struct wpi_buf tx_data;
 	uint32_t flags;
 	uint8_t type;
-	int ac, rate, totlen;
+	int ac, rate, hdrlen, totlen;
 
 	wh = mtod(m, struct ieee80211_frame *);
+	hdrlen = ieee80211_anyhdrsize(wh);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
-	totlen = m->m_pkthdr.len;
+	totlen = m->m_pkthdr.len - (hdrlen & 3);
 
 	ac = params->ibp_pri & 3;
 
@@ -2544,6 +2541,8 @@ wpi_tx_data_raw(struct wpi_softc *sc, st
 
 		tap->wt_flags = 0;
 		tap->wt_rate = rate;
+		if (params->ibp_flags & IEEE80211_BPF_DATAPAD)
+			tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD;
 
 		ieee80211_radiotap_tx(vap, m);
 	}
@@ -3434,31 +3433,28 @@ wpi_config(struct wpi_softc *sc)
 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
 		sc->rxon.flags |= htole32(WPI_RXON_AUTO | WPI_RXON_24GHZ);
 
+	sc->rxon.filter = WPI_FILTER_MULTICAST;
 	switch (ic->ic_opmode) {
 	case IEEE80211_M_STA:
 		sc->rxon.mode = WPI_MODE_STA;
-		sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
 		break;
 	case IEEE80211_M_IBSS:
 		sc->rxon.mode = WPI_MODE_IBSS;
-		sc->rxon.filter = htole32(WPI_FILTER_BEACON |
-		    WPI_FILTER_MULTICAST);
+		sc->rxon.filter |= WPI_FILTER_BEACON;
 		break;
 	/* XXX workaround for passive channels selection */
 	case IEEE80211_M_AHDEMO:
-		sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
-		/* FALLTHROUGH */
 	case IEEE80211_M_HOSTAP:
 		sc->rxon.mode = WPI_MODE_HOSTAP;
 		break;
 	case IEEE80211_M_MONITOR:
 		sc->rxon.mode = WPI_MODE_MONITOR;
-		sc->rxon.filter = htole32(WPI_FILTER_MULTICAST);
 		break;
 	default:
 		device_printf(sc->sc_dev, "unknown opmode %d\n", ic->ic_opmode);
 		return EINVAL;
 	}
+	sc->rxon.filter = htole32(sc->rxon.filter);
 	wpi_set_promisc(sc);
 	sc->rxon.cck_mask  = 0x0f;	/* not yet negotiated */
 	sc->rxon.ofdm_mask = 0xff;	/* not yet negotiated */
@@ -3677,7 +3673,7 @@ wpi_scan(struct wpi_softc *sc, struct ie
 	} else
 		hdr->crc_threshold = WPI_SCAN_CRC_TH_NEVER;
 
-	if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE))
+	if (!IEEE80211_IS_CHAN_PASSIVE(c))
 		chan->flags |= WPI_CHAN_ACTIVE;
 
 	/*
@@ -3702,7 +3698,7 @@ wpi_scan(struct wpi_softc *sc, struct ie
 		chan->rf_gain = 0x28;
 
 	DPRINTF(sc, WPI_DEBUG_SCAN, "Scanning %u Passive: %d\n",
-	     chan->chan, (c->ic_flags & IEEE80211_CHAN_PASSIVE) ? 1 : 0);
+	     chan->chan, IEEE80211_IS_CHAN_PASSIVE(c));
 
 	hdr->nchan++;
 	chan++;
@@ -3838,11 +3834,13 @@ wpi_update_beacon(struct ieee80211vap *v
 	struct wpi_softc *sc = ifp->if_softc;
 	int error;
 
+	WPI_LOCK(sc);
 	if ((error = wpi_setup_beacon(sc, ni)) != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not update beacon frame, error %d", __func__,
 		    error);
 	}
+	WPI_UNLOCK(sc);
 }
 
 static int
@@ -3939,6 +3937,8 @@ wpi_run(struct wpi_softc *sc, struct iee
 	/* Enable power-saving mode if requested by user. */
 	if (vap->iv_flags & IEEE80211_F_PMGTON)
 		(void)wpi_set_pslevel(sc, 0, 3, 1);
+	else
+		(void)wpi_set_pslevel(sc, 0, 0, 1);
 
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 
@@ -4384,6 +4384,8 @@ wpi_apm_init(struct wpi_softc *sc)
 	DELAY(20);
 	/* Disable L1-Active. */
 	wpi_prph_setbits(sc, WPI_APMG_PCI_STT, WPI_APMG_PCI_STT_L1A_DIS);
+	/* ??? */
+	wpi_prph_clrbits(sc, WPI_APMG_PS, 0x00000E00);
 	wpi_nic_unlock(sc);
 
 	return 0;

Modified: head/sys/dev/wpi/if_wpireg.h
==============================================================================
--- head/sys/dev/wpi/if_wpireg.h	Sat Feb 14 17:44:24 2015	(r278763)
+++ head/sys/dev/wpi/if_wpireg.h	Sat Feb 14 17:45:53 2015	(r278764)
@@ -470,6 +470,7 @@ struct wpi_cmd_data {
 #define WPI_TX_FULL_TXOP	(1 <<  7)
 #define WPI_TX_BT_DISABLE	(1 << 12) 	/* bluetooth coexistence */
 #define WPI_TX_AUTO_SEQ		(1 << 13)
+#define WPI_TX_MORE_FRAG	(1 << 14)
 #define WPI_TX_INSERT_TSTAMP	(1 << 16)
 
 	uint8_t		plcp;
@@ -964,11 +965,6 @@ static const char * const wpi_fw_errmsg[
 	"FATAL_ERROR"
 };
 
-/* XXX description for some error codes (error data). */
-/* 0x00000074 - wrong totlen field */
-/* 0x000003B3 - powersave error */
-/* 0x00000447 - wrong channel selected */
-
 #define WPI_READ(sc, reg)						\
 	bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502141745.t1EHjs3a079624>