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/ssb | |
| 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/ssb')
| -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 |
