Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f225763a authored by Michael Buesch's avatar Michael Buesch Committed by John W. Linville
Browse files

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: default avatarMichael Buesch <mb@bu3sch.de>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 316af76f
Loading
Loading
Loading
Loading
+71 −69
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
						unsigned long offset,
						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,
					     dma_desc_sync_size, dir);
}
@@ -158,7 +158,7 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
					     unsigned long offset,
					     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,
					  dma_desc_sync_size, dir);
}
@@ -613,7 +613,7 @@ static void b44_tx(struct b44 *bp)

		BUG_ON(skb == NULL);

		dma_unmap_single(bp->sdev->dma_dev,
		ssb_dma_unmap_single(bp->sdev,
				     rp->mapping,
				     skb->len,
				     DMA_TO_DEVICE);
@@ -653,29 +653,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
	if (skb == NULL)
		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,
				     DMA_FROM_DEVICE);

	/* Hardware bug work-around, the chip is unable to do PCI DMA
	   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) {
		/* Sigh... */
		if (!dma_mapping_error(mapping))
			dma_unmap_single(bp->sdev->dma_dev, mapping,
		if (!ssb_dma_mapping_error(bp->sdev, mapping))
			ssb_dma_unmap_single(bp->sdev, mapping,
					     RX_PKT_BUF_SZ, DMA_FROM_DEVICE);
		dev_kfree_skb_any(skb);
		skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
		if (skb == NULL)
			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,
					     DMA_FROM_DEVICE);
		if (dma_mapping_error(mapping) ||
		if (ssb_dma_mapping_error(bp->sdev, mapping) ||
			mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
			if (!dma_mapping_error(mapping))
				dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
			if (!ssb_dma_mapping_error(bp->sdev, mapping))
				ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
			dev_kfree_skb_any(skb);
			return -ENOMEM;
		}
@@ -750,7 +750,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
					     dest_idx * sizeof(dest_desc),
					     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,
				       DMA_FROM_DEVICE);
}
@@ -772,7 +772,7 @@ static int b44_rx(struct b44 *bp, int budget)
		struct rx_header *rh;
		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,
					    DMA_FROM_DEVICE);
		rh = (struct rx_header *) skb->data;
@@ -806,7 +806,7 @@ static int b44_rx(struct b44 *bp, int budget)
			skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
			if (skb_size < 0)
				goto drop_it;
			dma_unmap_single(bp->sdev->dma_dev, map,
			ssb_dma_unmap_single(bp->sdev, map,
					     skb_size, DMA_FROM_DEVICE);
			/* Leave out rx_header */
                	skb_put(skb, len + RX_PKT_OFFSET);
@@ -966,24 +966,24 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
		goto err_out;
	}

	mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE);
	if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
	mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE);
	if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) {
		struct sk_buff *bounce_skb;

		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
		if (!dma_mapping_error(mapping))
			dma_unmap_single(bp->sdev->dma_dev, mapping, len,
		if (!ssb_dma_mapping_error(bp->sdev, mapping))
			ssb_dma_unmap_single(bp->sdev, mapping, len,
					     DMA_TO_DEVICE);

		bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
		if (!bounce_skb)
			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);
		if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
			if (!dma_mapping_error(mapping))
				dma_unmap_single(bp->sdev->dma_dev, mapping,
		if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) {
			if (!ssb_dma_mapping_error(bp->sdev, mapping))
				ssb_dma_unmap_single(bp->sdev, mapping,
						     len, DMA_TO_DEVICE);
			dev_kfree_skb_any(bounce_skb);
			goto err_out;
@@ -1082,7 +1082,7 @@ static void b44_free_rings(struct b44 *bp)

		if (rp->skb == NULL)
			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);
		dev_kfree_skb_any(rp->skb);
		rp->skb = NULL;
@@ -1094,7 +1094,7 @@ static void b44_free_rings(struct b44 *bp)

		if (rp->skb == NULL)
			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);
		dev_kfree_skb_any(rp->skb);
		rp->skb = NULL;
@@ -1117,12 +1117,12 @@ static void b44_init_rings(struct b44 *bp)
	memset(bp->tx_ring, 0, B44_TX_RING_BYTES);

	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_BIDIRECTIONAL);

	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_TO_DEVICE);

@@ -1144,25 +1144,27 @@ static void b44_free_consistent(struct b44 *bp)
	bp->tx_buffers = NULL;
	if (bp->rx_ring) {
		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_BIDIRECTIONAL);
			kfree(bp->rx_ring);
		} else
			dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
					    bp->rx_ring, bp->rx_ring_dma);
			ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
						bp->rx_ring, bp->rx_ring_dma,
						GFP_KERNEL);
		bp->rx_ring = NULL;
		bp->flags &= ~B44_FLAG_RX_RING_HACK;
	}
	if (bp->tx_ring) {
		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_TO_DEVICE);
			kfree(bp->tx_ring);
		} else
			dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES,
					    bp->tx_ring, bp->tx_ring_dma);
			ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES,
						bp->tx_ring, bp->tx_ring_dma,
						GFP_KERNEL);
		bp->tx_ring = NULL;
		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;

	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) {
		/* Allocation may have failed due to pci_alloc_consistent
		   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)
			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_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) {
			kfree(rx_ring);
			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->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) {
		/* 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
		   than necessary...  */
		struct dma_desc *tx_ring;
@@ -1226,11 +1228,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp)
		if (!tx_ring)
			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_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) {
			kfree(tx_ring);
			goto out_err;
+35 −30
Original line number Diff line number Diff line
@@ -328,10 +328,10 @@ static inline
	dma_addr_t dmaaddr;

	if (tx) {
		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
		dmaaddr = ssb_dma_map_single(ring->dev->dev,
					     buf, len, DMA_TO_DEVICE);
	} else {
		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
		dmaaddr = ssb_dma_map_single(ring->dev->dev,
					     buf, len, DMA_FROM_DEVICE);
	}

@@ -343,10 +343,10 @@ static inline
			  dma_addr_t addr, size_t len, int tx)
{
	if (tx) {
		dma_unmap_single(ring->dev->dev->dma_dev,
		ssb_dma_unmap_single(ring->dev->dev,
				     addr, len, DMA_TO_DEVICE);
	} else {
		dma_unmap_single(ring->dev->dev->dma_dev,
		ssb_dma_unmap_single(ring->dev->dev,
				     addr, len, DMA_FROM_DEVICE);
	}
}
@@ -356,7 +356,7 @@ static inline
				 dma_addr_t addr, size_t len)
{
	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);
}

@@ -365,7 +365,7 @@ static inline
				    dma_addr_t addr, size_t len)
{
	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);
}

@@ -381,7 +381,6 @@ static inline

static int alloc_ringmemory(struct b43_dmaring *ring)
{
	struct device *dma_dev = ring->dev->dev->dma_dev;
	gfp_t flags = GFP_KERNEL;

	/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
@@ -392,10 +391,13 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
	 * For unknown reasons - possibly a hardware error - the BCM4311 rev
	 * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
	 * 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)
		flags |= GFP_DMA;
	ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
	ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
						  B43_DMA_RINGMEMSIZE,
						  &(ring->dmabase), flags);
	if (!ring->descbase) {
		b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
@@ -408,10 +410,13 @@ static int alloc_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;

	if (ring->type == B43_DMA_64BIT)
		flags |= GFP_DMA;

	dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
			  ring->descbase, ring->dmabase);
	ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
				ring->descbase, ring->dmabase, flags);
}

/* Reset the RX DMA channel */
@@ -518,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
				  dma_addr_t addr,
				  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;

	switch (ring->type) {
@@ -844,7 +849,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
			goto err_kfree_meta;

		/* 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,
					      b43_txhdr_size(dev),
					      DMA_TO_DEVICE);
@@ -859,7 +864,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
			if (!ring->txhdr_cache)
				goto err_kfree_meta;

			dma_test = dma_map_single(dev->dev->dma_dev,
			dma_test = ssb_dma_map_single(dev->dev,
						      ring->txhdr_cache,
						      b43_txhdr_size(dev),
						      DMA_TO_DEVICE);
@@ -873,7 +878,7 @@ 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_TO_DEVICE);
	}
+31 −32
Original line number Diff line number Diff line
@@ -393,11 +393,11 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
	dma_addr_t dmaaddr;

	if (tx)
		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
		dmaaddr = ssb_dma_map_single(ring->dev->dev,
					     buf, len,
					     DMA_TO_DEVICE);
	else
		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
		dmaaddr = ssb_dma_map_single(ring->dev->dev,
					     buf, len,
					     DMA_FROM_DEVICE);

@@ -411,11 +411,11 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring,
		      int tx)
{
	if (tx)
		dma_unmap_single(ring->dev->dev->dma_dev,
		ssb_dma_unmap_single(ring->dev->dev,
				     addr, len,
				     DMA_TO_DEVICE);
	else
		dma_unmap_single(ring->dev->dev->dma_dev,
		ssb_dma_unmap_single(ring->dev->dev,
				     addr, len,
				     DMA_FROM_DEVICE);
}
@@ -427,7 +427,7 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
{
	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);
}

@@ -438,7 +438,7 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
{
	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);
}

@@ -458,10 +458,11 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,

static int alloc_ringmemory(struct b43legacy_dmaring *ring)
{
	struct device *dma_dev = ring->dev->dev->dma_dev;

	ring->descbase = dma_alloc_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE,
					    &(ring->dmabase), GFP_KERNEL);
	/* GFP flags must match the flags in free_ringmemory()! */
	ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
						  B43legacy_DMA_RINGMEMSIZE,
						  &(ring->dmabase),
						  GFP_KERNEL);
	if (!ring->descbase) {
		b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
			     " failed\n");
@@ -474,10 +475,8 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring)

static void free_ringmemory(struct b43legacy_dmaring *ring)
{
	struct device *dma_dev = ring->dev->dev->dma_dev;

	dma_free_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE,
			  ring->descbase, ring->dmabase);
	ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE,
				ring->descbase, ring->dmabase, GFP_KERNEL);
}

/* Reset the RX DMA channel */
@@ -589,7 +588,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
					 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;

	switch (ring->type) {
@@ -893,7 +892,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
			goto err_kfree_meta;

		/* 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),
					      DMA_TO_DEVICE);

@@ -907,7 +906,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
			if (!ring->txhdr_cache)
				goto err_kfree_meta;

			dma_test = dma_map_single(dev->dev->dma_dev,
				dma_test = ssb_dma_map_single(dev->dev,
					ring->txhdr_cache,
					sizeof(struct b43legacy_txhdr_fw3),
					DMA_TO_DEVICE);
@@ -917,8 +916,8 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
				goto err_kfree_txhdr_cache;
		}

		dma_unmap_single(dev->dev->dma_dev,
				 dma_test, sizeof(struct b43legacy_txhdr_fw3),
		ssb_dma_unmap_single(dev->dev, dma_test,
				     sizeof(struct b43legacy_txhdr_fw3),
				     DMA_TO_DEVICE);
	}

+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ menu "Sonics Silicon Backplane"

config SSB_POSSIBLE
	bool
	depends on HAS_IOMEM
	depends on HAS_IOMEM && HAS_DMA
	default y

config SSB
+59 −16
Original line number Diff line number Diff line
@@ -462,18 +462,15 @@ static int ssb_devices_register(struct ssb_bus *bus)
#ifdef CONFIG_SSB_PCIHOST
			sdev->irq = bus->host_pci->irq;
			dev->parent = &bus->host_pci->dev;
			sdev->dma_dev = &bus->host_pci->dev;
#endif
			break;
		case SSB_BUSTYPE_PCMCIA:
#ifdef CONFIG_SSB_PCMCIAHOST
			sdev->irq = bus->host_pcmcia->irq.AssignedIRQ;
			dev->parent = &bus->host_pcmcia->dev;
			sdev->dma_dev = &bus->host_pcmcia->dev;
#endif
			break;
		case SSB_BUSTYPE_SSB:
			sdev->dma_dev = dev;
			break;
		}

@@ -1156,36 +1153,82 @@ u32 ssb_dma_translation(struct ssb_device *dev)
{
	switch (dev->bus->bustype) {
	case SSB_BUSTYPE_SSB:
	case SSB_BUSTYPE_PCMCIA:
		return 0;
	case SSB_BUSTYPE_PCI:
		return SSB_PCI_DMA;
	default:
		__ssb_dma_not_implemented(dev);
	}
	return 0;
}
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 = 0;
	int err;

#ifdef CONFIG_SSB_PCIHOST
	if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) {
		err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask);
	switch (dev->bus->bustype) {
	case SSB_BUSTYPE_PCI:
		err = pci_set_dma_mask(dev->bus->host_pci, mask);
		if (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;
	case SSB_BUSTYPE_SSB:
		return dma_set_mask(dev->dev, mask);
	default:
		__ssb_dma_not_implemented(dev);
	}
#endif
	dma_dev->coherent_dma_mask = mask;
	dma_dev->dma_mask = &dma_dev->coherent_dma_mask;

	return err;
	return -ENOSYS;
}
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)
{
	struct ssb_chipcommon *cc;
Loading