diff options
author | Olof Johansson <olof@lixom.net> | 2007-10-03 14:03:54 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:54:30 -0400 |
commit | af289e803fdf2fcd19cf4a57c3c896dba146c756 (patch) | |
tree | 038fe6e9a32ed958450bf0bd33227a3c23342ae8 | |
parent | 9ddf7774b9d760dc3fa4d5ae7d7fd92d4c02150b (diff) |
pasemi_mac: enable iommu support
pasemi_mac: enable iommu support
Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned
systems for performance reasons.
The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE
configuration option.
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | arch/powerpc/platforms/pasemi/Kconfig | 10 | ||||
-rw-r--r-- | arch/powerpc/platforms/pasemi/iommu.c | 15 | ||||
-rw-r--r-- | drivers/net/pasemi_mac.c | 50 | ||||
-rw-r--r-- | drivers/net/pasemi_mac.h | 8 |
4 files changed, 63 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index 95cd90fd81c7..e95261ef6f98 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
@@ -18,6 +18,16 @@ config PPC_PASEMI_IOMMU | |||
18 | help | 18 | help |
19 | IOMMU support for PA6T-1682M | 19 | IOMMU support for PA6T-1682M |
20 | 20 | ||
21 | config PPC_PASEMI_IOMMU_DMA_FORCE | ||
22 | bool "Force DMA engine to use IOMMU" | ||
23 | depends on PPC_PASEMI_IOMMU | ||
24 | help | ||
25 | This option forces the use of the IOMMU also for the | ||
26 | DMA engine. Otherwise the kernel will use it only when | ||
27 | running under a hypervisor. | ||
28 | |||
29 | If in doubt, say "N". | ||
30 | |||
21 | config PPC_PASEMI_MDIO | 31 | config PPC_PASEMI_MDIO |
22 | depends on PHYLIB | 32 | depends on PHYLIB |
23 | tristate "MDIO support via GPIO" | 33 | tristate "MDIO support via GPIO" |
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 9014d55c717b..a1111b5c6cb4 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/iommu.h> | 25 | #include <asm/iommu.h> |
26 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
27 | #include <asm/abs_addr.h> | 27 | #include <asm/abs_addr.h> |
28 | #include <asm/firmware.h> | ||
28 | 29 | ||
29 | 30 | ||
30 | #define IOBMAP_PAGE_SHIFT 12 | 31 | #define IOBMAP_PAGE_SHIFT 12 |
@@ -175,13 +176,17 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev) | |||
175 | { | 176 | { |
176 | pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev)); | 177 | pr_debug("pci_dma_dev_setup, dev %p (%s)\n", dev, pci_name(dev)); |
177 | 178 | ||
178 | /* DMA device is untranslated, but all other PCI-e goes through | 179 | #if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) |
179 | * the IOMMU | 180 | /* For non-LPAR environment, don't translate anything for the DMA |
181 | * engine. The exception to this is if the user has enabled | ||
182 | * CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time. | ||
180 | */ | 183 | */ |
181 | if (dev->vendor == 0x1959 && dev->device == 0xa007) | 184 | if (dev->vendor == 0x1959 && dev->device == 0xa007 && |
185 | !firmware_has_feature(FW_FEATURE_LPAR)) | ||
182 | dev->dev.archdata.dma_ops = &dma_direct_ops; | 186 | dev->dev.archdata.dma_ops = &dma_direct_ops; |
183 | else | 187 | #endif |
184 | dev->dev.archdata.dma_data = &iommu_table_iobmap; | 188 | |
189 | dev->dev.archdata.dma_data = &iommu_table_iobmap; | ||
185 | } | 190 | } |
186 | 191 | ||
187 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } | 192 | static void pci_dma_bus_setup_null(struct pci_bus *b) { } |
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 31ad2b9093a7..9f9a421c99b3 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <net/checksum.h> | 34 | #include <net/checksum.h> |
35 | 35 | ||
36 | #include <asm/irq.h> | 36 | #include <asm/irq.h> |
37 | #include <asm/firmware.h> | ||
37 | 38 | ||
38 | #include "pasemi_mac.h" | 39 | #include "pasemi_mac.h" |
39 | 40 | ||
@@ -89,6 +90,15 @@ MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value"); | |||
89 | 90 | ||
90 | static struct pasdma_status *dma_status; | 91 | static struct pasdma_status *dma_status; |
91 | 92 | ||
93 | static int translation_enabled(void) | ||
94 | { | ||
95 | #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) | ||
96 | return 1; | ||
97 | #else | ||
98 | return firmware_has_feature(FW_FEATURE_LPAR); | ||
99 | #endif | ||
100 | } | ||
101 | |||
92 | static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg, | 102 | static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg, |
93 | unsigned int val) | 103 | unsigned int val) |
94 | { | 104 | { |
@@ -193,6 +203,7 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev) | |||
193 | struct pasemi_mac_rxring *ring; | 203 | struct pasemi_mac_rxring *ring; |
194 | struct pasemi_mac *mac = netdev_priv(dev); | 204 | struct pasemi_mac *mac = netdev_priv(dev); |
195 | int chan_id = mac->dma_rxch; | 205 | int chan_id = mac->dma_rxch; |
206 | unsigned int cfg; | ||
196 | 207 | ||
197 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 208 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
198 | 209 | ||
@@ -232,20 +243,28 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev) | |||
232 | PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) | | 243 | PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) | |
233 | PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3)); | 244 | PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3)); |
234 | 245 | ||
235 | write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), | 246 | cfg = PAS_DMA_RXCHAN_CFG_HBU(2); |
236 | PAS_DMA_RXCHAN_CFG_HBU(2)); | 247 | |
248 | if (translation_enabled()) | ||
249 | cfg |= PAS_DMA_RXCHAN_CFG_CTR; | ||
250 | |||
251 | write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id), cfg); | ||
237 | 252 | ||
238 | write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if), | 253 | write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if), |
239 | PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers))); | 254 | PAS_DMA_RXINT_BASEL_BRBL(ring->buf_dma)); |
240 | 255 | ||
241 | write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if), | 256 | write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if), |
242 | PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) | | 257 | PAS_DMA_RXINT_BASEU_BRBH(ring->buf_dma >> 32) | |
243 | PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3)); | 258 | PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3)); |
244 | 259 | ||
245 | write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), | 260 | cfg = PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 | |
246 | PAS_DMA_RXINT_CFG_DHL(3) | PAS_DMA_RXINT_CFG_L2 | | 261 | PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP | |
247 | PAS_DMA_RXINT_CFG_LW | PAS_DMA_RXINT_CFG_RBP | | 262 | PAS_DMA_RXINT_CFG_HEN; |
248 | PAS_DMA_RXINT_CFG_HEN); | 263 | |
264 | if (translation_enabled()) | ||
265 | cfg |= PAS_DMA_RXINT_CFG_ITRR | PAS_DMA_RXINT_CFG_ITR; | ||
266 | |||
267 | write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if), cfg); | ||
249 | 268 | ||
250 | ring->next_to_fill = 0; | 269 | ring->next_to_fill = 0; |
251 | ring->next_to_clean = 0; | 270 | ring->next_to_clean = 0; |
@@ -275,6 +294,7 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev) | |||
275 | u32 val; | 294 | u32 val; |
276 | int chan_id = mac->dma_txch; | 295 | int chan_id = mac->dma_txch; |
277 | struct pasemi_mac_txring *ring; | 296 | struct pasemi_mac_txring *ring; |
297 | unsigned int cfg; | ||
278 | 298 | ||
279 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 299 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
280 | if (!ring) | 300 | if (!ring) |
@@ -304,11 +324,15 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev) | |||
304 | 324 | ||
305 | write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val); | 325 | write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val); |
306 | 326 | ||
307 | write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), | 327 | cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE | |
308 | PAS_DMA_TXCHAN_CFG_TY_IFACE | | 328 | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | |
309 | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | | 329 | PAS_DMA_TXCHAN_CFG_UP | |
310 | PAS_DMA_TXCHAN_CFG_UP | | 330 | PAS_DMA_TXCHAN_CFG_WT(2); |
311 | PAS_DMA_TXCHAN_CFG_WT(2)); | 331 | |
332 | if (translation_enabled()) | ||
333 | cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; | ||
334 | |||
335 | write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id), cfg); | ||
312 | 336 | ||
313 | ring->next_to_fill = 0; | 337 | ring->next_to_fill = 0; |
314 | ring->next_to_clean = 0; | 338 | ring->next_to_clean = 0; |
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h index 1a120408cf3f..60368df72634 100644 --- a/drivers/net/pasemi_mac.h +++ b/drivers/net/pasemi_mac.h | |||
@@ -212,6 +212,7 @@ enum { | |||
212 | #define PAS_DMA_RXINT_CFG_DHL_S 24 | 212 | #define PAS_DMA_RXINT_CFG_DHL_S 24 |
213 | #define PAS_DMA_RXINT_CFG_DHL(x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ | 213 | #define PAS_DMA_RXINT_CFG_DHL(x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ |
214 | PAS_DMA_RXINT_CFG_DHL_M) | 214 | PAS_DMA_RXINT_CFG_DHL_M) |
215 | #define PAS_DMA_RXINT_CFG_ITR 0x00400000 | ||
215 | #define PAS_DMA_RXINT_CFG_LW 0x00200000 | 216 | #define PAS_DMA_RXINT_CFG_LW 0x00200000 |
216 | #define PAS_DMA_RXINT_CFG_L2 0x00100000 | 217 | #define PAS_DMA_RXINT_CFG_L2 0x00100000 |
217 | #define PAS_DMA_RXINT_CFG_HEN 0x00080000 | 218 | #define PAS_DMA_RXINT_CFG_HEN 0x00080000 |
@@ -258,9 +259,11 @@ enum { | |||
258 | #define PAS_DMA_TXCHAN_CFG_WT_S 6 | 259 | #define PAS_DMA_TXCHAN_CFG_WT_S 6 |
259 | #define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \ | 260 | #define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \ |
260 | PAS_DMA_TXCHAN_CFG_WT_M) | 261 | PAS_DMA_TXCHAN_CFG_WT_M) |
261 | #define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */ | 262 | #define PAS_DMA_TXCHAN_CFG_TRD 0x00010000 /* translate data */ |
262 | #define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */ | 263 | #define PAS_DMA_TXCHAN_CFG_TRR 0x00008000 /* translate rings */ |
263 | #define PAS_DMA_TXCHAN_CFG_UP 0x00004000 /* update tx descr when sent */ | 264 | #define PAS_DMA_TXCHAN_CFG_UP 0x00004000 /* update tx descr when sent */ |
265 | #define PAS_DMA_TXCHAN_CFG_CL 0x00002000 /* Clean last line */ | ||
266 | #define PAS_DMA_TXCHAN_CFG_CF 0x00001000 /* Clean first line */ | ||
264 | #define PAS_DMA_TXCHAN_INCR(c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE) | 267 | #define PAS_DMA_TXCHAN_INCR(c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE) |
265 | #define PAS_DMA_TXCHAN_BASEL(c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE) | 268 | #define PAS_DMA_TXCHAN_BASEL(c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE) |
266 | #define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0 | 269 | #define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0 |
@@ -294,6 +297,7 @@ enum { | |||
294 | #define PAS_DMA_RXCHAN_CCMDSTA_FD 0x00001000 | 297 | #define PAS_DMA_RXCHAN_CCMDSTA_FD 0x00001000 |
295 | #define PAS_DMA_RXCHAN_CCMDSTA_DT 0x00000800 | 298 | #define PAS_DMA_RXCHAN_CCMDSTA_DT 0x00000800 |
296 | #define PAS_DMA_RXCHAN_CFG(c) (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE) | 299 | #define PAS_DMA_RXCHAN_CFG(c) (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE) |
300 | #define PAS_DMA_RXCHAN_CFG_CTR 0x00000400 | ||
297 | #define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380 | 301 | #define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380 |
298 | #define PAS_DMA_RXCHAN_CFG_HBU_S 7 | 302 | #define PAS_DMA_RXCHAN_CFG_HBU_S 7 |
299 | #define PAS_DMA_RXCHAN_CFG_HBU(x) (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \ | 303 | #define PAS_DMA_RXCHAN_CFG_HBU(x) (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \ |