aboutsummaryrefslogtreecommitdiff
path: root/drivers/ssb
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-25 11:37:07 +0200
committerIngo Molnar <mingo@elte.hu>2008-07-25 11:37:07 +0200
commit0e2f65ee30eee2db054f7fd73f462c5da33ec963 (patch)
tree26c61eb7745da0c0d9135e9d12088f570cb8530d /drivers/ssb
parentda7878d75b8520c9ae00d27dfbbce546a7bfdfbb (diff)
parentfb2e405fc1fc8b20d9c78eaa1c7fd5a297efde43 (diff)
Merge branch 'linus' into x86/pebs
Conflicts: arch/x86/Kconfig.cpu arch/x86/kernel/cpu/intel.c arch/x86/kernel/setup_64.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/ssb')
-rw-r--r--drivers/ssb/Kconfig2
-rw-r--r--drivers/ssb/driver_pcicore.c7
-rw-r--r--drivers/ssb/main.c75
-rw-r--r--drivers/ssb/pci.c20
4 files changed, 76 insertions, 28 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index cd845b8acd1..307b1f62d94 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -2,7 +2,7 @@ menu "Sonics Silicon Backplane"
config SSB_POSSIBLE
bool
- depends on HAS_IOMEM
+ depends on HAS_IOMEM && HAS_DMA
default y
config SSB
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index d28c5386809..538c570df33 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -537,6 +537,13 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
int err = 0;
u32 tmp;
+ if (dev->bus->bustype != SSB_BUSTYPE_PCI) {
+ /* This SSB device is not on a PCI host-bus. So the IRQs are
+ * not routed through the PCI core.
+ * So we must not enable routing through the PCI core. */
+ goto out;
+ }
+
if (!pdev)
goto out;
bus = pdev->bus;
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index d184f2aea78..d831a2beff3 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -462,18 +462,15 @@ static int ssb_devices_register(struct ssb_bus *bus)
#ifdef CONFIG_SSB_PCIHOST
sdev->irq = bus->host_pci->irq;
dev->parent = &bus->host_pci->dev;
- sdev->dma_dev = &bus->host_pci->dev;
#endif
break;
case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
dev->parent = &bus->host_pcmcia->dev;
- sdev->dma_dev = &bus->host_pcmcia->dev;
#endif
break;
case SSB_BUSTYPE_SSB:
- sdev->dma_dev = dev;
break;
}
@@ -1156,36 +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 *dma_dev = ssb_dev->dma_dev;
- int err = 0;
+ int err;
-#ifdef CONFIG_SSB_PCIHOST
- if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) {
- err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask);
+ 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(ssb_dev->bus->host_pci, mask);
+ 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);
}
-#endif
- dma_dev->coherent_dma_mask = mask;
- dma_dev->dma_mask = &dma_dev->coherent_dma_mask;
-
- return err;
+ 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;
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 57c4ccfab1e..f883dcfffe0 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -510,17 +510,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
sprom_do_read(bus, buf);
err = sprom_check_crc(buf, bus->sprom_size);
if (err) {
- /* check for rev 4 sprom - has special signature */
- if (buf[32] == 0x5372) {
- kfree(buf);
- buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
- GFP_KERNEL);
- if (!buf)
- goto out;
- bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
- sprom_do_read(bus, buf);
- err = sprom_check_crc(buf, bus->sprom_size);
- }
+ /* try for a 440 byte SPROM - revision 4 and higher */
+ kfree(buf);
+ buf = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
+ GFP_KERNEL);
+ if (!buf)
+ goto out;
+ bus->sprom_size = SSB_SPROMSIZE_WORDS_R4;
+ sprom_do_read(bus, buf);
+ err = sprom_check_crc(buf, bus->sprom_size);
if (err)
ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
" SPROM CRC (corrupt SPROM)\n");