From: Ivo van Doorn <ivdoorn@gmail.com>
To: "Mikko Virkkilä" <mikko.virkkila@bluegiga.com>
Cc: rt2400-devel@lists.sourceforge.net,
"John W. Linville" <linville@tuxdriver.com>,
"linux-wireless" <linux-wireless@vger.kernel.org>
Subject: Re: [RFC][PATCH] TX status reporting with help of an ack queue
Date: Mon, 15 Sep 2008 19:11:32 +0200 [thread overview]
Message-ID: <200809151911.32834.IvDoorn@gmail.com> (raw)
In-Reply-To: <1221494693.14102.22.camel@virkkmi-linux>
On Monday 15 September 2008, Mikko Virkkil=C3=A4 wrote:
> Modeled after the waiting-for-ack queue in the zd1211rw
> driver, this patch adds a similar queue to the rt2x00. If
> the tx state of a packet is unknown and a tx ack or
> tx fail is needed, then the packet is pushed to a
> waiting-for-ack queue. Each time an ack is received the
> queue is checked and a possible match is reported to
> mac80211 as a tx ack.
>=20
> If the queue gets filled up the oldest waiting packet
> will be discarded and a tx fail will be reported.
I believe it was mentioned it earlier as well, but this code belongs
to mac80211 rather than being copied in all individual drivers.
I think the best solution would be:
- Drivers set *unknown TX status* flag for mac80211
- Mac80211 sets the FIF_CONTROL flag for the RX filter (or adds a new
more specific flag FIF_ACK for hardware that allows this specific fi=
ltering (rt2800))
- Driver will set a *unknown TX status* flag per send out frame
- Mac80211 keeps track of ACK responses, and decides what to do when
no ACK has been received for the frame.
Note that rt61 might be tricky since that does support TX status report=
ing,
but it fails in only 1% of the cases to do this, which means enabling t=
his for rt61
would be far too much overhead.
> This doesn't use timers so a message might in theory be
> stuck in the queue indefinitely.
Well you wouldn't need timers actually, if you have a list of packets
waiting to be acked you can expect the frames to be acked in the order
of which they were send (when using the same queue).
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wi=
reless/rt2x00/rt2x00dev.c
> index 2f3bfc6..57020de 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -495,6 +495,30 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2=
x00dev)
> }
> EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
> =20
> +static struct sk_buff *rt2x00lib_get_match_from_ack_queue(
> + struct sk_buff_head *q, struct ieee80211_hdr *rx_hdr)
> +{
> + struct sk_buff *skb;
> + for (skb =3D q->next; skb !=3D (struct sk_buff *)q; skb =3D skb->ne=
xt) {
> + struct ieee80211_hdr *tx_hdr;
> + tx_hdr =3D (struct ieee80211_hdr *)skb->data;
> + if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) {
Why is this likely() do we really expect the first ack in the list to b=
e the rigth one?
And is this enough to match a frame to an ack?
> @@ -560,7 +584,22 @@ void rt2x00lib_txdone(struct queue_entry *entry,
> * status report back.
> */
> if (tx_info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
> - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
> + if (test_bit(TXDONE_UNKNOWN, &txdesc->flags)) {
> + struct sk_buff *failed_skb;
> + failed_skb =3D rt2x00lib_push_to_ack_queue(
> + &rt2x00dev->ack_wait_queue, entry->skb);
> + if (failed_skb) {
> + struct ieee80211_tx_info *info;
> + info =3D IEEE80211_SKB_CB(failed_skb);
> + info->status.excessive_retries =3D 1;
> + rt2x00dev->link.qual.tx_failed++;
> + rt2x00dev->low_level_stats.dot11RTSFailureCount++;
> + DEBUG(rt2x00dev, "ACK queue: fail oldest\n");
> + ieee80211_tx_status_irqsafe(rt2x00dev->hw,
> + failed_skb);
> + }
> + } else
> + ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
> else
> dev_kfree_skb_irq(entry->skb);
> =20
> @@ -694,7 +733,26 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00d=
ev,
> * mac80211 will clean up the skb structure.
> */
> rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
> - ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
> +
> + if (ieee80211_is_ack(hdr->frame_control)) {
> + struct sk_buff *match =3D NULL;
> + match =3D rt2x00lib_get_match_from_ack_queue(
> + &rt2x00dev->ack_wait_queue, hdr);
> + if (match) {
> + struct ieee80211_tx_info *tx_info;
> + tx_info =3D IEEE80211_SKB_CB(match);
> + tx_info->flags |=3D IEEE80211_TX_STAT_ACK;
> + rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
Incorrect, you need to check if this was an RTS frame if you want to in=
crement this counter.
> + rt2x00dev->link.qual.tx_success++;
> + DEBUG(rt2x00dev, "ACK hit in queue\n")
> + ieee80211_tx_status_irqsafe(rt2x00dev->hw, match);
> + } else {
> + DEBUG(rt2x00dev, "Got ACK but not in queue\n")
> + }
> + /* Unmap done at start of func, so just free */
> + dev_kfree_skb_irq(entry->skb);
> + } else
> + ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
This breaks when mac80211 requested FIF_CONTROL, you are now always
filtering out ACK frames no matter what mac80211 requested.
> /*
> * Replace the skb with the freshly allocated one.
> @@ -974,6 +1032,11 @@ static int rt2x00lib_initialize(struct rt2x00_d=
ev *rt2x00dev)
> return status;
> =20
> /*
> + * Initialize queue for messages waiting for acks
> + */
> + skb_queue_head_init(&rt2x00dev->ack_wait_queue);
> +
> + /*
> * Initialize the device.
> */
> status =3D rt2x00dev->ops->lib->initialize(rt2x00dev);
> @@ -1107,6 +1170,14 @@ exit:
> }
> EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev);
> =20
> +static void rt2x00lib_free_ack_wait_queue(struct rt2x00_dev *rt2x00d=
ev)
> +{
> + struct sk_buff_head *ack_wait_queue =3D &rt2x00dev->ack_wait_queue;
> + struct sk_buff *skb;
> + while ((skb =3D skb_dequeue(ack_wait_queue)))
> + dev_kfree_skb_any(skb);
> +}
> +
> void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
> {
> clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
> @@ -1142,6 +1213,11 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *r=
t2x00dev)
> * Free queue structures.
> */
> rt2x00queue_free(rt2x00dev);
> +
> + /*
> + * Free ack wait queue
> + */
> + rt2x00lib_free_ack_wait_queue(rt2x00dev);
skb_queue_purge(&rt2x00dev->ack_wait_queue) ?
> }
> EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
> =20
> diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wire=
less/rt2x00/rt73usb.c
> index 27dde3e..e082d30 100644
> --- a/drivers/net/wireless/rt2x00/rt73usb.c
> +++ b/drivers/net/wireless/rt2x00/rt73usb.c
> @@ -593,8 +593,7 @@ static void rt73usb_config_filter(struct rt2x00_d=
ev *rt2x00dev,
> !(filter_flags & FIF_FCSFAIL));
> rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL,
> !(filter_flags & FIF_PLCPFAIL));
> - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL,
> - !(filter_flags & FIF_CONTROL));
> + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0);
> rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME,
> !(filter_flags & FIF_PROMISC_IN_BSS));
> rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS,
> @@ -604,8 +603,7 @@ static void rt73usb_config_filter(struct rt2x00_d=
ev *rt2x00dev,
> rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST,
> !(filter_flags & FIF_ALLMULTI));
> rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);
> - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,
> - !(filter_flags & FIF_CONTROL));
> + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 0);
> rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
> }
> =20
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next parent reply other threads:[~2008-09-15 17:11 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1221494693.14102.22.camel@virkkmi-linux>
2008-09-15 17:11 ` Ivo van Doorn [this message]
2008-09-15 17:56 ` [RFC][PATCH] TX status reporting with help of an ack queue Mattias Nissler
2008-09-15 18:03 ` Johannes Berg
2008-09-15 19:00 ` Mattias Nissler
2008-09-15 19:21 ` Johannes Berg
2008-09-15 19:39 ` Mattias Nissler
2008-09-15 19:46 ` Johannes Berg
2008-09-15 20:20 ` Mattias Nissler
2008-09-15 20:33 ` Johannes Berg
2008-09-15 21:01 ` Mattias Nissler
2008-09-24 0:59 ` John W. Linville
2008-09-24 7:40 ` Mattias Nissler
2008-09-24 8:34 ` Johannes Berg
2008-09-15 21:28 ` Ivo van Doorn
2008-09-15 21:41 ` Mattias Nissler
2008-09-16 18:17 ` Ivo van Doorn
2008-09-17 23:08 ` Mattias Nissler
2008-09-16 6:24 ` Mikko Virkkilä
2008-09-16 4:58 ` Mikko Virkkilä
2008-09-16 18:18 ` Ivo van Doorn
2008-09-18 20:37 ` Mattias Nissler
2008-09-18 22:29 ` ACK matching [was: TX status reporting with help of an ack queue] Mattias Nissler
2008-09-19 9:08 ` Mikko Virkkilä
2008-09-19 9:46 ` Mattias Nissler
2008-09-19 9:54 ` Johannes Berg
2008-09-19 10:19 ` Mattias Nissler
2008-09-19 10:31 ` Johannes Berg
2008-09-19 13:51 ` Mattias Nissler
2008-09-19 13:55 ` Johannes Berg
2008-09-19 14:20 ` Mikko Virkkilä
2008-09-19 17:50 ` Jouni Malinen
2008-09-23 6:09 ` Mikko Virkkilä
2008-09-23 7:05 ` Mattias Nissler
2008-09-19 18:30 ` Ivo van Doorn
2008-10-19 5:49 ` Daniel Drake
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200809151911.32834.IvDoorn@gmail.com \
--to=ivdoorn@gmail.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=mikko.virkkila@bluegiga.com \
--cc=rt2400-devel@lists.sourceforge.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;
as well as URLs for NNTP newsgroup(s).