diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-05-08 02:06:27 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-05-08 19:41:24 -0400 |
commit | 34768bc8329194b14e42ee408a84edfa40059046 (patch) | |
tree | 3fff53138966f3a58e796a71c19a3b75de86fbf7 /arch/sparc64/kernel/pci_fire.c | |
parent | 5a4a3e592d0d66653297049373caa7ac5b4febe0 (diff) |
[SPARC64] PCI: Use root list of pbm's instead of pci_controller_info's
The idea is to move more and more things into the pbm,
with the eventual goal of eliminating the pci_controller_info
entirely as there really isn't any need for it.
This stage of the transformations requires some reworking of
the PCI error interrupt handling.
It might be tricky to get rid of the pci_controller_info parenting for
a few reasons:
1) When we get an uncorrectable or correctable error we want
to interrogate the IOMMU and streaming cache of both
PBMs for error status. These errors come from the UPA
front-end which is shared between the two PBM PCI bus
segments.
Historically speaking this is why I choose the datastructure
hierarchy of pci_controller_info-->pci_pbm_info
2) The probing does a portid/devhandle match to look for the
'other' pbm, but this is entirely an artifact and can be
eliminated trivially.
What we could do to solve #1 is to have a "buddy" pointer from one pbm
to another.
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 | 39 |
1 files changed, 10 insertions, 29 deletions
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 79ee5be948eb..f55c08ae0aa0 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
@@ -160,21 +160,9 @@ static struct pci_ops pci_fire_ops = { | |||
160 | .write = fire_write_pci_cfg, | 160 | .write = fire_write_pci_cfg, |
161 | }; | 161 | }; |
162 | 162 | ||
163 | static void pbm_scan_bus(struct pci_controller_info *p, | 163 | static void pci_fire_scan_bus(struct pci_pbm_info *pbm) |
164 | struct pci_pbm_info *pbm) | ||
165 | { | 164 | { |
166 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 165 | pbm->pci_bus = pci_scan_one_pbm(pbm); |
167 | } | ||
168 | |||
169 | static void pci_fire_scan_bus(struct pci_controller_info *p) | ||
170 | { | ||
171 | struct device_node *dp; | ||
172 | |||
173 | if ((dp = p->pbm_A.prom_node) != NULL) | ||
174 | pbm_scan_bus(p, &p->pbm_A); | ||
175 | |||
176 | if ((dp = p->pbm_B.prom_node) != NULL) | ||
177 | pbm_scan_bus(p, &p->pbm_B); | ||
178 | 166 | ||
179 | /* XXX register error interrupt handlers XXX */ | 167 | /* XXX register error interrupt handlers XXX */ |
180 | } | 168 | } |
@@ -313,7 +301,7 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) | |||
313 | } | 301 | } |
314 | 302 | ||
315 | static void pci_fire_pbm_init(struct pci_controller_info *p, | 303 | static void pci_fire_pbm_init(struct pci_controller_info *p, |
316 | struct device_node *dp, u32 portid) | 304 | struct device_node *dp, u32 portid) |
317 | { | 305 | { |
318 | const struct linux_prom64_registers *regs; | 306 | const struct linux_prom64_registers *regs; |
319 | struct pci_pbm_info *pbm; | 307 | struct pci_pbm_info *pbm; |
@@ -323,6 +311,11 @@ static void pci_fire_pbm_init(struct pci_controller_info *p, | |||
323 | else | 311 | else |
324 | pbm = &p->pbm_B; | 312 | pbm = &p->pbm_B; |
325 | 313 | ||
314 | pbm->next = pci_pbm_root; | ||
315 | pci_pbm_root = pbm; | ||
316 | |||
317 | pbm->scan_bus = pci_fire_scan_bus; | ||
318 | |||
326 | pbm->portid = portid; | 319 | pbm->portid = portid; |
327 | pbm->parent = p; | 320 | pbm->parent = p; |
328 | pbm->prom_node = dp; | 321 | pbm->prom_node = dp; |
@@ -354,19 +347,11 @@ void fire_pci_init(struct device_node *dp, const char *model_name) | |||
354 | struct pci_controller_info *p; | 347 | struct pci_controller_info *p; |
355 | u32 portid = of_getintprop_default(dp, "portid", 0xff); | 348 | u32 portid = of_getintprop_default(dp, "portid", 0xff); |
356 | struct iommu *iommu; | 349 | struct iommu *iommu; |
350 | struct pci_pbm_info *pbm; | ||
357 | 351 | ||
358 | for (p = pci_controller_root; p; p = p->next) { | 352 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
359 | struct pci_pbm_info *pbm; | ||
360 | |||
361 | if (p->pbm_A.prom_node && p->pbm_B.prom_node) | ||
362 | continue; | ||
363 | |||
364 | pbm = (p->pbm_A.prom_node ? | ||
365 | &p->pbm_A : | ||
366 | &p->pbm_B); | ||
367 | |||
368 | if (portid_compare(pbm->portid, portid)) { | 353 | if (portid_compare(pbm->portid, portid)) { |
369 | pci_fire_pbm_init(p, dp, portid); | 354 | pci_fire_pbm_init(pbm->parent, dp, portid); |
370 | return; | 355 | return; |
371 | } | 356 | } |
372 | } | 357 | } |
@@ -387,12 +372,8 @@ void fire_pci_init(struct device_node *dp, const char *model_name) | |||
387 | 372 | ||
388 | p->pbm_B.iommu = iommu; | 373 | p->pbm_B.iommu = iommu; |
389 | 374 | ||
390 | p->next = pci_controller_root; | ||
391 | pci_controller_root = p; | ||
392 | |||
393 | p->index = pci_num_controllers++; | 375 | p->index = pci_num_controllers++; |
394 | 376 | ||
395 | p->scan_bus = pci_fire_scan_bus; | ||
396 | /* XXX MSI support XXX */ | 377 | /* XXX MSI support XXX */ |
397 | p->pci_ops = &pci_fire_ops; | 378 | p->pci_ops = &pci_fire_ops; |
398 | 379 | ||