Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Oct 2012 11:38:06 -0600
From:      PseudoCylon <moonlightakkiy@yahoo.ca>
To:        Andre Oppermann <oppermann@networx.ch>
Cc:        FreeBSD Net <freebsd-net@freebsd.org>, freebsd-wireless@freebsd.org, freebsd-arch@freebsd.org
Subject:   Re: request for help: 'fixing' the 802.11 TX path
Message-ID:  <CAFZ_MY%2BZ-wtdqtTcqH2jKkpn=8nZatJ5qxp0oRpvXVietGwAmQ@mail.gmail.com>
In-Reply-To: <508E50A3.1030008@networx.ch>
References:  <CAFZ_MYL3v%2BhAea5RaBL4i9o_JjN6_u66znmXXcPsh11L7hHYEg@mail.gmail.com> <CAJ-Vmok5vJNYUbsUuk_Ps=7oLvpJutuyDZ7279bft1qYiYmeTA@mail.gmail.com> <508E50A3.1030008@networx.ch>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Oct 29, 2012 at 3:47 AM, Andre Oppermann <oppermann@networx.ch> wrote:
> On 29.10.2012 04:53, Adrian Chadd wrote:
>>
>> On 28 October 2012 20:43, PseudoCylon <moonlightakkiy@yahoo.ca> wrote:
>>
>>> Cannot we just add custom hand off function to ieee80211_start()?
>>
>>
>> Yes. That's the general idea. But what I don't want to do is have it
>> just wake up the driver TX taskqueue - well, unless we have to.
>>
>> That means we'll have two context switches for each frame being
>> transmitted and that as a concept just sucks.

Plan B

vap->iv_ifp->if_transmit = ieee80211_transmit;

ieee80211_transmit() /* new */
{
        /* Alternatively, we can make a list of param and attach mbuf to it. */
        HANDOFF(parent->if_snd, m);

        ieee80211_new_tx(vap, m);
}

/* enque packet, but keep working on the same mbuf */
ieee80211_new_tx(vap, m)
{
        encap;
        if (fragment)
                insert_fragmented_packet_to_queue;

        /* don't forget about a fragmented packet */
        for (; m->m_nextpkt != NULL; m = m->m_nextpkt)
                parent->if_new_tx(vap, m);
}

/* keep working on the same mbuf */
driver_new_tx(vap, m)
{
        do_descriptor_stuff;

        m->m_flags |= ALL_SET;

        /*
         * If, for instance, processing of queue #5 packet finished
before queue #1,
         * #5 packet will stay in queue until all of preceding packets
get processed.
         */
        if (parent->if_sc->sc_tx == NOT_RUNNING &&
            ifq_head->m_flags & ALL_SET)
                driver_pass2hw(parent);
}

/* finally, process mbuf from the head of queue */
driver_pass2hw()
{
        /* only one thread to dequeue */
        if (atomic_compset(&sc->sc_tx, NOT_RUNNING, RUNNING) == 0)
                return;

        for (;;) {
                DEQUEUE(ifq, m);
                if (!(m->m_flags & ALL_SET)) {
                        PREPEND();
                        break;
                }

                /*
                 * want to do seq stuff somewhere in ieee80211_*(),
                 * but I guess this is the only place could do.
                 */
                do_seqnum_stuff;

                /* simply put a packet onto dma-able memory area */
                pass2hw;
        }
        sc->sc_tx = NOT_RUNNING;
}

No additional context switching, no long-held lock, but first queue first tx.


AK

>>
>> See my (very recent) email to -wireless - I broke TCP throughput quite
>> substantially by moving ath(4) TX into the taskqueue. I thought the
>> problem was _just_ going to be how overlapping, direct dispatch TX
>> could be preempted by the RX tasklet and TX completion, but there's
>> obviously more going on.
>
>
> I can't believe that TCP is getting broken by just introducing some
> additional delay in the TX path.  That can't add more than 300ms,
> can it?  There must be something else going on.  Most likely either
> severe packet loss (the m_nextpkt leak you mentioned earlier) or
> severe packet re-ordering.
>
> So don't rule out the TX taskqueue concept quite yet.
>
> --
> Andre
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFZ_MY%2BZ-wtdqtTcqH2jKkpn=8nZatJ5qxp0oRpvXVietGwAmQ>