diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-06-20 05:50:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-27 09:09:15 -0400 |
commit | f225763a7d6c92c4932dbd528437997078496fcc (patch) | |
tree | 5d787c7c0bdabcf72e98603a85672ebe95a3682e /drivers/ssb/main.c | |
parent | 316af76f3475bb73dbb11f1c6d549ae589efb3d0 (diff) |
ssb, b43, b43legacy, b44: Rewrite SSB DMA API
This is a rewrite of the DMA API for SSB devices.
This is needed, because the old (non-existing) "API" made too many bad
assumptions on the API of the host-bus (PCI).
This introduces an almost complete SSB-DMA-API that maps to the lowlevel
bus-API based on the bustype.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb/main.c')
-rw-r--r-- | drivers/ssb/main.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index d184f2aea78d..d831a2beff39 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -462,18 +462,15 @@ static int ssb_devices_register(struct ssb_bus *bus) | |||
462 | #ifdef CONFIG_SSB_PCIHOST | 462 | #ifdef CONFIG_SSB_PCIHOST |
463 | sdev->irq = bus->host_pci->irq; | 463 | sdev->irq = bus->host_pci->irq; |
464 | dev->parent = &bus->host_pci->dev; | 464 | dev->parent = &bus->host_pci->dev; |
465 | sdev->dma_dev = &bus->host_pci->dev; | ||
466 | #endif | 465 | #endif |
467 | break; | 466 | break; |
468 | case SSB_BUSTYPE_PCMCIA: | 467 | case SSB_BUSTYPE_PCMCIA: |
469 | #ifdef CONFIG_SSB_PCMCIAHOST | 468 | #ifdef CONFIG_SSB_PCMCIAHOST |
470 | sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; | 469 | sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; |
471 | dev->parent = &bus->host_pcmcia->dev; | 470 | dev->parent = &bus->host_pcmcia->dev; |
472 | sdev->dma_dev = &bus->host_pcmcia->dev; | ||
473 | #endif | 471 | #endif |
474 | break; | 472 | break; |
475 | case SSB_BUSTYPE_SSB: | 473 | case SSB_BUSTYPE_SSB: |
476 | sdev->dma_dev = dev; | ||
477 | break; | 474 | break; |
478 | } | 475 | } |
479 | 476 | ||
@@ -1156,36 +1153,82 @@ u32 ssb_dma_translation(struct ssb_device *dev) | |||
1156 | { | 1153 | { |
1157 | switch (dev->bus->bustype) { | 1154 | switch (dev->bus->bustype) { |
1158 | case SSB_BUSTYPE_SSB: | 1155 | case SSB_BUSTYPE_SSB: |
1159 | case SSB_BUSTYPE_PCMCIA: | ||
1160 | return 0; | 1156 | return 0; |
1161 | case SSB_BUSTYPE_PCI: | 1157 | case SSB_BUSTYPE_PCI: |
1162 | return SSB_PCI_DMA; | 1158 | return SSB_PCI_DMA; |
1159 | default: | ||
1160 | __ssb_dma_not_implemented(dev); | ||
1163 | } | 1161 | } |
1164 | return 0; | 1162 | return 0; |
1165 | } | 1163 | } |
1166 | EXPORT_SYMBOL(ssb_dma_translation); | 1164 | EXPORT_SYMBOL(ssb_dma_translation); |
1167 | 1165 | ||
1168 | int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask) | 1166 | int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) |
1169 | { | 1167 | { |
1170 | struct device *dma_dev = ssb_dev->dma_dev; | 1168 | int err; |
1171 | int err = 0; | ||
1172 | 1169 | ||
1173 | #ifdef CONFIG_SSB_PCIHOST | 1170 | switch (dev->bus->bustype) { |
1174 | if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) { | 1171 | case SSB_BUSTYPE_PCI: |
1175 | err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask); | 1172 | err = pci_set_dma_mask(dev->bus->host_pci, mask); |
1176 | if (err) | 1173 | if (err) |
1177 | return err; | 1174 | return err; |
1178 | err = pci_set_consistent_dma_mask(ssb_dev->bus->host_pci, mask); | 1175 | err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); |
1179 | return err; | 1176 | return err; |
1177 | case SSB_BUSTYPE_SSB: | ||
1178 | return dma_set_mask(dev->dev, mask); | ||
1179 | default: | ||
1180 | __ssb_dma_not_implemented(dev); | ||
1180 | } | 1181 | } |
1181 | #endif | 1182 | return -ENOSYS; |
1182 | dma_dev->coherent_dma_mask = mask; | ||
1183 | dma_dev->dma_mask = &dma_dev->coherent_dma_mask; | ||
1184 | |||
1185 | return err; | ||
1186 | } | 1183 | } |
1187 | EXPORT_SYMBOL(ssb_dma_set_mask); | 1184 | EXPORT_SYMBOL(ssb_dma_set_mask); |
1188 | 1185 | ||
1186 | void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, | ||
1187 | dma_addr_t *dma_handle, gfp_t gfp_flags) | ||
1188 | { | ||
1189 | switch (dev->bus->bustype) { | ||
1190 | case SSB_BUSTYPE_PCI: | ||
1191 | if (gfp_flags & GFP_DMA) { | ||
1192 | /* Workaround: The PCI API does not support passing | ||
1193 | * a GFP flag. */ | ||
1194 | return dma_alloc_coherent(&dev->bus->host_pci->dev, | ||
1195 | size, dma_handle, gfp_flags); | ||
1196 | } | ||
1197 | return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); | ||
1198 | case SSB_BUSTYPE_SSB: | ||
1199 | return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); | ||
1200 | default: | ||
1201 | __ssb_dma_not_implemented(dev); | ||
1202 | } | ||
1203 | return NULL; | ||
1204 | } | ||
1205 | EXPORT_SYMBOL(ssb_dma_alloc_consistent); | ||
1206 | |||
1207 | void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, | ||
1208 | void *vaddr, dma_addr_t dma_handle, | ||
1209 | gfp_t gfp_flags) | ||
1210 | { | ||
1211 | switch (dev->bus->bustype) { | ||
1212 | case SSB_BUSTYPE_PCI: | ||
1213 | if (gfp_flags & GFP_DMA) { | ||
1214 | /* Workaround: The PCI API does not support passing | ||
1215 | * a GFP flag. */ | ||
1216 | dma_free_coherent(&dev->bus->host_pci->dev, | ||
1217 | size, vaddr, dma_handle); | ||
1218 | return; | ||
1219 | } | ||
1220 | pci_free_consistent(dev->bus->host_pci, size, | ||
1221 | vaddr, dma_handle); | ||
1222 | return; | ||
1223 | case SSB_BUSTYPE_SSB: | ||
1224 | dma_free_coherent(dev->dev, size, vaddr, dma_handle); | ||
1225 | return; | ||
1226 | default: | ||
1227 | __ssb_dma_not_implemented(dev); | ||
1228 | } | ||
1229 | } | ||
1230 | EXPORT_SYMBOL(ssb_dma_free_consistent); | ||
1231 | |||
1189 | int ssb_bus_may_powerdown(struct ssb_bus *bus) | 1232 | int ssb_bus_may_powerdown(struct ssb_bus *bus) |
1190 | { | 1233 | { |
1191 | struct ssb_chipcommon *cc; | 1234 | struct ssb_chipcommon *cc; |