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 /include/linux | |
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 'include/linux')
-rw-r--r-- | include/linux/ssb/ssb.h | 143 |
1 files changed, 139 insertions, 4 deletions
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 50dfd0dc4093..0fe5a0ded3ea 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -137,9 +137,6 @@ struct ssb_device { | |||
137 | const struct ssb_bus_ops *ops; | 137 | const struct ssb_bus_ops *ops; |
138 | 138 | ||
139 | struct device *dev; | 139 | struct device *dev; |
140 | /* Pointer to the device that has to be used for | ||
141 | * any DMA related operation. */ | ||
142 | struct device *dma_dev; | ||
143 | 140 | ||
144 | struct ssb_bus *bus; | 141 | struct ssb_bus *bus; |
145 | struct ssb_device_id id; | 142 | struct ssb_device_id id; |
@@ -399,13 +396,151 @@ static inline void ssb_block_write(struct ssb_device *dev, const void *buffer, | |||
399 | #endif /* CONFIG_SSB_BLOCKIO */ | 396 | #endif /* CONFIG_SSB_BLOCKIO */ |
400 | 397 | ||
401 | 398 | ||
399 | /* The SSB DMA API. Use this API for any DMA operation on the device. | ||
400 | * This API basically is a wrapper that calls the correct DMA API for | ||
401 | * the host device type the SSB device is attached to. */ | ||
402 | |||
402 | /* Translation (routing) bits that need to be ORed to DMA | 403 | /* Translation (routing) bits that need to be ORed to DMA |
403 | * addresses before they are given to a device. */ | 404 | * addresses before they are given to a device. */ |
404 | extern u32 ssb_dma_translation(struct ssb_device *dev); | 405 | extern u32 ssb_dma_translation(struct ssb_device *dev); |
405 | #define SSB_DMA_TRANSLATION_MASK 0xC0000000 | 406 | #define SSB_DMA_TRANSLATION_MASK 0xC0000000 |
406 | #define SSB_DMA_TRANSLATION_SHIFT 30 | 407 | #define SSB_DMA_TRANSLATION_SHIFT 30 |
407 | 408 | ||
408 | extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask); | 409 | extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask); |
410 | |||
411 | extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, | ||
412 | dma_addr_t *dma_handle, gfp_t gfp_flags); | ||
413 | extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, | ||
414 | void *vaddr, dma_addr_t dma_handle, | ||
415 | gfp_t gfp_flags); | ||
416 | |||
417 | static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev) | ||
418 | { | ||
419 | #ifdef CONFIG_SSB_DEBUG | ||
420 | printk(KERN_ERR "SSB: BUG! Calling DMA API for " | ||
421 | "unsupported bustype %d\n", dev->bus->bustype); | ||
422 | #endif /* DEBUG */ | ||
423 | } | ||
424 | |||
425 | static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr) | ||
426 | { | ||
427 | switch (dev->bus->bustype) { | ||
428 | case SSB_BUSTYPE_PCI: | ||
429 | return pci_dma_mapping_error(addr); | ||
430 | case SSB_BUSTYPE_SSB: | ||
431 | return dma_mapping_error(addr); | ||
432 | default: | ||
433 | __ssb_dma_not_implemented(dev); | ||
434 | } | ||
435 | return -ENOSYS; | ||
436 | } | ||
437 | |||
438 | static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p, | ||
439 | size_t size, enum dma_data_direction dir) | ||
440 | { | ||
441 | switch (dev->bus->bustype) { | ||
442 | case SSB_BUSTYPE_PCI: | ||
443 | return pci_map_single(dev->bus->host_pci, p, size, dir); | ||
444 | case SSB_BUSTYPE_SSB: | ||
445 | return dma_map_single(dev->dev, p, size, dir); | ||
446 | default: | ||
447 | __ssb_dma_not_implemented(dev); | ||
448 | } | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr, | ||
453 | size_t size, enum dma_data_direction dir) | ||
454 | { | ||
455 | switch (dev->bus->bustype) { | ||
456 | case SSB_BUSTYPE_PCI: | ||
457 | pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir); | ||
458 | return; | ||
459 | case SSB_BUSTYPE_SSB: | ||
460 | dma_unmap_single(dev->dev, dma_addr, size, dir); | ||
461 | return; | ||
462 | default: | ||
463 | __ssb_dma_not_implemented(dev); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev, | ||
468 | dma_addr_t dma_addr, | ||
469 | size_t size, | ||
470 | enum dma_data_direction dir) | ||
471 | { | ||
472 | switch (dev->bus->bustype) { | ||
473 | case SSB_BUSTYPE_PCI: | ||
474 | pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, | ||
475 | size, dir); | ||
476 | return; | ||
477 | case SSB_BUSTYPE_SSB: | ||
478 | dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir); | ||
479 | return; | ||
480 | default: | ||
481 | __ssb_dma_not_implemented(dev); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev, | ||
486 | dma_addr_t dma_addr, | ||
487 | size_t size, | ||
488 | enum dma_data_direction dir) | ||
489 | { | ||
490 | switch (dev->bus->bustype) { | ||
491 | case SSB_BUSTYPE_PCI: | ||
492 | pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, | ||
493 | size, dir); | ||
494 | return; | ||
495 | case SSB_BUSTYPE_SSB: | ||
496 | dma_sync_single_for_device(dev->dev, dma_addr, size, dir); | ||
497 | return; | ||
498 | default: | ||
499 | __ssb_dma_not_implemented(dev); | ||
500 | } | ||
501 | } | ||
502 | |||
503 | static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev, | ||
504 | dma_addr_t dma_addr, | ||
505 | unsigned long offset, | ||
506 | size_t size, | ||
507 | enum dma_data_direction dir) | ||
508 | { | ||
509 | switch (dev->bus->bustype) { | ||
510 | case SSB_BUSTYPE_PCI: | ||
511 | /* Just sync everything. That's all the PCI API can do. */ | ||
512 | pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, | ||
513 | offset + size, dir); | ||
514 | return; | ||
515 | case SSB_BUSTYPE_SSB: | ||
516 | dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset, | ||
517 | size, dir); | ||
518 | return; | ||
519 | default: | ||
520 | __ssb_dma_not_implemented(dev); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev, | ||
525 | dma_addr_t dma_addr, | ||
526 | unsigned long offset, | ||
527 | size_t size, | ||
528 | enum dma_data_direction dir) | ||
529 | { | ||
530 | switch (dev->bus->bustype) { | ||
531 | case SSB_BUSTYPE_PCI: | ||
532 | /* Just sync everything. That's all the PCI API can do. */ | ||
533 | pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, | ||
534 | offset + size, dir); | ||
535 | return; | ||
536 | case SSB_BUSTYPE_SSB: | ||
537 | dma_sync_single_range_for_device(dev->dev, dma_addr, offset, | ||
538 | size, dir); | ||
539 | return; | ||
540 | default: | ||
541 | __ssb_dma_not_implemented(dev); | ||
542 | } | ||
543 | } | ||
409 | 544 | ||
410 | 545 | ||
411 | #ifdef CONFIG_SSB_PCIHOST | 546 | #ifdef CONFIG_SSB_PCIHOST |