Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145124010
D3770.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D3770.diff
View Options
Index: head/sys/dev/wpi/if_wpi.c
===================================================================
--- head/sys/dev/wpi/if_wpi.c
+++ head/sys/dev/wpi/if_wpi.c
@@ -196,6 +196,7 @@
#endif
static void wpi_fatal_intr(struct wpi_softc *);
static void wpi_intr(void *);
+static void wpi_free_txfrags(struct wpi_softc *, uint16_t);
static int wpi_cmd2(struct wpi_softc *, struct wpi_buf *);
static int wpi_tx_data(struct wpi_softc *, struct mbuf *,
struct ieee80211_node *);
@@ -458,6 +459,7 @@
| IEEE80211_C_MONITOR /* monitor mode supported */
| IEEE80211_C_AHDEMO /* adhoc demo mode */
| IEEE80211_C_BGSCAN /* capable of bg scanning */
+ | IEEE80211_C_TXFRAG /* handle tx frags */
| IEEE80211_C_TXPMGT /* tx power management */
| IEEE80211_C_SHSLOT /* short slot time supported */
| IEEE80211_C_WPA /* 802.11i */
@@ -1168,6 +1170,7 @@
ring->qid = qid;
ring->queued = 0;
ring->cur = 0;
+ ring->pending = 0;
ring->update = 0;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
@@ -1288,6 +1291,7 @@
BUS_DMASYNC_PREWRITE);
ring->queued = 0;
ring->cur = 0;
+ ring->pending = 0;
ring->update = 0;
}
@@ -2572,6 +2576,34 @@
end: WPI_UNLOCK(sc);
}
+static void
+wpi_free_txfrags(struct wpi_softc *sc, uint16_t ac)
+{
+ struct wpi_tx_ring *ring;
+ struct wpi_tx_data *data;
+ uint8_t cur;
+
+ WPI_TXQ_LOCK(sc);
+ ring = &sc->txq[ac];
+
+ while (ring->pending != 0) {
+ ring->pending--;
+ cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT;
+ data = &ring->data[cur];
+
+ bus_dmamap_sync(ring->data_dmat, data->map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(ring->data_dmat, data->map);
+ m_freem(data->m);
+ data->m = NULL;
+
+ ieee80211_node_decref(data->ni);
+ data->ni = NULL;
+ }
+
+ WPI_TXQ_UNLOCK(sc);
+}
+
static int
wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
{
@@ -2582,9 +2614,9 @@
struct wpi_tx_ring *ring;
struct mbuf *m1;
bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER];
- uint8_t pad;
+ uint8_t cur, pad;
uint16_t hdrlen;
- int error, i, nsegs, totlen;
+ int error, i, nsegs, totlen, frag;
WPI_TXQ_LOCK(sc);
@@ -2601,6 +2633,7 @@
wh = mtod(buf->m, struct ieee80211_frame *);
hdrlen = ieee80211_anyhdrsize(wh);
totlen = buf->m->m_pkthdr.len;
+ frag = ((buf->m->m_flags & (M_FRAG | M_LASTFRAG)) == M_FRAG);
if (__predict_false(totlen < sizeof(struct ieee80211_frame_min))) {
error = EINVAL;
@@ -2614,15 +2647,16 @@
pad = 0;
ring = &sc->txq[buf->ac];
- desc = &ring->desc[ring->cur];
- data = &ring->data[ring->cur];
+ cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT;
+ desc = &ring->desc[cur];
+ data = &ring->data[cur];
/* Prepare TX firmware command. */
- cmd = &ring->cmd[ring->cur];
+ cmd = &ring->cmd[cur];
cmd->code = buf->code;
cmd->flags = 0;
cmd->qid = ring->qid;
- cmd->idx = ring->cur;
+ cmd->idx = cur;
memcpy(cmd->data, buf->data, buf->size);
@@ -2662,7 +2696,8 @@
if (ring->qid < WPI_CMD_QUEUE_NUM) {
if_inc_counter(buf->ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
- ieee80211_free_node(buf->ni);
+ if (!frag)
+ ieee80211_free_node(buf->ni);
}
m_freem(buf->m);
error = 0;
@@ -2678,7 +2713,7 @@
data->ni = buf->ni;
DPRINTF(sc, WPI_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n",
- __func__, ring->qid, ring->cur, totlen, nsegs);
+ __func__, ring->qid, cur, totlen, nsegs);
/* Fill TX descriptor. */
desc->nsegs = WPI_PAD32(totlen + pad) << 4 | (1 + nsegs);
@@ -2699,16 +2734,23 @@
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
- /* Kick TX ring. */
- ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
- sc->sc_update_tx_ring(sc, ring);
+ ring->pending += 1;
- if (ring->qid < WPI_CMD_QUEUE_NUM) {
- WPI_TXQ_STATE_LOCK(sc);
- ring->queued++;
- callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc);
- WPI_TXQ_STATE_UNLOCK(sc);
- }
+ if (!frag) {
+ if (ring->qid < WPI_CMD_QUEUE_NUM) {
+ WPI_TXQ_STATE_LOCK(sc);
+ ring->queued += ring->pending;
+ callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout,
+ sc);
+ WPI_TXQ_STATE_UNLOCK(sc);
+ }
+
+ /* Kick TX ring. */
+ ring->cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT;
+ ring->pending = 0;
+ sc->sc_update_tx_ring(sc, ring);
+ } else
+ ieee80211_node_incref(data->ni);
end: DPRINTF(sc, WPI_DEBUG_TRACE, error ? TRACE_STR_END_ERR : TRACE_STR_END,
__func__);
@@ -2793,6 +2835,8 @@
tap->wt_rate = rate;
if (k != NULL)
tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
+ if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
ieee80211_radiotap_tx(vap, m);
}
@@ -2808,7 +2852,7 @@
if (!IEEE80211_QOS_HAS_SEQ(wh))
flags |= WPI_TX_AUTO_SEQ;
if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)
- flags |= WPI_TX_MORE_FRAG; /* Cannot happen yet. */
+ flags |= WPI_TX_MORE_FRAG;
/* Check if frame must be protected using RTS/CTS or CTS-to-self. */
if (!ismcast) {
@@ -2866,6 +2910,15 @@
memcpy(tx->key, k->wk_key, k->wk_keylen);
}
+ if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) {
+ struct mbuf *next = m->m_nextpkt;
+
+ tx->lnext = htole16(next->m_pkthdr.len);
+ tx->fnext = htole32(tx->security |
+ (flags & WPI_TX_NEED_ACK) |
+ WPI_NEXT_STA_ID(tx->id));
+ }
+
tx->len = htole16(totlen);
tx->flags = htole32(flags);
tx->plcp = rate2plcp(rate);
@@ -2989,13 +3042,13 @@
}
static __inline int
-wpi_tx_ring_is_full(struct wpi_softc *sc, uint16_t ac)
+wpi_tx_ring_free_space(struct wpi_softc *sc, uint16_t ac)
{
struct wpi_tx_ring *ring = &sc->txq[ac];
int retval;
WPI_TXQ_STATE_LOCK(sc);
- retval = (ring->queued > WPI_TX_RING_HIMARK);
+ retval = WPI_TX_RING_HIMARK - ring->queued;
WPI_TXQ_STATE_UNLOCK(sc);
return retval;
@@ -3016,7 +3069,8 @@
WPI_TX_LOCK(sc);
- if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) {
+ /* NB: no fragments here */
+ if (sc->sc_running == 0 || wpi_tx_ring_free_space(sc, ac) < 1) {
error = sc->sc_running ? ENOBUFS : ENETDOWN;
goto unlock;
}
@@ -3055,8 +3109,9 @@
{
struct wpi_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
+ struct mbuf *mnext;
uint16_t ac;
- int error;
+ int error, nmbufs;
WPI_TX_LOCK(sc);
DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__);
@@ -3067,20 +3122,30 @@
goto unlock;
}
+ nmbufs = 1;
+ for (mnext = m->m_nextpkt; mnext != NULL; mnext = mnext->m_nextpkt)
+ nmbufs++;
+
/* Check for available space. */
ac = M_WME_GETAC(m);
- if (wpi_tx_ring_is_full(sc, ac)) {
+ if (wpi_tx_ring_free_space(sc, ac) < nmbufs) {
error = ENOBUFS;
goto unlock;
}
error = 0;
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
- if (wpi_tx_data(sc, m, ni) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
- ieee80211_free_node(ni);
- m_freem(m);
- }
+ do {
+ mnext = m->m_nextpkt;
+ if (wpi_tx_data(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS,
+ nmbufs);
+ wpi_free_txfrags(sc, ac);
+ ieee80211_free_mbuf(m);
+ ieee80211_free_node(ni);
+ break;
+ }
+ } while((m = mnext) != NULL);
DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__);
Index: head/sys/dev/wpi/if_wpireg.h
===================================================================
--- head/sys/dev/wpi/if_wpireg.h
+++ head/sys/dev/wpi/if_wpireg.h
@@ -520,6 +520,8 @@
uint8_t key[IEEE80211_KEYBUF_SIZE];
uint8_t tkip[IEEE80211_WEP_MICLEN];
uint32_t fnext;
+#define WPI_NEXT_STA_ID(id) ((id) << 8)
+
uint32_t lifetime;
#define WPI_LIFETIME_INFINITE 0xffffffff
Index: head/sys/dev/wpi/if_wpivar.h
===================================================================
--- head/sys/dev/wpi/if_wpivar.h
+++ head/sys/dev/wpi/if_wpivar.h
@@ -74,6 +74,7 @@
bus_dma_tag_t data_dmat;
uint8_t qid;
uint8_t cur;
+ uint8_t pending;
int16_t queued;
int update:1;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 17, 5:31 AM (11 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28802958
Default Alt Text
D3770.diff (7 KB)
Attached To
Mode
D3770: wpi(4): add support for TX fragmentation
Attached
Detach File
Event Timeline
Log In to Comment