Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Mar 2017 09:41:08 +0000 (UTC)
From:      Andriy Voskoboinyk <avos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315982 - head/sys/dev/iwn
Message-ID:  <201703260941.v2Q9f8hh094173@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avos
Date: Sun Mar 26 09:41:08 2017
New Revision: 315982
URL: https://svnweb.freebsd.org/changeset/base/315982

Log:
  iwn: deduplicate code in iwn_tx_data() and iwn_tx_data_raw().
  
  Some code was additionally moved for (future) lock splitting.
  
  Tested with Intel 6205, STA mode.
  
  Differential Revision:	https://reviews.freebsd.org/D10106

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

Modified: head/sys/dev/iwn/if_iwn.c
==============================================================================
--- head/sys/dev/iwn/if_iwn.c	Sun Mar 26 09:10:01 2017	(r315981)
+++ head/sys/dev/iwn/if_iwn.c	Sun Mar 26 09:41:08 2017	(r315982)
@@ -232,6 +232,8 @@ static int	iwn_tx_data(struct iwn_softc 
 static int	iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
 		    struct ieee80211_node *,
 		    const struct ieee80211_bpf_params *params);
+static int	iwn_tx_cmd(struct iwn_softc *, struct mbuf *,
+		    struct ieee80211_node *, struct iwn_tx_ring *);
 static void	iwn_xmit_task(void *arg0, int pending);
 static int	iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
 		    const struct ieee80211_bpf_params *);
@@ -4392,32 +4394,25 @@ iwn_tx_rate_to_linkq_offset(struct iwn_s
 static int
 iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 {
-	struct iwn_ops *ops = &sc->ops;
 	const struct ieee80211_txparam *tp = ni->ni_txparms;
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct iwn_node *wn = (void *)ni;
 	struct iwn_tx_ring *ring;
-	struct iwn_tx_desc *desc;
-	struct iwn_tx_data *data;
 	struct iwn_tx_cmd *cmd;
 	struct iwn_cmd_data *tx;
 	struct ieee80211_frame *wh;
 	struct ieee80211_key *k = NULL;
-	struct mbuf *m1;
 	uint32_t flags;
-	uint16_t qos;
-	u_int hdrlen;
-	bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
+	uint16_t seqno, qos;
 	uint8_t tid, type;
-	int ac, i, totlen, error, pad, nsegs = 0, rate;
+	int ac, totlen, rate;
 
 	DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
 
 	IWN_LOCK_ASSERT(sc);
 
 	wh = mtod(m, struct ieee80211_frame *);
-	hdrlen = ieee80211_anyhdrsize(wh);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
 
 	/* Select EDCA Access Category and TX ring for this frame. */
@@ -4428,7 +4423,21 @@ iwn_tx_data(struct iwn_softc *sc, struct
 		qos = 0;
 		tid = 0;
 	}
-	ac = M_WME_GETAC(m);
+
+	/* Choose a TX rate index. */
+	if (type == IEEE80211_FC0_TYPE_MGT ||
+	    type == IEEE80211_FC0_TYPE_CTL ||
+	    (m->m_flags & M_EAPOL) != 0)
+		rate = tp->mgmtrate;
+	else if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+		rate = tp->mcastrate;
+	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
+		rate = tp->ucastrate;
+	else {
+		/* XXX pass pktlen */
+		(void) ieee80211_ratectl_rate(ni, NULL, 0);
+		rate = ni->ni_txrate;
+	}
 
 	/*
 	 * XXX TODO: Group addressed frames aren't aggregated and must
@@ -4436,12 +4445,13 @@ iwn_tx_data(struct iwn_softc *sc, struct
 	 * assigned from net80211.
 	 */
 
+	ac = M_WME_GETAC(m);
+	seqno = ni->ni_txseqs[tid];
 	if (m->m_flags & M_AMPDU_MPDU) {
-		uint16_t seqno;
 		struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
 
 		if (!IEEE80211_AMPDU_RUNNING(tap)) {
-			return EINVAL;
+			return (EINVAL);
 		}
 
 		/*
@@ -4452,39 +4462,10 @@ iwn_tx_data(struct iwn_softc *sc, struct
 		 * being used!
 		 */
 		ac = *(int *)tap->txa_private;
-		seqno = ni->ni_txseqs[tid];
 		*(uint16_t *)wh->i_seq =
 		    htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
-		ring = &sc->txq[ac];
-		if ((seqno % 256) != ring->cur) {
-			device_printf(sc->sc_dev,
-			    "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n",
-			    __func__,
-			    m,
-			    seqno,
-			    seqno % 256,
-			    ring->cur);
-		}
 		ni->ni_txseqs[tid]++;
 	}
-	ring = &sc->txq[ac];
-	desc = &ring->desc[ring->cur];
-	data = &ring->data[ring->cur];
-
-	/* Choose a TX rate index. */
-	if (type == IEEE80211_FC0_TYPE_MGT ||
-	    type == IEEE80211_FC0_TYPE_CTL ||
-	    (m->m_flags & M_EAPOL) != 0)
-		rate = tp->mgmtrate;
-	else if (IEEE80211_IS_MULTICAST(wh->i_addr1))
-		rate = tp->mcastrate;
-	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
-		rate = tp->ucastrate;
-	else {
-		/* XXX pass pktlen */
-		(void) ieee80211_ratectl_rate(ni, NULL, 0);
-		rate = ni->ni_txrate;
-	}
 
 	/* Encrypt the frame if need be. */
 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
@@ -4509,17 +4490,6 @@ iwn_tx_data(struct iwn_softc *sc, struct
 		ieee80211_radiotap_tx(vap, m);
 	}
 
-	/* Prepare TX firmware command. */
-	cmd = &ring->cmd[ring->cur];
-	cmd->code = IWN_CMD_TX_DATA;
-	cmd->flags = 0;
-	cmd->qid = ring->qid;
-	cmd->idx = ring->cur;
-
-	tx = (struct iwn_cmd_data *)cmd->data;
-	/* NB: No need to clear tx, all fields are reinitialized here. */
-	tx->scratch = 0;	/* clear "scratch" area */
-
 	flags = 0;
 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 		/* Unicast frame, check if an ACK is expected. */
@@ -4562,6 +4532,25 @@ iwn_tx_data(struct iwn_softc *sc, struct
 		}
 	}
 
+	ring = &sc->txq[ac];
+	if ((m->m_flags & M_AMPDU_MPDU) != 0 &&
+	    (seqno % 256) != ring->cur) {
+		device_printf(sc->sc_dev,
+		    "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n",
+		    __func__,
+		    m,
+		    seqno,
+		    seqno % 256,
+		    ring->cur);
+	}
+
+	/* Prepare TX firmware command. */
+	cmd = &ring->cmd[ring->cur];
+	tx = (struct iwn_cmd_data *)cmd->data;
+
+	/* NB: No need to clear tx, all fields are reinitialized here. */
+	tx->scratch = 0;	/* clear "scratch" area */
+
 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
 	    type != IEEE80211_FC0_TYPE_DATA)
 		tx->id = sc->broadcast_id;
@@ -4582,19 +4571,6 @@ iwn_tx_data(struct iwn_softc *sc, struct
 	} else
 		tx->timeout = htole16(0);
 
-	if (hdrlen & 3) {
-		/* First segment length must be a multiple of 4. */
-		flags |= IWN_TX_NEED_PADDING;
-		pad = 4 - (hdrlen & 3);
-	} else
-		pad = 0;
-
-	tx->len = htole16(totlen);
-	tx->tid = tid;
-	tx->rts_ntries = 60;
-	tx->data_ntries = 15;
-	tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
-	tx->rate = iwn_rate_to_plcp(sc, ni, rate);
 	if (tx->id == sc->broadcast_id) {
 		/* Group or management frame. */
 		tx->linkq = 0;
@@ -4603,115 +4579,28 @@ iwn_tx_data(struct iwn_softc *sc, struct
 		flags |= IWN_TX_LINKQ;	/* enable MRR */
 	}
 
-	/* Set physical address of "scratch area". */
-	tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
-	tx->hiaddr = IWN_HIADDR(data->scratch_paddr);
-
-	/* Copy 802.11 header in TX command. */
-	memcpy((uint8_t *)(tx + 1), wh, hdrlen);
-
-	/* Trim 802.11 header. */
-	m_adj(m, hdrlen);
+	tx->tid = tid;
+	tx->rts_ntries = 60;
+	tx->data_ntries = 15;
+	tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
+	tx->rate = iwn_rate_to_plcp(sc, ni, rate);
 	tx->security = 0;
 	tx->flags = htole32(flags);
 
-	error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs,
-	    &nsegs, BUS_DMA_NOWAIT);
-	if (error != 0) {
-		if (error != EFBIG) {
-			device_printf(sc->sc_dev,
-			    "%s: can't map mbuf (error %d)\n", __func__, error);
-			return error;
-		}
-		/* Too many DMA segments, linearize mbuf. */
-		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__);
-			return ENOBUFS;
-		}
-		m = m1;
-
-		error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m,
-		    segs, &nsegs, BUS_DMA_NOWAIT);
-		if (error != 0) {
-			device_printf(sc->sc_dev,
-			    "%s: can't map mbuf (error %d)\n", __func__, error);
-			return error;
-		}
-	}
-
-	data->m = m;
-	data->ni = ni;
-
-	DPRINTF(sc, IWN_DEBUG_XMIT,
-	    "%s: qid %d idx %d len %d nsegs %d flags 0x%08x rate 0x%04x plcp 0x%08x\n",
-	    __func__,
-	    ring->qid,
-	    ring->cur,
-	    m->m_pkthdr.len,
-	    nsegs,
-	    flags,
-	    rate,
-	    tx->rate);
-
-	/* Fill TX descriptor. */
-	desc->nsegs = 1;
-	if (m->m_len != 0)
-		desc->nsegs += nsegs;
-	/* First DMA segment is used by the TX command. */
-	desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr));
-	desc->segs[0].len  = htole16(IWN_HIADDR(data->cmd_paddr) |
-	    (4 + sizeof (*tx) + hdrlen + pad) << 4);
-	/* Other DMA segments are for data payload. */
-	seg = &segs[0];
-	for (i = 1; i <= nsegs; i++) {
-		desc->segs[i].addr = htole32(IWN_LOADDR(seg->ds_addr));
-		desc->segs[i].len  = htole16(IWN_HIADDR(seg->ds_addr) |
-		    seg->ds_len << 4);
-		seg++;
-	}
-
-	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
-	bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map,
-	    BUS_DMASYNC_PREWRITE);
-	bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
-	    BUS_DMASYNC_PREWRITE);
-
-	/* Update TX scheduler. */
-	if (ring->qid >= sc->firstaggqueue)
-		ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen);
-
-	/* Kick TX ring. */
-	ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
-	IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
-
-	/* Mark TX ring as full if we reach a certain threshold. */
-	if (++ring->queued > IWN_TX_RING_HIMARK)
-		sc->qfullmsk |= 1 << ring->qid;
-
-	DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
-
-	return 0;
+	return (iwn_tx_cmd(sc, m, ni, ring));
 }
 
 static int
 iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
     struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
 {
-	struct iwn_ops *ops = &sc->ops;
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct iwn_tx_cmd *cmd;
 	struct iwn_cmd_data *tx;
 	struct ieee80211_frame *wh;
 	struct iwn_tx_ring *ring;
-	struct iwn_tx_desc *desc;
-	struct iwn_tx_data *data;
-	struct mbuf *m1;
-	bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
 	uint32_t flags;
-	u_int hdrlen;
-	int ac, totlen, error, pad, nsegs = 0, i, rate;
+	int ac, rate;
 	uint8_t type;
 
 	DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
@@ -4719,29 +4608,12 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 	IWN_LOCK_ASSERT(sc);
 
 	wh = mtod(m, struct ieee80211_frame *);
-	hdrlen = ieee80211_anyhdrsize(wh);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
 
 	ac = params->ibp_pri & 3;
 
-	ring = &sc->txq[ac];
-	desc = &ring->desc[ring->cur];
-	data = &ring->data[ring->cur];
-
 	/* Choose a TX rate. */
 	rate = params->ibp_rate0;
-	totlen = m->m_pkthdr.len;
-
-	/* Prepare TX firmware command. */
-	cmd = &ring->cmd[ring->cur];
-	cmd->code = IWN_CMD_TX_DATA;
-	cmd->flags = 0;
-	cmd->qid = ring->qid;
-	cmd->idx = ring->cur;
-
-	tx = (struct iwn_cmd_data *)cmd->data;
-	/* NB: No need to clear tx, all fields are reinitialized here. */
-	tx->scratch = 0;	/* clear "scratch" area */
 
 	flags = 0;
 	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
@@ -4762,6 +4634,23 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 		} else
 			flags |= IWN_TX_NEED_CTS | IWN_TX_FULL_TXOP;
 	}
+
+	if (ieee80211_radiotap_active_vap(vap)) {
+		struct iwn_tx_radiotap_header *tap = &sc->sc_txtap;
+
+		tap->wt_flags = 0;
+		tap->wt_rate = rate;
+
+		ieee80211_radiotap_tx(vap, m);
+	}
+
+	ring = &sc->txq[ac];
+	cmd = &ring->cmd[ring->cur];
+
+	tx = (struct iwn_cmd_data *)cmd->data;
+	/* NB: No need to clear tx, all fields are reinitialized here. */
+	tx->scratch = 0;	/* clear "scratch" area */
+
 	if (type == IEEE80211_FC0_TYPE_MGT) {
 		uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
@@ -4777,44 +4666,68 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 	} else
 		tx->timeout = htole16(0);
 
-	if (hdrlen & 3) {
-		/* First segment length must be a multiple of 4. */
-		flags |= IWN_TX_NEED_PADDING;
-		pad = 4 - (hdrlen & 3);
-	} else
-		pad = 0;
-
-	if (ieee80211_radiotap_active_vap(vap)) {
-		struct iwn_tx_radiotap_header *tap = &sc->sc_txtap;
-
-		tap->wt_flags = 0;
-		tap->wt_rate = rate;
-
-		ieee80211_radiotap_tx(vap, m);
-	}
-
-	tx->len = htole16(totlen);
 	tx->tid = 0;
 	tx->id = sc->broadcast_id;
 	tx->rts_ntries = params->ibp_try1;
 	tx->data_ntries = params->ibp_try0;
 	tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
 	tx->rate = iwn_rate_to_plcp(sc, ni, rate);
+	tx->security = 0;
+	tx->flags = htole32(flags);
 
 	/* Group or management frame. */
 	tx->linkq = 0;
 
+	return (iwn_tx_cmd(sc, m, ni, ring));
+}
+
+static int
+iwn_tx_cmd(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
+    struct iwn_tx_ring *ring)
+{
+	struct iwn_ops *ops = &sc->ops;
+	struct iwn_tx_cmd *cmd;
+	struct iwn_cmd_data *tx;
+	struct ieee80211_frame *wh;
+	struct iwn_tx_desc *desc;
+	struct iwn_tx_data *data;
+	bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER];
+	struct mbuf *m1;
+	u_int hdrlen;
+	int totlen, error, pad, nsegs = 0, i;
+
+	wh = mtod(m, struct ieee80211_frame *);
+	hdrlen = ieee80211_anyhdrsize(wh);
+	totlen = m->m_pkthdr.len;
+
+	desc = &ring->desc[ring->cur];
+	data = &ring->data[ring->cur];
+
+	/* Prepare TX firmware command. */
+	cmd = &ring->cmd[ring->cur];
+	cmd->code = IWN_CMD_TX_DATA;
+	cmd->flags = 0;
+	cmd->qid = ring->qid;
+	cmd->idx = ring->cur;
+
+	tx = (struct iwn_cmd_data *)cmd->data;
+	tx->len = htole16(totlen);
+
 	/* Set physical address of "scratch area". */
 	tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr));
 	tx->hiaddr = IWN_HIADDR(data->scratch_paddr);
+	if (hdrlen & 3) {
+		/* First segment length must be a multiple of 4. */
+		tx->flags |= htole32(IWN_TX_NEED_PADDING);
+		pad = 4 - (hdrlen & 3);
+	} else
+		pad = 0;
 
 	/* Copy 802.11 header in TX command. */
 	memcpy((uint8_t *)(tx + 1), wh, hdrlen);
 
 	/* Trim 802.11 header. */
 	m_adj(m, hdrlen);
-	tx->security = 0;
-	tx->flags = htole32(flags);
 
 	error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs,
 	    &nsegs, BUS_DMA_NOWAIT);
@@ -4845,8 +4758,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, st
 	data->m = m;
 	data->ni = ni;
 
-	DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n",
-	    __func__, ring->qid, ring->cur, m->m_pkthdr.len, nsegs);
+	DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d "
+	    "plcp %d\n",
+	    __func__, ring->qid, ring->cur, totlen, nsegs, tx->rate);
 
 	/* Fill TX descriptor. */
 	desc->nsegs = 1;



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