diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_psycho.c')
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 107 |
1 files changed, 49 insertions, 58 deletions
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0f35135a40c5..4801eb441236 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -265,12 +265,12 @@ static unsigned long stc_error_buf[128]; | |||
265 | static unsigned long stc_tag_buf[16]; | 265 | static unsigned long stc_tag_buf[16]; |
266 | static unsigned long stc_line_buf[16]; | 266 | static unsigned long stc_line_buf[16]; |
267 | 267 | ||
268 | static void __psycho_check_one_stc(struct pci_controller_info *p, | 268 | static void __psycho_check_one_stc(struct pci_pbm_info *pbm, |
269 | struct pci_pbm_info *pbm, | ||
270 | int is_pbm_a) | 269 | int is_pbm_a) |
271 | { | 270 | { |
271 | struct pci_controller_info *p = pbm->parent; | ||
272 | struct strbuf *strbuf = &pbm->stc; | 272 | struct strbuf *strbuf = &pbm->stc; |
273 | unsigned long regbase = p->pbm_A.controller_regs; | 273 | unsigned long regbase = pbm->controller_regs; |
274 | unsigned long err_base, tag_base, line_base; | 274 | unsigned long err_base, tag_base, line_base; |
275 | u64 control; | 275 | u64 control; |
276 | int i; | 276 | int i; |
@@ -362,20 +362,13 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, | |||
362 | spin_unlock(&stc_buf_lock); | 362 | spin_unlock(&stc_buf_lock); |
363 | } | 363 | } |
364 | 364 | ||
365 | static void __psycho_check_stc_error(struct pci_controller_info *p, | 365 | static void __psycho_check_stc_error(struct pci_pbm_info *pbm, |
366 | unsigned long afsr, | 366 | unsigned long afsr, |
367 | unsigned long afar, | 367 | unsigned long afar, |
368 | enum psycho_error_type type) | 368 | enum psycho_error_type type) |
369 | { | 369 | { |
370 | struct pci_pbm_info *pbm; | 370 | __psycho_check_one_stc(pbm, |
371 | 371 | (pbm == &pbm->parent->pbm_A)); | |
372 | pbm = &p->pbm_A; | ||
373 | if (pbm->stc.strbuf_enabled) | ||
374 | __psycho_check_one_stc(p, pbm, 1); | ||
375 | |||
376 | pbm = &p->pbm_B; | ||
377 | if (pbm->stc.strbuf_enabled) | ||
378 | __psycho_check_one_stc(p, pbm, 0); | ||
379 | } | 372 | } |
380 | 373 | ||
381 | /* When an Uncorrectable Error or a PCI Error happens, we | 374 | /* When an Uncorrectable Error or a PCI Error happens, we |
@@ -413,12 +406,13 @@ static void __psycho_check_stc_error(struct pci_controller_info *p, | |||
413 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) | 406 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) |
414 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) | 407 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) |
415 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL | 408 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL |
416 | static void psycho_check_iommu_error(struct pci_controller_info *p, | 409 | static void psycho_check_iommu_error(struct pci_pbm_info *pbm, |
417 | unsigned long afsr, | 410 | unsigned long afsr, |
418 | unsigned long afar, | 411 | unsigned long afar, |
419 | enum psycho_error_type type) | 412 | enum psycho_error_type type) |
420 | { | 413 | { |
421 | struct iommu *iommu = p->pbm_A.iommu; | 414 | struct pci_controller_info *p = pbm->parent; |
415 | struct iommu *iommu = pbm->iommu; | ||
422 | unsigned long iommu_tag[16]; | 416 | unsigned long iommu_tag[16]; |
423 | unsigned long iommu_data[16]; | 417 | unsigned long iommu_data[16]; |
424 | unsigned long flags; | 418 | unsigned long flags; |
@@ -465,7 +459,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, | |||
465 | psycho_write(iommu->iommu_control, | 459 | psycho_write(iommu->iommu_control, |
466 | control | PSYCHO_IOMMU_CTRL_DENAB); | 460 | control | PSYCHO_IOMMU_CTRL_DENAB); |
467 | for (i = 0; i < 16; i++) { | 461 | for (i = 0; i < 16; i++) { |
468 | unsigned long base = p->pbm_A.controller_regs; | 462 | unsigned long base = pbm->controller_regs; |
469 | 463 | ||
470 | iommu_tag[i] = | 464 | iommu_tag[i] = |
471 | psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); | 465 | psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); |
@@ -516,7 +510,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, | |||
516 | (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); | 510 | (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); |
517 | } | 511 | } |
518 | } | 512 | } |
519 | __psycho_check_stc_error(p, afsr, afar, type); | 513 | __psycho_check_stc_error(pbm, afsr, afar, type); |
520 | spin_unlock_irqrestore(&iommu->lock, flags); | 514 | spin_unlock_irqrestore(&iommu->lock, flags); |
521 | } | 515 | } |
522 | 516 | ||
@@ -541,9 +535,10 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, | |||
541 | 535 | ||
542 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | 536 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) |
543 | { | 537 | { |
544 | struct pci_controller_info *p = dev_id; | 538 | struct pci_pbm_info *pbm = dev_id; |
545 | unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR; | 539 | struct pci_controller_info *p = pbm->parent; |
546 | unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR; | 540 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; |
541 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; | ||
547 | unsigned long afsr, afar, error_bits; | 542 | unsigned long afsr, afar, error_bits; |
548 | int reported; | 543 | int reported; |
549 | 544 | ||
@@ -593,8 +588,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
593 | printk("(none)"); | 588 | printk("(none)"); |
594 | printk("]\n"); | 589 | printk("]\n"); |
595 | 590 | ||
596 | /* Interrogate IOMMU for error status. */ | 591 | /* Interrogate both IOMMUs for error status. */ |
597 | psycho_check_iommu_error(p, afsr, afar, UE_ERR); | 592 | psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); |
593 | psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); | ||
598 | 594 | ||
599 | return IRQ_HANDLED; | 595 | return IRQ_HANDLED; |
600 | } | 596 | } |
@@ -618,9 +614,10 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
618 | 614 | ||
619 | static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | 615 | static irqreturn_t psycho_ce_intr(int irq, void *dev_id) |
620 | { | 616 | { |
621 | struct pci_controller_info *p = dev_id; | 617 | struct pci_pbm_info *pbm = dev_id; |
622 | unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR; | 618 | struct pci_controller_info *p = pbm->parent; |
623 | unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR; | 619 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_CE_AFSR; |
620 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_CE_AFAR; | ||
624 | unsigned long afsr, afar, error_bits; | 621 | unsigned long afsr, afar, error_bits; |
625 | int reported; | 622 | int reported; |
626 | 623 | ||
@@ -823,11 +820,11 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | |||
823 | * a bug in the IOMMU support code or a PCI device driver. | 820 | * a bug in the IOMMU support code or a PCI device driver. |
824 | */ | 821 | */ |
825 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { | 822 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { |
826 | psycho_check_iommu_error(p, afsr, afar, PCI_ERR); | 823 | psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); |
827 | pci_scan_for_target_abort(p, pbm, pbm->pci_bus); | 824 | pci_scan_for_target_abort(pbm->parent, pbm, pbm->pci_bus); |
828 | } | 825 | } |
829 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) | 826 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) |
830 | pci_scan_for_master_abort(p, pbm, pbm->pci_bus); | 827 | pci_scan_for_master_abort(pbm->parent, pbm, pbm->pci_bus); |
831 | 828 | ||
832 | /* For excessive retries, PSYCHO/PBM will abort the device | 829 | /* For excessive retries, PSYCHO/PBM will abort the device |
833 | * and there is no way to specifically check for excessive | 830 | * and there is no way to specifically check for excessive |
@@ -837,7 +834,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | |||
837 | */ | 834 | */ |
838 | 835 | ||
839 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) | 836 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) |
840 | pci_scan_for_parity_error(p, pbm, pbm->pci_bus); | 837 | pci_scan_for_parity_error(pbm->parent, pbm, pbm->pci_bus); |
841 | 838 | ||
842 | return IRQ_HANDLED; | 839 | return IRQ_HANDLED; |
843 | } | 840 | } |
@@ -847,34 +844,33 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | |||
847 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ | 844 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ |
848 | #define PSYCHO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ | 845 | #define PSYCHO_ECCCTRL_UE 0x4000000000000000UL /* Enable UE Interrupts */ |
849 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ | 846 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ |
850 | static void psycho_register_error_handlers(struct pci_controller_info *p) | 847 | static void psycho_register_error_handlers(struct pci_pbm_info *pbm) |
851 | { | 848 | { |
852 | struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */ | ||
853 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 849 | struct of_device *op = of_find_device_by_node(pbm->prom_node); |
854 | unsigned long base = p->pbm_A.controller_regs; | 850 | unsigned long base = pbm->controller_regs; |
855 | u64 tmp; | 851 | u64 tmp; |
856 | 852 | ||
857 | if (!op) | 853 | if (!op) |
858 | return; | 854 | return; |
859 | 855 | ||
860 | /* Psycho interrupt property order is: | 856 | /* Psycho interrupt property order is: |
861 | * 0: PCIERR PBM B INO | 857 | * 0: PCIERR INO for this PBM |
862 | * 1: UE ERR | 858 | * 1: UE ERR |
863 | * 2: CE ERR | 859 | * 2: CE ERR |
864 | * 3: POWER FAIL | 860 | * 3: POWER FAIL |
865 | * 4: SPARE HARDWARE | 861 | * 4: SPARE HARDWARE |
866 | * 5: PCIERR PBM A INO | 862 | * 5: POWER MANAGEMENT |
867 | */ | 863 | */ |
868 | 864 | ||
869 | if (op->num_irqs < 6) | 865 | if (op->num_irqs < 6) |
870 | return; | 866 | return; |
871 | 867 | ||
872 | request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO UE", p); | 868 | request_irq(op->irqs[1], psycho_ue_intr, 0, |
873 | request_irq(op->irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO CE", p); | 869 | "PSYCHO_UE", pbm); |
874 | request_irq(op->irqs[5], psycho_pcierr_intr, IRQF_SHARED, | 870 | request_irq(op->irqs[2], psycho_ce_intr, 0, |
875 | "PSYCHO PCIERR-A", &p->pbm_A); | 871 | "PSYCHO_CE", pbm); |
876 | request_irq(op->irqs[0], psycho_pcierr_intr, IRQF_SHARED, | 872 | request_irq(op->irqs[0], psycho_pcierr_intr, 0, |
877 | "PSYCHO PCIERR-B", &p->pbm_B); | 873 | "PSYCHO_PCIERR", pbm); |
878 | 874 | ||
879 | /* Enable UE and CE interrupts for controller. */ | 875 | /* Enable UE and CE interrupts for controller. */ |
880 | psycho_write(base + PSYCHO_ECC_CTRL, | 876 | psycho_write(base + PSYCHO_ECC_CTRL, |
@@ -918,25 +914,16 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
918 | pci_config_write8(addr, 64); | 914 | pci_config_write8(addr, 64); |
919 | } | 915 | } |
920 | 916 | ||
921 | static void pbm_scan_bus(struct pci_controller_info *p, | 917 | static void psycho_scan_bus(struct pci_pbm_info *pbm) |
922 | struct pci_pbm_info *pbm) | ||
923 | { | 918 | { |
919 | pbm_config_busmastering(pbm); | ||
920 | pbm->is_66mhz_capable = 0; | ||
924 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 921 | pbm->pci_bus = pci_scan_one_pbm(pbm); |
925 | } | ||
926 | |||
927 | static void psycho_scan_bus(struct pci_controller_info *p) | ||
928 | { | ||
929 | pbm_config_busmastering(&p->pbm_B); | ||
930 | p->pbm_B.is_66mhz_capable = 0; | ||
931 | pbm_config_busmastering(&p->pbm_A); | ||
932 | p->pbm_A.is_66mhz_capable = 1; | ||
933 | pbm_scan_bus(p, &p->pbm_B); | ||
934 | pbm_scan_bus(p, &p->pbm_A); | ||
935 | 922 | ||
936 | /* After the PCI bus scan is complete, we can register | 923 | /* After the PCI bus scan is complete, we can register |
937 | * the error interrupt handlers. | 924 | * the error interrupt handlers. |
938 | */ | 925 | */ |
939 | psycho_register_error_handlers(p); | 926 | psycho_register_error_handlers(pbm); |
940 | } | 927 | } |
941 | 928 | ||
942 | static void psycho_iommu_init(struct pci_controller_info *p) | 929 | static void psycho_iommu_init(struct pci_controller_info *p) |
@@ -1096,6 +1083,11 @@ static void psycho_pbm_init(struct pci_controller_info *p, | |||
1096 | else | 1083 | else |
1097 | pbm = &p->pbm_B; | 1084 | pbm = &p->pbm_B; |
1098 | 1085 | ||
1086 | pbm->next = pci_pbm_root; | ||
1087 | pci_pbm_root = pbm; | ||
1088 | |||
1089 | pbm->scan_bus = psycho_scan_bus; | ||
1090 | |||
1099 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; | 1091 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; |
1100 | pbm->chip_version = 0; | 1092 | pbm->chip_version = 0; |
1101 | prop = of_find_property(dp, "version#", NULL); | 1093 | prop = of_find_property(dp, "version#", NULL); |
@@ -1127,6 +1119,7 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1127 | { | 1119 | { |
1128 | struct linux_prom64_registers *pr_regs; | 1120 | struct linux_prom64_registers *pr_regs; |
1129 | struct pci_controller_info *p; | 1121 | struct pci_controller_info *p; |
1122 | struct pci_pbm_info *pbm; | ||
1130 | struct iommu *iommu; | 1123 | struct iommu *iommu; |
1131 | struct property *prop; | 1124 | struct property *prop; |
1132 | u32 upa_portid; | 1125 | u32 upa_portid; |
@@ -1137,7 +1130,9 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1137 | if (prop) | 1130 | if (prop) |
1138 | upa_portid = *(u32 *) prop->value; | 1131 | upa_portid = *(u32 *) prop->value; |
1139 | 1132 | ||
1140 | for(p = pci_controller_root; p; p = p->next) { | 1133 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
1134 | struct pci_controller_info *p = pbm->parent; | ||
1135 | |||
1141 | if (p->pbm_A.portid == upa_portid) { | 1136 | if (p->pbm_A.portid == upa_portid) { |
1142 | is_pbm_a = (p->pbm_A.prom_node == NULL); | 1137 | is_pbm_a = (p->pbm_A.prom_node == NULL); |
1143 | psycho_pbm_init(p, dp, is_pbm_a); | 1138 | psycho_pbm_init(p, dp, is_pbm_a); |
@@ -1157,13 +1152,9 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1157 | } | 1152 | } |
1158 | p->pbm_A.iommu = p->pbm_B.iommu = iommu; | 1153 | p->pbm_A.iommu = p->pbm_B.iommu = iommu; |
1159 | 1154 | ||
1160 | p->next = pci_controller_root; | ||
1161 | pci_controller_root = p; | ||
1162 | |||
1163 | p->pbm_A.portid = upa_portid; | 1155 | p->pbm_A.portid = upa_portid; |
1164 | p->pbm_B.portid = upa_portid; | 1156 | p->pbm_B.portid = upa_portid; |
1165 | p->index = pci_num_controllers++; | 1157 | p->index = pci_num_controllers++; |
1166 | p->scan_bus = psycho_scan_bus; | ||
1167 | p->pci_ops = &psycho_ops; | 1158 | p->pci_ops = &psycho_ops; |
1168 | 1159 | ||
1169 | prop = of_find_property(dp, "reg", NULL); | 1160 | prop = of_find_property(dp, "reg", NULL); |