mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 13:11:45 +00:00
b43: Workaround DMA quirks
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>
This commit is contained in:
parent
0da926f057
commit
1033b3ea11
@ -980,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev)
|
||||
destroy_ring(dma, tx_ring_mcast);
|
||||
}
|
||||
|
||||
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;
|
||||
@ -989,14 +1025,9 @@ int b43_dma_init(struct b43_wldev *dev)
|
||||
|
||||
dmamask = supported_dma_mask(dev);
|
||||
type = dma_mask_to_engine_type(dmamask);
|
||||
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;
|
||||
}
|
||||
err = b43_dma_set_mask(dev, dmamask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = -ENOMEM;
|
||||
/* setup TX DMA channels. */
|
||||
|
Loading…
Reference in New Issue
Block a user