aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-10 14:03:51 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-10 14:03:51 -0400
commit1f4d4a7e8f5a46929a987ec17987dbbdd73029d4 (patch)
tree7925980f6295e6f3aba704f08837b03bf3578838 /arch
parent938473b24636d77dc5e9c3f41090d071b6cf4389 (diff)
parent46b304934de417a2238d659ef6459a74cb3f5e6b (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Avoid JBUS errors on some Niagara systems. [FUSION]: Fix mptspi.c build with CONFIG_PM not set. [TG3]: Handle Sun onboard tg3 chips more correctly. [SPARC64]: Dump local cpu registers in sun4v_log_error()
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c124
-rw-r--r--arch/sparc64/kernel/traps.c11
2 files changed, 125 insertions, 10 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 2b7a1f316a93..0c0895202970 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -599,18 +599,128 @@ struct pci_iommu_ops pci_sun4v_iommu_ops = {
599 599
600/* SUN4V PCI configuration space accessors. */ 600/* SUN4V PCI configuration space accessors. */
601 601
602static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func) 602struct pdev_entry {
603 struct pdev_entry *next;
604 u32 devhandle;
605 unsigned int bus;
606 unsigned int device;
607 unsigned int func;
608};
609
610#define PDEV_HTAB_SIZE 16
611#define PDEV_HTAB_MASK (PDEV_HTAB_SIZE - 1)
612static struct pdev_entry *pdev_htab[PDEV_HTAB_SIZE];
613
614static inline unsigned int pdev_hashfn(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
603{ 615{
604 if (bus == pbm->pci_first_busno) { 616 unsigned int val;
605 if (device == 0 && func == 0) 617
606 return 0; 618 val = (devhandle ^ (devhandle >> 4));
607 return 1; 619 val ^= bus;
620 val ^= device;
621 val ^= func;
622
623 return val & PDEV_HTAB_MASK;
624}
625
626static int pdev_htab_add(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
627{
628 struct pdev_entry *p = kmalloc(sizeof(*p), GFP_KERNEL);
629 struct pdev_entry **slot;
630
631 if (!p)
632 return -ENOMEM;
633
634 slot = &pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
635 p->next = *slot;
636 *slot = p;
637
638 p->devhandle = devhandle;
639 p->bus = bus;
640 p->device = device;
641 p->func = func;
642
643 return 0;
644}
645
646/* Recursively descend into the OBP device tree, rooted at toplevel_node,
647 * looking for a PCI device matching bus and devfn.
648 */
649static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
650{
651 toplevel_node = prom_getchild(toplevel_node);
652
653 while (toplevel_node != 0) {
654 int ret = obp_find(pregs, toplevel_node, bus, devfn);
655
656 if (ret != 0)
657 return ret;
658
659 ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
660 sizeof(*pregs) * PROMREG_MAX);
661 if (ret == 0 || ret == -1)
662 goto next_sibling;
663
664 if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
665 ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
666 break;
667
668 next_sibling:
669 toplevel_node = prom_getsibling(toplevel_node);
670 }
671
672 return toplevel_node;
673}
674
675static int pdev_htab_populate(struct pci_pbm_info *pbm)
676{
677 struct linux_prom_pci_registers pr[PROMREG_MAX];
678 u32 devhandle = pbm->devhandle;
679 unsigned int bus;
680
681 for (bus = pbm->pci_first_busno; bus <= pbm->pci_last_busno; bus++) {
682 unsigned int devfn;
683
684 for (devfn = 0; devfn < 256; devfn++) {
685 unsigned int device = PCI_SLOT(devfn);
686 unsigned int func = PCI_FUNC(devfn);
687
688 if (obp_find(pr, pbm->prom_node, bus, devfn)) {
689 int err = pdev_htab_add(devhandle, bus,
690 device, func);
691 if (err)
692 return err;
693 }
694 }
695 }
696
697 return 0;
698}
699
700static struct pdev_entry *pdev_find(u32 devhandle, unsigned int bus, unsigned int device, unsigned int func)
701{
702 struct pdev_entry *p;
703
704 p = pdev_htab[pdev_hashfn(devhandle, bus, device, func)];
705 while (p) {
706 if (p->devhandle == devhandle &&
707 p->bus == bus &&
708 p->device == device &&
709 p->func == func)
710 break;
711
712 p = p->next;
608 } 713 }
609 714
715 return p;
716}
717
718static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
719{
610 if (bus < pbm->pci_first_busno || 720 if (bus < pbm->pci_first_busno ||
611 bus > pbm->pci_last_busno) 721 bus > pbm->pci_last_busno)
612 return 1; 722 return 1;
613 return 0; 723 return pdev_find(pbm->devhandle, bus, device, func) == NULL;
614} 724}
615 725
616static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, 726static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
@@ -1063,6 +1173,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32
1063 1173
1064 pci_sun4v_get_bus_range(pbm); 1174 pci_sun4v_get_bus_range(pbm);
1065 pci_sun4v_iommu_init(pbm); 1175 pci_sun4v_iommu_init(pbm);
1176
1177 pdev_htab_populate(pbm);
1066} 1178}
1067 1179
1068void sun4v_pci_init(int node, char *model_name) 1180void sun4v_pci_init(int node, char *model_name)
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 2793a5d82380..563db528e031 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1797,7 +1797,9 @@ static const char *sun4v_err_type_to_str(u32 type)
1797 }; 1797 };
1798} 1798}
1799 1799
1800static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) 1800extern void __show_regs(struct pt_regs * regs);
1801
1802static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt)
1801{ 1803{
1802 int cnt; 1804 int cnt;
1803 1805
@@ -1830,6 +1832,8 @@ static void sun4v_log_error(struct sun4v_error_entry *ent, int cpu, const char *
1830 pfx, 1832 pfx,
1831 ent->err_raddr, ent->err_size, ent->err_cpu); 1833 ent->err_raddr, ent->err_size, ent->err_cpu);
1832 1834
1835 __show_regs(regs);
1836
1833 if ((cnt = atomic_read(ocnt)) != 0) { 1837 if ((cnt = atomic_read(ocnt)) != 0) {
1834 atomic_set(ocnt, 0); 1838 atomic_set(ocnt, 0);
1835 wmb(); 1839 wmb();
@@ -1862,7 +1866,7 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
1862 1866
1863 put_cpu(); 1867 put_cpu();
1864 1868
1865 sun4v_log_error(&local_copy, cpu, 1869 sun4v_log_error(regs, &local_copy, cpu,
1866 KERN_ERR "RESUMABLE ERROR", 1870 KERN_ERR "RESUMABLE ERROR",
1867 &sun4v_resum_oflow_cnt); 1871 &sun4v_resum_oflow_cnt);
1868} 1872}
@@ -1910,7 +1914,7 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
1910 } 1914 }
1911#endif 1915#endif
1912 1916
1913 sun4v_log_error(&local_copy, cpu, 1917 sun4v_log_error(regs, &local_copy, cpu,
1914 KERN_EMERG "NON-RESUMABLE ERROR", 1918 KERN_EMERG "NON-RESUMABLE ERROR",
1915 &sun4v_nonresum_oflow_cnt); 1919 &sun4v_nonresum_oflow_cnt);
1916 1920
@@ -2200,7 +2204,6 @@ static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
2200void die_if_kernel(char *str, struct pt_regs *regs) 2204void die_if_kernel(char *str, struct pt_regs *regs)
2201{ 2205{
2202 static int die_counter; 2206 static int die_counter;
2203 extern void __show_regs(struct pt_regs * regs);
2204 extern void smp_report_regs(void); 2207 extern void smp_report_regs(void);
2205 int count = 0; 2208 int count = 0;
2206 2209