#define TG3_RX_STD_RING_BYTES(tp) \
(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_MAX_SIZE_5700)
-void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr)
+void tg3_rx_prodring_fini(struct tg3 __unused *tp,
+ struct tg3_rx_prodring_set *tpr)
{ DBGP("%s\n", __func__);
if (tpr->rx_std) {
- free_phys(tpr->rx_std, TG3_RX_STD_RING_BYTES(tp));
+ dma_free(&tpr->rx_std_map, tpr->rx_std,
+ TG3_RX_STD_RING_BYTES(tp));
tpr->rx_std = NULL;
}
}
{ DBGP("%s\n", __func__);
if (tp->tx_ring) {
- free_phys(tp->tx_ring, TG3_TX_RING_BYTES);
+ dma_free(&tp->tx_desc_map, tp->tx_ring, TG3_TX_RING_BYTES);
tp->tx_ring = NULL;
}
tp->tx_buffers = NULL;
if (tp->rx_rcb) {
- free_phys(tp->rx_rcb, TG3_RX_RCB_RING_BYTES(tp));
- tp->rx_rcb_mapping = 0;
+ dma_free(&tp->rx_rcb_map, tp->rx_rcb,
+ TG3_RX_RCB_RING_BYTES(tp));
tp->rx_rcb = NULL;
}
- tg3_rx_prodring_fini(&tp->prodring);
+ tg3_rx_prodring_fini(tp, &tp->prodring);
if (tp->hw_status) {
- free_phys(tp->hw_status, TG3_HW_STATUS_SIZE);
- tp->status_mapping = 0;
+ dma_free(&tp->status_map, tp->hw_status, TG3_HW_STATUS_SIZE);
tp->hw_status = NULL;
}
}
struct tg3_hw_status *sblk;
struct tg3_rx_prodring_set *tpr = &tp->prodring;
- tp->hw_status = malloc_phys(TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT);
+ tp->hw_status = dma_alloc(tp->dma, &tp->status_map,
+ TG3_HW_STATUS_SIZE, TG3_DMA_ALIGNMENT);
if (!tp->hw_status) {
DBGC(tp->dev, "hw_status alloc failed\n");
goto err_out;
}
- tp->status_mapping = virt_to_bus(tp->hw_status);
memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
sblk = tp->hw_status;
- tpr->rx_std = malloc_phys(TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ tpr->rx_std = dma_alloc(tp->dma, &tpr->rx_std_map,
+ TG3_RX_STD_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
if (!tpr->rx_std) {
DBGC(tp->dev, "rx prodring alloc failed\n");
goto err_out;
}
- tpr->rx_std_mapping = virt_to_bus(tpr->rx_std);
memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
tp->tx_buffers = zalloc(sizeof(struct ring_info) * TG3_TX_RING_SIZE);
if (!tp->tx_buffers)
goto err_out;
- tp->tx_ring = malloc_phys(TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT);
+ tp->tx_ring = dma_alloc(tp->dma, &tp->tx_desc_map,
+ TG3_TX_RING_BYTES, TG3_DMA_ALIGNMENT);
if (!tp->tx_ring)
goto err_out;
- tp->tx_desc_mapping = virt_to_bus(tp->tx_ring);
/*
* When RSS is enabled, the status block format changes
tp->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
- tp->rx_rcb = malloc_phys(TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
+ tp->rx_rcb = dma_alloc(tp->dma, &tp->rx_rcb_map,
+ TG3_RX_RCB_RING_BYTES(tp), TG3_DMA_ALIGNMENT);
if (!tp->rx_rcb)
goto err_out;
- tp->rx_rcb_mapping = virt_to_bus(tp->rx_rcb);
memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
if (iobs[i] == NULL)
return;
- free_iob(iobs[i]);
+ /* RX iobufs were allocated via alloc_rx_iob() and are therefore
+ * DMA-mapped through the platform DMA API; they must be released
+ * via free_rx_iob() so the mapping is torn down.
+ */
+ free_rx_iob(iobs[i]);
iobs[i] = NULL;
}
struct tg3 *tp = dev->priv;
u32 len, entry;
- dma_addr_t mapping;
+ physaddr_t mapping;
if (tg3_tx_avail(tp) < 1) {
DBGC(dev, "Transmit ring full\n");
entry = tp->tx_prod;
iob_pad(iob, ETH_ZLEN);
- mapping = virt_to_bus(iob->data);
+ /* The netdevice core has already called iob_map_tx() for this
+ * iobuf (because netdev->dma is set), so iob_dma() returns the
+ * platform-translated bus address suitable for the device.
+ */
+ mapping = iob_dma(iob);
len = iob_len(iob);
tp->tx_buffers[entry].iob = iob;
* buffers the cpu only reads the last cacheline of the RX descriptor
* (to fetch the error flags, vlan tag, checksum, and opaque cookie).
*/
-static int tg3_alloc_rx_iob(struct tg3_rx_prodring_set *tpr, u32 dest_idx_unmasked)
+static int tg3_alloc_rx_iob(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
+ u32 dest_idx_unmasked)
{ DBGP("%s\n", __func__);
struct tg3_rx_buffer_desc *desc;
struct io_buffer *iob;
- dma_addr_t mapping;
+ physaddr_t mapping;
int dest_idx, iob_idx;
dest_idx = dest_idx_unmasked & (TG3_RX_STD_MAX_SIZE_5700 - 1);
*
* Callers depend upon this behavior and assume that
* we leave everything unchanged if we fail.
+ *
+ * Allocate the receive iobuf already DMA-mapped through the
+ * platform DMA API so the device may write into it under
+ * preboot DMA protection (IOMMU).
*/
- iob = alloc_iob(TG3_RX_STD_DMA_SZ);
+ iob = alloc_rx_iob(TG3_RX_STD_DMA_SZ, tp->dma);
if (iob == NULL)
return -ENOMEM;
iob_idx = dest_idx % TG3_DEF_RX_RING_PENDING;
tpr->rx_iobufs[iob_idx] = iob;
- mapping = virt_to_bus(iob->data);
+ mapping = iob_dma(iob);
desc->addr_hi = ((u64)mapping >> 32);
desc->addr_lo = ((u64)mapping & 0xffffffff);
while (tpr->rx_std_iob_cnt < TG3_DEF_RX_RING_PENDING) {
if (tpr->rx_iobufs[idx % TG3_DEF_RX_RING_PENDING] == NULL) {
- if (tg3_alloc_rx_iob(tpr, idx) < 0) {
+ if (tg3_alloc_rx_iob(tp, tpr, idx) < 0) {
DBGC(tp->dev, "alloc_iob() failed for descriptor %d\n", idx);
break;
}
#define TEST_BUFFER_SIZE 0x2000
-int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device);
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, physaddr_t buf_dma, int size, int to_device);
void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val);
static int tg3_test_dma(struct tg3 *tp)
{ DBGP("%s\n", __func__);
- dma_addr_t buf_dma;
+ struct dma_mapping buf_map;
+ physaddr_t buf_dma;
u32 *buf;
int ret = 0;
- buf = malloc_phys(TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT);
+ memset(&buf_map, 0, sizeof(buf_map));
+ buf = dma_alloc(tp->dma, &buf_map, TEST_BUFFER_SIZE, TG3_DMA_ALIGNMENT);
if (!buf) {
ret = -ENOMEM;
goto out_nofree;
}
- buf_dma = virt_to_bus(buf);
+ buf_dma = dma(&buf_map, buf);
DBGC2(tp->dev, "dma test buffer, virt: %p phys: %#016lx\n", buf, buf_dma);
if (tg3_flag(tp, 57765_PLUS)) {
}
out:
- free_phys(buf, TEST_BUFFER_SIZE);
+ dma_free(&buf_map, buf, TEST_BUFFER_SIZE);
out_nofree:
return ret;
}
tp->rx_mode = TG3_DEF_RX_MODE;
tp->tx_mode = TG3_DEF_TX_MODE;
+ /* Configure DMA. This must be done before any DMA allocation
+ * (including the self-test buffer in tg3_test_dma) so that
+ * buffers are mapped through the platform DMA implementation,
+ * which is required when preboot DMA protection (IOMMU) is
+ * active.
+ */
+ tp->dma = &pdev->dma;
+ dev->dma = tp->dma;
+ dma_set_mask_64bit ( tp->dma );
+
/* Subsystem IDs are required later */
pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->subsystem_vendor);
pci_read_config_word(tp->pdev, PCI_SUBSYSTEM_ID, &tp->subsystem_device);
u8 __reserved4[0xb00-0x9c8];
};
-typedef unsigned long dma_addr_t;
-
/* 'mapping' is superfluous as the chip does not write into
* the tx/rx post rings so we could just fetch it from there.
* But the cache behavior is better how we are doing it now.
u32 rx_std_iob_cnt;
struct tg3_rx_buffer_desc *rx_std;
struct io_buffer *rx_iobufs[TG3_DEF_RX_RING_PENDING];
- dma_addr_t rx_std_mapping;
+ struct dma_mapping rx_std_map;
};
#define TG3_IRQ_MAX_VECS_RSS 5
void *regs;
struct net_device *dev;
struct pci_device *pdev;
+ struct dma_device *dma;
u32 msg_enable;
struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers;
- dma_addr_t status_mapping;
- dma_addr_t rx_rcb_mapping;
- dma_addr_t tx_desc_mapping;
+ struct dma_mapping status_map;
+ struct dma_mapping rx_rcb_map;
+ struct dma_mapping tx_desc_map;
/* end tg3_napi */
/* begin "everything else" cacheline(s) section */
/* tg3_main.c forward declarations */
int tg3_init_rings(struct tg3 *tp);
-void tg3_rx_prodring_fini(struct tg3_rx_prodring_set *tpr);
+void tg3_rx_prodring_fini(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
///int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
/* tg3_phy.c forward declarations */
void tg3_init_bufmgr_config(struct tg3 *tp);
int tg3_get_device_address(struct tg3 *tp);
int tg3_halt(struct tg3 *tp);
-void tg3_set_txd(struct tg3 *tp, int entry, dma_addr_t mapping, int len, u32 flags);
+void tg3_set_txd(struct tg3 *tp, int entry, physaddr_t mapping, int len, u32 flags);
void tg3_set_power_state_0(struct tg3 *tp);
int tg3_alloc_consistent(struct tg3 *tp);
int tg3_init_hw(struct tg3 *tp, int reset_phy);
}
static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
- dma_addr_t mapping, u32 maxlen_flags,
+ physaddr_t mapping, u32 maxlen_flags,
u32 nic_addr)
{ DBGP("%s\n", __func__);
int i;
u32 txrcb, rxrcb, limit;
+ physaddr_t status_dma;
/* Disable all transmit rings but the first. */
if (!tg3_flag(tp, 5705_PLUS))
/* Clear status block in ram. */
memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
- /* Set status block DMA address */
+ /* Set status block DMA address. Use dma() so the platform DMA
+ * implementation (e.g. EFI PCI_IO Map) can translate the host
+ * virtual address into the bus address the device must use.
+ */
+ status_dma = dma(&tp->status_map, tp->hw_status);
+
tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
- ((u64) tp->status_mapping >> 32));
+ ((u64) status_dma >> 32));
tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
- ((u64) tp->status_mapping & 0xffffffff));
+ ((u64) status_dma & 0xffffffff));
if (tp->tx_ring) {
- tg3_set_bdinfo(tp, txrcb, tp->tx_desc_mapping,
+ tg3_set_bdinfo(tp, txrcb,
+ dma(&tp->tx_desc_map, tp->tx_ring),
(TG3_TX_RING_SIZE <<
BDINFO_FLAGS_MAXLEN_SHIFT),
NIC_SRAM_TX_BUFFER_DESC);
/* FIXME: will TG3_RX_RET_MAX_SIZE_5705 work on all cards? */
if (tp->rx_rcb) {
- tg3_set_bdinfo(tp, rxrcb, tp->rx_rcb_mapping,
+ tg3_set_bdinfo(tp, rxrcb,
+ dma(&tp->rx_rcb_map, tp->rx_rcb),
TG3_RX_RET_MAX_SIZE_5705 <<
BDINFO_FLAGS_MAXLEN_SHIFT, 0);
rxrcb += TG3_BDINFO_SIZE;
u32 val, rdmac_mode;
int i, err, limit;
struct tg3_rx_prodring_set *tpr = &tp->prodring;
+ physaddr_t rx_std_dma;
tg3_stop_fw(tp);
* The size of each ring is fixed in the firmware, but the location is
* configurable.
*/
+ rx_std_dma = dma(&tpr->rx_std_map, tpr->rx_std);
+
tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH,
- ((u64) tpr->rx_std_mapping >> 32));
+ ((u64) rx_std_dma >> 32));
tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
- ((u64) tpr->rx_std_mapping & 0xffffffff));
+ ((u64) rx_std_dma & 0xffffffff));
+
if (!tg3_flag(tp, 5717_PLUS))
tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
NIC_SRAM_RX_BUFFER_DESC);
}
void tg3_set_txd(struct tg3 *tp, int entry,
- dma_addr_t mapping, int len, u32 flags)
+ physaddr_t mapping, int len, u32 flags)
{ DBGP("%s\n", __func__);
struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
txd->vlan_tag = 0;
}
-int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, dma_addr_t buf_dma, int size, int to_device)
+int tg3_do_test_dma(struct tg3 *tp, u32 __unused *buf, physaddr_t buf_dma, int size, int to_device)
{ DBGP("%s\n", __func__);
struct tg3_internal_buffer_desc test_desc;