summaryrefslogtreecommitdiffstats
path: root/include/linux/ssb/ssb.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-20 17:43:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-20 17:43:29 -0700
commitdb6d8c7a4027b48d797b369a53f8470aaeed7063 (patch)
treee140c104a89abc2154e1f41a7db8ebecbb6fa0b4 /include/linux/ssb/ssb.h
parent3a533374283aea50eab3976d8a6d30532175f009 (diff)
parentfb65a7c091529bfffb1262515252c0d0f6241c5c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (1232 commits) iucv: Fix bad merging. net_sched: Add size table for qdiscs net_sched: Add accessor function for packet length for qdiscs net_sched: Add qdisc_enqueue wrapper highmem: Export totalhigh_pages. ipv6 mcast: Omit redundant address family checks in ip6_mc_source(). net: Use standard structures for generic socket address structures. ipv6 netns: Make several "global" sysctl variables namespace aware. netns: Use net_eq() to compare net-namespaces for optimization. ipv6: remove unused macros from net/ipv6.h ipv6: remove unused parameter from ip6_ra_control tcp: fix kernel panic with listening_get_next tcp: Remove redundant checks when setting eff_sacks tcp: options clean up tcp: Fix MD5 signatures for non-linear skbs sctp: Update sctp global memory limit allocations. sctp: remove unnecessary byteshifting, calculate directly in big-endian sctp: Allow only 1 listening socket with SO_REUSEADDR sctp: Do not leak memory on multiple listen() calls sctp: Support ipv6only AF_INET6 sockets. ...
Diffstat (limited to 'include/linux/ssb/ssb.h')
-rw-r--r--include/linux/ssb/ssb.h144
1 files changed, 140 insertions, 4 deletions
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 50dfd0dc409..4bf8cade9db 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -7,6 +7,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/mod_devicetable.h>
+#include <linux/dma-mapping.h>
#include <linux/ssb/ssb_regs.h>
@@ -137,9 +138,6 @@ struct ssb_device {
const struct ssb_bus_ops *ops;
struct device *dev;
- /* Pointer to the device that has to be used for
- * any DMA related operation. */
- struct device *dma_dev;
struct ssb_bus *bus;
struct ssb_device_id id;
@@ -399,13 +397,151 @@ static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
#endif /* CONFIG_SSB_BLOCKIO */
+/* The SSB DMA API. Use this API for any DMA operation on the device.
+ * This API basically is a wrapper that calls the correct DMA API for
+ * the host device type the SSB device is attached to. */
+
/* Translation (routing) bits that need to be ORed to DMA
* addresses before they are given to a device. */
extern u32 ssb_dma_translation(struct ssb_device *dev);
#define SSB_DMA_TRANSLATION_MASK 0xC0000000
#define SSB_DMA_TRANSLATION_SHIFT 30
-extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask);
+extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask);
+
+extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp_flags);
+extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ gfp_t gfp_flags);
+
+static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev)
+{
+#ifdef CONFIG_SSB_DEBUG
+ printk(KERN_ERR "SSB: BUG! Calling DMA API for "
+ "unsupported bustype %d\n", dev->bus->bustype);
+#endif /* DEBUG */
+}
+
+static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ return pci_dma_mapping_error(addr);
+ case SSB_BUSTYPE_SSB:
+ return dma_mapping_error(addr);
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+ return -ENOSYS;
+}
+
+static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
+ size_t size, enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ return pci_map_single(dev->bus->host_pci, p, size, dir);
+ case SSB_BUSTYPE_SSB:
+ return dma_map_single(dev->dev, p, size, dir);
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+ return 0;
+}
+
+static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir);
+ return;
+ case SSB_BUSTYPE_SSB:
+ dma_unmap_single(dev->dev, dma_addr, size, dir);
+ return;
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+}
+
+static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
+ dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
+ size, dir);
+ return;
+ case SSB_BUSTYPE_SSB:
+ dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
+ return;
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+}
+
+static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
+ dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
+ size, dir);
+ return;
+ case SSB_BUSTYPE_SSB:
+ dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
+ return;
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+}
+
+static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
+ dma_addr_t dma_addr,
+ unsigned long offset,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ /* Just sync everything. That's all the PCI API can do. */
+ pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
+ offset + size, dir);
+ return;
+ case SSB_BUSTYPE_SSB:
+ dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
+ size, dir);
+ return;
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+}
+
+static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
+ dma_addr_t dma_addr,
+ unsigned long offset,
+ size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dev->bus->bustype) {
+ case SSB_BUSTYPE_PCI:
+ /* Just sync everything. That's all the PCI API can do. */
+ pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
+ offset + size, dir);
+ return;
+ case SSB_BUSTYPE_SSB:
+ dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
+ size, dir);
+ return;
+ default:
+ __ssb_dma_not_implemented(dev);
+ }
+}
#ifdef CONFIG_SSB_PCIHOST