#include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/firmware.h>
 
 
 #define IOBMAP_PAGE_SHIFT      12
 {
        pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev));
 
-       /* DMA device is untranslated, but all other PCI-e goes through
-        * the IOMMU
+#if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+       /* For non-LPAR environment, don't translate anything for the DMA
+        * engine. The exception to this is if the user has enabled
+        * CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time.
         */
-       if (dev->vendor == 0x1959 && dev->device == 0xa007)
+       if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
+           !firmware_has_feature(FW_FEATURE_LPAR))
                dev->dev.archdata.dma_ops = &dma_direct_ops;
-       else
-               dev->dev.archdata.dma_data = &iommu_table_iobmap;
+#endif
+
+       dev->dev.archdata.dma_data = &iommu_table_iobmap;
 }
 
 static void pci_dma_bus_setup_null(struct pci_bus *b) { }
 
 #include <net/checksum.h>
 
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 #include "pasemi_mac.h"
 
 
 static struct pasdma_status *dma_status;
 
+static int translation_enabled(void)
+{
+#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
+       return 1;
+#else
+       return firmware_has_feature(FW_FEATURE_LPAR);
+#endif
+}
+
 static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
                          unsigned int val)
 {
        struct pasemi_mac_rxring *ring;
        struct pasemi_mac *mac = netdev_priv(dev);
        int chan_id = mac->dma_rxch;
+       unsigned int cfg;
 
        ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 
                           PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
                           PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-       write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
-                          PAS_DMA_RXCHAN_CFG_HBU(2));
+       cfg = PAS_DMA_RXCHAN_CFG_HBU(2);
+
+       if (translation_enabled())
+               cfg |= PAS_DMA_RXCHAN_CFG_CTR;
+
+       write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg);
 
        write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
-                          PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
+                          PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma));
 
        write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
-                          PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
+                          PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) |
                           PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
 
-       write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
-                     PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
-                     PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
-                     PAS_DMA_RXINT_CFG_HEN);
+       cfg = PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 |
+             PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP |
+             PAS_DMA_RXINT_CFG_HEN;
+
+       if (translation_enabled())
+               cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR;
+
+       write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), cfg);
 
        ring->next_to_fill = 0;
        ring->next_to_clean = 0;
        u32 val;
        int chan_id = mac->dma_txch;
        struct pasemi_mac_txring *ring;
+       unsigned int cfg;
 
        ring = kzalloc(sizeof(*ring), GFP_KERNEL);
        if (!ring)
 
        write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
 
-       write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
-                          PAS_DMA_TXCHAN_CFG_TY_IFACE |
-                          PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
-                          PAS_DMA_TXCHAN_CFG_UP |
-                          PAS_DMA_TXCHAN_CFG_WT(2));
+       cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
+             PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+             PAS_DMA_TXCHAN_CFG_UP |
+             PAS_DMA_TXCHAN_CFG_WT(2);
+
+       if (translation_enabled())
+               cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+       write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), cfg);
 
        ring->next_to_fill = 0;
        ring->next_to_clean = 0;
 
 #define    PAS_DMA_RXINT_CFG_DHL_S     24
 #define    PAS_DMA_RXINT_CFG_DHL(x)    (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \
                                         PAS_DMA_RXINT_CFG_DHL_M)
+#define    PAS_DMA_RXINT_CFG_ITR       0x00400000
 #define    PAS_DMA_RXINT_CFG_LW                0x00200000
 #define    PAS_DMA_RXINT_CFG_L2                0x00100000
 #define    PAS_DMA_RXINT_CFG_HEN       0x00080000
 #define    PAS_DMA_TXCHAN_CFG_WT_S     6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)    (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
                                         PAS_DMA_TXCHAN_CFG_WT_M)
-#define    PAS_DMA_TXCHAN_CFG_CF       0x00001000      /* Clean first line */
-#define    PAS_DMA_TXCHAN_CFG_CL       0x00002000      /* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_TRD      0x00010000      /* translate data */
+#define    PAS_DMA_TXCHAN_CFG_TRR      0x00008000      /* translate rings */
 #define    PAS_DMA_TXCHAN_CFG_UP       0x00004000      /* update tx descr when sent */
+#define    PAS_DMA_TXCHAN_CFG_CL       0x00002000      /* Clean last line */
+#define    PAS_DMA_TXCHAN_CFG_CF       0x00001000      /* Clean first line */
 #define PAS_DMA_TXCHAN_INCR(c)    (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define PAS_DMA_TXCHAN_BASEL(c)   (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0
 #define    PAS_DMA_RXCHAN_CCMDSTA_FD   0x00001000
 #define    PAS_DMA_RXCHAN_CCMDSTA_DT   0x00000800
 #define PAS_DMA_RXCHAN_CFG(c)     (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE)
+#define    PAS_DMA_RXCHAN_CFG_CTR      0x00000400
 #define    PAS_DMA_RXCHAN_CFG_HBU_M    0x00000380
 #define    PAS_DMA_RXCHAN_CFG_HBU_S    7
 #define    PAS_DMA_RXCHAN_CFG_HBU(x)   (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \