mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
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>
This commit is contained in:
parent
316af76f34
commit
f225763a7d
@ -148,9 +148,9 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
|
|||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
enum dma_data_direction dir)
|
enum dma_data_direction dir)
|
||||||
{
|
{
|
||||||
dma_sync_single_range_for_device(sdev->dma_dev, dma_base,
|
ssb_dma_sync_single_range_for_device(sdev, dma_base,
|
||||||
offset & dma_desc_align_mask,
|
offset & dma_desc_align_mask,
|
||||||
dma_desc_sync_size, dir);
|
dma_desc_sync_size, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
||||||
@ -158,9 +158,9 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
|
|||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
enum dma_data_direction dir)
|
enum dma_data_direction dir)
|
||||||
{
|
{
|
||||||
dma_sync_single_range_for_cpu(sdev->dma_dev, dma_base,
|
ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
|
||||||
offset & dma_desc_align_mask,
|
offset & dma_desc_align_mask,
|
||||||
dma_desc_sync_size, dir);
|
dma_desc_sync_size, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
||||||
@ -613,10 +613,10 @@ static void b44_tx(struct b44 *bp)
|
|||||||
|
|
||||||
BUG_ON(skb == NULL);
|
BUG_ON(skb == NULL);
|
||||||
|
|
||||||
dma_unmap_single(bp->sdev->dma_dev,
|
ssb_dma_unmap_single(bp->sdev,
|
||||||
rp->mapping,
|
rp->mapping,
|
||||||
skb->len,
|
skb->len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
rp->skb = NULL;
|
rp->skb = NULL;
|
||||||
dev_kfree_skb_irq(skb);
|
dev_kfree_skb_irq(skb);
|
||||||
}
|
}
|
||||||
@ -653,29 +653,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||||
RX_PKT_BUF_SZ,
|
RX_PKT_BUF_SZ,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
/* Hardware bug work-around, the chip is unable to do PCI DMA
|
/* Hardware bug work-around, the chip is unable to do PCI DMA
|
||||||
to/from anything above 1GB :-( */
|
to/from anything above 1GB :-( */
|
||||||
if (dma_mapping_error(mapping) ||
|
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||||
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
|
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
|
||||||
/* Sigh... */
|
/* Sigh... */
|
||||||
if (!dma_mapping_error(mapping))
|
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||||
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
|
RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
|
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
|
||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data,
|
mapping = ssb_dma_map_single(bp->sdev, skb->data,
|
||||||
RX_PKT_BUF_SZ,
|
RX_PKT_BUF_SZ,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
if (dma_mapping_error(mapping) ||
|
if (ssb_dma_mapping_error(bp->sdev, mapping) ||
|
||||||
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
|
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
|
||||||
if (!dma_mapping_error(mapping))
|
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||||
dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -750,9 +750,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
|
|||||||
dest_idx * sizeof(dest_desc),
|
dest_idx * sizeof(dest_desc),
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
dma_sync_single_for_device(bp->sdev->dma_dev, le32_to_cpu(src_desc->addr),
|
ssb_dma_sync_single_for_device(bp->sdev, le32_to_cpu(src_desc->addr),
|
||||||
RX_PKT_BUF_SZ,
|
RX_PKT_BUF_SZ,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int b44_rx(struct b44 *bp, int budget)
|
static int b44_rx(struct b44 *bp, int budget)
|
||||||
@ -772,7 +772,7 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||||||
struct rx_header *rh;
|
struct rx_header *rh;
|
||||||
u16 len;
|
u16 len;
|
||||||
|
|
||||||
dma_sync_single_for_cpu(bp->sdev->dma_dev, map,
|
ssb_dma_sync_single_for_cpu(bp->sdev, map,
|
||||||
RX_PKT_BUF_SZ,
|
RX_PKT_BUF_SZ,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
rh = (struct rx_header *) skb->data;
|
rh = (struct rx_header *) skb->data;
|
||||||
@ -806,8 +806,8 @@ static int b44_rx(struct b44 *bp, int budget)
|
|||||||
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
|
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
|
||||||
if (skb_size < 0)
|
if (skb_size < 0)
|
||||||
goto drop_it;
|
goto drop_it;
|
||||||
dma_unmap_single(bp->sdev->dma_dev, map,
|
ssb_dma_unmap_single(bp->sdev, map,
|
||||||
skb_size, DMA_FROM_DEVICE);
|
skb_size, DMA_FROM_DEVICE);
|
||||||
/* Leave out rx_header */
|
/* Leave out rx_header */
|
||||||
skb_put(skb, len + RX_PKT_OFFSET);
|
skb_put(skb, len + RX_PKT_OFFSET);
|
||||||
skb_pull(skb, RX_PKT_OFFSET);
|
skb_pull(skb, RX_PKT_OFFSET);
|
||||||
@ -966,25 +966,25 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
|
mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
|
||||||
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
|
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) {
|
||||||
struct sk_buff *bounce_skb;
|
struct sk_buff *bounce_skb;
|
||||||
|
|
||||||
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
|
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
|
||||||
if (!dma_mapping_error(mapping))
|
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||||
dma_unmap_single(bp->sdev->dma_dev, mapping, len,
|
ssb_dma_unmap_single(bp->sdev, mapping, len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
|
bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
|
||||||
if (!bounce_skb)
|
if (!bounce_skb)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data,
|
mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data,
|
||||||
len, DMA_TO_DEVICE);
|
len, DMA_TO_DEVICE);
|
||||||
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
|
if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) {
|
||||||
if (!dma_mapping_error(mapping))
|
if (!ssb_dma_mapping_error(bp->sdev, mapping))
|
||||||
dma_unmap_single(bp->sdev->dma_dev, mapping,
|
ssb_dma_unmap_single(bp->sdev, mapping,
|
||||||
len, DMA_TO_DEVICE);
|
len, DMA_TO_DEVICE);
|
||||||
dev_kfree_skb_any(bounce_skb);
|
dev_kfree_skb_any(bounce_skb);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@ -1082,8 +1082,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||||||
|
|
||||||
if (rp->skb == NULL)
|
if (rp->skb == NULL)
|
||||||
continue;
|
continue;
|
||||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ,
|
ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
dev_kfree_skb_any(rp->skb);
|
dev_kfree_skb_any(rp->skb);
|
||||||
rp->skb = NULL;
|
rp->skb = NULL;
|
||||||
}
|
}
|
||||||
@ -1094,8 +1094,8 @@ static void b44_free_rings(struct b44 *bp)
|
|||||||
|
|
||||||
if (rp->skb == NULL)
|
if (rp->skb == NULL)
|
||||||
continue;
|
continue;
|
||||||
dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len,
|
ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
dev_kfree_skb_any(rp->skb);
|
dev_kfree_skb_any(rp->skb);
|
||||||
rp->skb = NULL;
|
rp->skb = NULL;
|
||||||
}
|
}
|
||||||
@ -1117,14 +1117,14 @@ static void b44_init_rings(struct b44 *bp)
|
|||||||
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
|
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
|
||||||
|
|
||||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
||||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma,
|
ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
if (bp->flags & B44_FLAG_TX_RING_HACK)
|
||||||
dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma,
|
ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
for (i = 0; i < bp->rx_pending; i++) {
|
for (i = 0; i < bp->rx_pending; i++) {
|
||||||
if (b44_alloc_rx_skb(bp, -1, i) < 0)
|
if (b44_alloc_rx_skb(bp, -1, i) < 0)
|
||||||
@ -1144,25 +1144,27 @@ static void b44_free_consistent(struct b44 *bp)
|
|||||||
bp->tx_buffers = NULL;
|
bp->tx_buffers = NULL;
|
||||||
if (bp->rx_ring) {
|
if (bp->rx_ring) {
|
||||||
if (bp->flags & B44_FLAG_RX_RING_HACK) {
|
if (bp->flags & B44_FLAG_RX_RING_HACK) {
|
||||||
dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma,
|
ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
kfree(bp->rx_ring);
|
kfree(bp->rx_ring);
|
||||||
} else
|
} else
|
||||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||||
bp->rx_ring, bp->rx_ring_dma);
|
bp->rx_ring, bp->rx_ring_dma,
|
||||||
|
GFP_KERNEL);
|
||||||
bp->rx_ring = NULL;
|
bp->rx_ring = NULL;
|
||||||
bp->flags &= ~B44_FLAG_RX_RING_HACK;
|
bp->flags &= ~B44_FLAG_RX_RING_HACK;
|
||||||
}
|
}
|
||||||
if (bp->tx_ring) {
|
if (bp->tx_ring) {
|
||||||
if (bp->flags & B44_FLAG_TX_RING_HACK) {
|
if (bp->flags & B44_FLAG_TX_RING_HACK) {
|
||||||
dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma,
|
ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
kfree(bp->tx_ring);
|
kfree(bp->tx_ring);
|
||||||
} else
|
} else
|
||||||
dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
|
ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
|
||||||
bp->tx_ring, bp->tx_ring_dma);
|
bp->tx_ring, bp->tx_ring_dma,
|
||||||
|
GFP_KERNEL);
|
||||||
bp->tx_ring = NULL;
|
bp->tx_ring = NULL;
|
||||||
bp->flags &= ~B44_FLAG_TX_RING_HACK;
|
bp->flags &= ~B44_FLAG_TX_RING_HACK;
|
||||||
}
|
}
|
||||||
@ -1187,7 +1189,7 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
size = DMA_TABLE_BYTES;
|
size = DMA_TABLE_BYTES;
|
||||||
bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->rx_ring_dma, gfp);
|
bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp);
|
||||||
if (!bp->rx_ring) {
|
if (!bp->rx_ring) {
|
||||||
/* Allocation may have failed due to pci_alloc_consistent
|
/* Allocation may have failed due to pci_alloc_consistent
|
||||||
insisting on use of GFP_DMA, which is more restrictive
|
insisting on use of GFP_DMA, which is more restrictive
|
||||||
@ -1199,11 +1201,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||||||
if (!rx_ring)
|
if (!rx_ring)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring,
|
rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
if (dma_mapping_error(rx_ring_dma) ||
|
if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) ||
|
||||||
rx_ring_dma + size > DMA_30BIT_MASK) {
|
rx_ring_dma + size > DMA_30BIT_MASK) {
|
||||||
kfree(rx_ring);
|
kfree(rx_ring);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
@ -1214,9 +1216,9 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||||||
bp->flags |= B44_FLAG_RX_RING_HACK;
|
bp->flags |= B44_FLAG_RX_RING_HACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->tx_ring_dma, gfp);
|
bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp);
|
||||||
if (!bp->tx_ring) {
|
if (!bp->tx_ring) {
|
||||||
/* Allocation may have failed due to dma_alloc_coherent
|
/* Allocation may have failed due to ssb_dma_alloc_consistent
|
||||||
insisting on use of GFP_DMA, which is more restrictive
|
insisting on use of GFP_DMA, which is more restrictive
|
||||||
than necessary... */
|
than necessary... */
|
||||||
struct dma_desc *tx_ring;
|
struct dma_desc *tx_ring;
|
||||||
@ -1226,11 +1228,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
|
|||||||
if (!tx_ring)
|
if (!tx_ring)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring,
|
tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring,
|
||||||
DMA_TABLE_BYTES,
|
DMA_TABLE_BYTES,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (dma_mapping_error(tx_ring_dma) ||
|
if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) ||
|
||||||
tx_ring_dma + size > DMA_30BIT_MASK) {
|
tx_ring_dma + size > DMA_30BIT_MASK) {
|
||||||
kfree(tx_ring);
|
kfree(tx_ring);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
@ -328,11 +328,11 @@ static inline
|
|||||||
dma_addr_t dmaaddr;
|
dma_addr_t dmaaddr;
|
||||||
|
|
||||||
if (tx) {
|
if (tx) {
|
||||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||||
buf, len, DMA_TO_DEVICE);
|
buf, len, DMA_TO_DEVICE);
|
||||||
} else {
|
} else {
|
||||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||||
buf, len, DMA_FROM_DEVICE);
|
buf, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dmaaddr;
|
return dmaaddr;
|
||||||
@ -343,11 +343,11 @@ static inline
|
|||||||
dma_addr_t addr, size_t len, int tx)
|
dma_addr_t addr, size_t len, int tx)
|
||||||
{
|
{
|
||||||
if (tx) {
|
if (tx) {
|
||||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
ssb_dma_unmap_single(ring->dev->dev,
|
||||||
addr, len, DMA_TO_DEVICE);
|
addr, len, DMA_TO_DEVICE);
|
||||||
} else {
|
} else {
|
||||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
ssb_dma_unmap_single(ring->dev->dev,
|
||||||
addr, len, DMA_FROM_DEVICE);
|
addr, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,8 +356,8 @@ static inline
|
|||||||
dma_addr_t addr, size_t len)
|
dma_addr_t addr, size_t len)
|
||||||
{
|
{
|
||||||
B43_WARN_ON(ring->tx);
|
B43_WARN_ON(ring->tx);
|
||||||
dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
|
ssb_dma_sync_single_for_cpu(ring->dev->dev,
|
||||||
addr, len, DMA_FROM_DEVICE);
|
addr, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -365,8 +365,8 @@ static inline
|
|||||||
dma_addr_t addr, size_t len)
|
dma_addr_t addr, size_t len)
|
||||||
{
|
{
|
||||||
B43_WARN_ON(ring->tx);
|
B43_WARN_ON(ring->tx);
|
||||||
dma_sync_single_for_device(ring->dev->dev->dma_dev,
|
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||||
addr, len, DMA_FROM_DEVICE);
|
addr, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -381,7 +381,6 @@ static inline
|
|||||||
|
|
||||||
static int alloc_ringmemory(struct b43_dmaring *ring)
|
static int alloc_ringmemory(struct b43_dmaring *ring)
|
||||||
{
|
{
|
||||||
struct device *dma_dev = ring->dev->dev->dma_dev;
|
|
||||||
gfp_t flags = GFP_KERNEL;
|
gfp_t flags = GFP_KERNEL;
|
||||||
|
|
||||||
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
|
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
|
||||||
@ -392,11 +391,14 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
|
|||||||
* For unknown reasons - possibly a hardware error - the BCM4311 rev
|
* For unknown reasons - possibly a hardware error - the BCM4311 rev
|
||||||
* 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
|
* 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
|
||||||
* which accounts for the GFP_DMA flag below.
|
* which accounts for the GFP_DMA flag below.
|
||||||
|
*
|
||||||
|
* The flags here must match the flags in free_ringmemory below!
|
||||||
*/
|
*/
|
||||||
if (ring->type == B43_DMA_64BIT)
|
if (ring->type == B43_DMA_64BIT)
|
||||||
flags |= GFP_DMA;
|
flags |= GFP_DMA;
|
||||||
ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
|
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||||
&(ring->dmabase), flags);
|
B43_DMA_RINGMEMSIZE,
|
||||||
|
&(ring->dmabase), flags);
|
||||||
if (!ring->descbase) {
|
if (!ring->descbase) {
|
||||||
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
|
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -408,10 +410,13 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
|
|||||||
|
|
||||||
static void free_ringmemory(struct b43_dmaring *ring)
|
static void free_ringmemory(struct b43_dmaring *ring)
|
||||||
{
|
{
|
||||||
struct device *dma_dev = ring->dev->dev->dma_dev;
|
gfp_t flags = GFP_KERNEL;
|
||||||
|
|
||||||
dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
|
if (ring->type == B43_DMA_64BIT)
|
||||||
ring->descbase, ring->dmabase);
|
flags |= GFP_DMA;
|
||||||
|
|
||||||
|
ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
|
||||||
|
ring->descbase, ring->dmabase, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the RX DMA channel */
|
/* Reset the RX DMA channel */
|
||||||
@ -518,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
|||||||
dma_addr_t addr,
|
dma_addr_t addr,
|
||||||
size_t buffersize, bool dma_to_device)
|
size_t buffersize, bool dma_to_device)
|
||||||
{
|
{
|
||||||
if (unlikely(dma_mapping_error(addr)))
|
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
switch (ring->type) {
|
switch (ring->type) {
|
||||||
@ -844,10 +849,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||||||
goto err_kfree_meta;
|
goto err_kfree_meta;
|
||||||
|
|
||||||
/* test for ability to dma to txhdr_cache */
|
/* test for ability to dma to txhdr_cache */
|
||||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
dma_test = ssb_dma_map_single(dev->dev,
|
||||||
ring->txhdr_cache,
|
ring->txhdr_cache,
|
||||||
b43_txhdr_size(dev),
|
b43_txhdr_size(dev),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (b43_dma_mapping_error(ring, dma_test,
|
if (b43_dma_mapping_error(ring, dma_test,
|
||||||
b43_txhdr_size(dev), 1)) {
|
b43_txhdr_size(dev), 1)) {
|
||||||
@ -859,10 +864,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||||||
if (!ring->txhdr_cache)
|
if (!ring->txhdr_cache)
|
||||||
goto err_kfree_meta;
|
goto err_kfree_meta;
|
||||||
|
|
||||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
dma_test = ssb_dma_map_single(dev->dev,
|
||||||
ring->txhdr_cache,
|
ring->txhdr_cache,
|
||||||
b43_txhdr_size(dev),
|
b43_txhdr_size(dev),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (b43_dma_mapping_error(ring, dma_test,
|
if (b43_dma_mapping_error(ring, dma_test,
|
||||||
b43_txhdr_size(dev), 1)) {
|
b43_txhdr_size(dev), 1)) {
|
||||||
@ -873,9 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_unmap_single(dev->dev->dma_dev,
|
ssb_dma_unmap_single(dev->dev,
|
||||||
dma_test, b43_txhdr_size(dev),
|
dma_test, b43_txhdr_size(dev),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = alloc_ringmemory(ring);
|
err = alloc_ringmemory(ring);
|
||||||
|
@ -393,13 +393,13 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
|
|||||||
dma_addr_t dmaaddr;
|
dma_addr_t dmaaddr;
|
||||||
|
|
||||||
if (tx)
|
if (tx)
|
||||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||||
buf, len,
|
buf, len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
else
|
else
|
||||||
dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
|
dmaaddr = ssb_dma_map_single(ring->dev->dev,
|
||||||
buf, len,
|
buf, len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
return dmaaddr;
|
return dmaaddr;
|
||||||
}
|
}
|
||||||
@ -411,13 +411,13 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring,
|
|||||||
int tx)
|
int tx)
|
||||||
{
|
{
|
||||||
if (tx)
|
if (tx)
|
||||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
ssb_dma_unmap_single(ring->dev->dev,
|
||||||
addr, len,
|
addr, len,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
else
|
else
|
||||||
dma_unmap_single(ring->dev->dev->dma_dev,
|
ssb_dma_unmap_single(ring->dev->dev,
|
||||||
addr, len,
|
addr, len,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -427,8 +427,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
|
|||||||
{
|
{
|
||||||
B43legacy_WARN_ON(ring->tx);
|
B43legacy_WARN_ON(ring->tx);
|
||||||
|
|
||||||
dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
|
ssb_dma_sync_single_for_cpu(ring->dev->dev,
|
||||||
addr, len, DMA_FROM_DEVICE);
|
addr, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -438,8 +438,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
|
|||||||
{
|
{
|
||||||
B43legacy_WARN_ON(ring->tx);
|
B43legacy_WARN_ON(ring->tx);
|
||||||
|
|
||||||
dma_sync_single_for_device(ring->dev->dev->dma_dev,
|
ssb_dma_sync_single_for_device(ring->dev->dev,
|
||||||
addr, len, DMA_FROM_DEVICE);
|
addr, len, DMA_FROM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -458,10 +458,11 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
|
|||||||
|
|
||||||
static int alloc_ringmemory(struct b43legacy_dmaring *ring)
|
static int alloc_ringmemory(struct b43legacy_dmaring *ring)
|
||||||
{
|
{
|
||||||
struct device *dma_dev = ring->dev->dev->dma_dev;
|
/* GFP flags must match the flags in free_ringmemory()! */
|
||||||
|
ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
|
||||||
ring->descbase = dma_alloc_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE,
|
B43legacy_DMA_RINGMEMSIZE,
|
||||||
&(ring->dmabase), GFP_KERNEL);
|
&(ring->dmabase),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!ring->descbase) {
|
if (!ring->descbase) {
|
||||||
b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
|
b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
|
||||||
" failed\n");
|
" failed\n");
|
||||||
@ -474,10 +475,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring)
|
|||||||
|
|
||||||
static void free_ringmemory(struct b43legacy_dmaring *ring)
|
static void free_ringmemory(struct b43legacy_dmaring *ring)
|
||||||
{
|
{
|
||||||
struct device *dma_dev = ring->dev->dev->dma_dev;
|
ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE,
|
||||||
|
ring->descbase, ring->dmabase, GFP_KERNEL);
|
||||||
dma_free_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE,
|
|
||||||
ring->descbase, ring->dmabase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the RX DMA channel */
|
/* Reset the RX DMA channel */
|
||||||
@ -589,7 +588,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
|
|||||||
size_t buffersize,
|
size_t buffersize,
|
||||||
bool dma_to_device)
|
bool dma_to_device)
|
||||||
{
|
{
|
||||||
if (unlikely(dma_mapping_error(addr)))
|
if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
switch (ring->type) {
|
switch (ring->type) {
|
||||||
@ -893,9 +892,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||||||
goto err_kfree_meta;
|
goto err_kfree_meta;
|
||||||
|
|
||||||
/* test for ability to dma to txhdr_cache */
|
/* test for ability to dma to txhdr_cache */
|
||||||
dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache,
|
dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache,
|
||||||
sizeof(struct b43legacy_txhdr_fw3),
|
sizeof(struct b43legacy_txhdr_fw3),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
|
|
||||||
if (b43legacy_dma_mapping_error(ring, dma_test,
|
if (b43legacy_dma_mapping_error(ring, dma_test,
|
||||||
sizeof(struct b43legacy_txhdr_fw3), 1)) {
|
sizeof(struct b43legacy_txhdr_fw3), 1)) {
|
||||||
@ -907,7 +906,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||||||
if (!ring->txhdr_cache)
|
if (!ring->txhdr_cache)
|
||||||
goto err_kfree_meta;
|
goto err_kfree_meta;
|
||||||
|
|
||||||
dma_test = dma_map_single(dev->dev->dma_dev,
|
dma_test = ssb_dma_map_single(dev->dev,
|
||||||
ring->txhdr_cache,
|
ring->txhdr_cache,
|
||||||
sizeof(struct b43legacy_txhdr_fw3),
|
sizeof(struct b43legacy_txhdr_fw3),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
@ -917,9 +916,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
|
|||||||
goto err_kfree_txhdr_cache;
|
goto err_kfree_txhdr_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_unmap_single(dev->dev->dma_dev,
|
ssb_dma_unmap_single(dev->dev, dma_test,
|
||||||
dma_test, sizeof(struct b43legacy_txhdr_fw3),
|
sizeof(struct b43legacy_txhdr_fw3),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ring->dev = dev;
|
ring->dev = dev;
|
||||||
|
@ -2,7 +2,7 @@ menu "Sonics Silicon Backplane"
|
|||||||
|
|
||||||
config SSB_POSSIBLE
|
config SSB_POSSIBLE
|
||||||
bool
|
bool
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM && HAS_DMA
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SSB
|
config SSB
|
||||||
|
@ -462,18 +462,15 @@ static int ssb_devices_register(struct ssb_bus *bus)
|
|||||||
#ifdef CONFIG_SSB_PCIHOST
|
#ifdef CONFIG_SSB_PCIHOST
|
||||||
sdev->irq = bus->host_pci->irq;
|
sdev->irq = bus->host_pci->irq;
|
||||||
dev->parent = &bus->host_pci->dev;
|
dev->parent = &bus->host_pci->dev;
|
||||||
sdev->dma_dev = &bus->host_pci->dev;
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case SSB_BUSTYPE_PCMCIA:
|
case SSB_BUSTYPE_PCMCIA:
|
||||||
#ifdef CONFIG_SSB_PCMCIAHOST
|
#ifdef CONFIG_SSB_PCMCIAHOST
|
||||||
sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
|
sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
|
||||||
dev->parent = &bus->host_pcmcia->dev;
|
dev->parent = &bus->host_pcmcia->dev;
|
||||||
sdev->dma_dev = &bus->host_pcmcia->dev;
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case SSB_BUSTYPE_SSB:
|
case SSB_BUSTYPE_SSB:
|
||||||
sdev->dma_dev = dev;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,36 +1153,82 @@ u32 ssb_dma_translation(struct ssb_device *dev)
|
|||||||
{
|
{
|
||||||
switch (dev->bus->bustype) {
|
switch (dev->bus->bustype) {
|
||||||
case SSB_BUSTYPE_SSB:
|
case SSB_BUSTYPE_SSB:
|
||||||
case SSB_BUSTYPE_PCMCIA:
|
|
||||||
return 0;
|
return 0;
|
||||||
case SSB_BUSTYPE_PCI:
|
case SSB_BUSTYPE_PCI:
|
||||||
return SSB_PCI_DMA;
|
return SSB_PCI_DMA;
|
||||||
|
default:
|
||||||
|
__ssb_dma_not_implemented(dev);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ssb_dma_translation);
|
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;
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
#ifdef CONFIG_SSB_PCIHOST
|
switch (dev->bus->bustype) {
|
||||||
if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) {
|
case SSB_BUSTYPE_PCI:
|
||||||
err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask);
|
err = pci_set_dma_mask(dev->bus->host_pci, mask);
|
||||||
if (err)
|
if (err)
|
||||||
return 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;
|
return err;
|
||||||
|
case SSB_BUSTYPE_SSB:
|
||||||
|
return dma_set_mask(dev->dev, mask);
|
||||||
|
default:
|
||||||
|
__ssb_dma_not_implemented(dev);
|
||||||
}
|
}
|
||||||
#endif
|
return -ENOSYS;
|
||||||
dma_dev->coherent_dma_mask = mask;
|
|
||||||
dma_dev->dma_mask = &dma_dev->coherent_dma_mask;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ssb_dma_set_mask);
|
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)
|
int ssb_bus_may_powerdown(struct ssb_bus *bus)
|
||||||
{
|
{
|
||||||
struct ssb_chipcommon *cc;
|
struct ssb_chipcommon *cc;
|
||||||
|
@ -137,9 +137,6 @@ struct ssb_device {
|
|||||||
const struct ssb_bus_ops *ops;
|
const struct ssb_bus_ops *ops;
|
||||||
|
|
||||||
struct device *dev;
|
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_bus *bus;
|
||||||
struct ssb_device_id id;
|
struct ssb_device_id id;
|
||||||
@ -399,13 +396,151 @@ static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
|
|||||||
#endif /* CONFIG_SSB_BLOCKIO */
|
#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
|
/* Translation (routing) bits that need to be ORed to DMA
|
||||||
* addresses before they are given to a device. */
|
* addresses before they are given to a device. */
|
||||||
extern u32 ssb_dma_translation(struct ssb_device *dev);
|
extern u32 ssb_dma_translation(struct ssb_device *dev);
|
||||||
#define SSB_DMA_TRANSLATION_MASK 0xC0000000
|
#define SSB_DMA_TRANSLATION_MASK 0xC0000000
|
||||||
#define SSB_DMA_TRANSLATION_SHIFT 30
|
#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
|
#ifdef CONFIG_SSB_PCIHOST
|
||||||
|
Loading…
x
Reference in New Issue
Block a user