Dear All,
In order to switch the current channel to another idle one when the retry count reaches (2) and for the receiver to switch to the same channel during transmission, I added the following lines to the function (ath_tx_processq) (highlighted) but unfortunately, it didn't work, Any hints?
Thank you so much...
static void
ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ieee80211com *ic = &sc->sc_ic;
struct net_device *dev = ic->ic_dev;
struct ieee80211vap *vap = netdev_priv(dev);
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf = NULL;
struct ath_desc *ds = NULL;
struct ath_tx_status *ts = NULL;
struct ieee80211_node *ni = NULL;
struct ath_node *an = NULL;
unsigned int sr, lr;
HAL_STATUS status;
int uapsdq = 0;
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),
ath_get_last_ds_link(txq));
if (txq == sc->sc_uapsdq) {
DPRINTF(sc, ATH_DEBUG_UAPSD, "Reaping U-APSD txq\n");
uapsdq = 1;
}
while (1) {
ATH_TXQ_LOCK_IRQ(txq);
txq->axq_intrcnt = 0; /* reset periodic desc intr count */
bf = STAILQ_FIRST(&txq->axq_q);
if (bf == NULL) {
ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
goto bf_fail;
}
#ifdef ATH_SUPERG_FF
ds = &bf->bf_desc[bf->bf_numdescff];
DPRINTF(sc, ATH_DEBUG_TX_PROC, "Frame's last desc: %p\n",
ds);
#else
ds = bf->bf_desc; /* NB: last descriptor */
#endif
ts = &bf->bf_dsstatus.ds_txstat;
status = ath_hal_txprocdesc(ah, ds, ts);
#ifdef AR_DEBUG
if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
ath_printtxbuf(bf, status == HAL_OK);
#endif
if (status == HAL_EINPROGRESS) {
ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
goto bf_fail;
}
/* We make sure we don't remove the TX descriptor on
* which the HW is pointing since it contains the
* ds_link field, except if this is the last TX
* descriptor in the queue */
if ((txq->axq_depth > 1) && (bf->bf_daddr ==
ath_hal_gettxbuf(ah, txq->axq_qnum))) {
ATH_TXQ_UNLOCK_IRQ_EARLY(txq);
goto bf_fail;
}
ATH_TXQ_REMOVE_HEAD(txq, bf_list);
ATH_TXQ_UNLOCK_IRQ(txq);
ni = ATH_BUF_NI(bf);
if (ni != NULL) {
an = ATH_NODE(ni);
if (ts->ts_status == 0) {
u_int8_t txant = ts->ts_antenna;
sc->sc_stats.ast_ant_tx[txant]++;
sc->sc_ant_tx[txant]++;
#ifdef ATH_SUPERG_FF
if (bf->bf_numdescff > 0)
ni->ni_vap->iv_stats.is_tx_ffokcnt++;
#endif
if (ts->ts_rate & HAL_TXSTAT_ALTRATE)
sc->sc_stats.ast_tx_altrate++;
sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
/* Update HAL stats for ANI, only when on-channel */
if (!sc->sc_scanning &&
!(sc->sc_ic.ic_flags & IEEE80211_F_SCAN))
ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
ts->ts_rssi);
if (bf->bf_skb->priority == WME_AC_VO ||
bf->bf_skb->priority == WME_AC_VI)
ni->ni_ic->ic_wme.wme_hipri_traffic++;
ni->ni_inact = ni->ni_inact_reload;
} else {
#ifdef ATH_SUPERG_FF
if (bf->bf_numdescff > 0)
ni->ni_vap->iv_stats.is_tx_fferrcnt++;
#endif
if (ts->ts_status & HAL_TXERR_XRETRY) {
sc->sc_stats.ast_tx_xretries++;
if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) {
ni->ni_stats.ns_tx_eosplost++;
DPRINTF(sc, ATH_DEBUG_UAPSD,
"Frame in SP "
"retried out, "
"possible EOSP "
"stranded!!!\n");
}
}
if (ts->ts_status & HAL_TXERR_FIFO)
sc->sc_stats.ast_tx_fifoerr++;
if (ts->ts_status & HAL_TXERR_FILT)
sc->sc_stats.ast_tx_filtered++;
}
sr = ts->ts_shortretry;
lr = ts->ts_longretry;
if(lr== 2){
ic->ic_curchan->ic_freq = 2437;
ic-> ic_curchan->ic_ieee = 06;
ath_set_channel(ic);
ieee80211_send_csa_frame(vap, IEEE80211_CSA_CAN_STOP_TX,ic->ic_curchan->ic_ieee,0);
};
sc->sc_stats.ast_tx_shortretry += sr;
sc->sc_stats.ast_tx_longretry += lr;
/*
* Hand the descriptor to the rate control algorithm
* if the frame wasn't dropped for filtering or sent
* w/o waiting for an ack. In those cases the rssi
* and retry counts will be meaningless.
*/
if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
(bf->bf_flags & HAL_TXDESC_NOACK) == 0)
sc->sc_rc->ops->tx_complete(sc, an, bf);
}
bus_unmap_single(sc->sc_bdev, bf->bf_skbaddr,
bf->bf_skb->len, BUS_DMA_TODEVICE);
bf->bf_skbaddr = 0;
if (ni && uapsdq) {
/* detect EOSP for this node */
struct ieee80211_qosframe *qwh =
(struct ieee80211_qosframe *)bf->bf_skb->data;
an = ATH_NODE(ni);
KASSERT(ni != NULL, ("Processing U-APSD txq for "
"ath_buf with no node!"));
if (qwh->i_qos[0] & IEEE80211_QOS_EOSP) {
DPRINTF(sc, ATH_DEBUG_UAPSD,
"EOSP detected for node (" MAC_FMT ") on desc %p\n",
MAC_ADDR(ni->ni_macaddr), ds);
ATH_NODE_UAPSD_LOCK_IRQ(an);
ni->ni_flags &= ~IEEE80211_NODE_UAPSD_SP;
if ((an->an_uapsd_qdepth == 0) &&
(an->an_uapsd_overflowqdepth != 0)) {
STAILQ_CONCAT(&an->an_uapsd_q,
&an->an_uapsd_overflowq);
an->an_uapsd_qdepth =
an->an_uapsd_overflowqdepth;
an->an_uapsd_overflowqdepth = 0;
}
ATH_NODE_UAPSD_UNLOCK_IRQ(an);
}
}
{
struct ieee80211_frame *wh =
(struct ieee80211_frame *)bf->bf_skb->data;
if ((ts->ts_seqnum << IEEE80211_SEQ_SEQ_SHIFT) &
~IEEE80211_SEQ_SEQ_MASK) {
DPRINTF(sc, ATH_DEBUG_TX_PROC,
"Hardware assigned sequence number is "
"not sane (%d), ignoring it\n",
ts->ts_seqnum);
} else {
DPRINTF(sc, ATH_DEBUG_TX_PROC,
"Updating frame's sequence number "
"from %d to %d\n",
((le16toh(*(__le16 *)&wh->i_seq[0]) &
IEEE80211_SEQ_SEQ_MASK)) >>
IEEE80211_SEQ_SEQ_SHIFT,
ts->ts_seqnum);
*(__le16 *)&wh->i_seq[0] = htole16(
ts->ts_seqnum << IEEE80211_SEQ_SEQ_SHIFT |
(le16toh(*(__le16 *)&wh->i_seq[0]) &
~IEEE80211_SEQ_SEQ_MASK));
}
}
{
u_int32_t tstamp;
/* Extend tstamp to a full TSF.
* TX descriptor contains the transmit time in TUs,
* (bits 25-10 of the TSF). */
#define TSTAMP_TX_MASK ((2 ^ (27 - 1)) - 1) /* First 27 bits. */
tstamp = IEEE80211_TU_TO_TSF(ts->ts_tstamp);
bf->bf_tsf = ((bf->bf_tsf & ~TSTAMP_TX_MASK) | tstamp);
if ((bf->bf_tsf & TSTAMP_TX_MASK) < tstamp)
bf->bf_tsf -= TSTAMP_TX_MASK + 1;
}
{
struct sk_buff *tskb = NULL, *skb = bf->bf_skb;
#ifdef ATH_SUPERG_FF
unsigned int i;
#endif
/* HW is now finished with the SKB, so it is safe to
* remove padding. */
ath_skb_removepad(&sc->sc_ic, skb);
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
bf->bf_skb);
tskb = skb->next;
ieee80211_input_monitor(&sc->sc_ic, skb, bf,
1 /* TX */, bf->bf_tsf, sc);
skb = tskb;
#ifdef ATH_SUPERG_FF
/* Handle every skb after the first one - these are FF
* extra buffers */
for (i = 0; i < bf->bf_numdescff; i++) {
ath_skb_removepad(&sc->sc_ic, skb); /* XXX: padding for FF? */
DPRINTF(sc, ATH_DEBUG_TX_PROC, "capture skb %p\n",
skb);
tskb = skb->next;
ieee80211_input_monitor(&sc->sc_ic, skb, bf,
1 /* TX */, bf->bf_tsf, sc);
skb = tskb;
}
bf->bf_numdescff = 0;
#endif
}
ni = NULL;
ath_return_txbuf(sc, &bf);
}
bf_fail:
#ifdef ATH_SUPERG_FF
/* flush ff staging queue if buffer low */
if (txq->axq_depth <= sc->sc_fftxqmin - 1)
/* NB: consider only flushing a preset number based on age. */
ath_ffstageq_flush(sc, txq, ath_ff_neverflushtestdone);
#else
;
#endif /* ATH_SUPERG_FF */
}
--
Mohammad Jaser Abdelhadi
----------------------------------------------------------------------------
Communications Engineering-Senior Student
Princess Sumaya University for Technology
Mobile: +962777030924
Email: moh.jaser@yahoo.com \ mo.jaser@gmail.com