diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-28 01:39:14 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-30 03:27:34 -0400 |
commit | ad7ad57c6127042c411353dddb723765964815db (patch) | |
tree | 600484291d9cfa68d54dc9b230f5bd115f495213 /arch/sparc64/kernel/pci_fire.c | |
parent | c7f439b99efbea74c70a5531f92566db5a6731f2 (diff) |
[SPARC64]: Fix conflicts in SBUS/PCI/EBUS/ISA DMA handling.
Fully unify all of the DMA ops so that subordinate bus types to
the DMA operation providers (such as ebus, isa, of_device) can
work transparently.
Basically, we just make sure that for every system device we
create, the dev->archdata 'iommu' and 'stc' fields are filled
in.
Then we have two platform variants of the DMA ops, one for SUN4U which
actually programs the real hardware, and one for SUN4V which makes
hypervisor calls.
This also fixes the crashes in parport_pc on sparc64, reported by
Meelis Roos.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/pci_fire.c')
-rw-r--r-- | arch/sparc64/kernel/pci_fire.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7f5d473901c4..14d67fe21ab2 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
@@ -39,12 +39,12 @@ static void pci_fire_scan_bus(struct pci_pbm_info *pbm) | |||
39 | #define FIRE_IOMMU_FLUSH 0x40100UL | 39 | #define FIRE_IOMMU_FLUSH 0x40100UL |
40 | #define FIRE_IOMMU_FLUSHINV 0x40108UL | 40 | #define FIRE_IOMMU_FLUSHINV 0x40108UL |
41 | 41 | ||
42 | static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | 42 | static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) |
43 | { | 43 | { |
44 | struct iommu *iommu = pbm->iommu; | 44 | struct iommu *iommu = pbm->iommu; |
45 | u32 vdma[2], dma_mask; | 45 | u32 vdma[2], dma_mask; |
46 | u64 control; | 46 | u64 control; |
47 | int tsbsize; | 47 | int tsbsize, err; |
48 | 48 | ||
49 | /* No virtual-dma property on these guys, use largest size. */ | 49 | /* No virtual-dma property on these guys, use largest size. */ |
50 | vdma[0] = 0xc0000000; /* base */ | 50 | vdma[0] = 0xc0000000; /* base */ |
@@ -68,7 +68,9 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
68 | */ | 68 | */ |
69 | fire_write(iommu->iommu_flushinv, ~(u64)0); | 69 | fire_write(iommu->iommu_flushinv, ~(u64)0); |
70 | 70 | ||
71 | pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); | 71 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); |
72 | if (err) | ||
73 | return err; | ||
72 | 74 | ||
73 | fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); | 75 | fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); |
74 | 76 | ||
@@ -78,6 +80,8 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
78 | 0x00000002 /* Bypass enable */ | | 80 | 0x00000002 /* Bypass enable */ | |
79 | 0x00000001 /* Translation enable */); | 81 | 0x00000001 /* Translation enable */); |
80 | fire_write(iommu->iommu_control, control); | 82 | fire_write(iommu->iommu_control, control); |
83 | |||
84 | return 0; | ||
81 | } | 85 | } |
82 | 86 | ||
83 | /* Based at pbm->controller_regs */ | 87 | /* Based at pbm->controller_regs */ |
@@ -167,8 +171,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) | |||
167 | fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); | 171 | fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); |
168 | } | 172 | } |
169 | 173 | ||
170 | static void pci_fire_pbm_init(struct pci_controller_info *p, | 174 | static int pci_fire_pbm_init(struct pci_controller_info *p, |
171 | struct device_node *dp, u32 portid) | 175 | struct device_node *dp, u32 portid) |
172 | { | 176 | { |
173 | const struct linux_prom64_registers *regs; | 177 | const struct linux_prom64_registers *regs; |
174 | struct pci_pbm_info *pbm; | 178 | struct pci_pbm_info *pbm; |
@@ -203,7 +207,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, | |||
203 | pci_get_pbm_props(pbm); | 207 | pci_get_pbm_props(pbm); |
204 | 208 | ||
205 | pci_fire_hw_init(pbm); | 209 | pci_fire_hw_init(pbm); |
206 | pci_fire_pbm_iommu_init(pbm); | 210 | |
211 | return pci_fire_pbm_iommu_init(pbm); | ||
207 | } | 212 | } |
208 | 213 | ||
209 | static inline int portid_compare(u32 x, u32 y) | 214 | static inline int portid_compare(u32 x, u32 y) |
@@ -222,7 +227,8 @@ void fire_pci_init(struct device_node *dp, const char *model_name) | |||
222 | 227 | ||
223 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 228 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
224 | if (portid_compare(pbm->portid, portid)) { | 229 | if (portid_compare(pbm->portid, portid)) { |
225 | pci_fire_pbm_init(pbm->parent, dp, portid); | 230 | if (pci_fire_pbm_init(pbm->parent, dp, portid)) |
231 | goto fatal_memory_error; | ||
226 | return; | 232 | return; |
227 | } | 233 | } |
228 | } | 234 | } |
@@ -250,7 +256,9 @@ void fire_pci_init(struct device_node *dp, const char *model_name) | |||
250 | */ | 256 | */ |
251 | pci_memspace_mask = 0x7fffffffUL; | 257 | pci_memspace_mask = 0x7fffffffUL; |
252 | 258 | ||
253 | pci_fire_pbm_init(p, dp, portid); | 259 | if (pci_fire_pbm_init(p, dp, portid)) |
260 | goto fatal_memory_error; | ||
261 | |||
254 | return; | 262 | return; |
255 | 263 | ||
256 | fatal_memory_error: | 264 | fatal_memory_error: |