From: Dave Taht <dave.taht@gmail.com>
To: cerowrt@lists.bufferbloat.net,
"cerowrt-devel@lists.bufferbloat.net"
<cerowrt-devel@lists.bufferbloat.net>
Subject: [Cerowrt-devel] [bug #442] tearing apart ath_tx_start in search of the hang
Date: Mon, 14 Apr 2014 16:08:00 -0700 [thread overview]
Message-ID: <CAA93jw5tEb4Za_XoBQh9RPiPz8F7C4KvPUs4HEbrsqKBWNq5rg@mail.gmail.com> (raw)
So what we are seeing here is some sort of problem with accounting
for pending_frames on a given queue. And since we've had a reminder
of how useful code review can be - and I'd rather like to understand
this logic anyway -
// my comments in //
/* Upon failure caller should free skb */
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txctl->sta;
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
struct ath_atx_tid *tid = NULL;
struct ath_buf *bf;
int q;
int ret;
ret = ath_tx_prepare(hw, skb, txctl);
if (ret)
return ret;
hdr = (struct ieee80211_hdr *) skb->data;
/*
* At this point, the vif, hw_key and sta pointers in the tx control
* info are no longer valid (overwritten by the ath_frame_info data.
*/
// I haven't looked at what skb_get_queue_mapping can return yet
q = skb_get_queue_mapping(skb);
ath_txq_lock(sc, txq);
if (txq == sc->tx.txq_map[q] &&
++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
ieee80211_stop_queue(sc->hw, q);
txq->stopped = true;
// is there a difference between stopped and sleeping?
}
// So if the queue is not mapped properly we don't increment pending
// frames. Also we are dependent on C processing the if left to right,
// which is a good assumption, but it leaves the ++txq as a side effect
if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
tid = ath_get_skb_tid(sc, txctl->an, skb);
if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
ath_txq_unlock(sc, txq);
txq = sc->tx.uapsdq;
// So here we have a bit of state that changes after we've got some pending
// state above that's been changed. I imagine this lock could stay unlocked
// for a while and lead to races elsewhere.
// haven't a clue what tx.uapsdq is
ath_txq_lock(sc, txq);
} else if (txctl->an &&
ieee80211_is_data_present(hdr->frame_control)) {
WARN_ON(tid->ac->txq != txctl->txq);
if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
tid->ac->clear_ps_filter = true;
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
TX_STAT_INC(txq->axq_qnum, a_queued_sw);
__skb_queue_tail(&tid->buf_q, skb);
if (!txctl->an->sleeping)
ath_tx_queue_tid(txq, tid);
// so if we're not sleeping, queue it up
// and regardless if we're sleeping or not, schedule it
ath_txq_schedule(sc, txq);
goto out;
}
// So if data is not present OR txctl->an is invalid OR
IEEE80211_TX_CTL_PS_RESPONSE is set in flags
/// we fall through to here.
bf = ath_tx_setup_buffer(sc, txq, tid, skb);
// if we fell through to here, tid can be null unless data was present
if (!bf) {
ath_txq_skb_done(sc, txq, skb);
if (txctl->paprd)
dev_kfree_skb_any(skb);
else
ieee80211_free_txskb(sc->hw, skb);
goto out;
}
// Well, I note that we incremented the frames earlier in some cases
// should they be decremented above?
bf->bf_state.bfs_paprd = txctl->paprd;
if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies;
ath_set_rates(vif, sta, bf);
ath_tx_send_normal(sc, txq, tid, skb);
// Not clear as to why you set_rates here, and I assume tx_send_normal
// sends a non-aggregate
out:
ath_txq_unlock(sc, txq);
return 0;
}
--
Dave Täht
NSFW: https://w2.eff.org/Censorship/Internet_censorship_bills/russell_0296_indecent.article
next reply other threads:[~2014-04-14 23:08 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-14 23:08 Dave Taht [this message]
2014-04-15 8:56 ` Robert Bradley
2014-04-16 17:28 ` Robert Bradley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.bufferbloat.net/postorius/lists/cerowrt-devel.lists.bufferbloat.net/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAA93jw5tEb4Za_XoBQh9RPiPz8F7C4KvPUs4HEbrsqKBWNq5rg@mail.gmail.com \
--to=dave.taht@gmail.com \
--cc=cerowrt-devel@lists.bufferbloat.net \
--cc=cerowrt@lists.bufferbloat.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox