aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-04-23 13:13:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-23 21:25:36 -0400
commit1033b3ea11820ea1fb1b877207bd6724e9aaedc3 (patch)
tree6037db5b31dcaa0596f5cca9843612707c881279 /drivers
parent0da926f05748d273e7b2b673b0de21629ae9acdd (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/b43/dma.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 21c886a9a1d9..6dcbb3c87e72 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -980,6 +980,42 @@ void b43_dma_free(struct b43_wldev *dev)
980 destroy_ring(dma, tx_ring_mcast); 980 destroy_ring(dma, tx_ring_mcast);
981} 981}
982 982
983static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
984{
985 u64 orig_mask = mask;
986 bool fallback = 0;
987 int err;
988
989 /* Try to set the DMA mask. If it fails, try falling back to a
990 * lower mask, as we can always also support a lower one. */
991 while (1) {
992 err = ssb_dma_set_mask(dev->dev, mask);
993 if (!err)
994 break;
995 if (mask == DMA_64BIT_MASK) {
996 mask = DMA_32BIT_MASK;
997 fallback = 1;
998 continue;
999 }
1000 if (mask == DMA_32BIT_MASK) {
1001 mask = DMA_30BIT_MASK;
1002 fallback = 1;
1003 continue;
1004 }
1005 b43err(dev->wl, "The machine/kernel does not support "
1006 "the required %u-bit DMA mask\n",
1007 (unsigned int)dma_mask_to_engine_type(orig_mask));
1008 return -EOPNOTSUPP;
1009 }
1010 if (fallback) {
1011 b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
1012 (unsigned int)dma_mask_to_engine_type(orig_mask),
1013 (unsigned int)dma_mask_to_engine_type(mask));
1014 }
1015
1016 return 0;
1017}
1018
983int b43_dma_init(struct b43_wldev *dev) 1019int b43_dma_init(struct b43_wldev *dev)
984{ 1020{
985 struct b43_dma *dma = &dev->dma; 1021 struct b43_dma *dma = &dev->dma;
@@ -989,14 +1025,9 @@ int b43_dma_init(struct b43_wldev *dev)
989 1025
990 dmamask = supported_dma_mask(dev); 1026 dmamask = supported_dma_mask(dev);
991 type = dma_mask_to_engine_type(dmamask); 1027 type = dma_mask_to_engine_type(dmamask);
992 err = ssb_dma_set_mask(dev->dev, dmamask); 1028 err = b43_dma_set_mask(dev, dmamask);
993 if (err) { 1029 if (err)
994 b43err(dev->wl, "The machine/kernel does not support " 1030 return err;
995 "the required DMA mask (0x%08X%08X)\n",
996 (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
997 (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
998 return -EOPNOTSUPP;
999 }
1000 1031
1001 err = -ENOMEM; 1032 err = -ENOMEM;
1002 /* setup TX DMA channels. */ 1033 /* setup TX DMA channels. */