mirror of
https://github.com/proski/madwifi
synced 2024-11-22 14:31:22 +03:00
Remove axq_link, for benoit.
The last descriptor is now implicit in the structure and meta-data of the buffers; axq_link does not need to be maintained separately. Add macros to to return the last buffer, descriptor, and link them as necessary. Make the queue moving macro implicitly link descriptors, and remove the explicit descriptor linking in this case. ath_node_move_data is still desperately in need of a review; it is used in XR. git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3620 0192ed92-7a03-0410-a25b-9323aeb14dbd
This commit is contained in:
parent
3dc12c74ec
commit
dfdda8ca55
345
ath/if_ath.c
345
ath/if_ath.c
@ -2118,15 +2118,13 @@ ath_intr_process_rx_descriptors(struct ath_softc *sc, int* pneedmark, u_int64_t
|
|||||||
sizeof(*qwhl),
|
sizeof(*qwhl),
|
||||||
BUS_DMA_TODEVICE);
|
BUS_DMA_TODEVICE);
|
||||||
|
|
||||||
if (uapsd_xmit_q->axq_link) {
|
|
||||||
*uapsd_xmit_q->axq_link =
|
ATH_TXQ_LINK_DESC(uapsd_xmit_q,
|
||||||
ath_ds_link_swap(STAILQ_FIRST(&an->an_uapsd_q)->bf_daddr);
|
STAILQ_FIRST(
|
||||||
}
|
&an->an_uapsd_q));
|
||||||
/* below leaves an_uapsd_q NULL */
|
/* Below leaves an_uapsd_q NULL. */
|
||||||
STAILQ_CONCAT(&uapsd_xmit_q->axq_q,
|
STAILQ_CONCAT(&uapsd_xmit_q->axq_q,
|
||||||
&an->an_uapsd_q);
|
&an->an_uapsd_q);
|
||||||
uapsd_xmit_q->axq_link =
|
|
||||||
&last_desc->ds_link;
|
|
||||||
ath_hal_puttxbuf(sc->sc_ah,
|
ath_hal_puttxbuf(sc->sc_ah,
|
||||||
uapsd_xmit_q->axq_qnum,
|
uapsd_xmit_q->axq_qnum,
|
||||||
(STAILQ_FIRST(&uapsd_xmit_q->axq_q))->bf_daddr);
|
(STAILQ_FIRST(&uapsd_xmit_q->axq_q))->bf_daddr);
|
||||||
@ -2917,8 +2915,8 @@ ath_txq_dump(struct ath_softc *sc, struct ath_txq *txq)
|
|||||||
struct ath_buf *bf;
|
struct ath_buf *bf;
|
||||||
|
|
||||||
DPRINTF(sc, ATH_DEBUG_WATCHDOG, "txq:%p : axq_qnum:%u axq_depth:%d "
|
DPRINTF(sc, ATH_DEBUG_WATCHDOG, "txq:%p : axq_qnum:%u axq_depth:%d "
|
||||||
"axq_link:%p TXDP:%08x\n",
|
"TXDP:%08x\n",
|
||||||
txq, txq->axq_qnum, txq->axq_depth, txq->axq_link,
|
txq, txq->axq_qnum, txq->axq_depth,
|
||||||
ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum));
|
ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum));
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -2981,54 +2979,53 @@ ath_tx_txqaddbuf(struct ath_softc *sc, struct ieee80211_node *ni,
|
|||||||
|
|
||||||
if (ath_cac_running_dbgmsg(sc))
|
if (ath_cac_running_dbgmsg(sc))
|
||||||
return;
|
return;
|
||||||
/*
|
|
||||||
* Insert the frame on the outbound list and
|
/* Insert the frame on the outbound list and
|
||||||
* pass it on to the hardware.
|
* pass it on to the hardware. */
|
||||||
*/
|
|
||||||
ATH_TXQ_LOCK_IRQ(txq);
|
ATH_TXQ_LOCK_IRQ(txq);
|
||||||
if (ni && ni->ni_vap && txq == &ATH_VAP(ni->ni_vap)->av_mcastq) {
|
if (ni && ni->ni_vap && txq == &ATH_VAP(ni->ni_vap)->av_mcastq) {
|
||||||
/*
|
/* The CAB queue is started from the SWBA handler since
|
||||||
* The CAB queue is started from the SWBA handler since
|
* frames only go out on DTIM and to avoid possible races. */
|
||||||
* frames only go out on DTIM and to avoid possible races.
|
|
||||||
*/
|
|
||||||
ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_SWBA);
|
ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_SWBA);
|
||||||
|
|
||||||
|
ATH_TXQ_LINK_DESC(txq, bf);
|
||||||
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
||||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "MC txq [%d] depth = %d\n",
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
||||||
txq->axq_qnum, txq->axq_depth);
|
"link[%u]=%08llx (%p)\n",
|
||||||
if (txq->axq_link != NULL) {
|
txq->axq_qnum,
|
||||||
*txq->axq_link = ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT, "link[%u](%p)=%08llx (%p)\n",
|
|
||||||
txq->axq_qnum, txq->axq_link,
|
|
||||||
(u_int64_t)bf->bf_daddr, bf->bf_desc);
|
(u_int64_t)bf->bf_daddr, bf->bf_desc);
|
||||||
}
|
|
||||||
txq->axq_link = &ds->ds_link;
|
|
||||||
/* We do not start tx on this queue as it will be done as
|
/* We do not start tx on this queue as it will be done as
|
||||||
"CAB" data at DTIM intervals. */
|
* "CAB" data at DTIM intervals. */
|
||||||
ath_hal_intrset(ah, sc->sc_imask);
|
ath_hal_intrset(ah, sc->sc_imask);
|
||||||
} else {
|
} else {
|
||||||
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
ATH_TXQ_LINK_DESC(txq, bf);
|
||||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "UC txq [%d] depth = %d\n",
|
if (!STAILQ_FIRST(&txq->axq_q)) {
|
||||||
txq->axq_qnum, txq->axq_depth);
|
|
||||||
if (txq->axq_link == NULL) {
|
|
||||||
u_int32_t txdp;
|
u_int32_t txdp;
|
||||||
|
|
||||||
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
|
ath_hal_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT, "TXDP[%u] = %08llx (%p)\n",
|
DPRINTF(sc, ATH_DEBUG_XMIT, "TXDP[%u] = %08llx (%p)\n",
|
||||||
txq->axq_qnum, (u_int64_t)bf->bf_daddr, bf->bf_desc);
|
txq->axq_qnum, (u_int64_t)bf->bf_daddr,
|
||||||
|
bf->bf_desc);
|
||||||
txdp = ath_hal_gettxbuf(ah, txq->axq_qnum);
|
txdp = ath_hal_gettxbuf(ah, txq->axq_qnum);
|
||||||
if (txdp != bf->bf_daddr) {
|
if (txdp != bf->bf_daddr) {
|
||||||
DPRINTF(sc, ATH_DEBUG_WATCHDOG,
|
DPRINTF(sc, ATH_DEBUG_WATCHDOG,
|
||||||
"TXQ%d: BUG TXDP:%08x instead of %08llx\n",
|
"TXQ%d: BUG TXDP:%08x instead "
|
||||||
|
"of %08llx\n",
|
||||||
txq->axq_qnum, txdp,
|
txq->axq_qnum, txdp,
|
||||||
(u_int64_t)bf->bf_daddr);
|
(u_int64_t)bf->bf_daddr);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
*txq->axq_link = ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT, "link[%u] (%p)=%08llx (%p)\n",
|
|
||||||
txq->axq_qnum, txq->axq_link,
|
|
||||||
(u_int64_t)bf->bf_daddr, bf->bf_desc);
|
|
||||||
}
|
}
|
||||||
txq->axq_link = &ds->ds_link;
|
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
||||||
|
|
||||||
|
DPRINTF(sc, ATH_DEBUG_TX_PROC, "UC txq [%d] depth = %d\n",
|
||||||
|
txq->axq_qnum, txq->axq_depth);
|
||||||
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
||||||
|
"link[%u] (%08x)=%08llx (%p)\n",
|
||||||
|
txq->axq_qnum,
|
||||||
|
ATH_TXQ_LAST_DESC(txq)->ds_link,
|
||||||
|
(u_int64_t)bf->bf_daddr, bf->bf_desc);
|
||||||
|
|
||||||
ath_hal_txstart(ah, txq->axq_qnum);
|
ath_hal_txstart(ah, txq->axq_qnum);
|
||||||
sc->sc_dev->trans_start = jiffies;
|
sc->sc_dev->trans_start = jiffies;
|
||||||
}
|
}
|
||||||
@ -5080,8 +5077,11 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
|||||||
skb = bf->bf_skb;
|
skb = bf->bf_skb;
|
||||||
curlen = skb->len;
|
curlen = skb->len;
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"Updating beacon - mcast pending=%d.\n", avp->av_mcastq.axq_depth);
|
"Updating beacon - mcast pending=%d.\n",
|
||||||
if (ieee80211_beacon_update(SKB_NI(bf->bf_skb), &avp->av_boff, skb, !!avp->av_mcastq.axq_depth, &is_dtim)) {
|
avp->av_mcastq.axq_depth);
|
||||||
|
if (ieee80211_beacon_update(SKB_NI(bf->bf_skb), &avp->av_boff, skb,
|
||||||
|
!!STAILQ_FIRST(&avp->av_mcastq.axq_q),
|
||||||
|
&is_dtim)) {
|
||||||
bus_unmap_single(sc->sc_bdev,
|
bus_unmap_single(sc->sc_bdev,
|
||||||
bf->bf_skbaddr, curlen, BUS_DMA_TODEVICE);
|
bf->bf_skbaddr, curlen, BUS_DMA_TODEVICE);
|
||||||
bf->bf_skbaddr = 0;
|
bf->bf_skbaddr = 0;
|
||||||
@ -5101,16 +5101,16 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
|||||||
*/
|
*/
|
||||||
tim_bitctl = ((struct ieee80211_tim_ie *)avp->av_boff.bo_tim)->tim_bitctl;
|
tim_bitctl = ((struct ieee80211_tim_ie *)avp->av_boff.bo_tim)->tim_bitctl;
|
||||||
if ((tim_bitctl & BITCTL_BUFD_MCAST) &&
|
if ((tim_bitctl & BITCTL_BUFD_MCAST) &&
|
||||||
(avp->av_mcastq.axq_depth) &&
|
STAILQ_FIRST(&avp->av_mcastq.axq_q) &&
|
||||||
(sc->sc_cabq->axq_depth) &&
|
STAILQ_FIRST(&sc->sc_cabq->axq_q) &&
|
||||||
(sc->sc_nvaps > 1) &&
|
(sc->sc_nvaps > 1) &&
|
||||||
(sc->sc_stagbeacons)) {
|
(sc->sc_stagbeacons)) {
|
||||||
ath_tx_draintxq(sc, sc->sc_cabq);
|
ath_tx_draintxq(sc, sc->sc_cabq);
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"Drained previous cabq transmit traffic to make room for next VAP.\n");
|
"Drained previous cabq transmit traffic to make room for next VAP.\n");
|
||||||
} else if ((sc->sc_cabq->axq_depth) &&
|
} else if (STAILQ_FIRST(&sc->sc_cabq->axq_q) &&
|
||||||
ATH_TXQ_SETUP(sc, sc->sc_cabq->axq_qnum) &&
|
ATH_TXQ_SETUP(sc, sc->sc_cabq->axq_qnum) &&
|
||||||
(!txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum))) {
|
!txqactive(sc->sc_ah, sc->sc_cabq->axq_qnum)) {
|
||||||
DPRINTF(sc,
|
DPRINTF(sc,
|
||||||
ATH_DEBUG_BEACON,
|
ATH_DEBUG_BEACON,
|
||||||
"Draining %d stalled CABQ transmit buffers.\n",
|
"Draining %d stalled CABQ transmit buffers.\n",
|
||||||
@ -5152,27 +5152,26 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
|||||||
ATH_TXQ_LOCK_IRQ_INSIDE(cabq);
|
ATH_TXQ_LOCK_IRQ_INSIDE(cabq);
|
||||||
bfmcast = STAILQ_FIRST(&avp->av_mcastq.axq_q);
|
bfmcast = STAILQ_FIRST(&avp->av_mcastq.axq_q);
|
||||||
if (bfmcast != NULL) {
|
if (bfmcast != NULL) {
|
||||||
|
struct ath_buf *tbf;
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"Multicast pending. "
|
"Multicast pending. "
|
||||||
"Linking CABQ to avp->av_mcastq.axq_q.\n");
|
"Linking CABQ to avp->av_mcastq.axq_q.\n");
|
||||||
/* link the descriptors */
|
|
||||||
if (cabq->axq_link == NULL) {
|
/* Set the MORE_DATA bit for each packet except the
|
||||||
ath_hal_puttxbuf(ah, cabq->axq_qnum,
|
* last one */
|
||||||
bfmcast->bf_daddr);
|
STAILQ_FOREACH(tbf, &avp->av_mcastq.axq_q, bf_list) {
|
||||||
} else {
|
if (tbf != STAILQ_LAST(&avp->av_mcastq.axq_q,
|
||||||
*cabq->axq_link = ath_ds_link_swap(bfmcast->bf_daddr);
|
|
||||||
}
|
|
||||||
/* Set the MORE_DATA bit for each packet except the last one */
|
|
||||||
STAILQ_FOREACH(bfmcast, &avp->av_mcastq.axq_q, bf_list) {
|
|
||||||
if (bfmcast != STAILQ_LAST(&avp->av_mcastq.axq_q,
|
|
||||||
ath_buf, bf_list))
|
ath_buf, bf_list))
|
||||||
((struct ieee80211_frame *)
|
((struct ieee80211_frame *)
|
||||||
bfmcast->bf_skb->data)->i_fc[1] |=
|
tbf->bf_skb->data)->i_fc[1] |=
|
||||||
IEEE80211_FC1_MORE_DATA;
|
IEEE80211_FC1_MORE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append the private VAP mcast list to the cabq */
|
/* Append the private VAP mcast list to the cabq. */
|
||||||
ATH_TXQ_MOVE_MCASTQ(&avp->av_mcastq, cabq);
|
ATH_TXQ_MOVE_Q(&avp->av_mcastq, cabq);
|
||||||
|
if (!STAILQ_FIRST(&cabq->axq_q))
|
||||||
|
ath_hal_puttxbuf(ah, cabq->axq_qnum,
|
||||||
|
bfmcast->bf_daddr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
@ -5182,7 +5181,7 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap, int *needmar
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NB: gated by beacon so safe to start here */
|
/* NB: gated by beacon so safe to start here */
|
||||||
if (cabq->axq_depth > 0) {
|
if (STAILQ_FIRST(&cabq->axq_q)) {
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"Checking CABQ - CABQ being started.\n");
|
"Checking CABQ - CABQ being started.\n");
|
||||||
if (!ath_hal_txstart(ah, cabq->axq_qnum)) {
|
if (!ath_hal_txstart(ah, cabq->axq_qnum)) {
|
||||||
@ -5285,8 +5284,11 @@ ath_beacon_send(struct ath_softc *sc, int *needmark, uint64_t hw_tsf)
|
|||||||
sc, vap,
|
sc, vap,
|
||||||
needmark)) != NULL) {
|
needmark)) != NULL) {
|
||||||
if (bflink != NULL)
|
if (bflink != NULL)
|
||||||
*bflink = ath_ds_link_swap(bf->bf_daddr);
|
*bflink = ath_ds_link_swap(
|
||||||
else /* For the first bf, save bf_addr for later */
|
bf->bf_daddr);
|
||||||
|
else
|
||||||
|
/* For the first bf, save
|
||||||
|
* bf_addr for later */
|
||||||
bfaddr = bf->bf_daddr;
|
bfaddr = bf->bf_daddr;
|
||||||
|
|
||||||
bflink = &bf->bf_desc->ds_link;
|
bflink = &bf->bf_desc->ds_link;
|
||||||
@ -5973,10 +5975,9 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
struct ath_txq tmp_q;
|
struct ath_txq tmp_q;
|
||||||
memset(&tmp_q, 0, sizeof(tmp_q));
|
memset(&tmp_q, 0, sizeof(tmp_q));
|
||||||
STAILQ_INIT(&tmp_q.axq_q);
|
STAILQ_INIT(&tmp_q.axq_q);
|
||||||
/*
|
|
||||||
* collect all the data towards the node
|
/* Collect all the data towards the node
|
||||||
* in to the tmp_q.
|
* in to the tmp_q. */
|
||||||
*/
|
|
||||||
index = WME_AC_VO;
|
index = WME_AC_VO;
|
||||||
while (index >= WME_AC_BE && txq != sc->sc_ac2q[index]) {
|
while (index >= WME_AC_BE && txq != sc->sc_ac2q[index]) {
|
||||||
txq = sc->sc_ac2q[index];
|
txq = sc->sc_ac2q[index];
|
||||||
@ -5984,10 +5985,9 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
ATH_TXQ_LOCK_IRQ(txq);
|
ATH_TXQ_LOCK_IRQ(txq);
|
||||||
ath_hal_stoptxdma(ah, txq->axq_qnum);
|
ath_hal_stoptxdma(ah, txq->axq_qnum);
|
||||||
bf = prev = STAILQ_FIRST(&txq->axq_q);
|
bf = prev = STAILQ_FIRST(&txq->axq_q);
|
||||||
/*
|
|
||||||
* skip all the buffers that are done
|
/* Skip all the buffers that are done
|
||||||
* until the first one that is in progress
|
* until the first one that is in progress. */
|
||||||
*/
|
|
||||||
while (bf) {
|
while (bf) {
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
ds = &bf->bf_desc[bf->bf_numdescff];
|
ds = &bf->bf_desc[bf->bf_numdescff];
|
||||||
@ -6002,7 +6002,7 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
bf = STAILQ_NEXT(bf, bf_list);
|
bf = STAILQ_NEXT(bf, bf_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save the pointer to the last buf that's done */
|
/* Save the pointer to the last buf that's done. */
|
||||||
if (prev == bf)
|
if (prev == bf)
|
||||||
bf_tmp = NULL;
|
bf_tmp = NULL;
|
||||||
else
|
else
|
||||||
@ -6027,27 +6027,26 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
STAILQ_INSERT_TAIL(&tmp_q.axq_q,
|
STAILQ_INSERT_TAIL(&tmp_q.axq_q,
|
||||||
bf, bf_list);
|
bf, bf_list);
|
||||||
bf = STAILQ_NEXT(prev, bf_list);
|
bf = STAILQ_NEXT(prev, bf_list);
|
||||||
/*
|
/* After deleting the node
|
||||||
* after deleting the node
|
* link the descriptors. */
|
||||||
* link the descriptors
|
|
||||||
*/
|
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
ds = &prev->bf_desc[prev->bf_numdescff];
|
ds = &prev->bf_desc
|
||||||
|
[prev->bf_numdescff];
|
||||||
#else
|
#else
|
||||||
/* NB: last descriptor */
|
/* NB: last descriptor. */
|
||||||
ds = prev->bf_desc;
|
ds = prev->bf_desc;
|
||||||
#endif
|
#endif
|
||||||
ds->ds_link = ath_ds_link_swap(bf->bf_daddr);
|
ds->ds_link = ath_ds_link_swap(
|
||||||
|
bf->bf_daddr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prev = bf;
|
prev = bf;
|
||||||
bf = STAILQ_NEXT(bf, bf_list);
|
bf = STAILQ_NEXT(bf, bf_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* if the last buf was deleted.
|
/* If the last buf. was deleted.
|
||||||
* set the pointer to the last descriptor.
|
* set the pointer to the last descriptor. */
|
||||||
*/
|
|
||||||
bf = STAILQ_FIRST(&txq->axq_q);
|
bf = STAILQ_FIRST(&txq->axq_q);
|
||||||
if (bf) {
|
if (bf) {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -6064,22 +6063,14 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
status = ath_hal_txprocdesc(
|
status = ath_hal_txprocdesc(
|
||||||
ah, ds, ts
|
ah, ds, ts
|
||||||
);
|
);
|
||||||
if (status == HAL_EINPROGRESS)
|
|
||||||
txq->axq_link =
|
|
||||||
&ds->ds_link;
|
|
||||||
else
|
|
||||||
txq->axq_link = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
txq->axq_link = NULL;
|
|
||||||
|
|
||||||
ATH_TXQ_UNLOCK_IRQ(txq);
|
ATH_TXQ_UNLOCK_IRQ(txq);
|
||||||
|
|
||||||
/*
|
/* Restart the DMA from the first
|
||||||
* restart the DMA from the first
|
* buffer that was not DMA'd. */
|
||||||
* buffer that was not DMA'd.
|
|
||||||
*/
|
|
||||||
if (bf_tmp)
|
if (bf_tmp)
|
||||||
bf = STAILQ_NEXT(bf_tmp, bf_list);
|
bf = STAILQ_NEXT(bf_tmp, bf_list);
|
||||||
else
|
else
|
||||||
@ -6090,12 +6081,11 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
ath_hal_txstart(ah, txq->axq_qnum);
|
ath_hal_txstart(ah, txq->axq_qnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* queue them on to the XR txqueue.
|
/* Queue them on to the XR txqueue.
|
||||||
* can not directly put them on to the XR txq. since the
|
* Can not directly put them on to the XR txq, since the
|
||||||
* skb data size may be greater than the XR fragmentation
|
* SKB data size may be greater than the XR fragmentation
|
||||||
* threshold size.
|
* threshold size. */
|
||||||
*/
|
|
||||||
bf = STAILQ_FIRST(&tmp_q.axq_q);
|
bf = STAILQ_FIRST(&tmp_q.axq_q);
|
||||||
index = 0;
|
index = 0;
|
||||||
while (bf) {
|
while (bf) {
|
||||||
@ -6118,9 +6108,7 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
struct ath_desc *ds = NULL;
|
struct ath_desc *ds = NULL;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
|
||||||
/*
|
/* Move data from XR txq to Normal txqs. */
|
||||||
* move data from XR txq to Normal txqs.
|
|
||||||
*/
|
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT_PROC,
|
DPRINTF(sc, ATH_DEBUG_XMIT_PROC,
|
||||||
"move buffers from XR to NORMAL\n");
|
"move buffers from XR to NORMAL\n");
|
||||||
memset(&wme_tmp_qs, 0, sizeof(wme_tmp_qs));
|
memset(&wme_tmp_qs, 0, sizeof(wme_tmp_qs));
|
||||||
@ -6131,10 +6119,8 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
ATH_TXQ_LOCK_IRQ(txq);
|
ATH_TXQ_LOCK_IRQ(txq);
|
||||||
ath_hal_stoptxdma(ah, txq->axq_qnum);
|
ath_hal_stoptxdma(ah, txq->axq_qnum);
|
||||||
bf = prev = STAILQ_FIRST(&txq->axq_q);
|
bf = prev = STAILQ_FIRST(&txq->axq_q);
|
||||||
/*
|
/* Skip all the buffers that are done
|
||||||
* skip all the buffers that are done
|
* until the first one that is in progress. */
|
||||||
* until the first one that is in progress
|
|
||||||
*/
|
|
||||||
while (bf) {
|
while (bf) {
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
ds = &bf->bf_desc[bf->bf_numdescff];
|
ds = &bf->bf_desc[bf->bf_numdescff];
|
||||||
@ -6148,17 +6134,14 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
prev= bf;
|
prev= bf;
|
||||||
bf = STAILQ_NEXT(bf, bf_list);
|
bf = STAILQ_NEXT(bf, bf_list);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* save the pointer to the last buf that's
|
/* Save the pointer to the last buf that's done. */
|
||||||
* done
|
|
||||||
*/
|
|
||||||
if (prev == bf)
|
if (prev == bf)
|
||||||
bf_tmp1 = NULL;
|
bf_tmp1 = NULL;
|
||||||
else
|
else
|
||||||
bf_tmp1 = prev;
|
bf_tmp1 = prev;
|
||||||
/*
|
|
||||||
* collect all the data in to four temp SW queues.
|
/* Collect all the data in to four temp SW queues. */
|
||||||
*/
|
|
||||||
while (bf) {
|
while (bf) {
|
||||||
if (ni == ATH_BUF_NI(bf)) {
|
if (ni == ATH_BUF_NI(bf)) {
|
||||||
if (prev == bf) {
|
if (prev == bf) {
|
||||||
@ -6176,29 +6159,20 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
skb = bf_tmp->bf_skb;
|
skb = bf_tmp->bf_skb;
|
||||||
wh = (struct ieee80211_frame *)skb->data;
|
wh = (struct ieee80211_frame *)skb->data;
|
||||||
if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
|
if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
|
||||||
/* XXX validate skb->priority, remove
|
/* XXX: Validate skb->priority, remove
|
||||||
* mask */
|
* mask */
|
||||||
wmeq = &wme_tmp_qs[skb->priority & 0x3];
|
wmeq = &wme_tmp_qs[skb->priority & 0x3];
|
||||||
} else
|
} else
|
||||||
wmeq = &wme_tmp_qs[WME_AC_BE];
|
wmeq = &wme_tmp_qs[WME_AC_BE];
|
||||||
|
ATH_TXQ_LINK_DESC(wmeq, bf_tmp);
|
||||||
STAILQ_INSERT_TAIL(&wmeq->axq_q, bf_tmp, bf_list);
|
STAILQ_INSERT_TAIL(&wmeq->axq_q, bf_tmp, bf_list);
|
||||||
ds = bf_tmp->bf_desc;
|
|
||||||
/*
|
|
||||||
* link the descriptors
|
|
||||||
*/
|
|
||||||
if (wmeq->axq_link != NULL) {
|
|
||||||
*wmeq->axq_link =
|
|
||||||
ath_ds_link_swap(bf_tmp->bf_daddr);
|
|
||||||
DPRINTF(sc, ATH_DEBUG_XMIT,
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
||||||
"link[%u](%p)=%08llx (%p)\n",
|
"link[%u]=%08llx (%p)\n",
|
||||||
wmeq->axq_qnum, wmeq->axq_link,
|
wmeq->axq_qnum,
|
||||||
(u_int64_t)bf_tmp->bf_daddr,
|
(u_int64_t)bf_tmp->bf_daddr,
|
||||||
bf_tmp->bf_desc);
|
bf_tmp->bf_desc);
|
||||||
}
|
|
||||||
wmeq->axq_link = &ds->ds_link;
|
/* Update the rate information. (?) */
|
||||||
/*
|
|
||||||
* update the rate information
|
|
||||||
*/
|
|
||||||
} else {
|
} else {
|
||||||
prev = bf;
|
prev = bf;
|
||||||
bf = STAILQ_NEXT(bf, bf_list);
|
bf = STAILQ_NEXT(bf, bf_list);
|
||||||
@ -6218,26 +6192,12 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
/* NB: last descriptor */
|
/* NB: last descriptor */
|
||||||
ds = prev->bf_desc;
|
ds = prev->bf_desc;
|
||||||
#endif
|
#endif
|
||||||
ts = &bf->bf_dsstatus.ds_txstat;
|
|
||||||
status = ath_hal_txprocdesc(ah, ds, ts);
|
|
||||||
if (status == HAL_EINPROGRESS)
|
|
||||||
txq->axq_link = &ds->ds_link;
|
|
||||||
else
|
|
||||||
txq->axq_link = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* if the list is empty reset the pointer.
|
|
||||||
*/
|
|
||||||
txq->axq_link = NULL;
|
|
||||||
}
|
}
|
||||||
ATH_TXQ_UNLOCK_IRQ(txq);
|
ATH_TXQ_UNLOCK_IRQ(txq);
|
||||||
|
|
||||||
/*
|
/* Restart the DMA from the first buffer that was not DMA'd. */
|
||||||
* restart the DMA from the first
|
|
||||||
* buffer that was not DMA'd.
|
|
||||||
*/
|
|
||||||
if (bf_tmp1)
|
if (bf_tmp1)
|
||||||
bf = STAILQ_NEXT(bf_tmp1, bf_list);
|
bf = STAILQ_NEXT(bf_tmp1, bf_list);
|
||||||
else
|
else
|
||||||
@ -6261,13 +6221,8 @@ ath_node_move_data(const struct ieee80211_node *ni)
|
|||||||
(index >= WME_AC_BE)) {
|
(index >= WME_AC_BE)) {
|
||||||
wmeq = &wme_tmp_qs[index];
|
wmeq = &wme_tmp_qs[index];
|
||||||
bf = STAILQ_FIRST(&wmeq->axq_q);
|
bf = STAILQ_FIRST(&wmeq->axq_q);
|
||||||
if (bf) {
|
if (bf)
|
||||||
ATH_TXQ_MOVE_Q(wmeq, txq);
|
ATH_TXQ_MOVE_Q(wmeq, txq);
|
||||||
if (txq->axq_link != NULL) {
|
|
||||||
*(txq->axq_link) =
|
|
||||||
ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7034,7 +6989,6 @@ ath_grppoll_txq_setup(struct ath_softc *sc, int qtype, int period)
|
|||||||
|
|
||||||
txq->axq_qnum = qnum;
|
txq->axq_qnum = qnum;
|
||||||
}
|
}
|
||||||
txq->axq_link = NULL;
|
|
||||||
STAILQ_INIT(&txq->axq_q);
|
STAILQ_INIT(&txq->axq_q);
|
||||||
ATH_TXQ_LOCK_INIT(txq);
|
ATH_TXQ_LOCK_INIT(txq);
|
||||||
txq->axq_depth = 0;
|
txq->axq_depth = 0;
|
||||||
@ -7058,7 +7012,7 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
|||||||
ath_keyix_t keyix = HAL_TXKEYIX_INVALID;
|
ath_keyix_t keyix = HAL_TXKEYIX_INVALID;
|
||||||
unsigned int pollsperrate, pos;
|
unsigned int pollsperrate, pos;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
struct ath_buf *bf, *head = NULL;
|
struct ath_buf *bf = NULL, *head = NULL;
|
||||||
struct ieee80211com *ic = vap->iv_ic;
|
struct ieee80211com *ic = vap->iv_ic;
|
||||||
struct ath_softc *sc = ic->ic_dev->priv;
|
struct ath_softc *sc = ic->ic_dev->priv;
|
||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
@ -7068,7 +7022,6 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
|||||||
u_int8_t cix, rtindex = 0;
|
u_int8_t cix, rtindex = 0;
|
||||||
u_int type;
|
u_int type;
|
||||||
struct ath_txq *txq = &sc->sc_grpplq;
|
struct ath_txq *txq = &sc->sc_grpplq;
|
||||||
struct ath_desc *ds = NULL;
|
|
||||||
int rates[XR_NUM_RATES];
|
int rates[XR_NUM_RATES];
|
||||||
u_int8_t ratestr[16], numpollstr[16];
|
u_int8_t ratestr[16], numpollstr[16];
|
||||||
struct rate_to_str_map {
|
struct rate_to_str_map {
|
||||||
@ -7206,24 +7159,23 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
|||||||
}
|
}
|
||||||
ATH_TXBUF_UNLOCK_IRQ(sc);
|
ATH_TXBUF_UNLOCK_IRQ(sc);
|
||||||
|
|
||||||
bf->bf_skbaddr = bus_map_single(sc->sc_bdev,
|
|
||||||
skb->data, skb->len, BUS_DMA_TODEVICE);
|
|
||||||
bf->bf_skb = skb;
|
bf->bf_skb = skb;
|
||||||
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
bf->bf_desc->ds_data = bus_map_single(sc->sc_bdev,
|
||||||
ds = bf->bf_desc;
|
skb->data, skb->len, BUS_DMA_TODEVICE);;
|
||||||
ds->ds_data = bf->bf_skbaddr;
|
|
||||||
if (i == pollcount && amode == (HAL_ANTENNA_MAX_MODE - 1)) {
|
if ((i == pollcount) && (amode == (HAL_ANTENNA_MAX_MODE - 1))) {
|
||||||
type = HAL_PKT_TYPE_NORMAL;
|
type = HAL_PKT_TYPE_NORMAL;
|
||||||
flags |= (HAL_TXDESC_CLRDMASK | HAL_TXDESC_VEOL);
|
flags |= (HAL_TXDESC_CLRDMASK | HAL_TXDESC_VEOL);
|
||||||
} else {
|
} else {
|
||||||
flags |= HAL_TXDESC_CTSENA;
|
flags |= HAL_TXDESC_CTSENA;
|
||||||
type = HAL_PKT_TYPE_GRP_POLL;
|
type = HAL_PKT_TYPE_GRP_POLL;
|
||||||
}
|
}
|
||||||
if (i == 0 && amode == HAL_ANTENNA_FIXED_A) {
|
if ((i == 0) && (amode == HAL_ANTENNA_FIXED_A)) {
|
||||||
flags |= HAL_TXDESC_CLRDMASK;
|
flags |= HAL_TXDESC_CLRDMASK;
|
||||||
head = bf;
|
head = bf;
|
||||||
}
|
}
|
||||||
ath_hal_setuptxdesc(ah, ds,
|
|
||||||
|
ath_hal_setuptxdesc(ah, bf->bf_desc,
|
||||||
skb->len + IEEE80211_CRC_LEN, /* frame length */
|
skb->len + IEEE80211_CRC_LEN, /* frame length */
|
||||||
sizeof(struct ieee80211_frame), /* header length */
|
sizeof(struct ieee80211_frame), /* header length */
|
||||||
type, /* Atheros packet type */
|
type, /* Atheros packet type */
|
||||||
@ -7238,19 +7190,17 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
|||||||
0, /* comp iv len */
|
0, /* comp iv len */
|
||||||
ATH_COMP_PROC_NO_COMP_NO_CCS /* comp scheme */
|
ATH_COMP_PROC_NO_COMP_NO_CCS /* comp scheme */
|
||||||
);
|
);
|
||||||
ath_hal_filltxdesc(ah, ds,
|
ath_hal_filltxdesc(ah, bf->bf_desc,
|
||||||
roundup(skb->len, 4), /* buffer length */
|
roundup(skb->len, 4), /* buffer length */
|
||||||
AH_TRUE, /* first segment */
|
AH_TRUE, /* first segment */
|
||||||
AH_TRUE, /* last segment */
|
AH_TRUE, /* last segment */
|
||||||
ds /* first descriptor */
|
bf->bf_desc /* first descriptor */
|
||||||
);
|
);
|
||||||
/* NB: The desc swap function becomes void,
|
|
||||||
* if descriptor swapping is not enabled */
|
ath_desc_swap(bf->bf_desc);
|
||||||
ath_desc_swap(ds);
|
ATH_TXQ_LINK_DESC(txq, bf);
|
||||||
if (txq->axq_link) {
|
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
|
||||||
*txq->axq_link = ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
}
|
|
||||||
txq->axq_link = &ds->ds_link;
|
|
||||||
pollsperrate++;
|
pollsperrate++;
|
||||||
if (pollsperrate > rates[rtindex]) {
|
if (pollsperrate > rates[rtindex]) {
|
||||||
rtindex = (rtindex + 1) % MAX_GRPPOLL_RATE;
|
rtindex = (rtindex + 1) % MAX_GRPPOLL_RATE;
|
||||||
@ -7259,7 +7209,7 @@ static void ath_grppoll_start(struct ieee80211vap *vap, int pollcount)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* make it circular */
|
/* make it circular */
|
||||||
ds->ds_link = ath_ds_link_swap(head->bf_daddr);
|
bf->bf_desc->ds_link = ath_ds_link_swap(head->bf_daddr);
|
||||||
/* start the queue */
|
/* start the queue */
|
||||||
ath_hal_puttxbuf(ah, txq->axq_qnum, head->bf_daddr);
|
ath_hal_puttxbuf(ah, txq->axq_qnum, head->bf_daddr);
|
||||||
ath_hal_txstart(ah, txq->axq_qnum);
|
ath_hal_txstart(ah, txq->axq_qnum);
|
||||||
@ -7400,7 +7350,6 @@ ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
|||||||
struct ath_txq *txq = &sc->sc_txq[qnum];
|
struct ath_txq *txq = &sc->sc_txq[qnum];
|
||||||
|
|
||||||
txq->axq_qnum = qnum;
|
txq->axq_qnum = qnum;
|
||||||
txq->axq_link = NULL;
|
|
||||||
STAILQ_INIT(&txq->axq_q);
|
STAILQ_INIT(&txq->axq_q);
|
||||||
ATH_TXQ_LOCK_INIT(txq);
|
ATH_TXQ_LOCK_INIT(txq);
|
||||||
txq->axq_depth = 0;
|
txq->axq_depth = 0;
|
||||||
@ -7617,9 +7566,9 @@ ath_tx_findindex(const HAL_RATE_TABLE *rt, int rate)
|
|||||||
static void
|
static void
|
||||||
ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
||||||
{
|
{
|
||||||
struct ath_buf *lastbuf;
|
struct ath_buf *tbf;
|
||||||
|
|
||||||
/* case the delivery queue just sent and can move overflow q over */
|
/* Case the delivery queue just sent and can move overflow q over. */
|
||||||
if (an->an_uapsd_qdepth == 0 && an->an_uapsd_overflowqdepth != 0) {
|
if (an->an_uapsd_qdepth == 0 && an->an_uapsd_overflowqdepth != 0) {
|
||||||
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
||||||
"Delivery queue empty, replacing with overflow queue\n");
|
"Delivery queue empty, replacing with overflow queue\n");
|
||||||
@ -7628,14 +7577,13 @@ ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
|||||||
an->an_uapsd_overflowqdepth = 0;
|
an->an_uapsd_overflowqdepth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* most common case - room on delivery q */
|
/* Most common case - room on delivery q. */
|
||||||
if (an->an_uapsd_qdepth < an->an_node.ni_uapsd_maxsp) {
|
if (an->an_uapsd_qdepth < an->an_node.ni_uapsd_maxsp) {
|
||||||
/* add to delivery q */
|
/* Add to delivery q. */
|
||||||
if ((lastbuf = STAILQ_LAST(&an->an_uapsd_q, ath_buf, bf_list))) {
|
ATH_STQ_LINK_DESC(&an->an_uapsd_q, bf);
|
||||||
lastbuf->bf_desc->ds_link = ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
}
|
|
||||||
STAILQ_INSERT_TAIL(&an->an_uapsd_q, bf, bf_list);
|
STAILQ_INSERT_TAIL(&an->an_uapsd_q, bf, bf_list);
|
||||||
an->an_uapsd_qdepth++;
|
an->an_uapsd_qdepth++;
|
||||||
|
|
||||||
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
||||||
"Added AC %d frame to delivery queue, "
|
"Added AC %d frame to delivery queue, "
|
||||||
"new depth: %d\n",
|
"new depth: %d\n",
|
||||||
@ -7643,30 +7591,24 @@ ath_tx_uapsdqueue(struct ath_softc *sc, struct ath_node *an, struct ath_buf *bf)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if need to make room on overflow queue */
|
/* Check if need to make room on overflow queue. */
|
||||||
if (an->an_uapsd_overflowqdepth == an->an_node.ni_uapsd_maxsp) {
|
if (an->an_uapsd_overflowqdepth == an->an_node.ni_uapsd_maxsp) {
|
||||||
/*
|
/* Pop oldest from delivery queue and cleanup. */
|
||||||
* pop oldest from delivery queue and cleanup
|
tbf = STAILQ_FIRST(&an->an_uapsd_q);
|
||||||
*/
|
|
||||||
lastbuf = STAILQ_FIRST(&an->an_uapsd_q);
|
|
||||||
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
STAILQ_REMOVE_HEAD(&an->an_uapsd_q, bf_list);
|
||||||
ath_return_txbuf(sc, &lastbuf);
|
ath_return_txbuf(sc, &tbf);
|
||||||
|
|
||||||
/*
|
/* Move oldest from overflow to delivery. */
|
||||||
* move oldest from overflow to delivery
|
tbf = STAILQ_FIRST(&an->an_uapsd_overflowq);
|
||||||
*/
|
|
||||||
lastbuf = STAILQ_FIRST(&an->an_uapsd_overflowq);
|
|
||||||
STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list);
|
STAILQ_REMOVE_HEAD(&an->an_uapsd_overflowq, bf_list);
|
||||||
an->an_uapsd_overflowqdepth--;
|
an->an_uapsd_overflowqdepth--;
|
||||||
STAILQ_INSERT_TAIL(&an->an_uapsd_q, lastbuf, bf_list);
|
STAILQ_INSERT_TAIL(&an->an_uapsd_q, tbf, bf_list);
|
||||||
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
DPRINTF(sc, ATH_DEBUG_UAPSD,
|
||||||
"Delivery and overflow queues full. Dropped oldest.\n");
|
"Delivery and overflow queues full. Dropped oldest.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add to overflow q */
|
/* Add to overflow q/ */
|
||||||
if ((lastbuf = STAILQ_LAST(&an->an_uapsd_overflowq, ath_buf, bf_list))) {
|
ATH_STQ_LINK_DESC(&an->an_uapsd_overflowq, bf);
|
||||||
lastbuf->bf_desc->ds_link = ath_ds_link_swap(bf->bf_daddr);
|
|
||||||
}
|
|
||||||
STAILQ_INSERT_TAIL(&an->an_uapsd_overflowq, bf, bf_list);
|
STAILQ_INSERT_TAIL(&an->an_uapsd_overflowq, bf, bf_list);
|
||||||
an->an_uapsd_overflowqdepth++;
|
an->an_uapsd_overflowqdepth++;
|
||||||
DPRINTF(sc, ATH_DEBUG_UAPSD, "Added AC %d to overflow queue, "
|
DPRINTF(sc, ATH_DEBUG_UAPSD, "Added AC %d to overflow queue, "
|
||||||
@ -7951,9 +7893,9 @@ ath_tx_start(struct net_device *dev, struct ieee80211_node *ni,
|
|||||||
* multicast frames must be buffered until after the beacon.
|
* multicast frames must be buffered until after the beacon.
|
||||||
* We use the private mcast queue for that.
|
* We use the private mcast queue for that.
|
||||||
*/
|
*/
|
||||||
if (ismcast && (vap->iv_ps_sta || avp->av_mcastq.axq_depth)) {
|
if (ismcast && (vap->iv_ps_sta || STAILQ_FIRST(&avp->av_mcastq.axq_q))) {
|
||||||
txq = &avp->av_mcastq;
|
txq = &avp->av_mcastq;
|
||||||
/* XXX? more bit in 802.11 frame header */
|
/* XXX: More bit in 802.11 frame header? */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -8291,9 +8233,9 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
|||||||
HAL_STATUS status;
|
HAL_STATUS status;
|
||||||
int uapsdq = 0;
|
int uapsdq = 0;
|
||||||
|
|
||||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "TX queue: %d (0x%x), link: %p\n",
|
DPRINTF(sc, ATH_DEBUG_TX_PROC, "TX queue: %d (0x%x), link: %08x\n",
|
||||||
txq->axq_qnum, ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
txq->axq_qnum, ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||||
txq->axq_link);
|
ATH_TXQ_LAST_DESC(txq)->ds_link);
|
||||||
|
|
||||||
if (txq == sc->sc_uapsdq) {
|
if (txq == sc->sc_uapsdq) {
|
||||||
DPRINTF(sc, ATH_DEBUG_UAPSD, "Reaping U-APSD txq\n");
|
DPRINTF(sc, ATH_DEBUG_UAPSD, "Reaping U-APSD txq\n");
|
||||||
@ -8501,10 +8443,10 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
|||||||
bf_fail:
|
bf_fail:
|
||||||
#ifdef ATH_SUPERG_FF
|
#ifdef ATH_SUPERG_FF
|
||||||
/* flush ff staging queue if buffer low */
|
/* flush ff staging queue if buffer low */
|
||||||
if (txq->axq_depth <= sc->sc_fftxqmin - 1) {
|
if (txq->axq_depth <= sc->sc_fftxqmin - 1)
|
||||||
/* NB: consider only flushing a preset number based on age. */
|
/* NB: consider only flushing a preset number based on age. */
|
||||||
ath_ffstageq_flush(sc, txq, ath_ff_neverflushtestdone);
|
ath_ffstageq_flush(sc, txq, ath_ff_neverflushtestdone);
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
;
|
;
|
||||||
#endif /* ATH_SUPERG_FF */
|
#endif /* ATH_SUPERG_FF */
|
||||||
@ -8553,7 +8495,7 @@ ath_tx_tasklet_q0123(TQUEUE_ARG data)
|
|||||||
if (txqactive(sc->sc_ah, 3))
|
if (txqactive(sc->sc_ah, 3))
|
||||||
ath_tx_processq(sc, &sc->sc_txq[3]);
|
ath_tx_processq(sc, &sc->sc_txq[3]);
|
||||||
if (ATH_TXQ_SETUP(sc, sc->sc_cabq->axq_qnum)
|
if (ATH_TXQ_SETUP(sc, sc->sc_cabq->axq_qnum)
|
||||||
&& sc->sc_cabq->axq_depth) {
|
&& STAILQ_FIRST(&sc->sc_cabq->axq_q)) {
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"Processing CABQ... it is active in HAL.\n");
|
"Processing CABQ... it is active in HAL.\n");
|
||||||
ath_tx_processq(sc, sc->sc_cabq);
|
ath_tx_processq(sc, sc->sc_cabq);
|
||||||
@ -8599,7 +8541,7 @@ ath_tx_tasklet(TQUEUE_ARG data)
|
|||||||
else if (sc->sc_cabq->axq_qnum == i) { /* is CABQ */
|
else if (sc->sc_cabq->axq_qnum == i) { /* is CABQ */
|
||||||
DPRINTF(sc, ATH_DEBUG_BEACON,
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
||||||
"NOT processing CABQ... it is %s.\n",
|
"NOT processing CABQ... it is %s.\n",
|
||||||
sc->sc_cabq->axq_depth ? "not setup" : "empty");
|
STAILQ_FIRST(&sc->sc_cabq->axq_q) ? "not setup" : "empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
netif_wake_queue(dev);
|
netif_wake_queue(dev);
|
||||||
@ -8668,9 +8610,10 @@ ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
|
|||||||
struct ath_hal *ah = sc->sc_ah;
|
struct ath_hal *ah = sc->sc_ah;
|
||||||
|
|
||||||
(void) ath_hal_stoptxdma(ah, txq->axq_qnum);
|
(void) ath_hal_stoptxdma(ah, txq->axq_qnum);
|
||||||
DPRINTF(sc, ATH_DEBUG_RESET, "TX queue [%u] 0x%x, link %p\n",
|
DPRINTF(sc, ATH_DEBUG_RESET, "TX queue [%u] 0x%x, link %08x\n",
|
||||||
txq->axq_qnum,
|
txq->axq_qnum,
|
||||||
ath_hal_gettxbuf(ah, txq->axq_qnum), txq->axq_link);
|
ath_hal_gettxbuf(ah, txq->axq_qnum),
|
||||||
|
ATH_TXQ_LAST_DESC(txq)->ds_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -455,8 +455,16 @@ struct ath_buf {
|
|||||||
const char* bf_taken_at_func;
|
const char* bf_taken_at_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* The last descriptor for a buffer.
|
||||||
|
* NB: This code assumes that the descriptors for a buf are allocated,
|
||||||
|
* contiguously. This assumption is made elsewhere too. */
|
||||||
|
#ifdef ATH_SUPERG_FF
|
||||||
|
# define ATH_BUF_LAST_DESC(_bf) ((_bf)->bf_desc + (_bf)->bf_numdescff)
|
||||||
|
#else
|
||||||
|
# define ATH_BUF_LAST_DESC(_bf) ((_bf)->bf_desc)
|
||||||
|
#endif
|
||||||
/* BF_XX(...) macros will blow up if _bf is NULL, but not if _bf->bf_skb is
|
/* BF_XX(...) macros will blow up if _bf is NULL, but not if _bf->bf_skb is
|
||||||
* null*/
|
* null. */
|
||||||
#define ATH_BUF_CB(_bf) (((_bf)->bf_skb) ? SKB_CB((_bf)->bf_skb) : NULL)
|
#define ATH_BUF_CB(_bf) (((_bf)->bf_skb) ? SKB_CB((_bf)->bf_skb) : NULL)
|
||||||
#define ATH_BUF_NI(_bf) (((_bf)->bf_skb) ? SKB_NI((_bf)->bf_skb) : NULL)
|
#define ATH_BUF_NI(_bf) (((_bf)->bf_skb) ? SKB_NI((_bf)->bf_skb) : NULL)
|
||||||
#define ATH_BUF_AN(_bf) (((_bf)->bf_skb) ? SKB_AN((_bf)->bf_skb) : NULL)
|
#define ATH_BUF_AN(_bf) (((_bf)->bf_skb) ? SKB_AN((_bf)->bf_skb) : NULL)
|
||||||
@ -496,7 +504,6 @@ struct proc_dir_entry;
|
|||||||
*/
|
*/
|
||||||
struct ath_txq {
|
struct ath_txq {
|
||||||
u_int axq_qnum; /* hardware q number */
|
u_int axq_qnum; /* hardware q number */
|
||||||
u_int32_t *axq_link; /* link ptr in last TX desc */
|
|
||||||
STAILQ_HEAD(, ath_buf) axq_q; /* transmit queue */
|
STAILQ_HEAD(, ath_buf) axq_q; /* transmit queue */
|
||||||
spinlock_t axq_lock; /* lock on q and link */
|
spinlock_t axq_lock; /* lock on q and link */
|
||||||
int axq_depth; /* queue depth */
|
int axq_depth; /* queue depth */
|
||||||
@ -576,6 +583,10 @@ struct ath_vap {
|
|||||||
#define ATH_TXQ_LOCK_CHECK(_tq)
|
#define ATH_TXQ_LOCK_CHECK(_tq)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ATH_TXQ_LAST(_txq) \
|
||||||
|
STAILQ_LAST(&(_txq)->axq_q, ath_buf, bf_list)
|
||||||
|
#define ATH_TXQ_LAST_DESC(_txq) \
|
||||||
|
ATH_BUF_LAST_DESC(ATH_TXQ_LAST((_txq)))
|
||||||
#define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \
|
#define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \
|
||||||
STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
|
STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
|
||||||
(_tq)->axq_depth++; \
|
(_tq)->axq_depth++; \
|
||||||
@ -583,24 +594,29 @@ struct ath_vap {
|
|||||||
} while (0)
|
} while (0)
|
||||||
#define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
|
#define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
|
||||||
STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
|
STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
|
||||||
if (--(_tq)->axq_depth <= 0) \
|
--(_tq)->axq_depth; \
|
||||||
(_tq)->axq_link = NULL; \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
/* move buffers from MCASTQ to CABQ */
|
/* Concat. buffers from one queue to other. */
|
||||||
#define ATH_TXQ_MOVE_MCASTQ(_tqs,_tqd) do { \
|
#define ATH_TXQ_MOVE_Q(_tqs,_tqd) do { \
|
||||||
(_tqd)->axq_depth += (_tqs)->axq_depth; \
|
(_tqd)->axq_depth += (_tqs)->axq_depth; \
|
||||||
(_tqd)->axq_totalqueued += (_tqs)->axq_totalqueued; \
|
(_tqd)->axq_totalqueued += (_tqs)->axq_totalqueued; \
|
||||||
(_tqd)->axq_link = (_tqs)->axq_link; \
|
ATH_TXQ_LINK_DESC((_tqd), STAILQ_FIRST(&(_tqs)->axq_q)); \
|
||||||
STAILQ_CONCAT(&(_tqd)->axq_q, &(_tqs)->axq_q); \
|
STAILQ_CONCAT(&(_tqd)->axq_q, &(_tqs)->axq_q); \
|
||||||
(_tqs)->axq_depth = 0; \
|
(_tqs)->axq_depth = 0; \
|
||||||
(_tqs)->axq_totalqueued = 0; \
|
(_tqs)->axq_totalqueued = 0; \
|
||||||
(_tqs)->axq_link = NULL; \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define ATH_TXQ_LINK_DESC(_txq, _bf) \
|
||||||
|
ATH_STQ_LINK_DESC(&(_txq)->axq_q, (_bf))
|
||||||
|
|
||||||
/*
|
/* NB: This macro's behaviour is dependent upon it being called *before* _bf is
|
||||||
* concat buffers from one queue to other
|
* inserted into _stq. */
|
||||||
*/
|
#define ATH_STQ_LINK_DESC(_stq, _bf) do { \
|
||||||
#define ATH_TXQ_MOVE_Q(_tqs,_tqd) ATH_TXQ_MOVE_MCASTQ(_tqs,_tqd)
|
if (STAILQ_FIRST((_stq))) \
|
||||||
|
ATH_BUF_LAST_DESC( \
|
||||||
|
STAILQ_LAST((_stq), ath_buf, bf_list) \
|
||||||
|
)->ds_link = \
|
||||||
|
ath_ds_link_swap((_bf)->bf_daddr); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define BSTUCK_THRESH 10 /* # of stuck beacons before resetting NB: this is a guess*/
|
#define BSTUCK_THRESH 10 /* # of stuck beacons before resetting NB: this is a guess*/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user