diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-03-01 02:35:04 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 04:55:06 -0400 |
commit | a2fb23af1c31ad6e0c281e56d385f803229d57fa (patch) | |
tree | 9c093cd9cc639cfaac4e2b1057f5d45eb6ab69e3 /arch/sparc64/kernel/pci_sun4v.c | |
parent | deb66c4521e119442aa266553e8cbfc86eb71232 (diff) |
[SPARC64]: Probe PCI bus using OF device tree.
Almost entirely taken from the 64-bit PowerPC PCI code.
This allowed to eliminate a ton of cruft from the sparc64
PCI layer.
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 | 199 |
1 files changed, 24 insertions, 175 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index bd74c155519e..eec7def379dc 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -53,8 +53,8 @@ static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long pro | |||
53 | /* Interrupts must be disabled. */ | 53 | /* Interrupts must be disabled. */ |
54 | static long pci_iommu_batch_flush(struct pci_iommu_batch *p) | 54 | static long pci_iommu_batch_flush(struct pci_iommu_batch *p) |
55 | { | 55 | { |
56 | struct pcidev_cookie *pcp = p->pdev->sysdata; | 56 | struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller; |
57 | unsigned long devhandle = pcp->pbm->devhandle; | 57 | unsigned long devhandle = pbm->devhandle; |
58 | unsigned long prot = p->prot; | 58 | unsigned long prot = p->prot; |
59 | unsigned long entry = p->entry; | 59 | unsigned long entry = p->entry; |
60 | u64 *pglist = p->pglist; | 60 | u64 *pglist = p->pglist; |
@@ -159,7 +159,6 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un | |||
159 | 159 | ||
160 | static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) | 160 | static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) |
161 | { | 161 | { |
162 | struct pcidev_cookie *pcp; | ||
163 | struct pci_iommu *iommu; | 162 | struct pci_iommu *iommu; |
164 | unsigned long flags, order, first_page, npages, n; | 163 | unsigned long flags, order, first_page, npages, n; |
165 | void *ret; | 164 | void *ret; |
@@ -178,8 +177,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr | |||
178 | 177 | ||
179 | memset((char *)first_page, 0, PAGE_SIZE << order); | 178 | memset((char *)first_page, 0, PAGE_SIZE << order); |
180 | 179 | ||
181 | pcp = pdev->sysdata; | 180 | iommu = pdev->dev.archdata.iommu; |
182 | iommu = pcp->pbm->iommu; | ||
183 | 181 | ||
184 | spin_lock_irqsave(&iommu->lock, flags); | 182 | spin_lock_irqsave(&iommu->lock, flags); |
185 | entry = pci_arena_alloc(&iommu->arena, npages); | 183 | entry = pci_arena_alloc(&iommu->arena, npages); |
@@ -226,15 +224,15 @@ arena_alloc_fail: | |||
226 | 224 | ||
227 | static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) | 225 | static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) |
228 | { | 226 | { |
229 | struct pcidev_cookie *pcp; | 227 | struct pci_pbm_info *pbm; |
230 | struct pci_iommu *iommu; | 228 | struct pci_iommu *iommu; |
231 | unsigned long flags, order, npages, entry; | 229 | unsigned long flags, order, npages, entry; |
232 | u32 devhandle; | 230 | u32 devhandle; |
233 | 231 | ||
234 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; | 232 | npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; |
235 | pcp = pdev->sysdata; | 233 | iommu = pdev->dev.archdata.iommu; |
236 | iommu = pcp->pbm->iommu; | 234 | pbm = pdev->dev.archdata.host_controller; |
237 | devhandle = pcp->pbm->devhandle; | 235 | devhandle = pbm->devhandle; |
238 | entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); | 236 | entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); |
239 | 237 | ||
240 | spin_lock_irqsave(&iommu->lock, flags); | 238 | spin_lock_irqsave(&iommu->lock, flags); |
@@ -259,7 +257,6 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, | |||
259 | 257 | ||
260 | static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) | 258 | static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) |
261 | { | 259 | { |
262 | struct pcidev_cookie *pcp; | ||
263 | struct pci_iommu *iommu; | 260 | struct pci_iommu *iommu; |
264 | unsigned long flags, npages, oaddr; | 261 | unsigned long flags, npages, oaddr; |
265 | unsigned long i, base_paddr; | 262 | unsigned long i, base_paddr; |
@@ -267,8 +264,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, | |||
267 | unsigned long prot; | 264 | unsigned long prot; |
268 | long entry; | 265 | long entry; |
269 | 266 | ||
270 | pcp = pdev->sysdata; | 267 | iommu = pdev->dev.archdata.iommu; |
271 | iommu = pcp->pbm->iommu; | ||
272 | 268 | ||
273 | if (unlikely(direction == PCI_DMA_NONE)) | 269 | if (unlikely(direction == PCI_DMA_NONE)) |
274 | goto bad; | 270 | goto bad; |
@@ -324,7 +320,7 @@ iommu_map_fail: | |||
324 | 320 | ||
325 | static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | 321 | static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) |
326 | { | 322 | { |
327 | struct pcidev_cookie *pcp; | 323 | struct pci_pbm_info *pbm; |
328 | struct pci_iommu *iommu; | 324 | struct pci_iommu *iommu; |
329 | unsigned long flags, npages; | 325 | unsigned long flags, npages; |
330 | long entry; | 326 | long entry; |
@@ -336,9 +332,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ | |||
336 | return; | 332 | return; |
337 | } | 333 | } |
338 | 334 | ||
339 | pcp = pdev->sysdata; | 335 | iommu = pdev->dev.archdata.iommu; |
340 | iommu = pcp->pbm->iommu; | 336 | pbm = pdev->dev.archdata.host_controller; |
341 | devhandle = pcp->pbm->devhandle; | 337 | devhandle = pbm->devhandle; |
342 | 338 | ||
343 | npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); | 339 | npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK); |
344 | npages >>= IO_PAGE_SHIFT; | 340 | npages >>= IO_PAGE_SHIFT; |
@@ -460,7 +456,6 @@ iommu_map_failed: | |||
460 | 456 | ||
461 | static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | 457 | static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) |
462 | { | 458 | { |
463 | struct pcidev_cookie *pcp; | ||
464 | struct pci_iommu *iommu; | 459 | struct pci_iommu *iommu; |
465 | unsigned long flags, npages, prot; | 460 | unsigned long flags, npages, prot; |
466 | u32 dma_base; | 461 | u32 dma_base; |
@@ -480,8 +475,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n | |||
480 | return 1; | 475 | return 1; |
481 | } | 476 | } |
482 | 477 | ||
483 | pcp = pdev->sysdata; | 478 | iommu = pdev->dev.archdata.iommu; |
484 | iommu = pcp->pbm->iommu; | ||
485 | 479 | ||
486 | if (unlikely(direction == PCI_DMA_NONE)) | 480 | if (unlikely(direction == PCI_DMA_NONE)) |
487 | goto bad; | 481 | goto bad; |
@@ -537,7 +531,7 @@ iommu_map_failed: | |||
537 | 531 | ||
538 | static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | 532 | static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) |
539 | { | 533 | { |
540 | struct pcidev_cookie *pcp; | 534 | struct pci_pbm_info *pbm; |
541 | struct pci_iommu *iommu; | 535 | struct pci_iommu *iommu; |
542 | unsigned long flags, i, npages; | 536 | unsigned long flags, i, npages; |
543 | long entry; | 537 | long entry; |
@@ -548,9 +542,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in | |||
548 | WARN_ON(1); | 542 | WARN_ON(1); |
549 | } | 543 | } |
550 | 544 | ||
551 | pcp = pdev->sysdata; | 545 | iommu = pdev->dev.archdata.iommu; |
552 | iommu = pcp->pbm->iommu; | 546 | pbm = pdev->dev.archdata.host_controller; |
553 | devhandle = pcp->pbm->devhandle; | 547 | devhandle = pbm->devhandle; |
554 | 548 | ||
555 | bus_addr = sglist->dma_address & IO_PAGE_MASK; | 549 | bus_addr = sglist->dma_address & IO_PAGE_MASK; |
556 | 550 | ||
@@ -600,132 +594,12 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = { | |||
600 | .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, | 594 | .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, |
601 | }; | 595 | }; |
602 | 596 | ||
603 | /* SUN4V PCI configuration space accessors. */ | ||
604 | |||
605 | struct pdev_entry { | ||
606 | struct pdev_entry *next; | ||
607 | u32 devhandle; | ||
608 | unsigned int bus; | ||
609 | unsigned int device; | ||
610 | unsigned int func; | ||
611 | }; | ||
612 | |||
613 | #define PDEV_HTAB_SIZE 16 | ||
614 | #define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1) | ||
615 | static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE]; | ||
616 | |||
617 | static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) | ||
618 | { | ||
619 | unsigned int val; | ||
620 | |||
621 | val = (devhandle ^ (devhandle >> 4)); | ||
622 | val ^= bus; | ||
623 | val ^= device; | ||
624 | val ^= func; | ||
625 | |||
626 | return val & PDEV_HTAB_MASK; | ||
627 | } | ||
628 | |||
629 | static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) | ||
630 | { | ||
631 | struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
632 | struct pdev_entry **slot; | ||
633 | |||
634 | if (!p) | ||
635 | return -ENOMEM; | ||
636 | |||
637 | slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; | ||
638 | p->next = *slot; | ||
639 | *slot = p; | ||
640 | |||
641 | p->devhandle = devhandle; | ||
642 | p->bus = bus; | ||
643 | p->device = device; | ||
644 | p->func = func; | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | /* Recursively descend into the OBP device tree, rooted at toplevel_node, | ||
650 | * looking for a PCI device matching bus and devfn. | ||
651 | */ | ||
652 | static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn) | ||
653 | { | ||
654 | toplevel_node = toplevel_node->child; | ||
655 | |||
656 | while (toplevel_node != NULL) { | ||
657 | struct linux_prom_pci_registers *regs; | ||
658 | struct property *prop; | ||
659 | int ret; | ||
660 | |||
661 | ret = obp_find(toplevel_node, bus, devfn); | ||
662 | if (ret != 0) | ||
663 | return ret; | ||
664 | |||
665 | prop = of_find_property(toplevel_node, "reg", NULL); | ||
666 | if (!prop) | ||
667 | goto next_sibling; | ||
668 | |||
669 | regs = prop->value; | ||
670 | if (((regs->phys_hi >> 16) & 0xff) == bus && | ||
671 | ((regs->phys_hi >> 8) & 0xff) == devfn) | ||
672 | break; | ||
673 | |||
674 | next_sibling: | ||
675 | toplevel_node = toplevel_node->sibling; | ||
676 | } | ||
677 | |||
678 | return toplevel_node != NULL; | ||
679 | } | ||
680 | |||
681 | static int pdev_htab_populate(struct pci_pbm_info *pbm) | ||
682 | { | ||
683 | u32 devhandle = pbm->devhandle; | ||
684 | unsigned int bus; | ||
685 | |||
686 | for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) { | ||
687 | unsigned int devfn; | ||
688 | |||
689 | for (devfn = 0; devfn < 256; devfn++) { | ||
690 | unsigned int device = PCI_SLOT(devfn); | ||
691 | unsigned int func = PCI_FUNC(devfn); | ||
692 | |||
693 | if (obp_find(pbm->prom_node, bus, devfn)) { | ||
694 | int err = pdev_htab_add(devhandle, bus, | ||
695 | device, func); | ||
696 | if (err) | ||
697 | return err; | ||
698 | } | ||
699 | } | ||
700 | } | ||
701 | |||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func) | ||
706 | { | ||
707 | struct pdev_entry *p; | ||
708 | |||
709 | p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)]; | ||
710 | while (p) { | ||
711 | if (p->devhandle == devhandle && | ||
712 | p->bus == bus && | ||
713 | p->device == device && | ||
714 | p->func == func) | ||
715 | break; | ||
716 | |||
717 | p = p->next; | ||
718 | } | ||
719 | |||
720 | return p; | ||
721 | } | ||
722 | |||
723 | static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) | 597 | static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) |
724 | { | 598 | { |
725 | if (bus < pbm->pci_first_busno || | 599 | if (bus < pbm->pci_first_busno || |
726 | bus > pbm->pci_last_busno) | 600 | bus > pbm->pci_last_busno) |
727 | return 1; | 601 | return 1; |
728 | return pdev_find(pbm->devhandle, bus, device, func) == NULL; | 602 | return 0; |
729 | } | 603 | } |
730 | 604 | ||
731 | static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | 605 | static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, |
@@ -800,27 +674,7 @@ static struct pci_ops pci_sun4v_ops = { | |||
800 | static void pbm_scan_bus(struct pci_controller_info *p, | 674 | static void pbm_scan_bus(struct pci_controller_info *p, |
801 | struct pci_pbm_info *pbm) | 675 | struct pci_pbm_info *pbm) |
802 | { | 676 | { |
803 | struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); | 677 | pbm->pci_bus = pci_scan_one_pbm(pbm); |
804 | |||
805 | if (!cookie) { | ||
806 | prom_printf("%s: Critical allocation failure.\n", pbm->name); | ||
807 | prom_halt(); | ||
808 | } | ||
809 | |||
810 | /* All we care about is the PBM. */ | ||
811 | cookie->pbm = pbm; | ||
812 | |||
813 | pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm); | ||
814 | #if 0 | ||
815 | pci_fixup_host_bridge_self(pbm->pci_bus); | ||
816 | pbm->pci_bus->self->sysdata = cookie; | ||
817 | #endif | ||
818 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); | ||
819 | pci_record_assignments(pbm, pbm->pci_bus); | ||
820 | pci_assign_unassigned(pbm, pbm->pci_bus); | ||
821 | pci_fixup_irq(pbm, pbm->pci_bus); | ||
822 | pci_determine_66mhz_disposition(pbm, pbm->pci_bus); | ||
823 | pci_setup_busmastering(pbm, pbm->pci_bus); | ||
824 | } | 678 | } |
825 | 679 | ||
826 | static void pci_sun4v_scan_bus(struct pci_controller_info *p) | 680 | static void pci_sun4v_scan_bus(struct pci_controller_info *p) |
@@ -846,8 +700,7 @@ static void pci_sun4v_scan_bus(struct pci_controller_info *p) | |||
846 | 700 | ||
847 | static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) | 701 | static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource) |
848 | { | 702 | { |
849 | struct pcidev_cookie *pcp = pdev->sysdata; | 703 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
850 | struct pci_pbm_info *pbm = pcp->pbm; | ||
851 | struct resource *res, *root; | 704 | struct resource *res, *root; |
852 | u32 reg; | 705 | u32 reg; |
853 | int where, size, is_64bit; | 706 | int where, size, is_64bit; |
@@ -1410,8 +1263,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, | |||
1410 | struct pci_dev *pdev, | 1263 | struct pci_dev *pdev, |
1411 | struct msi_desc *entry) | 1264 | struct msi_desc *entry) |
1412 | { | 1265 | { |
1413 | struct pcidev_cookie *pcp = pdev->sysdata; | 1266 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1414 | struct pci_pbm_info *pbm = pcp->pbm; | ||
1415 | unsigned long devino, msiqid; | 1267 | unsigned long devino, msiqid; |
1416 | struct msi_msg msg; | 1268 | struct msi_msg msg; |
1417 | int msi_num, err; | 1269 | int msi_num, err; |
@@ -1455,7 +1307,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, | |||
1455 | if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) | 1307 | if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) |
1456 | goto out_err; | 1308 | goto out_err; |
1457 | 1309 | ||
1458 | pcp->msi_num = msi_num; | 1310 | pdev->dev.archdata.msi_num = msi_num; |
1459 | 1311 | ||
1460 | if (entry->msi_attrib.is_64) { | 1312 | if (entry->msi_attrib.is_64) { |
1461 | msg.address_hi = pbm->msi64_start >> 32; | 1313 | msg.address_hi = pbm->msi64_start >> 32; |
@@ -1484,12 +1336,11 @@ out_err: | |||
1484 | static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, | 1336 | static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, |
1485 | struct pci_dev *pdev) | 1337 | struct pci_dev *pdev) |
1486 | { | 1338 | { |
1487 | struct pcidev_cookie *pcp = pdev->sysdata; | 1339 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1488 | struct pci_pbm_info *pbm = pcp->pbm; | ||
1489 | unsigned long msiqid, err; | 1340 | unsigned long msiqid, err; |
1490 | unsigned int msi_num; | 1341 | unsigned int msi_num; |
1491 | 1342 | ||
1492 | msi_num = pcp->msi_num; | 1343 | msi_num = pdev->dev.archdata.msi_num; |
1493 | err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); | 1344 | err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); |
1494 | if (err) { | 1345 | if (err) { |
1495 | printk(KERN_ERR "%s: getmsiq gives error %lu\n", | 1346 | printk(KERN_ERR "%s: getmsiq gives error %lu\n", |
@@ -1559,8 +1410,6 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node | |||
1559 | pci_sun4v_get_bus_range(pbm); | 1410 | pci_sun4v_get_bus_range(pbm); |
1560 | pci_sun4v_iommu_init(pbm); | 1411 | pci_sun4v_iommu_init(pbm); |
1561 | pci_sun4v_msi_init(pbm); | 1412 | pci_sun4v_msi_init(pbm); |
1562 | |||
1563 | pdev_htab_populate(pbm); | ||
1564 | } | 1413 | } |
1565 | 1414 | ||
1566 | void sun4v_pci_init(struct device_node *dp, char *model_name) | 1415 | void sun4v_pci_init(struct device_node *dp, char *model_name) |