Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136960650
D3770.id9024.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D3770.id9024.diff
View Options
Index: sys/dev/wpi/if_wpi.c
===================================================================
--- sys/dev/wpi/if_wpi.c
+++ 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,41 @@
end: WPI_UNLOCK(sc);
}
+static void
+wpi_free_txfrags(struct wpi_softc *sc, uint16_t ac)
+{
+ struct wpi_tx_ring *ring;
+
+ WPI_TXQ_LOCK(sc);
+ ring = &sc->txq[ac];
+
+ WPI_TXQ_STATE_LOCK(sc);
+ ring->queued -= ring->pending;
+ if (ring->queued == 0)
+ callout_stop(&sc->tx_timeout);
+ WPI_TXQ_STATE_UNLOCK(sc);
+
+ while (ring->pending--) {
+ if (ring->cur == 0)
+ ring->cur = WPI_TX_RING_COUNT - 1;
+ else
+ ring->cur--;
+
+ struct wpi_tx_data *data = &ring->data[ring->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)
{
@@ -2584,7 +2623,7 @@
bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER];
uint8_t pad;
uint16_t hdrlen;
- int error, i, nsegs, totlen;
+ int error, i, nsegs, totlen, frag;
WPI_TXQ_LOCK(sc);
@@ -2601,6 +2640,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;
@@ -2699,17 +2739,26 @@
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);
-
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);
+ if (!frag) {
+ callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout,
+ sc);
+ }
WPI_TXQ_STATE_UNLOCK(sc);
}
+ /* Kick TX ring. */
+ ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
+ if (frag) {
+ ring->pending += 1;
+ ieee80211_node_incref(data->ni);
+ } else {
+ ring->pending = 0;
+ sc->sc_update_tx_ring(sc, ring);
+ }
+
end: DPRINTF(sc, WPI_DEBUG_TRACE, error ? TRACE_STD_END_ERR : TRACE_STR_END,
__func__);
@@ -2793,6 +2842,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 +2859,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 +2917,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 +3049,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 +3076,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 +3116,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 +3129,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: sys/dev/wpi/if_wpireg.h
===================================================================
--- sys/dev/wpi/if_wpireg.h
+++ 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: sys/dev/wpi/if_wpivar.h
===================================================================
--- sys/dev/wpi/if_wpivar.h
+++ 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
Fri, Nov 21, 8:32 PM (20 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25799311
Default Alt Text
D3770.id9024.diff (6 KB)
Attached To
Mode
D3770: wpi(4): add support for TX fragmentation
Attached
Detach File
Event Timeline
Log In to Comment