[PATCH] Fix alignment issues with DMA TX on BCM4331

Larry Finger Larry.Finger at lwfinger.net
Sat Aug 13 18:14:53 EDT 2011


On 08/13/2011 05:02 PM, Rafał Miłecki wrote:
> W dniu 13 sierpnia 2011 23:57 użytkownik Larry Finger
> <Larry.Finger at lwfinger.net>  napisał:
>> On 08/12/2011 05:27 AM, David Woodhouse wrote:
>>>
>>> When the TX descriptor ring is not aligned to 8KiB on BCM4331, we have
>>> to write the full address to the TXINDEX register or the DMA engine gets
>>> confused after the first time we wrap round to slot zero.
>>>
>>> [ 7438.538945] Poked TX with address fe0 for slot 254
>>> [ 7438.539077] Acking gen reason 20000000
>>> [ 7438.539177] irq xmitstat 20fc1001 0000007f
>>> [ 7438.607861] Poked TX with address 0 for slot 0
>>> [ 7438.608567] Acking gen reason 20000000
>>> [ 7438.608668] irq xmitstat 20fe1001 00000080
>>> [ 7438.608709] irq xmitstat 20000011 00000080
>>> [ 7438.608724] b43-phy2 debug: Out of order TX status report on DMA ring
>>> 1. Expected 256, but got 0
>>> [ 7438.608739] irq xmitstat 20020011 00000080
>>> [ 7438.608750] b43-phy2 debug: Out of order TX status report on DMA ring
>>> 1. Expected 256, but got 2
>>> [ 7438.608765] irq xmitstat 20040011 00000080
>>>
>>> We write 0xff0 to the TXADDRLO register to see if the DMA engine is
>>> capable of unaligned operation. If it *is*, then it'll have this problem
>>> and we have to write the full address to TXINDEX. Comments in brcmsmac
>>> indicate that the low 13 bits are required.
>>>
>>> If we're doing this, we *also* have to write to TXCTL to enable the DMA
>>> engine *after* setting up the ring address.
>>>
>>> Signed-off-by: David Woodhouse<David.Woodhouse at intel.com>
>>> --
>>> I've made that change to the initialisation order of TXCTL vs.
>>> TXADDR{HI,LO} unconditional; is there a reason not to?
>>>
>>> diff --git a/drivers/net/wireless/b43/dma.c
>>> b/drivers/net/wireless/b43/dma.c
>>> index 82168f8..92dd6d9 100644
>>> --- a/drivers/net/wireless/b43/dma.c
>>> +++ b/drivers/net/wireless/b43/dma.c
>>> @@ -225,8 +225,10 @@ static void op64_fill_descriptor(struct b43_dmaring
>>> *ring,
>>>
>>>   static void op64_poke_tx(struct b43_dmaring *ring, int slot)
>>>   {
>>> -       b43_dma_write(ring, B43_DMA64_TXINDEX,
>>> -                     (u32) (slot * sizeof(struct b43_dmadesc64)));
>>> +       u32 indexval = slot * sizeof(struct b43_dmadesc64);
>>> +       if (ring->unaligned)
>>> +               indexval |= (u32)ring->dmabase;
>>> +       b43_dma_write(ring, B43_DMA64_TXINDEX, indexval);
>>>   }
>>>
>>>   static void op64_tx_suspend(struct b43_dmaring *ring)
>>> @@ -704,9 +710,14 @@ static int dmacontroller_setup(struct b43_dmaring
>>> *ring)
>>>                         &    B43_DMA64_TXADDREXT_MASK;
>>>                         if (!parity)
>>>                                 value |= B43_DMA64_TXPARITYDISABLE;
>>> -                       b43_dma_write(ring, B43_DMA64_TXCTL, value);
>>> +
>>> +                       b43_dma_write(ring, B43_DMA64_TXRINGLO, 0xff0);
>>
>> Should there be a new symbol rather than this magic number?
>>
>>> +                       if (b43_dma_read(ring, B43_DMA64_TXRINGLO))
>>> +                               ring->unaligned = 1;
>>> +
>>>                         b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo);
>>>                         b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);
>>> +                       b43_dma_write(ring, B43_DMA64_TXCTL, value);
>>>                 } else {
>>>                         u32 ringbase = (u32) (ring->dmabase);
>>>                         addrext = b43_dma_address(&ring->dev->dma,
>>> ringbase, B43_DMA_ADDR_EXT);
>>> diff --git a/drivers/net/wireless/b43/dma.h
>>> b/drivers/net/wireless/b43/dma.h
>>> index 7e20b04f..16dc565 100644
>>> --- a/drivers/net/wireless/b43/dma.h
>>> +++ b/drivers/net/wireless/b43/dma.h
>>> @@ -251,6 +251,8 @@ struct b43_dmaring {
>>>         int index;
>>>         /* Boolean. Is this a TX ring? */
>>>         bool tx;
>>> +       /* Boolean. Is this ring capable of 16-byte alignment? */
>>> +       bool unaligned;
>>>         /* The type of DMA engine used. */
>>>         enum b43_dmatype type;
>>>         /* Boolean. Is this ring stopped at ieee80211 level? */
>>>
>>
>> Tested on BCM4318 on 32-bit system.
>
> The question is if your card supports unaligned (and as result, if you
> tested it at all)

I should have made it clearer. My card does 32-bit DMA, thus this code does not 
change anything in its code. What I tested is that the patch did not break 
operations on my card due to some unforeseen complication.

Larry



More information about the b43-dev mailing list