]> err.no Git - linux-2.6/blobdiff - drivers/ssb/main.c
Merge branch 'for-linus' of git://git.o-hand.com/linux-mfd
[linux-2.6] / drivers / ssb / main.c
index 6ce92e82b64e98c9a0ae18d3bc89e5891032fedd..d831a2beff393079d9a20686494bf022be1f7651 100644 (file)
@@ -1153,31 +1153,82 @@ u32 ssb_dma_translation(struct ssb_device *dev)
 {
        switch (dev->bus->bustype) {
        case SSB_BUSTYPE_SSB:
-       case SSB_BUSTYPE_PCMCIA:
                return 0;
        case SSB_BUSTYPE_PCI:
                return SSB_PCI_DMA;
+       default:
+               __ssb_dma_not_implemented(dev);
        }
        return 0;
 }
 EXPORT_SYMBOL(ssb_dma_translation);
 
-int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask)
+int ssb_dma_set_mask(struct ssb_device *dev, u64 mask)
 {
-       struct device *dev = ssb_dev->dev;
-
-#ifdef CONFIG_SSB_PCIHOST
-       if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI &&
-           !dma_supported(dev, mask))
-               return -EIO;
-#endif
-       dev->coherent_dma_mask = mask;
-       dev->dma_mask = &dev->coherent_dma_mask;
+       int err;
 
-       return 0;
+       switch (dev->bus->bustype) {
+       case SSB_BUSTYPE_PCI:
+               err = pci_set_dma_mask(dev->bus->host_pci, mask);
+               if (err)
+                       return err;
+               err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask);
+               return err;
+       case SSB_BUSTYPE_SSB:
+               return dma_set_mask(dev->dev, mask);
+       default:
+               __ssb_dma_not_implemented(dev);
+       }
+       return -ENOSYS;
 }
 EXPORT_SYMBOL(ssb_dma_set_mask);
 
+void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
+                               dma_addr_t *dma_handle, gfp_t gfp_flags)
+{
+       switch (dev->bus->bustype) {
+       case SSB_BUSTYPE_PCI:
+               if (gfp_flags & GFP_DMA) {
+                       /* Workaround: The PCI API does not support passing
+                        * a GFP flag. */
+                       return dma_alloc_coherent(&dev->bus->host_pci->dev,
+                                                 size, dma_handle, gfp_flags);
+               }
+               return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle);
+       case SSB_BUSTYPE_SSB:
+               return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags);
+       default:
+               __ssb_dma_not_implemented(dev);
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(ssb_dma_alloc_consistent);
+
+void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
+                            void *vaddr, dma_addr_t dma_handle,
+                            gfp_t gfp_flags)
+{
+       switch (dev->bus->bustype) {
+       case SSB_BUSTYPE_PCI:
+               if (gfp_flags & GFP_DMA) {
+                       /* Workaround: The PCI API does not support passing
+                        * a GFP flag. */
+                       dma_free_coherent(&dev->bus->host_pci->dev,
+                                         size, vaddr, dma_handle);
+                       return;
+               }
+               pci_free_consistent(dev->bus->host_pci, size,
+                                   vaddr, dma_handle);
+               return;
+       case SSB_BUSTYPE_SSB:
+               dma_free_coherent(dev->dev, size, vaddr, dma_handle);
+               return;
+       default:
+               __ssb_dma_not_implemented(dev);
+       }
+}
+EXPORT_SYMBOL(ssb_dma_free_consistent);
+
 int ssb_bus_may_powerdown(struct ssb_bus *bus)
 {
        struct ssb_chipcommon *cc;