Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156678871
D10106.id26666.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D10106.id26666.diff
View Options
Index: head/sys/dev/iwn/if_iwn.c
===================================================================
--- head/sys/dev/iwn/if_iwn.c
+++ head/sys/dev/iwn/if_iwn.c
@@ -232,6 +232,8 @@
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 @@
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 @@
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 @@
* 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 @@
* 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 @@
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 @@
}
}
+ 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 @@
} 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 @@
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_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 @@
} 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 @@
} 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 @@
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;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, May 16, 3:32 PM (11 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33130278
Default Alt Text
D10106.id26666.diff (12 KB)
Attached To
Mode
D10106: iwn: deduplicate some parts of iwn_tx_data() and iwn_tx_data_raw()
Attached
Detach File
Event Timeline
Log In to Comment