lkml.org 
[lkml]   [2008]   [Apr]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[25/37] b43: Workaround DMA quirks
    2.6.25-stable review patch.  If anyone has any objections, please let us
    know.

    ------------------
    From: Michael Buesch <mb@bu3sch.de>

    commit 1033b3ea11820ea1fb1b877207bd6724e9aaedc3 upstream

    Some mainboards/CPUs don't allow DMA masks bigger than a certain limit.
    Some VIA crap^h^h^h^hdevices have an upper limit of 0xFFFFFFFF. So in this
    case a 64-bit b43 device would always fail to acquire the mask.
    Implement a workaround to fallback to lower DMA mask, as we can always
    also support a lower mask.

    Signed-off-by: Michael Buesch <mb@bu3sch.de>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>


    ---
    drivers/net/wireless/b43/dma.c | 73 +++++++++++++++++++++++++++++------------
    1 file changed, 52 insertions(+), 21 deletions(-)

    --- a/drivers/net/wireless/b43/dma.c
    +++ b/drivers/net/wireless/b43/dma.c
    @@ -822,6 +822,18 @@ static u64 supported_dma_mask(struct b43
    return DMA_30BIT_MASK;
    }

    +static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
    +{
    + if (dmamask == DMA_30BIT_MASK)
    + return B43_DMA_30BIT;
    + if (dmamask == DMA_32BIT_MASK)
    + return B43_DMA_32BIT;
    + if (dmamask == DMA_64BIT_MASK)
    + return B43_DMA_64BIT;
    + B43_WARN_ON(1);
    + return B43_DMA_30BIT;
    +}
    +
    /* Main initialization function. */
    static
    struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
    @@ -982,6 +994,42 @@ void b43_dma_free(struct b43_wldev *dev)
    dma->tx_ring0 = NULL;
    }

    +static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
    +{
    + u64 orig_mask = mask;
    + bool fallback = 0;
    + int err;
    +
    + /* Try to set the DMA mask. If it fails, try falling back to a
    + * lower mask, as we can always also support a lower one. */
    + while (1) {
    + err = ssb_dma_set_mask(dev->dev, mask);
    + if (!err)
    + break;
    + if (mask == DMA_64BIT_MASK) {
    + mask = DMA_32BIT_MASK;
    + fallback = 1;
    + continue;
    + }
    + if (mask == DMA_32BIT_MASK) {
    + mask = DMA_30BIT_MASK;
    + fallback = 1;
    + continue;
    + }
    + b43err(dev->wl, "The machine/kernel does not support "
    + "the required %u-bit DMA mask\n",
    + (unsigned int)dma_mask_to_engine_type(orig_mask));
    + return -EOPNOTSUPP;
    + }
    + if (fallback) {
    + b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
    + (unsigned int)dma_mask_to_engine_type(orig_mask),
    + (unsigned int)dma_mask_to_engine_type(mask));
    + }
    +
    + return 0;
    +}
    +
    int b43_dma_init(struct b43_wldev *dev)
    {
    struct b43_dma *dma = &dev->dma;
    @@ -991,27 +1039,10 @@ int b43_dma_init(struct b43_wldev *dev)
    enum b43_dmatype type;

    dmamask = supported_dma_mask(dev);
    - switch (dmamask) {
    - default:
    - B43_WARN_ON(1);
    - case DMA_30BIT_MASK:
    - type = B43_DMA_30BIT;
    - break;
    - case DMA_32BIT_MASK:
    - type = B43_DMA_32BIT;
    - break;
    - case DMA_64BIT_MASK:
    - type = B43_DMA_64BIT;
    - break;
    - }
    - err = ssb_dma_set_mask(dev->dev, dmamask);
    - if (err) {
    - b43err(dev->wl, "The machine/kernel does not support "
    - "the required DMA mask (0x%08X%08X)\n",
    - (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
    - (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
    - return -EOPNOTSUPP;
    - }
    + type = dma_mask_to_engine_type(dmamask);
    + err = b43_dma_set_mask(dev, dmamask);
    + if (err)
    + return err;

    err = -ENOMEM;
    /* setup TX DMA channels. */
    --


    \
     
     \ /
      Last update: 2008-04-29 19:33    [W:4.195 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site