diff options
author | David S. Miller <davem@davemloft.net> | 2006-06-22 03:01:56 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-24 02:15:21 -0400 |
commit | c2a5a46be4a1c682e18e29e67785126b7610b14d (patch) | |
tree | b9101fa7547c9c5d86ff550e6398a8cf7c2f283a /arch/sparc64/kernel/pci_sun4v.c | |
parent | 486ad10a7e1b2bb61ea9e48c4d9510f50cd74fc5 (diff) |
[SPARC64]: Fix for Niagara memory corruption.
On some sun4v systems, after netboot the ethernet controller and it's
DMA mappings can be left active. The net result is that the kernel
can end up using memory the ethernet controller will continue to DMA
into, resulting in corruption.
To deal with this, we are more careful about importing IOMMU
translations which OBP has left in the IO-TLB. If the mapping maps
into an area the firmware claimed was free and available memory for
the kernel to use, we demap instead of import that IOMMU entry.
This is going to cause the network chip to take a PCI master abort on
the next DMA it attempts, if it has been left going like this. All
tests show that this is handled properly by the PCI layer and the e1000
drivers.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index b63b2834133..b275c7df018 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -988,8 +988,13 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm, | |||
988 | HV_PCI_TSBID(0, i), | 988 | HV_PCI_TSBID(0, i), |
989 | &io_attrs, &ra); | 989 | &io_attrs, &ra); |
990 | if (ret == HV_EOK) { | 990 | if (ret == HV_EOK) { |
991 | cnt++; | 991 | if (page_in_phys_avail(ra)) { |
992 | __set_bit(i, arena->map); | 992 | pci_sun4v_iommu_demap(devhandle, |
993 | HV_PCI_TSBID(0, i), 1); | ||
994 | } else { | ||
995 | cnt++; | ||
996 | __set_bit(i, arena->map); | ||
997 | } | ||
993 | } | 998 | } |
994 | } | 999 | } |
995 | 1000 | ||
@@ -1062,9 +1067,9 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
1062 | iommu->arena.limit = num_tsb_entries; | 1067 | iommu->arena.limit = num_tsb_entries; |
1063 | 1068 | ||
1064 | sz = probe_existing_entries(pbm, iommu); | 1069 | sz = probe_existing_entries(pbm, iommu); |
1065 | 1070 | if (sz) | |
1066 | printk("%s: TSB entries [%lu], existing mapings [%lu]\n", | 1071 | printk("%s: Imported %lu TSB entries from OBP\n", |
1067 | pbm->name, num_tsb_entries, sz); | 1072 | pbm->name, sz); |
1068 | } | 1073 | } |
1069 | 1074 | ||
1070 | static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) | 1075 | static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) |