From 2481d76615d5e15340ccfb0243fe8779766dfc6e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Aug 2008 21:56:35 -0700 Subject: sparc: Add mutex for set property calls. On some platforms, the I2C controller is shared between the OS and OBP. OBP uses this I2C controller to access the EEPROM, and thus is programmed when the kernel calls prom_setprop(). Wrap such calls with the new of_set_property_mutex. Relevant I2C bus drivers can grab this mutex around top-level I2C operations to provide the proper protection. Signed-off-by: David S. Miller --- arch/sparc64/kernel/prom.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 3c048ac4e63..922dd612612 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -59,6 +59,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); +DEFINE_MUTEX(of_set_property_mutex); +EXPORT_SYMBOL(of_set_property_mutex); + int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; @@ -82,7 +85,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *old_val = prop->value; int ret; + mutex_lock(&of_set_property_mutex); ret = prom_setprop(dp->node, name, val, len); + mutex_unlock(&of_set_property_mutex); + err = -EINVAL; if (ret >= 0) { prop->value = new_val; -- cgit v1.2.3 From 44266215e3c8209613cea014721015113b7cd2d9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 20 Aug 2008 16:34:39 -0700 Subject: sparc: Implement irq_of_parse_and_map() and irq_dispose_mapping(). This allows more OF layer code to be shared between powerpc and sparc. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index f8b50cbf4bf..8a0d82343a2 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -55,6 +55,17 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); +int irq_of_parse_and_map(struct device_node *node, int index) +{ + struct of_device *op = of_find_device_by_node(node); + + if (!op || index >= op->num_irqs) + return 0xffffffff; + + return op->irqs[index]; +} +EXPORT_SYMBOL(irq_of_parse_and_map); + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); -- cgit v1.2.3 From fe06ccaad20257e3bd348b2df9e811fd92211a80 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 20:10:23 -0700 Subject: sparc64: Split syscall_trace() into two functions. Christoph Hellwig noticed that having both entry and exit logic in one function no longer makes sense, and having seperate ones simplifies things a lot. Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.h | 3 ++- arch/sparc64/kernel/ptrace.c | 38 +++++++++++++++++++------------------ arch/sparc64/kernel/sparc64_ksyms.c | 1 - arch/sparc64/kernel/syscalls.S | 20 ++++++++----------- 4 files changed, 30 insertions(+), 32 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index fc294a29289..2255244442f 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -22,7 +22,8 @@ extern void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags); -extern asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p); +extern asmlinkage int syscall_trace_enter(struct pt_regs *regs); +extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); extern void bad_trap_tl1(struct pt_regs *regs, long lvl); diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index bd578cc4856..db2ddf2e829 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -1050,31 +1050,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) +asmlinkage int syscall_trace_enter(struct pt_regs *regs) { int ret = 0; /* do the secure computing check first */ secure_computing(regs->u_regs[UREG_G1]); - if (unlikely(current->audit_context) && syscall_exit_p) { - unsigned long tstate = regs->tstate; - int result = AUDITSC_SUCCESS; - - if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) - result = AUDITSC_FAILURE; - - audit_syscall_exit(result, regs->u_regs[UREG_I0]); - } - - if (test_thread_flag(TIF_SYSCALL_TRACE)) { - if (syscall_exit_p) - tracehook_report_syscall_exit(regs, 0); - else - ret = tracehook_report_syscall_entry(regs); - } + if (test_thread_flag(TIF_SYSCALL_TRACE)) + ret = tracehook_report_syscall_entry(regs); - if (unlikely(current->audit_context) && !syscall_exit_p && !ret) + if (unlikely(current->audit_context) && !ret) audit_syscall_entry((test_thread_flag(TIF_32BIT) ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64), @@ -1086,3 +1072,19 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) return ret; } + +asmlinkage void syscall_trace_leave(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) { + unsigned long tstate = regs->tstate; + int result = AUDITSC_SUCCESS; + + if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) + result = AUDITSC_FAILURE; + + audit_syscall_exit(result, regs->u_regs[UREG_I0]); + } + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); +} diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 0804f71df6c..d44b2eeb25d 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -68,7 +68,6 @@ extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern __kernel_size_t strlen(const char *); -extern void syscall_trace(struct pt_regs *, int); extern void sys_sigsuspend(void); extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc64/kernel/syscalls.S index a2f24270ed8..7a6786a7136 100644 --- a/arch/sparc64/kernel/syscalls.S +++ b/arch/sparc64/kernel/syscalls.S @@ -65,9 +65,8 @@ sys32_rt_sigreturn: andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 be,pt %icc, rtrap nop - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 + call syscall_trace_leave + add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap nop @@ -159,9 +158,8 @@ linux_sparc_ni_syscall: or %l7, %lo(sys_ni_syscall), %l7 linux_syscall_trace32: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 + call syscall_trace_enter + add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 srl %i0, 0, %o0 @@ -172,9 +170,8 @@ linux_syscall_trace32: srl %i3, 0, %o3 linux_syscall_trace: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - clr %o1 + call syscall_trace_enter + add %sp, PTREGS_OFF, %o0 brnz,pn %o0, 3f mov -ENOSYS, %o0 mov %i0, %o0 @@ -275,9 +272,8 @@ ret_sys_call: b,pt %xcc, rtrap stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] linux_syscall_trace2: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 + call syscall_trace_leave + add %sp, PTREGS_OFF, %o0 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ba,pt %xcc, rtrap stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] -- cgit v1.2.3 From 8394b3a84bf3e4665da4e535d34980aa6ba78969 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 20:13:42 -0700 Subject: sparc64: Kill duplicated sys_pause() implementation. sys32_pause() is identical to the generically provided sys_pause() in kernel/signal.c Noticed by Christoph Hellwig. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sys_sparc32.c | 8 -------- arch/sparc64/kernel/systbls.S | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 3d118531baf..3320c9d0075 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -575,14 +575,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -/* These are here just in case some old sparc32 binary calls it. */ -asmlinkage long sys32_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 0fdbf3ba956..5daee4b04dd 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -23,7 +23,7 @@ sys_call_table32: /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 -/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause +/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid -- cgit v1.2.3 From b28422e32b9127ab4178ce05a419069db3d11d19 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 21:32:42 -0700 Subject: sparc64: Convert UltraSPARC-III memory controller driver to OF driver probing. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 119 +++++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 41 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 6d4f02e8a4c..b9cd736a11f 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -1,6 +1,6 @@ -/* memctrlr.c: Driver for UltraSPARC-III memory controller. +/* chmc.c: Driver for UltraSPARC-III memory controller. * - * Copyright (C) 2001, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 2001, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -13,13 +13,25 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include +#define DRV_MODULE_NAME "chmc" +#define PFX DRV_MODULE_NAME ": " +#define DRV_MODULE_VERSION "0.2" + +MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); +MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_MODULE_VERSION); + #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 @@ -343,16 +355,25 @@ static void fetch_decode_regs(struct mctrl_info *mp) read_mcreg(mp, CHMCTRL_DECODE4)); } -static int init_one_mctrl(struct device_node *dp) +static int __devinit chmc_probe(struct of_device *op, + const struct of_device_id *match) { - struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); - int portid = of_getintprop_default(dp, "portid", -1); - const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; + struct mctrl_info *mp; + unsigned long ver; const void *pval; - int len; + int len, portid; + + __asm__ ("rdpr %%ver, %0" : "=r" (ver)); + if ((ver >> 32UL) == __JALAPENO_ID || + (ver >> 32UL) == __SERRANO_ID) + return -ENODEV; + mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) - return -1; + return -ENOMEM; + + portid = of_getintprop_default(dp, "portid", -1); if (portid == -1) goto fail; @@ -362,18 +383,19 @@ static int init_one_mctrl(struct device_node *dp) if (!pval) mp->layout_size = 0; else { - if (mp->layout_size > sizeof(mp->layout_prop)) + if (mp->layout_size > sizeof(mp->layout_prop)) { + printk(KERN_ERR PFX "Unexpected memory-layout property " + "size %d.\n", mp->layout_size); goto fail; + } memcpy(&mp->layout_prop, pval, len); } - regs = of_get_property(dp, "reg", NULL); - if (!regs || regs->reg_size != 0x48) - goto fail; - - mp->regs = ioremap(regs->phys_addr, regs->reg_size); - if (mp->regs == NULL) + mp->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); + if (!mp->regs) { + printk(KERN_ERR PFX "Could not map registers.\n"); goto fail; + } if (mp->layout_size != 0UL) { mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); @@ -388,54 +410,69 @@ static int init_one_mctrl(struct device_node *dp) list_add(&mp->list, &mctrl_list); /* Report the device. */ - printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", + printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, - mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); + (mp->layout_size ? "ACTIVE" : "INACTIVE")); + + dev_set_drvdata(&op->dev, mp); return 0; fail: if (mp) { if (mp->regs != NULL) - iounmap(mp->regs); + of_iounmap(&op->resource[0], mp->regs, 0x48); kfree(mp); } return -1; } -static int __init chmc_init(void) +static int __devexit chmc_remove(struct of_device *op) { - struct device_node *dp; + struct mctrl_info *mp = dev_get_drvdata(&op->dev); - /* This driver is only for cheetah platforms. */ - if (tlb_type != cheetah && tlb_type != cheetah_plus) - return -ENODEV; + if (mp) { + list_del(&mp->list); + of_iounmap(&op->resource[0], mp->regs, 0x48); + kfree(mp); + } + return 0; +} - for_each_node_by_name(dp, "memory-controller") - init_one_mctrl(dp); +static struct of_device_id chmc_match[] = { + { + .name = "memory-controller", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, chmc_match); - for_each_node_by_name(dp, "mc-us3") - init_one_mctrl(dp); +static struct of_platform_driver chmc_driver = { + .name = "chmc", + .match_table = chmc_match, + .probe = chmc_probe, + .remove = __devexit_p(chmc_remove), +}; - return 0; +static inline bool chmc_platform(void) +{ + if (tlb_type == cheetah || tlb_type == cheetah_plus) + return true; + return false; } -static void __exit chmc_cleanup(void) +static int __init chmc_init(void) { - struct list_head *head = &mctrl_list; - struct list_head *tmp = head->next; + if (!chmc_platform()) + return -ENODEV; - for (;;) { - struct mctrl_info *p = - list_entry(tmp, struct mctrl_info, list); - if (tmp == head) - break; - tmp = tmp->next; + return of_register_driver(&chmc_driver, &of_bus_type); +} - list_del(&p->list); - iounmap(p->regs); - kfree(p); - } +static void __exit chmc_cleanup(void) +{ + if (chmc_platform()) + of_unregister_driver(&chmc_driver); } module_init(chmc_init); -- cgit v1.2.3 From 83ef64b9dea6e3ed287a45d56166913bffcd2497 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 21:45:44 -0700 Subject: sparc64: Use consistent chmc_ prefix in variables, types, and functions. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 237 +++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 117 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index b9cd736a11f..2f73ddc8676 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -35,35 +35,35 @@ MODULE_VERSION(DRV_MODULE_VERSION); #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 -#define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) +#define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) /* OBP memory-layout property format. */ -struct obp_map { +struct chmc_obp_map { unsigned char dimm_map[144]; unsigned char pin_map[576]; }; #define DIMM_LABEL_SZ 8 -struct obp_mem_layout { +struct chmc_obp_mem_layout { /* One max 8-byte string label per DIMM. Usually * this matches the label on the motherboard where * that DIMM resides. */ - char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; + char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ]; /* If symmetric use map[0], else it is * asymmetric and map[1] should be used. */ - char symmetric; + char symmetric; - struct obp_map map[2]; + struct chmc_obp_map map[2]; }; #define CHMCTRL_NBANKS 4 -struct bank_info { - struct mctrl_info *mp; +struct chmc_bank_info { + struct chmc *p; int bank_id; u64 raw_reg; @@ -77,28 +77,28 @@ struct bank_info { unsigned long size; }; -struct mctrl_info { - struct list_head list; - int portid; +struct chmc { + struct list_head list; + int portid; - struct obp_mem_layout layout_prop; - int layout_size; + struct chmc_obp_mem_layout layout_prop; + int layout_size; - void __iomem *regs; + void __iomem *regs; - u64 timing_control1; - u64 timing_control2; - u64 timing_control3; - u64 timing_control4; - u64 memaddr_control; + u64 timing_control1; + u64 timing_control2; + u64 timing_control3; + u64 timing_control4; + u64 memaddr_control; - struct bank_info logical_banks[CHMCTRL_NBANKS]; + struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; }; static LIST_HEAD(mctrl_list); /* Does BANK decode PHYS_ADDR? */ -static int bank_match(struct bank_info *bp, unsigned long phys_addr) +static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) { unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; @@ -130,14 +130,13 @@ static int bank_match(struct bank_info *bp, unsigned long phys_addr) } /* Given PHYS_ADDR, search memory controller banks for a match. */ -static struct bank_info *find_bank(unsigned long phys_addr) +static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) { struct list_head *mctrl_head = &mctrl_list; struct list_head *mctrl_entry = mctrl_head->next; for (;;) { - struct mctrl_info *mp = - list_entry(mctrl_entry, struct mctrl_info, list); + struct chmc *p = list_entry(mctrl_entry, struct chmc, list); int bank_no; if (mctrl_entry == mctrl_head) @@ -145,10 +144,10 @@ static struct bank_info *find_bank(unsigned long phys_addr) mctrl_entry = mctrl_entry->next; for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { - struct bank_info *bp; + struct chmc_bank_info *bp; - bp = &mp->logical_banks[bank_no]; - if (bank_match(bp, phys_addr)) + bp = &p->logical_banks[bank_no]; + if (chmc_bank_match(bp, phys_addr)) return bp; } } @@ -163,11 +162,11 @@ int chmc_getunumber(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) { - struct bank_info *bp; - struct obp_mem_layout *prop; + struct chmc_bank_info *bp; + struct chmc_obp_mem_layout *prop; int bank_in_controller, first_dimm; - bp = find_bank(phys_addr); + bp = chmc_find_bank(phys_addr); if (bp == NULL || syndrome_code < SYNDROME_MIN || syndrome_code > SYNDROME_MAX) { @@ -178,13 +177,13 @@ int chmc_getunumber(int syndrome_code, return 0; } - prop = &bp->mp->layout_prop; + prop = &bp->p->layout_prop; bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); first_dimm *= CHMCTRL_NDIMMS; if (syndrome_code != SYNDROME_MIN) { - struct obp_map *map; + struct chmc_obp_map *map; int qword, where_in_line, where, map_index, map_offset; unsigned int map_val; @@ -252,7 +251,7 @@ int chmc_getunumber(int syndrome_code, * the code is executing, you must use special ASI load/store else * you go through the global mapping. */ -static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) +static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset) { unsigned long ret, this_cpu; @@ -260,14 +259,14 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) this_cpu = real_hard_smp_processor_id(); - if (mp->portid == this_cpu) { + if (p->portid == this_cpu) { __asm__ __volatile__("ldxa [%1] %2, %0" : "=r" (ret) : "r" (offset), "i" (ASI_MCU_CTRL_REG)); } else { __asm__ __volatile__("ldxa [%1] %2, %0" : "=r" (ret) - : "r" (mp->regs + offset), + : "r" (p->regs + offset), "i" (ASI_PHYS_BYPASS_EC_E)); } @@ -277,164 +276,168 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) } #if 0 /* currently unused */ -static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) +static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val) { - if (mp->portid == smp_processor_id()) { + if (p->portid == smp_processor_id()) { __asm__ __volatile__("stxa %0, [%1] %2" : : "r" (val), "r" (offset), "i" (ASI_MCU_CTRL_REG)); } else { __asm__ __volatile__("ldxa %0, [%1] %2" : : "r" (val), - "r" (mp->regs + offset), + "r" (p->regs + offset), "i" (ASI_PHYS_BYPASS_EC_E)); } } #endif -static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) +static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val) { - struct bank_info *p = &mp->logical_banks[which_bank]; - - p->mp = mp; - p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; - p->raw_reg = val; - p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; - p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; - p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; - p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; - p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; - - p->base = (p->um); - p->base &= ~(p->uk); - p->base <<= PA_UPPER_BITS_SHIFT; - - switch(p->lk) { + struct chmc_bank_info *bp = &p->logical_banks[which_bank]; + + bp->p = p; + bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank; + bp->raw_reg = val; + bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; + bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; + bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; + bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; + bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; + + bp->base = (bp->um); + bp->base &= ~(bp->uk); + bp->base <<= PA_UPPER_BITS_SHIFT; + + switch(bp->lk) { case 0xf: default: - p->interleave = 1; + bp->interleave = 1; break; case 0xe: - p->interleave = 2; + bp->interleave = 2; break; case 0xc: - p->interleave = 4; + bp->interleave = 4; break; case 0x8: - p->interleave = 8; + bp->interleave = 8; break; case 0x0: - p->interleave = 16; + bp->interleave = 16; break; }; /* UK[10] is reserved, and UK[11] is not set for the SDRAM * bank size definition. */ - p->size = (((unsigned long)p->uk & - ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; - p->size /= p->interleave; + bp->size = (((unsigned long)bp->uk & + ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; + bp->size /= bp->interleave; } -static void fetch_decode_regs(struct mctrl_info *mp) +static void chmc_fetch_decode_regs(struct chmc *p) { - if (mp->layout_size == 0) + if (p->layout_size == 0) return; - interpret_one_decode_reg(mp, 0, - read_mcreg(mp, CHMCTRL_DECODE1)); - interpret_one_decode_reg(mp, 1, - read_mcreg(mp, CHMCTRL_DECODE2)); - interpret_one_decode_reg(mp, 2, - read_mcreg(mp, CHMCTRL_DECODE3)); - interpret_one_decode_reg(mp, 3, - read_mcreg(mp, CHMCTRL_DECODE4)); + chmc_interpret_one_decode_reg(p, 0, + chmc_read_mcreg(p, CHMCTRL_DECODE1)); + chmc_interpret_one_decode_reg(p, 1, + chmc_read_mcreg(p, CHMCTRL_DECODE2)); + chmc_interpret_one_decode_reg(p, 2, + chmc_read_mcreg(p, CHMCTRL_DECODE3)); + chmc_interpret_one_decode_reg(p, 3, + chmc_read_mcreg(p, CHMCTRL_DECODE4)); } static int __devinit chmc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct mctrl_info *mp; unsigned long ver; const void *pval; int len, portid; + struct chmc *p; + int err; + err = -ENODEV; __asm__ ("rdpr %%ver, %0" : "=r" (ver)); if ((ver >> 32UL) == __JALAPENO_ID || (ver >> 32UL) == __SERRANO_ID) - return -ENODEV; - - mp = kzalloc(sizeof(*mp), GFP_KERNEL); - if (!mp) - return -ENOMEM; + goto out; portid = of_getintprop_default(dp, "portid", -1); if (portid == -1) - goto fail; + goto out; - mp->portid = portid; pval = of_get_property(dp, "memory-layout", &len); - mp->layout_size = len; - if (!pval) - mp->layout_size = 0; - else { - if (mp->layout_size > sizeof(mp->layout_prop)) { - printk(KERN_ERR PFX "Unexpected memory-layout property " - "size %d.\n", mp->layout_size); - goto fail; - } - memcpy(&mp->layout_prop, pval, len); + if (pval && len > sizeof(p->layout_prop)) { + printk(KERN_ERR PFX "Unexpected memory-layout property " + "size %d.\n", len); + goto out; + } + + err = -ENOMEM; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR PFX "Could not allocate struct chmc.\n"); + goto out; } - mp->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); - if (!mp->regs) { + p->portid = portid; + p->layout_size = len; + if (!pval) + p->layout_size = 0; + else + memcpy(&p->layout_prop, pval, len); + + p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); + if (!p->regs) { printk(KERN_ERR PFX "Could not map registers.\n"); - goto fail; + goto out_free; } - if (mp->layout_size != 0UL) { - mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); - mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); - mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); - mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); - mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); + if (p->layout_size != 0UL) { + p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1); + p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2); + p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3); + p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4); + p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL); } - fetch_decode_regs(mp); + chmc_fetch_decode_regs(p); - list_add(&mp->list, &mctrl_list); + list_add(&p->list, &mctrl_list); /* Report the device. */ printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, - (mp->layout_size ? "ACTIVE" : "INACTIVE")); + (p->layout_size ? "ACTIVE" : "INACTIVE")); - dev_set_drvdata(&op->dev, mp); + dev_set_drvdata(&op->dev, p); - return 0; + err = 0; -fail: - if (mp) { - if (mp->regs != NULL) - of_iounmap(&op->resource[0], mp->regs, 0x48); - kfree(mp); - } - return -1; +out: + return err; + +out_free: + kfree(p); + goto out; } static int __devexit chmc_remove(struct of_device *op) { - struct mctrl_info *mp = dev_get_drvdata(&op->dev); + struct chmc *p = dev_get_drvdata(&op->dev); - if (mp) { - list_del(&mp->list); - of_iounmap(&op->resource[0], mp->regs, 0x48); - kfree(mp); + if (p) { + list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, 0x48); + kfree(p); } return 0; } -- cgit v1.2.3 From 881d021ab0d675f519b68df916fde969940ef988 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 22:08:34 -0700 Subject: sparc64: Add generic interface for registering a dimm printing handler. The way to do this varies by platform type and the exact memory controller the cpu uses. For Spitfire cpus we currently just use prom_getunumber() and hope that works. For Cheetah cpus we have a memory controller driver that can compute this information. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 21 +++++++++++---- arch/sparc64/kernel/traps.c | 62 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 13 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 2f73ddc8676..a3c79fd5dd3 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -22,6 +22,7 @@ #include #include #include +#include #define DRV_MODULE_NAME "chmc" #define PFX DRV_MODULE_NAME ": " @@ -158,9 +159,9 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) /* This is the main purpose of this driver. */ #define SYNDROME_MIN -1 #define SYNDROME_MAX 144 -int chmc_getunumber(int syndrome_code, - unsigned long phys_addr, - char *buf, int buflen) +static int chmc_print_dimm(int syndrome_code, + unsigned long phys_addr, + char *buf, int buflen) { struct chmc_bank_info *bp; struct chmc_obp_mem_layout *prop; @@ -466,16 +467,26 @@ static inline bool chmc_platform(void) static int __init chmc_init(void) { + int ret; + if (!chmc_platform()) return -ENODEV; - return of_register_driver(&chmc_driver, &of_bus_type); + ret = register_dimm_printer(chmc_print_dimm); + if (!ret) { + ret = of_register_driver(&chmc_driver, &of_bus_type); + if (ret) + unregister_dimm_printer(chmc_print_dimm); + } + return ret; } static void __exit chmc_cleanup(void) { - if (chmc_platform()) + if (chmc_platform()) { + unregister_dimm_printer(chmc_print_dimm); of_unregister_driver(&chmc_driver); + } } module_init(chmc_init); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 3d924121c79..17880ccfa3c 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "entry.h" #include "kstack.h" @@ -128,6 +129,55 @@ void do_BUG(const char *file, int line) } #endif +static DEFINE_SPINLOCK(dimm_handler_lock); +static dimm_printer_t dimm_handler; + +static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen) +{ + unsigned long flags; + int ret = -ENODEV; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (dimm_handler) { + ret = dimm_handler(synd_code, paddr, buf, buflen); + } else if (tlb_type == spitfire) { + if (prom_getunumber(synd_code, paddr, buf, buflen) == -1) + ret = -EINVAL; + else + ret = 0; + } else + ret = -ENODEV; + spin_unlock_irqrestore(&dimm_handler_lock, flags); + + return ret; +} + +int register_dimm_printer(dimm_printer_t func) +{ + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (!dimm_handler) + dimm_handler = func; + else + ret = -EEXIST; + spin_unlock_irqrestore(&dimm_handler_lock, flags); + + return ret; +} + +void unregister_dimm_printer(dimm_printer_t func) +{ + unsigned long flags; + + spin_lock_irqsave(&dimm_handler_lock, flags); + if (dimm_handler == func) + dimm_handler = NULL; + spin_unlock_irqrestore(&dimm_handler_lock, flags); +} + + void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { siginfo_t info; @@ -375,8 +425,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un if (udbl & bit) { scode = ecc_syndrome_table[udbl & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) p = syndrome_unknown; else p = memmod_str; @@ -387,8 +436,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un if (udbh & bit) { scode = ecc_syndrome_table[udbh & 0xff]; - if (prom_getunumber(scode, afar, - memmod_str, sizeof(memmod_str)) == -1) + if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) p = syndrome_unknown; else p = memmod_str; @@ -1061,8 +1109,6 @@ static const char *cheetah_get_string(unsigned long bit) return "???"; } -extern int chmc_getunumber(int, unsigned long, char *, int); - static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, unsigned long afsr, unsigned long afar, int recoverable) { @@ -1104,7 +1150,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; syndrome = cheetah_ecc_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), @@ -1115,7 +1161,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; syndrome = cheetah_mtag_syntab[syndrome]; - ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); + ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), -- cgit v1.2.3 From 41660e9ac639c97840258d3c5294f618ca8cc46f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 24 Aug 2008 22:17:29 -0700 Subject: sparc64: Allow chmc to be built as a module. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 3 ++- arch/sparc64/kernel/sparc64_ksyms.c | 2 ++ arch/sparc64/kernel/traps.c | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 418b5782096..313735fa5f2 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o pci.o starfire.o \ - power.o sbus.o sparc64_ksyms.o chmc.o \ + power.o sbus.o sparc64_ksyms.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o @@ -25,6 +25,7 @@ obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o +obj-$(CONFIG_US3_MC) += chmc.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o obj-$(CONFIG_AUDIT) += audit.o diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index d44b2eeb25d..3b2890c207f 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -299,3 +299,5 @@ EXPORT_SYMBOL(xor_niagara_2); EXPORT_SYMBOL(xor_niagara_3); EXPORT_SYMBOL(xor_niagara_4); EXPORT_SYMBOL(xor_niagara_5); + +EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 17880ccfa3c..71644da6cad 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -166,6 +166,7 @@ int register_dimm_printer(dimm_printer_t func) return ret; } +EXPORT_SYMBOL_GPL(register_dimm_printer); void unregister_dimm_printer(dimm_printer_t func) { @@ -176,7 +177,7 @@ void unregister_dimm_printer(dimm_printer_t func) dimm_handler = NULL; spin_unlock_irqrestore(&dimm_handler_lock, flags); } - +EXPORT_SYMBOL_GPL(unregister_dimm_printer); void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { -- cgit v1.2.3 From 85269eb5542b425b99d79dc4c312dce0157eac7e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 13:38:30 -0700 Subject: sparc64: Add JBUS UltraSPARC-IIIi support to memory controller driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 536 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 453 insertions(+), 83 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index a3c79fd5dd3..3e14952e940 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -33,6 +33,12 @@ MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); +static int mc_type; +#define MC_TYPE_SAFARI 1 +#define MC_TYPE_JBUS 2 + +static dimm_printer_t us3mc_dimm_printer; + #define CHMCTRL_NDGRPS 2 #define CHMCTRL_NDIMMS 4 @@ -96,8 +102,386 @@ struct chmc { struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; }; +#define JBUSMC_REGS_SIZE 8 + +#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000 +#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000 +#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000 +#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000 +#define JB_MC_REG1_XOR 0x0000010000000000 +#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000 +#define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 +#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000 +#define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 +#define JB_MC_REG1_INTERLEAVE 0x0000000001800000 +#define JB_MC_REG1_INTERLEAVE_SHIFT 23 +#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000 +#define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 +#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000 +#define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 + +#define PART_TYPE_X8 0 +#define PART_TYPE_X4 1 + +#define INTERLEAVE_NONE 0 +#define INTERLEAVE_SAME 1 +#define INTERLEAVE_INTERNAL 2 +#define INTERLEAVE_BOTH 3 + +#define ADDR_GEN_128MB 0 +#define ADDR_GEN_256MB 1 +#define ADDR_GEN_512MB 2 +#define ADDR_GEN_1GB 3 + +#define JB_NUM_DIMM_GROUPS 2 +#define JB_NUM_DIMMS_PER_GROUP 2 +#define JB_NUM_DIMMS (JB_NUM_DIMM_GROUPS * JB_NUM_DIMMS_PER_GROUP) + +struct jbusmc_obp_map { + unsigned char dimm_map[18]; + unsigned char pin_map[144]; +}; + +struct jbusmc_obp_mem_layout { + /* One max 8-byte string label per DIMM. Usually + * this matches the label on the motherboard where + * that DIMM resides. + */ + char dimm_labels[JB_NUM_DIMMS][DIMM_LABEL_SZ]; + + /* If symmetric use map[0], else it is + * asymmetric and map[1] should be used. + */ + char symmetric; + + struct jbusmc_obp_map map; + + char _pad; +}; + +struct jbusmc_dimm_group { + struct jbusmc *controller; + int index; + u64 base_addr; + u64 size; +}; + +struct jbusmc { + void __iomem *regs; + u64 mc_reg_1; + u32 portid; + struct jbusmc_obp_mem_layout layout; + int layout_len; + int num_dimm_groups; + struct jbusmc_dimm_group dimm_groups[JB_NUM_DIMM_GROUPS]; + struct list_head list; +}; + +static DEFINE_SPINLOCK(mctrl_list_lock); static LIST_HEAD(mctrl_list); +static void mc_list_add(struct list_head *list) +{ + spin_lock(&mctrl_list_lock); + list_add(list, &mctrl_list); + spin_unlock(&mctrl_list_lock); +} + +static void mc_list_del(struct list_head *list) +{ + spin_lock(&mctrl_list_lock); + list_del_init(list); + spin_unlock(&mctrl_list_lock); +} + +#define SYNDROME_MIN -1 +#define SYNDROME_MAX 144 + +/* Covert syndrome code into the way the bits are positioned + * on the bus. + */ +static int syndrome_to_qword_code(int syndrome_code) +{ + if (syndrome_code < 128) + syndrome_code += 16; + else if (syndrome_code < 128 + 9) + syndrome_code -= (128 - 7); + else if (syndrome_code < (128 + 9 + 3)) + syndrome_code -= (128 + 9 - 4); + else + syndrome_code -= (128 + 9 + 3); + return syndrome_code; +} + +/* All this magic has to do with how a cache line comes over the wire + * on Safari and JBUS. A 64-bit line comes over in 1 or more quadword + * cycles, each of which transmit ECC/MTAG info as well as the actual + * data. + */ +#define L2_LINE_SIZE 64 +#define L2_LINE_ADDR_MSK (L2_LINE_SIZE - 1) +#define QW_PER_LINE 4 +#define QW_BYTES (L2_LINE_SIZE / QW_PER_LINE) +#define QW_BITS 144 +#define SAFARI_LAST_BIT (576 - 1) +#define JBUS_LAST_BIT (144 - 1) + +static void get_pin_and_dimm_str(int syndrome_code, unsigned long paddr, + int *pin_p, char **dimm_str_p, void *_prop, + int base_dimm_offset) +{ + int qword_code = syndrome_to_qword_code(syndrome_code); + int cache_line_offset; + int offset_inverse; + int dimm_map_index; + int map_val; + + if (mc_type == MC_TYPE_JBUS) { + struct jbusmc_obp_mem_layout *p = _prop; + + /* JBUS */ + cache_line_offset = qword_code; + offset_inverse = (JBUS_LAST_BIT - cache_line_offset); + dimm_map_index = offset_inverse / 8; + map_val = p->map.dimm_map[dimm_map_index]; + map_val = ((map_val >> ((7 - (offset_inverse & 7)))) & 1); + *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; + *pin_p = p->map.pin_map[cache_line_offset]; + } else { + struct chmc_obp_mem_layout *p = _prop; + struct chmc_obp_map *mp; + int qword; + + /* Safari */ + if (p->symmetric) + mp = &p->map[0]; + else + mp = &p->map[1]; + + qword = (paddr & L2_LINE_ADDR_MSK) / QW_BYTES; + cache_line_offset = ((3 - qword) * QW_BITS) + qword_code; + offset_inverse = (SAFARI_LAST_BIT - cache_line_offset); + dimm_map_index = offset_inverse >> 2; + map_val = mp->dimm_map[dimm_map_index]; + map_val = ((map_val >> ((3 - (offset_inverse & 3)) << 1)) & 0x3); + *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; + *pin_p = mp->pin_map[cache_line_offset]; + } +} + +static struct jbusmc_dimm_group *jbusmc_find_dimm_group(unsigned long phys_addr) +{ + struct jbusmc *p; + + list_for_each_entry(p, &mctrl_list, list) { + int i; + + for (i = 0; i < p->num_dimm_groups; i++) { + struct jbusmc_dimm_group *dp = &p->dimm_groups[i]; + + if (phys_addr < dp->base_addr || + (dp->base_addr + dp->size) <= phys_addr) + continue; + + return dp; + } + } + return NULL; +} + +static int jbusmc_print_dimm(int syndrome_code, + unsigned long phys_addr, + char *buf, int buflen) +{ + struct jbusmc_obp_mem_layout *prop; + struct jbusmc_dimm_group *dp; + struct jbusmc *p; + int first_dimm; + + dp = jbusmc_find_dimm_group(phys_addr); + if (dp == NULL || + syndrome_code < SYNDROME_MIN || + syndrome_code > SYNDROME_MAX) { + buf[0] = '?'; + buf[1] = '?'; + buf[2] = '?'; + buf[3] = '\0'; + } + p = dp->controller; + prop = &p->layout; + + first_dimm = dp->index * JB_NUM_DIMMS_PER_GROUP; + + if (syndrome_code != SYNDROME_MIN) { + char *dimm_str; + int pin; + + get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, + &dimm_str, prop, first_dimm); + sprintf(buf, "%s, pin %3d", dimm_str, pin); + } else { + int dimm; + + /* Multi-bit error, we just dump out all the + * dimm labels associated with this dimm group. + */ + for (dimm = 0; dimm < JB_NUM_DIMMS_PER_GROUP; dimm++) { + sprintf(buf, "%s ", + prop->dimm_labels[first_dimm + dimm]); + buf += strlen(buf); + } + } + + return 0; +} + +static u64 __devinit jbusmc_dimm_group_size(u64 base, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + u64 max = base + (8UL * 1024 * 1024 * 1024); + u64 max_seen = base; + int i; + + for (i = 0; i < num_mem_regs; i++) { + const struct linux_prom64_registers *ent; + u64 this_base; + u64 this_end; + + ent = &mem_regs[i]; + this_base = ent->phys_addr; + this_end = this_base + ent->reg_size; + if (base < this_base || base >= this_end) + continue; + if (this_end > max) + this_end = max; + if (this_end > max_seen) + max_seen = this_end; + } + + return max_seen - base; +} + +static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p, + unsigned long index, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + struct jbusmc_dimm_group *dp = &p->dimm_groups[index]; + + dp->controller = p; + dp->index = index; + + dp->base_addr = (p->portid * (64UL * 1024 * 1024 * 1024)); + dp->base_addr += (index * (8UL * 1024 * 1024 * 1024)); + dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs); +} + +static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, + const struct linux_prom64_registers *mem_regs, + int num_mem_regs) +{ + if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) { + jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs); + p->num_dimm_groups++; + } + if (p->mc_reg_1 & JB_MC_REG1_DIMM2_BANK2) { + jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs); + p->num_dimm_groups++; + } +} + +static int __devinit jbusmc_probe(struct of_device *op, + const struct of_device_id *match) +{ + const struct linux_prom64_registers *mem_regs; + struct device_node *mem_node; + int err, len, num_mem_regs; + struct jbusmc *p; + const u32 *prop; + const void *ml; + + err = -ENODEV; + mem_node = of_find_node_by_path("/memory"); + if (!mem_node) { + printk(KERN_ERR PFX "Cannot find /memory node.\n"); + goto out; + } + mem_regs = of_get_property(mem_node, "reg", &len); + if (!mem_regs) { + printk(KERN_ERR PFX "Cannot get reg property of /memory node.\n"); + goto out; + } + num_mem_regs = len / sizeof(*mem_regs); + + err = -ENOMEM; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR PFX "Cannot allocate struct jbusmc.\n"); + goto out; + } + + INIT_LIST_HEAD(&p->list); + + err = -ENODEV; + prop = of_get_property(op->node, "portid", &len); + if (!prop || len != 4) { + printk(KERN_ERR PFX "Cannot find portid.\n"); + goto out_free; + } + + p->portid = *prop; + + prop = of_get_property(op->node, "memory-control-register-1", &len); + if (!prop || len != 8) { + printk(KERN_ERR PFX "Cannot get memory control register 1.\n"); + goto out_free; + } + + p->mc_reg_1 = ((u64)prop[0] << 32) | (u64) prop[1]; + + err = -ENOMEM; + p->regs = of_ioremap(&op->resource[0], 0, JBUSMC_REGS_SIZE, "jbusmc"); + if (!p->regs) { + printk(KERN_ERR PFX "Cannot map jbusmc regs.\n"); + goto out_free; + } + + err = -ENODEV; + ml = of_get_property(op->node, "memory-layout", &p->layout_len); + if (!ml) { + printk(KERN_ERR PFX "Cannot get memory layout property.\n"); + goto out_iounmap; + } + if (p->layout_len > sizeof(p->layout)) { + printk(KERN_ERR PFX "Unexpected memory-layout size %d\n", + p->layout_len); + goto out_iounmap; + } + memcpy(&p->layout, ml, p->layout_len); + + jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs); + + mc_list_add(&p->list); + + printk(KERN_INFO PFX "UltraSPARC-IIIi memory controller at %s\n", + op->node->full_name); + + dev_set_drvdata(&op->dev, p); + + err = 0; + +out: + return err; + +out_iounmap: + of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); + +out_free: + kfree(p); + goto out; +} + /* Does BANK decode PHYS_ADDR? */ static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) { @@ -133,17 +517,11 @@ static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) /* Given PHYS_ADDR, search memory controller banks for a match. */ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) { - struct list_head *mctrl_head = &mctrl_list; - struct list_head *mctrl_entry = mctrl_head->next; + struct chmc *p; - for (;;) { - struct chmc *p = list_entry(mctrl_entry, struct chmc, list); + list_for_each_entry(p, &mctrl_list, list) { int bank_no; - if (mctrl_entry == mctrl_head) - break; - mctrl_entry = mctrl_entry->next; - for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { struct chmc_bank_info *bp; @@ -157,8 +535,6 @@ static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) } /* This is the main purpose of this driver. */ -#define SYNDROME_MIN -1 -#define SYNDROME_MAX 144 static int chmc_print_dimm(int syndrome_code, unsigned long phys_addr, char *buf, int buflen) @@ -184,54 +560,12 @@ static int chmc_print_dimm(int syndrome_code, first_dimm *= CHMCTRL_NDIMMS; if (syndrome_code != SYNDROME_MIN) { - struct chmc_obp_map *map; - int qword, where_in_line, where, map_index, map_offset; - unsigned int map_val; - - /* Yaay, single bit error so we can figure out - * the exact dimm. - */ - if (prop->symmetric) - map = &prop->map[0]; - else - map = &prop->map[1]; - - /* Covert syndrome code into the way the bits are - * positioned on the bus. - */ - if (syndrome_code < 144 - 16) - syndrome_code += 16; - else if (syndrome_code < 144) - syndrome_code -= (144 - 7); - else if (syndrome_code < (144 + 3)) - syndrome_code -= (144 + 3 - 4); - else - syndrome_code -= 144 + 3; + char *dimm_str; + int pin; - /* All this magic has to do with how a cache line - * comes over the wire on Safari. A 64-bit line - * comes over in 4 quadword cycles, each of which - * transmit ECC/MTAG info as well as the actual - * data. 144 bits per quadword, 576 total. - */ -#define LINE_SIZE 64 -#define LINE_ADDR_MSK (LINE_SIZE - 1) -#define QW_PER_LINE 4 -#define QW_BYTES (LINE_SIZE / QW_PER_LINE) -#define QW_BITS 144 -#define LAST_BIT (576 - 1) - - qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES; - where_in_line = ((3 - qword) * QW_BITS) + syndrome_code; - where = (LAST_BIT - where_in_line); - map_index = where >> 2; - map_offset = where & 0x3; - map_val = map->dimm_map[map_index]; - map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1)); - - sprintf(buf, "%s, pin %3d", - prop->dimm_labels[first_dimm + map_val], - map->pin_map[where_in_line]); + get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, + &dimm_str, prop, first_dimm); + sprintf(buf, "%s, pin %3d", dimm_str, pin); } else { int dimm; @@ -412,9 +746,8 @@ static int __devinit chmc_probe(struct of_device *op, chmc_fetch_decode_regs(p); - list_add(&p->list, &mctrl_list); + mc_list_add(&p->list); - /* Report the device. */ printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", dp->full_name, (p->layout_size ? "ACTIVE" : "INACTIVE")); @@ -431,63 +764,100 @@ out_free: goto out; } -static int __devexit chmc_remove(struct of_device *op) +static int __devinit us3mc_probe(struct of_device *op, + const struct of_device_id *match) +{ + if (mc_type == MC_TYPE_SAFARI) + return chmc_probe(op, match); + else if (mc_type == MC_TYPE_JBUS) + return jbusmc_probe(op, match); + return -ENODEV; +} + +static void __devexit chmc_destroy(struct of_device *op, struct chmc *p) +{ + list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, 0x48); + kfree(p); +} + +static void __devexit jbusmc_destroy(struct of_device *op, struct jbusmc *p) { - struct chmc *p = dev_get_drvdata(&op->dev); + mc_list_del(&p->list); + of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); + kfree(p); +} + +static int __devexit us3mc_remove(struct of_device *op) +{ + void *p = dev_get_drvdata(&op->dev); if (p) { - list_del(&p->list); - of_iounmap(&op->resource[0], p->regs, 0x48); - kfree(p); + if (mc_type == MC_TYPE_SAFARI) + chmc_destroy(op, p); + else if (mc_type == MC_TYPE_JBUS) + jbusmc_destroy(op, p); } return 0; } -static struct of_device_id chmc_match[] = { +static struct of_device_id us3mc_match[] = { { .name = "memory-controller", }, {}, }; -MODULE_DEVICE_TABLE(of, chmc_match); +MODULE_DEVICE_TABLE(of, us3mc_match); -static struct of_platform_driver chmc_driver = { - .name = "chmc", - .match_table = chmc_match, - .probe = chmc_probe, - .remove = __devexit_p(chmc_remove), +static struct of_platform_driver us3mc_driver = { + .name = "us3mc", + .match_table = us3mc_match, + .probe = us3mc_probe, + .remove = __devexit_p(us3mc_remove), }; -static inline bool chmc_platform(void) +static inline bool us3mc_platform(void) { if (tlb_type == cheetah || tlb_type == cheetah_plus) return true; return false; } -static int __init chmc_init(void) +static int __init us3mc_init(void) { + unsigned long ver; int ret; - if (!chmc_platform()) + if (!us3mc_platform()) return -ENODEV; - ret = register_dimm_printer(chmc_print_dimm); + __asm__ ("rdpr %%ver, %0" : "=r" (ver)); + if ((ver >> 32UL) == __JALAPENO_ID || + (ver >> 32UL) == __SERRANO_ID) { + mc_type = MC_TYPE_JBUS; + us3mc_dimm_printer = jbusmc_print_dimm; + } else { + mc_type = MC_TYPE_SAFARI; + us3mc_dimm_printer = chmc_print_dimm; + } + + ret = register_dimm_printer(us3mc_dimm_printer); + if (!ret) { - ret = of_register_driver(&chmc_driver, &of_bus_type); + ret = of_register_driver(&us3mc_driver, &of_bus_type); if (ret) - unregister_dimm_printer(chmc_print_dimm); + unregister_dimm_printer(us3mc_dimm_printer); } return ret; } -static void __exit chmc_cleanup(void) +static void __exit us3mc_cleanup(void) { - if (chmc_platform()) { - unregister_dimm_printer(chmc_print_dimm); - of_unregister_driver(&chmc_driver); + if (us3mc_platform()) { + unregister_dimm_printer(us3mc_dimm_printer); + of_unregister_driver(&us3mc_driver); } } -module_init(chmc_init); -module_exit(chmc_cleanup); +module_init(us3mc_init); +module_exit(us3mc_cleanup); -- cgit v1.2.3 From 783c98b911fce8d47aa2906468ca39d44d46d7ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 16:21:08 -0700 Subject: sparc64: Use the cond_syscall()s in kernel/sys_ni.c instead of home-grown copy. This also allows arch/sparc64/kernel/pci.c to be properly CONFIG_PCI conditional compiled in the Makefile. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 4 ++-- arch/sparc64/kernel/pci.c | 18 ------------------ 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 313735fa5f2..360a348e5bb 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -10,13 +10,13 @@ extra-y := head.o init_task.o vmlinux.lds obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ - unaligned.o central.o pci.o starfire.o \ + unaligned.o central.o starfire.o \ power.o sbus.o sparc64_ksyms.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += ebus.o pci_common.o \ +obj-$(CONFIG_PCI) += ebus.o pci.o pci_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 55096195458..9bb4b8cbcac 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -28,22 +28,6 @@ #include "pci_impl.h" -#ifndef CONFIG_PCI -/* A "nop" PCI implementation. */ -asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - return 0; -} -#else - /* List of all PCI controllers found in the system. */ struct pci_pbm_info *pci_pbm_root = NULL; @@ -1215,5 +1199,3 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, *start = rp->start - offset; *end = rp->end - offset; } - -#endif /* !(CONFIG_PCI) */ -- cgit v1.2.3 From 51e0f004a9ab9104acbe323c0b20e0279bf9be85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 25 Aug 2008 16:44:58 -0700 Subject: sparc64: Fix irq_of_parse_and_map() and irq_dispose_mapping(). Stephen Rothwell noticed that I committed an earlier version of the patch that didn't have two things fixed: 1) irq_of_parse_and_map() should return "unsigned int" not "int" and it should return zero for "no irq" 2) irq_dispose_mapping() should be an inline function, not a macro, for type checking With feedback and suggestions from Anton Vorontsov. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 8a0d82343a2..a30f2af0bf2 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -55,12 +55,12 @@ struct of_device *of_find_device_by_node(struct device_node *dp) } EXPORT_SYMBOL(of_find_device_by_node); -int irq_of_parse_and_map(struct device_node *node, int index) +unsigned int irq_of_parse_and_map(struct device_node *node, int index) { struct of_device *op = of_find_device_by_node(node); if (!op || index >= op->num_irqs) - return 0xffffffff; + return 0; return op->irqs[index]; } -- cgit v1.2.3 From 902663f6ea4a2603bee0d88450aae2d653a46f5d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 22:25:03 -0700 Subject: sparc: Delete bare sbus char bpp driver, obsoleted by parport_sunbpp Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 60d36d14255..214da1bd8a5 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 334ae614772b1147435dce9be3911f9040dff0d9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 17:01:57 -0700 Subject: sparc: Kill SBUS DVMA layer. This thing was completely pointless. Just find the OF device in the parent of drivers that want to program this device, and map the DMA regs inside such drivers too. This also moves the dummy claim_dma_lock() and release_dma_lock() implementation to floppy_32.h, which makes it handle this issue just like floppy_64.h does. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 3b2890c207f..8e6ac5c1b7b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -161,7 +161,6 @@ EXPORT_SYMBOL(auxio_set_lte); #endif #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); -EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); EXPORT_SYMBOL(sbus_alloc_consistent); EXPORT_SYMBOL(sbus_free_consistent); -- cgit v1.2.3 From 7a715f46012f3552294154978aed59cba9804928 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:37:58 -0700 Subject: sparc: Make SBUS DMA interfaces take struct device. This is the first step in converting all the SBUS drivers over to generic dma_*(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 8e6ac5c1b7b..1c56c8b854d 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -170,8 +170,6 @@ EXPORT_SYMBOL(sbus_map_sg); EXPORT_SYMBOL(sbus_unmap_sg); EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); EXPORT_SYMBOL(sbus_dma_sync_single_for_device); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); #endif EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(outsw); -- cgit v1.2.3 From 738f2b7b813913e651f39387d007dd961755dee2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 18:09:11 -0700 Subject: sparc: Convert all SBUS drivers to dma_*() interfaces. And all the SBUS dma interfaces are deleted. A private implementation remains inside of the 32-bit sparc port which exists only for the sake of the implementation of dma_*(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 1c56c8b854d..901c26437b6 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -162,14 +162,6 @@ EXPORT_SYMBOL(auxio_set_lte); #ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); -EXPORT_SYMBOL(sbus_alloc_consistent); -EXPORT_SYMBOL(sbus_free_consistent); -EXPORT_SYMBOL(sbus_map_single); -EXPORT_SYMBOL(sbus_unmap_single); -EXPORT_SYMBOL(sbus_map_sg); -EXPORT_SYMBOL(sbus_unmap_sg); -EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); -EXPORT_SYMBOL(sbus_dma_sync_single_for_device); #endif EXPORT_SYMBOL(outsb); EXPORT_SYMBOL(outsw); -- cgit v1.2.3 From 63237eeb5ac92d618a0a6055f4b1f65c5d14682b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Aug 2008 23:33:42 -0700 Subject: sparc: Move SBUS DMA attribute interfaces out of asm/sbus.h This is in preparation for the subsequent asm/sbus.h removal. Also, make these routines take a "struct device" or no arguments, as appropriate. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index e33a8a660e9..aa47022e13f 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -52,13 +52,23 @@ #define STRBUF_TAG_VALID 0x02UL /* Enable 64-bit DVMA mode for the given device. */ -void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) +void sbus_set_sbus64(struct device *dev, int bursts) { - struct iommu *iommu = sdev->ofdev.dev.archdata.iommu; - int slot = sdev->slot; + struct iommu *iommu = dev->archdata.iommu; + struct of_device *op = to_of_device(dev); + const struct linux_prom_registers *regs; unsigned long cfg_reg; + int slot; u64 val; + regs = of_get_property(op->node, "reg", NULL); + if (!regs) { + printk(KERN_ERR "sbus_set_sbus64: Cannot find regs for %s\n", + op->node->full_name); + return; + } + slot = regs->which_io; + cfg_reg = iommu->write_complete_reg; switch (slot) { case 0: -- cgit v1.2.3 From 33c4655c00e6af3ec4023f2cafd63dd4a42de49b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 02:56:39 -0700 Subject: sparc: Kill SBUS layer IRQ hooks. IRQs are obtained by drivers from the of_device struct. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index aa47022e13f..60fac2d64b1 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -650,26 +650,6 @@ fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void sbus_fill_device_irq(struct sbus_dev *sdev) -{ - struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); - const struct linux_prom_irqs *irqs; - - irqs = of_get_property(dp, "interrupts", NULL); - if (!irqs) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - unsigned int pri = irqs[0].pri; - - sdev->num_irqs = 1; - if (pri < 0x20) - pri += sdev->slot * 8; - - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); - } -} - void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) { } @@ -679,10 +659,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) sbus_iommu_init(dp->node, sbus); } -void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) -{ -} - int __init sbus_arch_preinit(void) { return 0; -- cgit v1.2.3 From 104364810ff5b0844a2183fbca989f70e86d486b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 03:38:42 -0700 Subject: sparc: Remove SBUS layer resource and irq handling. All the drivers use OF device objects now for this information. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 60fac2d64b1..0193e382319 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -650,10 +650,6 @@ fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) -{ -} - void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) { sbus_iommu_init(dp->node, sbus); -- cgit v1.2.3 From 98261dd1a393777f4400d8ad5a29e97cb30e5422 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 03:47:56 -0700 Subject: sparc: Remove dinky old-style SBUS probing facilities. No drivers or code uses this stuff any more, every driver has been converted over to OF device probing. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 901c26437b6..08c58a8457b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -160,7 +160,6 @@ EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); #endif #ifdef CONFIG_SBUS -EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(sbus_set_sbus64); #endif EXPORT_SYMBOL(outsb); -- cgit v1.2.3 From f8e4d32cb5153a9d6a8e8864e357dad1349f3b85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:20:14 -0700 Subject: sparc: Kill sbus_arch_preinit(). 32-bit sparc just needed it to register the ioport procfs bits, do this via an arch_initcall() instead. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 0193e382319..0b3e7bc96f6 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -655,11 +655,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) sbus_iommu_init(dp->node, sbus); } -int __init sbus_arch_preinit(void) -{ - return 0; -} - void __init sbus_arch_postinit(void) { extern void firetruck_init(void); -- cgit v1.2.3 From 5059625ed8862e897760b86effff0f8a35989c0d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:22:37 -0700 Subject: sparc: Add OF archdata propagation helper. Add a helper function that, given a bus of_device node, propagates all iommu, stc, and host_controller values down to the child nodes. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index a30f2af0bf2..b22475f85a5 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -66,6 +66,28 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index) } EXPORT_SYMBOL(irq_of_parse_and_map); +/* Take the archdata values for IOMMU, STC, and HOSTDATA found in + * BUS and propagate to all child of_device objects. + */ +void of_propagate_archdata(struct of_device *bus) +{ + struct dev_archdata *bus_sd = &bus->dev.archdata; + struct device_node *bus_dp = bus->node; + struct device_node *dp; + + for (dp = bus_dp->child; dp; dp = dp->sibling) { + struct of_device *op = of_find_device_by_node(dp); + + op->dev.archdata.iommu = bus_sd->iommu; + op->dev.archdata.stc = bus_sd->stc; + op->dev.archdata.host_controller = bus_sd->host_controller; + op->dev.archdata.numa_node = bus_sd->numa_node; + + if (dp->child) + of_propagate_archdata(op); + } +} + #ifdef CONFIG_PCI struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); -- cgit v1.2.3 From 046e26a8ba10b8ceff822f8d91451ab6c1e08c4e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 04:54:04 -0700 Subject: sparc: Remove generic SBUS probing layer. The individual SBUS IOMMU arch code now sets the IOMMU information directly into the OF device objects. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sbus.c | 122 +++++++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 55 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 0b3e7bc96f6..60605eaf49b 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -201,10 +201,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) return imap + diff; } -unsigned int sbus_build_irq(void *buscookie, unsigned int ino) +static unsigned int sbus_build_irq(struct of_device *op, unsigned int ino) { - struct sbus_bus *sbus = (struct sbus_bus *)buscookie; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long imap, iclr; int sbus_level = 0; @@ -265,12 +264,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; afsr_reg = reg_base + SYSIO_UE_AFSR; afar_reg = reg_base + SYSIO_UE_AFAR; @@ -285,9 +284,11 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + /* Log the error. */ printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", - sbus->portid, + portid, (((error_bits & SYSIO_UEAFSR_PPIO) ? "PIO" : ((error_bits & SYSIO_UEAFSR_PDRD) ? @@ -295,12 +296,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) ((error_bits & SYSIO_UEAFSR_PDWR) ? "DVMA Write" : "???"))))); printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, (afsr & SYSIO_UEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); + printk("SYSIO[%x]: Secondary UE errors [", portid); reported = 0; if (afsr & SYSIO_UEAFSR_SPIO) { reported++; @@ -337,12 +338,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; afsr_reg = reg_base + SYSIO_CE_AFSR; afar_reg = reg_base + SYSIO_CE_AFAR; @@ -357,8 +358,10 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", - sbus->portid, + portid, (((error_bits & SYSIO_CEAFSR_PPIO) ? "PIO" : ((error_bits & SYSIO_CEAFSR_PDRD) ? @@ -370,14 +373,14 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) * XXX UDB CE trap handler does... -DaveM */ printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, (afsr & SYSIO_CEAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); - printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); + printk("SYSIO[%x]: Secondary CE errors [", portid); reported = 0; if (afsr & SYSIO_CEAFSR_SPIO) { reported++; @@ -414,11 +417,11 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) { - struct sbus_bus *sbus = dev_id; - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct of_device *op = dev_id; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long afsr_reg, afar_reg, reg_base; unsigned long afsr, afar, error_bits; - int reported; + int reported, portid; reg_base = iommu->write_complete_reg - 0x2000UL; afsr_reg = reg_base + SYSIO_SBUS_AFSR; @@ -433,9 +436,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); upa_writeq(error_bits, afsr_reg); + portid = of_getintprop_default(op->node, "portid", -1); + /* Log the error. */ printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", - sbus->portid, + portid, (((error_bits & SYSIO_SBAFSR_PLE) ? "Late PIO Error" : ((error_bits & SYSIO_SBAFSR_PTO) ? @@ -444,11 +449,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) "Error Ack" : "???")))), (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); printk("SYSIO[%x]: size[%lx] MID[%lx]\n", - sbus->portid, + portid, (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, (afsr & SYSIO_SBAFSR_MID) >> 37UL); - printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); - printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); + printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); + printk("SYSIO[%x]: Secondary SBUS errors [", portid); reported = 0; if (afsr & SYSIO_SBAFSR_SLE) { reported++; @@ -480,34 +485,37 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) #define SYSIO_CE_INO 0x35 #define SYSIO_SBUSERR_INO 0x36 -static void __init sysio_register_error_handlers(struct sbus_bus *sbus) +static void __init sysio_register_error_handlers(struct of_device *op) { - struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; + struct iommu *iommu = op->dev.archdata.iommu; unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; unsigned int irq; u64 control; + int portid; + + portid = of_getintprop_default(op->node, "portid", -1); - irq = sbus_build_irq(sbus, SYSIO_UE_INO); + irq = sbus_build_irq(op, SYSIO_UE_INO); if (request_irq(irq, sysio_ue_handler, 0, - "SYSIO_UE", sbus) < 0) { + "SYSIO_UE", op) < 0) { prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", - sbus->portid); + portid); prom_halt(); } - irq = sbus_build_irq(sbus, SYSIO_CE_INO); + irq = sbus_build_irq(op, SYSIO_CE_INO); if (request_irq(irq, sysio_ce_handler, 0, - "SYSIO_CE", sbus) < 0) { + "SYSIO_CE", op) < 0) { prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", - sbus->portid); + portid); prom_halt(); } - irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); + irq = sbus_build_irq(op, SYSIO_SBUSERR_INO); if (request_irq(irq, sysio_sbus_error_handler, 0, - "SYSIO_SBERR", sbus) < 0) { + "SYSIO_SBERR", op) < 0) { prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", - sbus->portid); + portid); prom_halt(); } @@ -523,19 +531,15 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) } /* Boot time initialization. */ -static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) +static void __init sbus_iommu_init(struct of_device *op) { const struct linux_prom64_registers *pr; - struct device_node *dp; + struct device_node *dp = op->node; struct iommu *iommu; struct strbuf *strbuf; unsigned long regs, reg_base; + int i, portid; u64 control; - int i; - - dp = of_find_node_by_phandle(__node); - - sbus->portid = of_getintprop_default(dp, "upa-portid", -1); pr = of_get_property(dp, "reg", NULL); if (!pr) { @@ -552,9 +556,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) if (!strbuf) goto fatal_memory_error; - sbus->ofdev.dev.archdata.iommu = iommu; - sbus->ofdev.dev.archdata.stc = strbuf; - sbus->ofdev.dev.archdata.numa_node = -1; + op->dev.archdata.iommu = iommu; + op->dev.archdata.stc = strbuf; + op->dev.archdata.numa_node = -1; reg_base = regs + SYSIO_IOMMUREG_BASE; iommu->iommu_control = reg_base + IOMMU_CONTROL; @@ -582,8 +586,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) */ iommu->write_complete_reg = regs + 0x2000UL; - printk("SYSIO: UPA portID %x, at %016lx\n", - sbus->portid, regs); + portid = of_getintprop_default(op->node, "portid", -1); + printk(KERN_INFO "SYSIO: UPA portID %x, at %016lx\n", + portid, regs); /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) @@ -641,23 +646,30 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) /* Now some Xfire specific grot... */ if (this_is_starfire) - starfire_hookup(sbus->portid); + starfire_hookup(portid); - sysio_register_error_handlers(sbus); + sysio_register_error_handlers(op); return; fatal_memory_error: prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); } -void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) -{ - sbus_iommu_init(dp->node, sbus); -} - -void __init sbus_arch_postinit(void) +static int __init sbus_init(void) { extern void firetruck_init(void); + struct device_node *dp; + + for_each_node_by_name(dp, "sbus") { + struct of_device *op = of_find_device_by_node(dp); + + sbus_iommu_init(op); + of_propagate_archdata(op); + } firetruck_init(); + + return 0; } + +subsys_initcall(sbus_init); -- cgit v1.2.3 From 47a2d7288538e7f334a0be318317b138f0e3dfbe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 19:45:20 -0700 Subject: sparc: Kill sbus_bus_type. No longer used. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index b22475f85a5..6ae92536517 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -93,11 +93,6 @@ struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #endif -#ifdef CONFIG_SBUS -struct bus_type sbus_bus_type; -EXPORT_SYMBOL(sbus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -874,10 +869,6 @@ static int __init of_bus_driver_init(void) if (!err) err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif -#ifdef CONFIG_SBUS - if (!err) - err = of_bus_type_init(&sbus_bus_type, "sbus"); -#endif if (!err) scan_of_devices(); -- cgit v1.2.3 From 9dc69230a96a84ca8e6eef89cd34fad0dd8a1a09 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 27 Aug 2008 19:54:01 -0700 Subject: sparc: Kill now spurious includes of sbus.h In order to make this week I also had to add an include of linux/dma-mapping.h to asm/pci_32.h because drivers/pci/pci.c really depends upon getting this header somehow. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 1 - arch/sparc64/kernel/sbus.c | 4 +++- arch/sparc64/kernel/sparc64_ksyms.c | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 9b6689d9d57..2817a272b4c 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 60605eaf49b..9d7dfb8cc27 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -11,15 +11,17 @@ #include #include #include +#include +#include #include -#include #include #include #include #include #include #include +#include #include #include "iommu_common.h" diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 08c58a8457b..142c16983d1 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -44,7 +44,6 @@ #include #include #ifdef CONFIG_SBUS -#include #include #endif #ifdef CONFIG_PCI -- cgit v1.2.3 From a0b31b578f9ab34826703762113f9d42f3ae9819 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 17:34:31 -0700 Subject: sparc64: Check for RTC class device in update_persistent_clock(). As we convert the various by-hand sparc64 RTC drivers to use the generic RTC framework and drivers, we need to keep the NTP set_rtc_mmss() support via update_persistent_clock() working. In the end, after all the RTC device cases are converted, this local set_rtc_mmss() function will be deleted. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index cc16fdcf98a..184321b88a6 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -405,6 +405,11 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { + struct rtc_device *rtc = rtc_class_open("rtc0"); + + if (rtc) + return rtc_set_mmss(rtc, now.tv_sec); + return set_rtc_mmss(now.tv_sec); } -- cgit v1.2.3 From 1518e7ed08019539498f772faa1f9368fed91361 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 21:06:27 -0700 Subject: sparc64: Convert Mostek rtc to use generic RTC layer driver. Based largely upon a patch by Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc64/kernel/sparc64_ksyms.c | 3 - arch/sparc64/kernel/time.c | 416 +++++++++--------------------------- 2 files changed, 102 insertions(+), 317 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 142c16983d1..4c3a6a87c8a 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -152,8 +151,6 @@ EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(__flush_dcache_range); #endif -EXPORT_SYMBOL(mostek_lock); -EXPORT_SYMBOL(mstk48t02_regs); #ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 184321b88a6..9c2c3d84443 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -30,13 +30,14 @@ #include #include #include +#include #include #include #include #include +#include #include -#include #include #include #include @@ -50,17 +51,12 @@ #include "entry.h" -DEFINE_SPINLOCK(mostek_lock); DEFINE_SPINLOCK(rtc_lock); -void __iomem *mstk48t02_regs = NULL; #ifdef CONFIG_PCI unsigned long ds1287_regs = 0UL; static void __iomem *bq4802_regs; #endif -static void __iomem *mstk48t08_regs; -static void __iomem *mstk48t59_regs; - static int set_rtc_mmss(unsigned long); #define TICK_PRIV_BIT (1UL << 63) @@ -413,144 +409,10 @@ int update_persistent_clock(struct timespec now) return set_rtc_mmss(now.tv_sec); } -/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ -static void __init kick_start_clock(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 sec, tmp; - int i, count; - - prom_printf("CLOCK: Clock was stopped. Kick start "); - - spin_lock_irq(&mostek_lock); - - /* Turn on the kick start bit to start the oscillator. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_SEC); - tmp &= ~MSTK_STOP; - mostek_write(regs + MOSTEK_SEC, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp |= MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Delay to allow the clock oscillator to start. */ - sec = MSTK_REG_SEC(regs); - for (i = 0; i < 3; i++) { - while (sec == MSTK_REG_SEC(regs)) - for (count = 0; count < 100000; count++) - /* nothing */ ; - prom_printf("."); - sec = MSTK_REG_SEC(regs); - } - prom_printf("\n"); - - spin_lock_irq(&mostek_lock); - - /* Turn off kick start and set a "valid" time and date. */ - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - MSTK_SET_REG_SEC(regs,0); - MSTK_SET_REG_MIN(regs,0); - MSTK_SET_REG_HOUR(regs,0); - MSTK_SET_REG_DOW(regs,5); - MSTK_SET_REG_DOM(regs,1); - MSTK_SET_REG_MONTH(regs,8); - MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - /* Ensure the kick start bit is off. If it isn't, turn it off. */ - while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { - prom_printf("CLOCK: Kick start still on!\n"); - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - tmp = mostek_read(regs + MOSTEK_HOUR); - tmp &= ~MSTK_KICK_START; - mostek_write(regs + MOSTEK_HOUR, tmp); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - } - - prom_printf("CLOCK: Kick start procedure successful.\n"); -} - -/* Return nonzero if the clock chip battery is low. */ -static int __init has_low_battery(void) -{ - void __iomem *regs = mstk48t02_regs; - u8 data1, data2; - - spin_lock_irq(&mostek_lock); - - data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ - mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ - data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ - mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ - - spin_unlock_irq(&mostek_lock); - - return (data1 == data2); /* Was the write blocked? */ -} - -static void __init mostek_set_system_time(void __iomem *mregs) -{ - unsigned int year, mon, day, hour, min, sec; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - /* Traditional Mostek chip. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); -} - /* Probe for the real time clock chip. */ static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; - void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; @@ -559,16 +421,11 @@ static void __init set_system_time(void) void __iomem *bregs = 0UL; #endif - if (!mregs && !dregs && !bregs) { + if (!dregs && !bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } - if (mregs) { - mostek_set_system_time(mregs); - return; - } - if (bregs) { unsigned char val = readb(bregs + 0x0e); unsigned int century; @@ -689,12 +546,9 @@ retry: return -EOPNOTSUPP; } -static int __init clock_model_matches(const char *model) +static int __init rtc_model_matches(const char *model) { - if (strcmp(model, "mk48t02") && - strcmp(model, "mk48t08") && - strcmp(model, "mk48t59") && - strcmp(model, "m5819") && + if (strcmp(model, "m5819") && strcmp(model, "m5819p") && strcmp(model, "m5823") && strcmp(model, "ds1287") && @@ -704,7 +558,7 @@ static int __init clock_model_matches(const char *model) return 1; } -static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; const char *model = of_get_property(dp, "model", NULL); @@ -715,14 +569,7 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (!model) model = compat; - if (!model || !clock_model_matches(model)) - return -ENODEV; - - /* On an Enterprise system there can be multiple mostek clocks. - * We should only match the one that is on the central FHC bus. - */ - if (!strcmp(dp->parent->name, "fhc") && - strcmp(dp->parent->parent->name, "central") != 0) + if (!model || !rtc_model_matches(model)) return -ENODEV; size = (op->resource[0].end - op->resource[0].start) + 1; @@ -738,32 +585,12 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id ds1287_regs = (unsigned long) regs; } else if (!strcmp(model, "bq4802")) { bq4802_regs = regs; - } else -#endif - if (model[5] == '0' && model[6] == '2') { - mstk48t02_regs = regs; - } else if(model[5] == '0' && model[6] == '8') { - mstk48t08_regs = regs; - mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; - } else { - mstk48t59_regs = regs; - mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; } - +#endif printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); local_irq_save(flags); - if (mstk48t02_regs != NULL) { - /* Report a low battery voltage condition. */ - if (has_low_battery()) - prom_printf("NVRAM: Low battery voltage!\n"); - - /* Kick start the clock if it is completely stopped. */ - if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) - kick_start_clock(); - } - set_system_time(); local_irq_restore(flags); @@ -771,21 +598,102 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id return 0; } -static struct of_device_id clock_match[] = { +static struct of_device_id rtc_match[] = { { - .name = "eeprom", + .name = "rtc", + }, + {}, +}; + +static struct of_platform_driver rtc_driver = { + .match_table = rtc_match, + .probe = rtc_probe, + .driver = { + .name = "rtc", }, +}; + +static unsigned char mostek_read_byte(struct device *dev, u32 ofs) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *regs; + unsigned char val; + + regs = (void __iomem *) pdev->resource[0].start; + val = readb(regs + ofs); + + /* the year 0 is 1968 */ + if (ofs == M48T59_YEAR) { + val += 0x68; + if ((val & 0xf) > 9) + val += 6; + } + return val; +} + +static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) +{ + struct platform_device *pdev = to_platform_device(dev); + void __iomem *regs; + + regs = (void __iomem *) pdev->resource[0].start; + if (ofs == M48T59_YEAR) { + if (val < 0x68) + val += 0x32; + else + val -= 0x68; + if ((val & 0xf) > 9) + val += 6; + if ((val & 0xf0) > 0x9A) + val += 0x60; + } + writeb(val, regs + ofs); +} + +static struct m48t59_plat_data m48t59_data = { + .read_byte = mostek_read_byte, + .write_byte = mostek_write_byte, +}; + +static struct platform_device m48t59_rtc = { + .name = "rtc-m48t59", + .id = 0, + .num_resources = 1, + .dev = { + .platform_data = &m48t59_data, + }, +}; + +static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *dp = op->node; + + /* On an Enterprise system there can be multiple mostek clocks. + * We should only match the one that is on the central FHC bus. + */ + if (!strcmp(dp->parent->name, "fhc") && + strcmp(dp->parent->parent->name, "central") != 0) + return -ENODEV; + + printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", + dp->full_name, op->resource[0].start); + + m48t59_rtc.resource = &op->resource[0]; + return platform_device_register(&m48t59_rtc); +} + +static struct of_device_id mostek_match[] = { { - .name = "rtc", + .name = "eeprom", }, {}, }; -static struct of_platform_driver clock_driver = { - .match_table = clock_match, - .probe = clock_probe, +static struct of_platform_driver mostek_driver = { + .match_table = mostek_match, + .probe = mostek_probe, .driver = { - .name = "clock", + .name = "mostek", }, }; @@ -806,7 +714,10 @@ static int __init clock_init(void) return 0; } - return of_register_driver(&clock_driver, &of_platform_bus_type); + (void) of_register_driver(&rtc_driver, &of_platform_bus_type); + (void) of_register_driver(&mostek_driver, &of_platform_bus_type); + + return 0; } /* Must be after subsys_initcall() so that busses are probed. Must @@ -1078,7 +989,6 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; - void __iomem *mregs = mstk48t02_regs; #ifdef CONFIG_PCI unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; @@ -1087,62 +997,15 @@ static int set_rtc_mmss(unsigned long nowtime) void __iomem *bregs = 0UL; #endif unsigned long flags; - u8 tmp; /* * Not having a register set can lead to trouble. * Also starfire doesn't have a tod clock. */ - if (!mregs && !dregs && !bregs) + if (!dregs && !bregs) return -1; - if (mregs) { - spin_lock_irqsave(&mostek_lock, flags); - - /* Read the current RTC minutes. */ - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - chip_minutes = MSTK_REG_MIN(mregs); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(mregs + MOSTEK_CREG, tmp); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(mregs,real_seconds); - MSTK_SET_REG_MIN(mregs,real_minutes); - - tmp = mostek_read(mregs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(mregs + MOSTEK_CREG, tmp); - - spin_unlock_irqrestore(&mostek_lock, flags); - - return 0; - } else { - spin_unlock_irqrestore(&mostek_lock, flags); - - return -1; - } - } else if (bregs) { + if (bregs) { int retval = 0; unsigned char val = readb(bregs + 0x0e); @@ -1485,74 +1348,6 @@ static int cmos_set_rtc_time(struct rtc_time *rtc_tm) } #endif /* CONFIG_PCI */ -static void mostek_get_rtc_time(struct rtc_time *rtc_tm) -{ - void __iomem *regs = mstk48t02_regs; - u8 tmp; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - rtc_tm->tm_sec = MSTK_REG_SEC(regs); - rtc_tm->tm_min = MSTK_REG_MIN(regs); - rtc_tm->tm_hour = MSTK_REG_HOUR(regs); - rtc_tm->tm_mday = MSTK_REG_DOM(regs); - rtc_tm->tm_mon = MSTK_REG_MONTH(regs); - rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); - rtc_tm->tm_wday = MSTK_REG_DOW(regs); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_READ; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - rtc_tm->tm_mon--; - rtc_tm->tm_wday--; - rtc_tm->tm_year -= 1900; -} - -static int mostek_set_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char mon, day, hrs, min, sec, wday; - void __iomem *regs = mstk48t02_regs; - unsigned int yrs; - u8 tmp; - - yrs = rtc_tm->tm_year + 1900; - mon = rtc_tm->tm_mon + 1; - day = rtc_tm->tm_mday; - wday = rtc_tm->tm_wday + 1; - hrs = rtc_tm->tm_hour; - min = rtc_tm->tm_min; - sec = rtc_tm->tm_sec; - - spin_lock_irq(&mostek_lock); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp |= MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - MSTK_SET_REG_SEC(regs, sec); - MSTK_SET_REG_MIN(regs, min); - MSTK_SET_REG_HOUR(regs, hrs); - MSTK_SET_REG_DOW(regs, wday); - MSTK_SET_REG_DOM(regs, day); - MSTK_SET_REG_MONTH(regs, mon); - MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO); - - tmp = mostek_read(regs + MOSTEK_CREG); - tmp &= ~MSTK_CREG_WRITE; - mostek_write(regs + MOSTEK_CREG, tmp); - - spin_unlock_irq(&mostek_lock); - - return 0; -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1580,11 +1375,6 @@ static struct mini_rtc_ops cmos_rtc_ops = { }; #endif /* CONFIG_PCI */ -static struct mini_rtc_ops mostek_rtc_ops = { - .get_rtc_time = mostek_get_rtc_time, - .set_rtc_time = mostek_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1717,8 +1507,6 @@ static int __init rtc_mini_init(void) else if (ds1287_regs) mini_rtc_ops = &cmos_rtc_ops; #endif /* CONFIG_PCI */ - else if (mstk48t02_regs) - mini_rtc_ops = &mostek_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From da86783dda5ad8c64b945157108d1ace7aa79bbf Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 22:16:15 -0700 Subject: sparc64: Use generic CMOS driver. Based largely upon a patch by Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 372 +++++++++++++++------------------------------ 1 file changed, 120 insertions(+), 252 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 9c2c3d84443..abdeead4e5b 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -52,10 +52,7 @@ #include "entry.h" DEFINE_SPINLOCK(rtc_lock); -#ifdef CONFIG_PCI -unsigned long ds1287_regs = 0UL; static void __iomem *bq4802_regs; -#endif static int set_rtc_mmss(unsigned long); @@ -413,69 +410,38 @@ int update_persistent_clock(struct timespec now) static void __init set_system_time(void) { unsigned int year, mon, day, hour, min, sec; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; -#else - unsigned long dregs = 0UL; - void __iomem *bregs = 0UL; -#endif + unsigned char val = readb(bregs + 0x0e); + unsigned int century; - if (!dregs && !bregs) { + if (!bregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } - if (bregs) { - unsigned char val = readb(bregs + 0x0e); - unsigned int century; + /* BQ4802 RTC chip. */ - /* BQ4802 RTC chip. */ + writeb(val | 0x08, bregs + 0x0e); - writeb(val | 0x08, bregs + 0x0e); + sec = readb(bregs + 0x00); + min = readb(bregs + 0x02); + hour = readb(bregs + 0x04); + day = readb(bregs + 0x06); + mon = readb(bregs + 0x09); + year = readb(bregs + 0x0a); + century = readb(bregs + 0x0f); - sec = readb(bregs + 0x00); - min = readb(bregs + 0x02); - hour = readb(bregs + 0x04); - day = readb(bregs + 0x06); - mon = readb(bregs + 0x09); - year = readb(bregs + 0x0a); - century = readb(bregs + 0x0f); + writeb(val, bregs + 0x0e); - writeb(val, bregs + 0x0e); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - BCD_TO_BIN(century); + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + BCD_TO_BIN(century); - year += (century * 100); - } else { - /* Dallas 12887 RTC chip. */ - - do { - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - } + year += (century * 100); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); @@ -546,48 +512,79 @@ retry: return -EOPNOTSUPP; } -static int __init rtc_model_matches(const char *model) -{ - if (strcmp(model, "m5819") && - strcmp(model, "m5819p") && - strcmp(model, "m5823") && - strcmp(model, "ds1287") && - strcmp(model, "bq4802")) - return 0; +unsigned long cmos_regs; +EXPORT_SYMBOL(cmos_regs); - return 1; -} +struct resource rtc_cmos_resource; + +static struct platform_device rtc_cmos_device = { + .name = "rtc_cmos", + .id = -1, + .resource = &rtc_cmos_resource, + .num_resources = 1, +}; static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *dp = op->node; - const char *model = of_get_property(dp, "model", NULL); - const char *compat = of_get_property(dp, "compatible", NULL); - unsigned long size, flags; - void __iomem *regs; + struct resource *r; - if (!model) - model = compat; + printk(KERN_INFO "%s: RTC regs at 0x%lx\n", + op->node->full_name, op->resource[0].start); - if (!model || !rtc_model_matches(model)) - return -ENODEV; + /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons + * up a fake resource so that the probe works for all cases. + * When the RTC is behind an ISA bus it will have IORESOURCE_IO + * already, whereas when it's behind EBUS is will be IORESOURCE_MEM. + */ + + r = &rtc_cmos_resource; + r->flags = IORESOURCE_IO; + r->name = op->resource[0].name; + r->start = op->resource[0].start; + r->end = op->resource[0].end; + + cmos_regs = op->resource[0].start; + return platform_device_register(&rtc_cmos_device); +} + +static struct of_device_id rtc_match[] = { + { + .name = "rtc", + .compatible = "m5819", + }, + { + .name = "rtc", + .compatible = "isa-m5819p", + }, + { + .name = "rtc", + .compatible = "isa-m5823p", + }, + { + .name = "rtc", + .compatible = "ds1287", + }, + {}, +}; + +static struct of_platform_driver rtc_driver = { + .match_table = rtc_match, + .probe = rtc_probe, + .driver = { + .name = "rtc", + }, +}; - size = (op->resource[0].end - op->resource[0].start) + 1; - regs = of_ioremap(&op->resource[0], 0, size, "clock"); - if (!regs) +static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) +{ + struct device_node *dp = op->node; + unsigned long flags; + + bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802"); + if (!bq4802_regs) return -ENOMEM; -#ifdef CONFIG_PCI - if (!strcmp(model, "ds1287") || - !strcmp(model, "m5819") || - !strcmp(model, "m5819p") || - !strcmp(model, "m5823")) { - ds1287_regs = (unsigned long) regs; - } else if (!strcmp(model, "bq4802")) { - bq4802_regs = regs; - } -#endif - printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); + printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs); local_irq_save(flags); @@ -598,18 +595,18 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id * return 0; } -static struct of_device_id rtc_match[] = { +static struct of_device_id bq4802_match[] = { { .name = "rtc", + .compatible = "bq4802", }, - {}, }; -static struct of_platform_driver rtc_driver = { - .match_table = rtc_match, - .probe = rtc_probe, +static struct of_platform_driver bq4802_driver = { + .match_table = bq4802_match, + .probe = bq4802_probe, .driver = { - .name = "rtc", + .name = "bq4802", }, }; @@ -716,6 +713,7 @@ static int __init clock_init(void) (void) of_register_driver(&rtc_driver, &of_platform_bus_type); (void) of_register_driver(&mostek_driver, &of_platform_bus_type); + (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); return 0; } @@ -989,96 +987,51 @@ unsigned long long sched_clock(void) static int set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes, chip_minutes; -#ifdef CONFIG_PCI - unsigned long dregs = ds1287_regs; void __iomem *bregs = bq4802_regs; -#else - unsigned long dregs = 0UL; - void __iomem *bregs = 0UL; -#endif unsigned long flags; + unsigned char val; + int retval = 0; /* * Not having a register set can lead to trouble. * Also starfire doesn't have a tod clock. */ - if (!dregs && !bregs) + if (!bregs) return -1; - if (bregs) { - int retval = 0; - unsigned char val = readb(bregs + 0x0e); + spin_lock_irqsave(&rtc_lock, flags); - /* BQ4802 RTC chip. */ + val = readb(bregs + 0x0e); - writeb(val | 0x08, bregs + 0x0e); + /* BQ4802 RTC chip. */ - chip_minutes = readb(bregs + 0x02); - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; + writeb(val | 0x08, bregs + 0x0e); - if (abs(real_minutes - chip_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - writeb(real_seconds, bregs + 0x00); - writeb(real_minutes, bregs + 0x02); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } + chip_minutes = readb(bregs + 0x02); + BCD_TO_BIN(chip_minutes); + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) + real_minutes += 30; + real_minutes %= 60; - writeb(val, bregs + 0x0e); - - return retval; + if (abs(real_minutes - chip_minutes) < 30) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + writeb(real_seconds, bregs + 0x00); + writeb(real_minutes, bregs + 0x02); } else { - int retval = 0; - unsigned char save_control, save_freq_select; - - /* Stolen from arch/i386/kernel/time.c, see there for - * credits and descriptive comments. - */ - spin_lock_irqsave(&rtc_lock, flags); - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - chip_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + chip_minutes, real_minutes); + retval = -1; + } - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock_irqrestore(&rtc_lock, flags); + writeb(val, bregs + 0x0e); - return retval; - } + spin_unlock_irqrestore(&rtc_lock, flags); + + return retval; } #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ @@ -1202,7 +1155,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time) return hypervisor_set_time(seconds); } -#ifdef CONFIG_PCI static void bq4802_get_rtc_time(struct rtc_time *time) { unsigned char val = readb(bq4802_regs + 0x0e); @@ -1275,79 +1227,6 @@ static int bq4802_set_rtc_time(struct rtc_time *time) return 0; } -static void cmos_get_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char ctrl; - - rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); - rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); - rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); - rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); - rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); - rtc_tm->tm_year = CMOS_READ(RTC_YEAR); - rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); - - ctrl = CMOS_READ(RTC_CONTROL); - if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(rtc_tm->tm_sec); - BCD_TO_BIN(rtc_tm->tm_min); - BCD_TO_BIN(rtc_tm->tm_hour); - BCD_TO_BIN(rtc_tm->tm_mday); - BCD_TO_BIN(rtc_tm->tm_mon); - BCD_TO_BIN(rtc_tm->tm_year); - BCD_TO_BIN(rtc_tm->tm_wday); - } - - if (rtc_tm->tm_year <= 69) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} - -static int cmos_set_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned char mon, day, hrs, min, sec; - unsigned char save_control, save_freq_select; - unsigned int yrs; - - yrs = rtc_tm->tm_year; - mon = rtc_tm->tm_mon + 1; - day = rtc_tm->tm_mday; - hrs = rtc_tm->tm_hour; - min = rtc_tm->tm_min; - sec = rtc_tm->tm_sec; - - if (yrs >= 100) - yrs -= 100; - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - } - - save_control = CMOS_READ(RTC_CONTROL); - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DAY_OF_MONTH); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); - - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return 0; -} -#endif /* CONFIG_PCI */ - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1363,18 +1242,11 @@ static struct mini_rtc_ops hypervisor_rtc_ops = { .set_rtc_time = hypervisor_set_rtc_time, }; -#ifdef CONFIG_PCI static struct mini_rtc_ops bq4802_rtc_ops = { .get_rtc_time = bq4802_get_rtc_time, .set_rtc_time = bq4802_set_rtc_time, }; -static struct mini_rtc_ops cmos_rtc_ops = { - .get_rtc_time = cmos_get_rtc_time, - .set_rtc_time = cmos_set_rtc_time, -}; -#endif /* CONFIG_PCI */ - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1501,12 +1373,8 @@ static int __init rtc_mini_init(void) mini_rtc_ops = &hypervisor_rtc_ops; else if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; -#ifdef CONFIG_PCI else if (bq4802_regs) mini_rtc_ops = &bq4802_rtc_ops; - else if (ds1287_regs) - mini_rtc_ops = &cmos_rtc_ops; -#endif /* CONFIG_PCI */ else return -ENODEV; -- cgit v1.2.3 From 29b503f11cd648b3628be3a546f97da95a6670ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Aug 2008 21:54:34 -0700 Subject: sparc64: Use generic BQ4802 RTC driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 201 +++------------------------------------------ 1 file changed, 11 insertions(+), 190 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index abdeead4e5b..5e199a0e437 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -52,9 +52,6 @@ #include "entry.h" DEFINE_SPINLOCK(rtc_lock); -static void __iomem *bq4802_regs; - -static int set_rtc_mmss(unsigned long); #define TICK_PRIV_BIT (1UL << 63) #define TICKCMP_IRQ_BIT (1UL << 63) @@ -403,50 +400,7 @@ int update_persistent_clock(struct timespec now) if (rtc) return rtc_set_mmss(rtc, now.tv_sec); - return set_rtc_mmss(now.tv_sec); -} - -/* Probe for the real time clock chip. */ -static void __init set_system_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - void __iomem *bregs = bq4802_regs; - unsigned char val = readb(bregs + 0x0e); - unsigned int century; - - if (!bregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - /* BQ4802 RTC chip. */ - - writeb(val | 0x08, bregs + 0x0e); - - sec = readb(bregs + 0x00); - min = readb(bregs + 0x02); - hour = readb(bregs + 0x04); - day = readb(bregs + 0x06); - mon = readb(bregs + 0x09); - year = readb(bregs + 0x0a); - century = readb(bregs + 0x0f); - - writeb(val, bregs + 0x0e); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - BCD_TO_BIN(century); - - year += (century * 100); - - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); + return -1; } /* davem suggests we keep this within the 4M locked kernel image */ @@ -575,24 +529,20 @@ static struct of_platform_driver rtc_driver = { }, }; +static struct platform_device rtc_bq4802_device = { + .name = "rtc-bq4802", + .id = -1, + .num_resources = 1, +}; + static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *dp = op->node; - unsigned long flags; - - bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802"); - if (!bq4802_regs) - return -ENOMEM; - - printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs); - local_irq_save(flags); - - set_system_time(); - - local_irq_restore(flags); + printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", + op->node->full_name, op->resource[0].start); - return 0; + rtc_bq4802_device.resource = &op->resource[0]; + return platform_device_register(&rtc_bq4802_device); } static struct of_device_id bq4802_match[] = { @@ -984,56 +934,6 @@ unsigned long long sched_clock(void) >> SPARC64_NSEC_PER_CYC_SHIFT; } -static int set_rtc_mmss(unsigned long nowtime) -{ - int real_seconds, real_minutes, chip_minutes; - void __iomem *bregs = bq4802_regs; - unsigned long flags; - unsigned char val; - int retval = 0; - - /* - * Not having a register set can lead to trouble. - * Also starfire doesn't have a tod clock. - */ - if (!bregs) - return -1; - - spin_lock_irqsave(&rtc_lock, flags); - - val = readb(bregs + 0x0e); - - /* BQ4802 RTC chip. */ - - writeb(val | 0x08, bregs + 0x0e); - - chip_minutes = readb(bregs + 0x02); - BCD_TO_BIN(chip_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) - real_minutes += 30; - real_minutes %= 60; - - if (abs(real_minutes - chip_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - writeb(real_seconds, bregs + 0x00); - writeb(real_minutes, bregs + 0x02); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - chip_minutes, real_minutes); - retval = -1; - } - - writeb(val, bregs + 0x0e); - - spin_unlock_irqrestore(&rtc_lock, flags); - - return retval; -} - #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ static unsigned char mini_rtc_status; /* bitmapped status byte. */ @@ -1155,78 +1055,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time) return hypervisor_set_time(seconds); } -static void bq4802_get_rtc_time(struct rtc_time *time) -{ - unsigned char val = readb(bq4802_regs + 0x0e); - unsigned int century; - - writeb(val | 0x08, bq4802_regs + 0x0e); - - time->tm_sec = readb(bq4802_regs + 0x00); - time->tm_min = readb(bq4802_regs + 0x02); - time->tm_hour = readb(bq4802_regs + 0x04); - time->tm_mday = readb(bq4802_regs + 0x06); - time->tm_mon = readb(bq4802_regs + 0x09); - time->tm_year = readb(bq4802_regs + 0x0a); - time->tm_wday = readb(bq4802_regs + 0x08); - century = readb(bq4802_regs + 0x0f); - - writeb(val, bq4802_regs + 0x0e); - - BCD_TO_BIN(time->tm_sec); - BCD_TO_BIN(time->tm_min); - BCD_TO_BIN(time->tm_hour); - BCD_TO_BIN(time->tm_mday); - BCD_TO_BIN(time->tm_mon); - BCD_TO_BIN(time->tm_year); - BCD_TO_BIN(time->tm_wday); - BCD_TO_BIN(century); - - time->tm_year += (century * 100); - time->tm_year -= 1900; - - time->tm_mon--; -} - -static int bq4802_set_rtc_time(struct rtc_time *time) -{ - unsigned char val = readb(bq4802_regs + 0x0e); - unsigned char sec, min, hrs, day, mon, yrs, century; - unsigned int year; - - year = time->tm_year + 1900; - century = year / 100; - yrs = year % 100; - - mon = time->tm_mon + 1; /* tm_mon starts at zero */ - day = time->tm_mday; - hrs = time->tm_hour; - min = time->tm_min; - sec = time->tm_sec; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - BIN_TO_BCD(century); - - writeb(val | 0x08, bq4802_regs + 0x0e); - - writeb(sec, bq4802_regs + 0x00); - writeb(min, bq4802_regs + 0x02); - writeb(hrs, bq4802_regs + 0x04); - writeb(day, bq4802_regs + 0x06); - writeb(mon, bq4802_regs + 0x09); - writeb(yrs, bq4802_regs + 0x0a); - writeb(century, bq4802_regs + 0x0f); - - writeb(val, bq4802_regs + 0x0e); - - return 0; -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1242,11 +1070,6 @@ static struct mini_rtc_ops hypervisor_rtc_ops = { .set_rtc_time = hypervisor_set_rtc_time, }; -static struct mini_rtc_ops bq4802_rtc_ops = { - .get_rtc_time = bq4802_get_rtc_time, - .set_rtc_time = bq4802_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1373,8 +1196,6 @@ static int __init rtc_mini_init(void) mini_rtc_ops = &hypervisor_rtc_ops; else if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; - else if (bq4802_regs) - mini_rtc_ops = &bq4802_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From 84d6bd5ef79a6ccc21af97b870f6ef94fbc9b11e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 01:34:27 -0700 Subject: sparc64: Use generic sun4v RTC driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 83 +++++----------------------------------------- 1 file changed, 8 insertions(+), 75 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 5e199a0e437..15d16dbca1d 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -424,48 +424,6 @@ static int starfire_set_time(u32 val) return 0; } -static u32 hypervisor_get_time(void) -{ - unsigned long ret, time; - int retries = 10000; - -retry: - ret = sun4v_tod_get(&time); - if (ret == HV_EOK) - return time; - if (ret == HV_EWOULDBLOCK) { - if (--retries > 0) { - udelay(100); - goto retry; - } - printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); - return 0; - } - printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); - return 0; -} - -static int hypervisor_set_time(u32 secs) -{ - unsigned long ret; - int retries = 10000; - -retry: - ret = sun4v_tod_set(secs); - if (ret == HV_EOK) - return 0; - if (ret == HV_EWOULDBLOCK) { - if (--retries > 0) { - udelay(100); - goto retry; - } - printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); - return -EAGAIN; - } - printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); - return -EOPNOTSUPP; -} - unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); @@ -644,6 +602,11 @@ static struct of_platform_driver mostek_driver = { }, }; +static struct platform_device rtc_sun4v_device = { + .name = "rtc-sun4v", + .id = -1, +}; + static int __init clock_init(void) { if (this_is_starfire) { @@ -653,13 +616,8 @@ static int __init clock_init(void) -xtime.tv_sec, -xtime.tv_nsec); return 0; } - if (tlb_type == hypervisor) { - xtime.tv_sec = hypervisor_get_time(); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - return 0; - } + if (tlb_type == hypervisor) + return platform_device_register(&rtc_sun4v_device); (void) of_register_driver(&rtc_driver, &of_platform_bus_type); (void) of_register_driver(&mostek_driver, &of_platform_bus_type); @@ -1037,24 +995,6 @@ static int starfire_set_rtc_time(struct rtc_time *time) return starfire_set_time(seconds); } -static void hypervisor_get_rtc_time(struct rtc_time *time) -{ - u32 seconds = hypervisor_get_time(); - - to_tm(seconds, time); - time->tm_year -= 1900; - time->tm_mon -= 1; -} - -static int hypervisor_set_rtc_time(struct rtc_time *time) -{ - u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, - time->tm_mday, time->tm_hour, - time->tm_min, time->tm_sec); - - return hypervisor_set_time(seconds); -} - struct mini_rtc_ops { void (*get_rtc_time)(struct rtc_time *); int (*set_rtc_time)(struct rtc_time *); @@ -1065,11 +1005,6 @@ static struct mini_rtc_ops starfire_rtc_ops = { .set_rtc_time = starfire_set_rtc_time, }; -static struct mini_rtc_ops hypervisor_rtc_ops = { - .get_rtc_time = hypervisor_get_rtc_time, - .set_rtc_time = hypervisor_set_rtc_time, -}; - static struct mini_rtc_ops *mini_rtc_ops; static inline void mini_get_rtc_time(struct rtc_time *time) @@ -1192,9 +1127,7 @@ static int __init rtc_mini_init(void) { int retval; - if (tlb_type == hypervisor) - mini_rtc_ops = &hypervisor_rtc_ops; - else if (this_is_starfire) + if (this_is_starfire) mini_rtc_ops = &starfire_rtc_ops; else return -ENODEV; -- cgit v1.2.3 From f2be6de88d247cd57010944f62267b53c47d5ae3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 01:35:19 -0700 Subject: sparc64: Use generic starfire RTC driver. Also, delete the mini RTC driver, no longer used. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 293 ++------------------------------------------- 1 file changed, 8 insertions(+), 285 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 15d16dbca1d..ea05038a8c1 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -403,27 +403,6 @@ int update_persistent_clock(struct timespec now) return -1; } -/* davem suggests we keep this within the 4M locked kernel image */ -static u32 starfire_get_time(void) -{ - static char obp_gettod[32]; - static u32 unix_tod; - - sprintf(obp_gettod, "h# %08x unix-gettod", - (unsigned int) (long) &unix_tod); - prom_feval(obp_gettod); - - return unix_tod; -} - -static int starfire_set_time(u32 val) -{ - /* Do nothing, time is set using the service processor - * console on this platform. - */ - return 0; -} - unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); @@ -607,15 +586,16 @@ static struct platform_device rtc_sun4v_device = { .id = -1, }; +static struct platform_device rtc_starfire_device = { + .name = "rtc-starfire", + .id = -1, +}; + static int __init clock_init(void) { - if (this_is_starfire) { - xtime.tv_sec = starfire_get_time(); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - return 0; - } + if (this_is_starfire) + return platform_device_register(&rtc_starfire_device); + if (tlb_type == hypervisor) return platform_device_register(&rtc_sun4v_device); @@ -892,265 +872,8 @@ unsigned long long sched_clock(void) >> SPARC64_NSEC_PER_CYC_SHIFT; } -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -static unsigned char mini_rtc_status; /* bitmapped status byte. */ - -#define FEBRUARY 2 -#define STARTOFTIME 1970 -#define SECDAY 86400L -#define SECYR (SECDAY * 365) -#define leapyear(year) ((year) % 4 == 0 && \ - ((year) % 100 != 0 || (year) % 400 == 0)) -#define days_in_year(a) (leapyear(a) ? 366 : 365) -#define days_in_month(a) (month_days[(a) - 1]) - -static int month_days[12] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/* - * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) - */ -static void GregorianDay(struct rtc_time * tm) -{ - int leapsToDate; - int lastYear; - int day; - int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - - lastYear = tm->tm_year - 1; - - /* - * Number of leap corrections to apply up to end of last year - */ - leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400; - - /* - * This year is a leap year if it is divisible by 4 except when it is - * divisible by 100 unless it is divisible by 400 - * - * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was - */ - day = tm->tm_mon > 2 && leapyear(tm->tm_year); - - day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + - tm->tm_mday; - - tm->tm_wday = day % 7; -} - -static void to_tm(int tim, struct rtc_time *tm) -{ - register int i; - register long hms, day; - - day = tim / SECDAY; - hms = tim % SECDAY; - - /* Hours, minutes, seconds are easy */ - tm->tm_hour = hms / 3600; - tm->tm_min = (hms % 3600) / 60; - tm->tm_sec = (hms % 3600) % 60; - - /* Number of years in days */ - for (i = STARTOFTIME; day >= days_in_year(i); i++) - day -= days_in_year(i); - tm->tm_year = i; - - /* Number of months in days left */ - if (leapyear(tm->tm_year)) - days_in_month(FEBRUARY) = 29; - for (i = 1; day >= days_in_month(i); i++) - day -= days_in_month(i); - days_in_month(FEBRUARY) = 28; - tm->tm_mon = i; - - /* Days are what is left over (+1) from all that. */ - tm->tm_mday = day + 1; - - /* - * Determine the day of week - */ - GregorianDay(tm); -} - -/* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, - * aka Unix time. So we have to convert to/from rtc_time. - */ -static void starfire_get_rtc_time(struct rtc_time *time) -{ - u32 seconds = starfire_get_time(); - - to_tm(seconds, time); - time->tm_year -= 1900; - time->tm_mon -= 1; -} - -static int starfire_set_rtc_time(struct rtc_time *time) -{ - u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, - time->tm_mday, time->tm_hour, - time->tm_min, time->tm_sec); - - return starfire_set_time(seconds); -} - -struct mini_rtc_ops { - void (*get_rtc_time)(struct rtc_time *); - int (*set_rtc_time)(struct rtc_time *); -}; - -static struct mini_rtc_ops starfire_rtc_ops = { - .get_rtc_time = starfire_get_rtc_time, - .set_rtc_time = starfire_set_rtc_time, -}; - -static struct mini_rtc_ops *mini_rtc_ops; - -static inline void mini_get_rtc_time(struct rtc_time *time) -{ - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - mini_rtc_ops->get_rtc_time(time); - spin_unlock_irqrestore(&rtc_lock, flags); -} - -static inline int mini_set_rtc_time(struct rtc_time *time) -{ - unsigned long flags; - int err; - - spin_lock_irqsave(&rtc_lock, flags); - err = mini_rtc_ops->set_rtc_time(time); - spin_unlock_irqrestore(&rtc_lock, flags); - - return err; -} - -static int mini_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct rtc_time wtime; - void __user *argp = (void __user *)arg; - - switch (cmd) { - - case RTC_PLL_GET: - return -EINVAL; - - case RTC_PLL_SET: - return -EINVAL; - - case RTC_UIE_OFF: /* disable ints from RTC updates. */ - return 0; - - case RTC_UIE_ON: /* enable ints for RTC updates. */ - return -EINVAL; - - case RTC_RD_TIME: /* Read the time/date from RTC */ - /* this doesn't get week-day, who cares */ - memset(&wtime, 0, sizeof(wtime)); - mini_get_rtc_time(&wtime); - - return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; - - case RTC_SET_TIME: /* Set the RTC */ - { - int year, days; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&wtime, argp, sizeof(wtime))) - return -EFAULT; - - year = wtime.tm_year + 1900; - days = month_days[wtime.tm_mon] + - ((wtime.tm_mon == 1) && leapyear(year)); - - if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || - (wtime.tm_mday < 1)) - return -EINVAL; - - if (wtime.tm_mday < 0 || wtime.tm_mday > days) - return -EINVAL; - - if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || - wtime.tm_min < 0 || wtime.tm_min >= 60 || - wtime.tm_sec < 0 || wtime.tm_sec >= 60) - return -EINVAL; - - return mini_set_rtc_time(&wtime); - } - } - - return -EINVAL; -} - -static int mini_rtc_open(struct inode *inode, struct file *file) -{ - lock_kernel(); - if (mini_rtc_status & RTC_IS_OPEN) { - unlock_kernel(); - return -EBUSY; - } - - mini_rtc_status |= RTC_IS_OPEN; - unlock_kernel(); - - return 0; -} - -static int mini_rtc_release(struct inode *inode, struct file *file) -{ - mini_rtc_status &= ~RTC_IS_OPEN; - return 0; -} - - -static const struct file_operations mini_rtc_fops = { - .owner = THIS_MODULE, - .ioctl = mini_rtc_ioctl, - .open = mini_rtc_open, - .release = mini_rtc_release, -}; - -static struct miscdevice rtc_mini_dev = -{ - .minor = RTC_MINOR, - .name = "rtc", - .fops = &mini_rtc_fops, -}; - -static int __init rtc_mini_init(void) -{ - int retval; - - if (this_is_starfire) - mini_rtc_ops = &starfire_rtc_ops; - else - return -ENODEV; - - printk(KERN_INFO "Mini RTC Driver\n"); - - retval = misc_register(&rtc_mini_dev); - if (retval < 0) - return retval; - - return 0; -} - -static void __exit rtc_mini_exit(void) -{ - misc_deregister(&rtc_mini_dev); -} - int __devinit read_current_timer(unsigned long *timer_val) { *timer_val = tick_ops->get_tick(); return 0; } - -module_init(rtc_mini_init); -module_exit(rtc_mini_exit); -- cgit v1.2.3 From ae05f87ee2f403228bca6d28fef29d6be0bfbedc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 22:42:34 -0700 Subject: sparc64: Propagate PCI device archdata into OF device tree for EBUS. In order to convert EBUS drivers doing DMA into pure OF drivers, we need the of_device->dev.archdata setup properly. EBUS instances that can provide DMA for device nodes sit on PCI, so detect and propagate the information there. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 9bb4b8cbcac..71d423a1c17 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -337,6 +337,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct pci_bus *bus, int devfn) { struct dev_archdata *sd; + struct of_device *op; struct pci_dev *dev; const char *type; u32 class; @@ -350,14 +351,17 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, sd->stc = &pbm->stc; sd->host_controller = pbm; sd->prom_node = node; - sd->op = of_find_device_by_node(node); + sd->op = op = of_find_device_by_node(node); sd->numa_node = pbm->numa_node; - sd = &sd->op->dev.archdata; + sd = &op->dev.archdata; sd->iommu = pbm->iommu; sd->stc = &pbm->stc; sd->numa_node = pbm->numa_node; + if (!strcmp(node->name, "ebus")) + of_propagate_archdata(op); + type = of_get_property(node, "device_type", NULL); if (type == NULL) type = ""; -- cgit v1.2.3 From aae7fb87ec4d2df6cb551670b1765cf4e5795a3b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 29 Aug 2008 23:10:21 -0700 Subject: sparc: Move EBUS DMA interfaces into seperate header file. These have no dependencies on the EBUS probing layer, the clients setup the registers and all of those details. The EBUS DMA layer just programs and manages the DMA controller found in EBUS. Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 214da1bd8a5..88408741c32 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 356d164757310cd822d71da2027d50ec39798b7f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 00:36:11 -0700 Subject: sparc: Kill EBUS driver layer. All that remains is the EBUS DMA programming library for sparc64. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 4 +- arch/sparc64/kernel/ebus.c | 295 +----------------------------------- arch/sparc64/kernel/pci.c | 4 +- arch/sparc64/kernel/sparc64_ksyms.c | 4 - 4 files changed, 5 insertions(+), 302 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 360a348e5bb..928aa7c8058 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -11,12 +11,12 @@ obj-y := process.o setup.o cpu.o idprom.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o starfire.o \ - power.o sbus.o sparc64_ksyms.o \ + power.o sbus.o sparc64_ksyms.o ebus.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += ebus.o pci.o pci_common.o \ +obj-$(CONFIG_PCI) += pci.o pci_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 88408741c32..77dbf6d45fa 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -1,5 +1,4 @@ -/* - * ebus.c: PCI to EBus bridge device. +/* ebus.c: EBUS DMA library code. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -9,24 +8,12 @@ #include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -/* EBUS dma library. */ - #define EBDMA_CSR 0x00UL /* Control/Status */ #define EBDMA_ADDR 0x04UL /* DMA Address */ #define EBDMA_COUNT 0x08UL /* DMA Count */ @@ -268,283 +255,3 @@ void ebus_dma_enable(struct ebus_dma_info *p, int on) spin_unlock_irqrestore(&p->lock, flags); } EXPORT_SYMBOL(ebus_dma_enable); - -struct linux_ebus *ebus_chain = NULL; - -static inline void *ebus_alloc(size_t size) -{ - void *mem; - - mem = kzalloc(size, GFP_ATOMIC); - if (!mem) - panic("ebus_alloc: out of memory"); - return mem; -} - -static void __init fill_ebus_child(struct device_node *dp, - struct linux_ebus_child *dev, - int non_standard_regs) -{ - struct of_device *op; - const int *regs; - int i, len; - - dev->prom_node = dp; - printk(" (%s)", dp->name); - - regs = of_get_property(dp, "reg", &len); - if (!regs) - dev->num_addrs = 0; - else - dev->num_addrs = len / sizeof(regs[0]); - - if (non_standard_regs) { - /* This is to handle reg properties which are not - * in the parent relative format. One example are - * children of the i2c device on CompactPCI systems. - * - * So, for such devices we just record the property - * raw in the child resources. - */ - for (i = 0; i < dev->num_addrs; i++) - dev->resource[i].start = regs[i]; - } else { - for (i = 0; i < dev->num_addrs; i++) { - int rnum = regs[i]; - if (rnum >= dev->parent->num_addrs) { - prom_printf("UGH: property for %s was %d, need < %d\n", - dp->name, len, dev->parent->num_addrs); - prom_halt(); - } - dev->resource[i].start = dev->parent->resource[i].start; - dev->resource[i].end = dev->parent->resource[i].end; - dev->resource[i].flags = IORESOURCE_MEM; - dev->resource[i].name = dp->name; - } - } - - op = of_find_device_by_node(dp); - if (!op) { - dev->num_irqs = 0; - } else { - dev->num_irqs = op->num_irqs; - for (i = 0; i < dev->num_irqs; i++) - dev->irqs[i] = op->irqs[i]; - } - - if (!dev->num_irqs) { - /* - * Oh, well, some PROMs don't export interrupts - * property to children of EBus devices... - * - * Be smart about PS/2 keyboard and mouse. - */ - if (!strcmp(dev->parent->prom_node->name, "8042")) { - if (!strcmp(dev->prom_node->name, "kb_ps2")) { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[0]; - } else { - dev->num_irqs = 1; - dev->irqs[0] = dev->parent->irqs[1]; - } - } - } -} - -static int __init child_regs_nonstandard(struct linux_ebus_device *dev) -{ - if (!strcmp(dev->prom_node->name, "i2c") || - !strcmp(dev->prom_node->name, "SUNW,lombus")) - return 1; - return 0; -} - -static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) -{ - struct linux_ebus_child *child; - struct dev_archdata *sd; - struct of_device *op; - int i, len; - - dev->prom_node = dp; - - printk(" [%s", dp->name); - - op = of_find_device_by_node(dp); - if (!op) { - dev->num_addrs = 0; - dev->num_irqs = 0; - } else { - const int *regs = of_get_property(dp, "reg", &len); - - if (!regs) - len = 0; - dev->num_addrs = len / sizeof(struct linux_prom_registers); - - for (i = 0; i < dev->num_addrs; i++) - memcpy(&dev->resource[i], - &op->resource[i], - sizeof(struct resource)); - - dev->num_irqs = op->num_irqs; - for (i = 0; i < dev->num_irqs; i++) - dev->irqs[i] = op->irqs[i]; - } - - sd = &dev->ofdev.dev.archdata; - sd->prom_node = dp; - sd->op = &dev->ofdev; - sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; - sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; - sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; - - dev->ofdev.node = dp; - dev->ofdev.dev.parent = &dev->bus->ofdev.dev; - dev->ofdev.dev.bus = &ebus_bus_type; - dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); - - /* Register with core */ - if (of_device_register(&dev->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - dp = dp->child; - if (dp) { - printk(" ->"); - dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = dev->children; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child, - child_regs_nonstandard(dev)); - - while ((dp = dp->sibling) != NULL) { - child->next = ebus_alloc(sizeof(struct linux_ebus_child)); - - child = child->next; - child->next = NULL; - child->parent = dev; - child->bus = dev->bus; - fill_ebus_child(dp, child, - child_regs_nonstandard(dev)); - } - } - printk("]"); -} - -static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) -{ - struct pci_dev *pdev = start; - - while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) - if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || - pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) - break; - - *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); - - return pdev; -} - -void __init ebus_init(void) -{ - struct linux_ebus_device *dev; - struct linux_ebus *ebus; - struct pci_dev *pdev; - struct device_node *dp; - int is_rio; - int num_ebus = 0; - - pdev = find_next_ebus(NULL, &is_rio); - if (!pdev) { - printk("ebus: No EBus's found.\n"); - return; - } - - dp = pci_device_to_OF_node(pdev); - - ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); - ebus->next = NULL; - ebus->is_rio = is_rio; - - while (dp) { - struct device_node *child; - - /* SUNW,pci-qfe uses four empty ebuses on it. - I think we should not consider them here, - as they have half of the properties this - code expects and once we do PCI hot-plug, - we'd have to tweak with the ebus_chain - in the runtime after initialization. -jj */ - if (!dp->child) { - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) { - if (ebus == ebus_chain) { - ebus_chain = NULL; - printk("ebus: No EBus's found.\n"); - return; - } - break; - } - ebus->is_rio = is_rio; - dp = pci_device_to_OF_node(pdev); - continue; - } - printk("ebus%d:", num_ebus); - - ebus->index = num_ebus; - ebus->prom_node = dp; - ebus->self = pdev; - - ebus->ofdev.node = dp; - ebus->ofdev.dev.parent = &pdev->dev; - ebus->ofdev.dev.bus = &ebus_bus_type; - dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); - - /* Register with core */ - if (of_device_register(&ebus->ofdev) != 0) - printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dp->path_component_name); - - - child = dp->child; - if (!child) - goto next_ebus; - - ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = ebus->devices; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(child, dev); - - while ((child = child->sibling) != NULL) { - dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); - - dev = dev->next; - dev->next = NULL; - dev->children = NULL; - dev->bus = ebus; - fill_ebus_device(child, dev); - } - - next_ebus: - printk("\n"); - - pdev = find_next_ebus(pdev, &is_rio); - if (!pdev) - break; - - dp = pci_device_to_OF_node(pdev); - - ebus->next = ebus_alloc(sizeof(struct linux_ebus)); - ebus = ebus->next; - ebus->next = NULL; - ebus->is_rio = is_rio; - ++num_ebus; - } - pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ -} diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 71d423a1c17..218778617ee 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -18,11 +18,12 @@ #include #include #include +#include +#include #include #include #include -#include #include #include @@ -808,7 +809,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - ebus_init(); power_init(); return 0; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 4c3a6a87c8a..30bba8b0a3b 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -45,9 +45,6 @@ #ifdef CONFIG_SBUS #include #endif -#ifdef CONFIG_PCI -#include -#endif #include #include #include @@ -165,7 +162,6 @@ EXPORT_SYMBOL(insb); EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); #ifdef CONFIG_PCI -EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); -- cgit v1.2.3 From e0ac612e6997429a21887475709ca6d6224971f2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 00:37:36 -0700 Subject: sparc: Kill ebus_bus_type. No longer used. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 6ae92536517..e427086e3b5 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -88,11 +88,6 @@ void of_propagate_archdata(struct of_device *bus) } } -#ifdef CONFIG_PCI -struct bus_type ebus_bus_type; -EXPORT_SYMBOL(ebus_bus_type); -#endif - struct bus_type of_platform_bus_type; EXPORT_SYMBOL(of_platform_bus_type); @@ -865,11 +860,6 @@ static int __init of_bus_driver_init(void) int err; err = of_bus_type_init(&of_platform_bus_type, "of"); -#ifdef CONFIG_PCI - if (!err) - err = of_bus_type_init(&ebus_bus_type, "ebus"); -#endif - if (!err) scan_of_devices(); -- cgit v1.2.3 From c510b9bfa1c34c1452f7a4389ff6de4f72a78193 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 01:18:56 -0700 Subject: sparc64: Don't invoke power_init() from pcibios_init(). That's just silly, use device_initcall() instead. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 ---- arch/sparc64/kernel/power.c | 16 +++++----------- 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 218778617ee..83c50a62970 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -799,8 +799,6 @@ static void __init pci_scan_each_controller_bus(void) pbm->scan_bus(pbm); } -extern void power_init(void); - static int __init pcibios_init(void) { pci_controller_probe(); @@ -809,8 +807,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - power_init(); - return 0; } diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 3bb987a6d03..7536255ab57 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -1,29 +1,22 @@ /* power.c: Power management driver. * - * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include #include #include -#include -#include -#include #include #include -#include #include #include -#include #include #include #include #include #include -#include - /* * sysctl - toggle power-off restriction for serial console * systems in machine_power_off() @@ -111,8 +104,9 @@ static struct of_platform_driver power_driver = { }, }; -void __init power_init(void) +static int __init power_init(void) { - of_register_driver(&power_driver, &of_platform_bus_type); - return; + return of_register_driver(&power_driver, &of_platform_bus_type); } + +device_initcall(power_init); -- cgit v1.2.3 From 6d19c88f53bb3471a15152ea4fbdbebd36c0046c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 02:30:24 -0700 Subject: sparc64: Convert SCHIZO PCI controller driver into a real driver. The idea is to convert all of the PCI controller drivers into genuine OF drivers, then we can get rid of this terrible probing table and infrastructure in arch/sparc64/kernel/pci.c Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 15 ++--- arch/sparc64/kernel/pci_schizo.c | 117 ++++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 48 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 83c50a62970..73f1d42d486 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -167,9 +167,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); extern void psycho_init(struct device_node *, const char *); -extern void schizo_init(struct device_node *, const char *); -extern void schizo_plus_init(struct device_node *, const char *); -extern void tomatillo_init(struct device_node *, const char *); extern void sun4v_pci_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); @@ -182,12 +179,6 @@ static struct { { "pci108e,a001", sabre_init }, { "SUNW,psycho", psycho_init }, { "pci108e,8000", psycho_init }, - { "SUNW,schizo", schizo_init }, - { "pci108e,8001", schizo_init }, - { "SUNW,schizo+", schizo_plus_init }, - { "pci108e,8002", schizo_plus_init }, - { "SUNW,tomatillo", tomatillo_init }, - { "pci108e,a801", tomatillo_init }, { "SUNW,sun4v-pci", sun4v_pci_init }, { "pciex108e,80f0", fire_pci_init }, }; @@ -795,8 +786,10 @@ static void __init pci_scan_each_controller_bus(void) { struct pci_pbm_info *pbm; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) - pbm->scan_bus(pbm); + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (pbm->scan_bus) + pbm->scan_bus(pbm); + } } static int __init pcibios_init(void) diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 9248c6737f0..b95dd548583 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1,6 +1,6 @@ /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. * - * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 2001, 2002, 2003, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -13,14 +13,15 @@ #include #include -#include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "schizo" +#define PFX DRIVER_NAME ": " + /* All SCHIZO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -1084,7 +1085,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __init schizo_scan_bus(struct pci_pbm_info *pbm) +static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = @@ -1187,9 +1188,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) break; default: - prom_printf("SCHIZO: strange virtual-dma size.\n"); - prom_halt(); - }; + printk(KERN_ERR PFX "Strange virtual-dma size.\n"); + return -EINVAL; + } /* Register addresses, SCHIZO has iommu ctx flushing. */ iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; @@ -1212,7 +1213,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); } @@ -1222,8 +1223,10 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) */ err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() fails with %d\n", err); return err; + } schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); @@ -1236,7 +1239,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) case 128: control |= SCHIZO_IOMMU_TSBSZ_128K; break; - }; + } control |= SCHIZO_IOMMU_CTRL_ENAB; schizo_write(iommu->iommu_control, control); @@ -1334,9 +1337,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int __init schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, - int chip_type) +static int __devinit schizo_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 portid, + int chip_type) { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; @@ -1382,7 +1385,6 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = schizo_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -1420,6 +1422,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, schizo_pbm_strbuf_init(pbm); + schizo_scan_bus(pbm); + return 0; } @@ -1433,8 +1437,7 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static void __init __schizo_init(struct device_node *dp, char *model_name, - int chip_type) +static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_type) { struct pci_controller_info *p; struct pci_pbm_info *pbm; @@ -1447,48 +1450,88 @@ static void __init __schizo_init(struct device_node *dp, char *model_name, if (portid_compare(pbm->portid, portid, chip_type)) { if (schizo_pbm_init(pbm->parent, dp, portid, chip_type)) - goto fatal_memory_error; - return; + return -ENOMEM; + return 0; } } p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); + goto out_free; + } p->pbm_B.iommu = iommu; if (schizo_pbm_init(p, dp, portid, chip_type)) - goto fatal_memory_error; + goto out_free; - return; + return 0; -fatal_memory_error: - prom_printf("SCHIZO: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return -ENOMEM; } -void __init schizo_init(struct device_node *dp, char *model_name) +static int __devinit schizo_probe(struct of_device *op, + const struct of_device_id *match) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); + return __schizo_init(op->node, (unsigned long) match->data); } -void __init schizo_plus_init(struct device_node *dp, char *model_name) -{ - __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); -} +/* The ordering of this table is very important. Some Tomatillo + * nodes announce that they are compatible with both pci108e,a801 + * and pci108e,8001. So list the chips in reverse chronological + * order. + */ +static struct of_device_id schizo_match[] = { + { + .name = "pci", + .compatible = "pci108e,a801", + .data = (void *) PBM_CHIP_TYPE_TOMATILLO, + }, + { + .name = "pci", + .compatible = "pci108e,8002", + .data = (void *) PBM_CHIP_TYPE_SCHIZO_PLUS, + }, + { + .name = "pci", + .compatible = "pci108e,8001", + .data = (void *) PBM_CHIP_TYPE_SCHIZO, + }, + {}, +}; -void __init tomatillo_init(struct device_node *dp, char *model_name) +static struct of_platform_driver schizo_driver = { + .name = DRIVER_NAME, + .match_table = schizo_match, + .probe = schizo_probe, +}; + +static int __init schizo_init(void) { - __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); + return of_register_driver(&schizo_driver, &of_bus_type); } + +subsys_initcall(schizo_init); -- cgit v1.2.3 From 3822b50964d6702b7d8ba18ffd132d4bf786a17e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 02:50:29 -0700 Subject: sparc64: Convert SUN4V PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 - arch/sparc64/kernel/pci_sun4v.c | 123 +++++++++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 42 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 73f1d42d486..445f5882546 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -167,7 +167,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); extern void psycho_init(struct device_node *, const char *); -extern void sun4v_pci_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { @@ -179,7 +178,6 @@ static struct { { "pci108e,a001", sabre_init }, { "SUNW,psycho", psycho_init }, { "pci108e,8000", psycho_init }, - { "SUNW,sun4v-pci", sun4v_pci_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a104c80d319..c1e72beade2 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -13,12 +13,10 @@ #include #include #include +#include #include #include -#include -#include -#include #include #include @@ -27,6 +25,9 @@ #include "pci_sun4v.h" +#define DRIVER_NAME "pci_sun4v" +#define PFX DRIVER_NAME ": " + static unsigned long vpci_major = 1; static unsigned long vpci_minor = 1; @@ -583,7 +584,7 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, return cnt; } -static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) +static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { struct iommu *iommu = pbm->iommu; struct property *prop; @@ -603,9 +604,9 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) } if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { - prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", - vdma[0], vdma[1]); - prom_halt(); + printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", + vdma[0], vdma[1]); + return -EINVAL; }; dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); @@ -625,8 +626,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) sz = (sz + 7UL) & ~7UL; iommu->arena.map = kzalloc(sz, GFP_KERNEL); if (!iommu->arena.map) { - prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); - prom_halt(); + printk(KERN_ERR PFX "Error, kmalloc(arena.map) failed.\n"); + return -ENOMEM; } iommu->arena.limit = num_tsb_entries; @@ -634,6 +635,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) if (sz) printk("%s: Imported %lu TSB entries from OBP\n", pbm->name, sz); + + return 0; } #ifdef CONFIG_PCI_MSI @@ -890,10 +893,11 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) } #endif /* !(CONFIG_PCI_MSI) */ -static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 devhandle) +static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, + struct device_node *dp, u32 devhandle) { struct pci_pbm_info *pbm; + int err; if (devhandle & 0x40) pbm = &p->pbm_B; @@ -905,7 +909,6 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->numa_node = of_node_to_nid(dp); - pbm->scan_bus = pci_sun4v_scan_bus; pbm->pci_ops = &sun4v_pci_ops; pbm->config_space_reg_bits = 12; @@ -924,50 +927,58 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); pci_get_pbm_props(pbm); - pci_sun4v_iommu_init(pbm); + + err = pci_sun4v_iommu_init(pbm); + if (err) + return err; + pci_sun4v_msi_init(pbm); + + pci_sun4v_scan_bus(pbm); + + return 0; } -void __init sun4v_pci_init(struct device_node *dp, char *model_name) +static int __devinit pci_sun4v_probe(struct of_device *op, + const struct of_device_id *match) { + const struct linux_prom64_registers *regs; static int hvapi_negotiated = 0; struct pci_controller_info *p; struct pci_pbm_info *pbm; + struct device_node *dp; struct iommu *iommu; - struct property *prop; - struct linux_prom64_registers *regs; u32 devhandle; int i; + dp = op->node; + if (!hvapi_negotiated++) { int err = sun4v_hvapi_register(HV_GRP_PCI, vpci_major, &vpci_minor); if (err) { - prom_printf("SUN4V_PCI: Could not register hvapi, " - "err=%d\n", err); - prom_halt(); + printk(KERN_ERR PFX "Could not register hvapi, " + "err=%d\n", err); + return err; } - printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", + printk(KERN_INFO PFX "Registered hvapi major[%lu] minor[%lu]\n", vpci_major, vpci_minor); dma_ops = &sun4v_dma_ops; } - prop = of_find_property(dp, "reg", NULL); - if (!prop) { - prom_printf("SUN4V_PCI: Could not find config registers\n"); - prom_halt(); + regs = of_get_property(dp, "reg", NULL); + if (!regs) { + printk(KERN_ERR PFX "Could not find config registers\n"); + return -ENODEV; } - regs = prop->value; - devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (pbm->devhandle == (devhandle ^ 0x40)) { - pci_sun4v_pbm_init(pbm->parent, dp, devhandle); - return; + return pci_sun4v_pbm_init(pbm->parent, dp, devhandle); } } @@ -975,31 +986,63 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name) unsigned long page = get_zeroed_page(GFP_ATOMIC); if (!page) - goto fatal_memory_error; + return -ENOMEM; per_cpu(iommu_batch, i).pglist = (u64 *) page; } p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); + goto out_free; + } p->pbm_B.iommu = iommu; - pci_sun4v_pbm_init(p, dp, devhandle); - return; + return pci_sun4v_pbm_init(p, dp, devhandle); -fatal_memory_error: - prom_printf("SUN4V_PCI: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return -ENOMEM; } + +static struct of_device_id pci_sun4v_match[] = { + { + .name = "pci", + .compatible = "SUNW,sun4v-pci", + }, + {}, +}; + +static struct of_platform_driver pci_sun4v_driver = { + .name = DRIVER_NAME, + .match_table = pci_sun4v_match, + .probe = pci_sun4v_probe, +}; + +static int __init pci_sun4v_init(void) +{ + return of_register_driver(&pci_sun4v_driver, &of_bus_type); +} + +subsys_initcall(pci_sun4v_init); -- cgit v1.2.3 From b20bfe41badcbf38512fbe1118fe2e0817098e77 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:13:20 -0700 Subject: sparc64: Convert PSYCHO PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 3 -- arch/sparc64/kernel/pci_psycho.c | 95 +++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 28 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 445f5882546..c66c9bbc975 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -166,7 +166,6 @@ void pci_config_write32(u32 *addr, u32 val) /* Probe for all PCI controllers in the system. */ extern void sabre_init(struct device_node *, const char *); -extern void psycho_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { @@ -176,8 +175,6 @@ static struct { { "SUNW,sabre", sabre_init }, { "pci108e,a000", sabre_init }, { "pci108e,a001", sabre_init }, - { "SUNW,psycho", psycho_init }, - { "pci108e,8000", psycho_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index ef5fe29202c..4e8f87aad20 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -17,11 +17,13 @@ #include #include #include -#include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "psycho" +#define PFX DRIVER_NAME ": " + /* All PSYCHO registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -840,7 +842,7 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); control |= PSYCHO_IOMMU_CTRL_DENAB; psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for(i = 0; i < 16; i++) { + for (i = 0; i < 16; i++) { psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); } @@ -850,8 +852,10 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) */ err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() fails\n"); return err; + } psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(iommu->page_table)); @@ -982,7 +986,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = psycho_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -1002,7 +1005,7 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->prom_node = dp; pbm->name = dp->full_name; - printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", + printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", pbm->name, pbm->chip_version, pbm->chip_revision); @@ -1011,24 +1014,28 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pci_get_pbm_props(pbm); psycho_pbm_strbuf_init(pbm, is_pbm_a); + + psycho_scan_bus(pbm); } #define PSYCHO_CONFIGSPACE 0x001000000UL -void __init psycho_init(struct device_node *dp, char *model_name) +static int __devinit psycho_probe(struct of_device *op, + const struct of_device_id *match) { - struct linux_prom64_registers *pr_regs; + const struct linux_prom64_registers *pr_regs; + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; - struct property *prop; + int is_pbm_a, err; + const u32 *p32; u32 upa_portid; - int is_pbm_a; upa_portid = 0xff; - prop = of_find_property(dp, "upa-portid", NULL); - if (prop) - upa_portid = *(u32 *) prop->value; + p32 = of_get_property(dp, "upa-portid", NULL); + if (p32) + upa_portid = *p32; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { struct pci_controller_info *p = pbm->parent; @@ -1036,24 +1043,34 @@ void __init psycho_init(struct device_node *dp, char *model_name) if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); psycho_pbm_init(p, dp, is_pbm_a); - return; + return 0; } } + err = -ENOMEM; p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } + iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free; + } p->pbm_A.iommu = p->pbm_B.iommu = iommu; p->pbm_A.portid = upa_portid; p->pbm_B.portid = upa_portid; - prop = of_find_property(dp, "reg", NULL); - pr_regs = prop->value; + pr_regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; + if (!pr_regs) { + printk(KERN_ERR PFX "No reg property.\n"); + goto out_free; + } p->pbm_A.controller_regs = pr_regs[2].phys_addr; p->pbm_B.controller_regs = pr_regs[2].phys_addr; @@ -1063,14 +1080,42 @@ void __init psycho_init(struct device_node *dp, char *model_name) psycho_controller_hwinit(&p->pbm_A); - if (psycho_iommu_init(&p->pbm_A)) - goto fatal_memory_error; + err = psycho_iommu_init(&p->pbm_A); + if (err) + goto out_free; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + psycho_pbm_init(p, dp, is_pbm_a); - return; -fatal_memory_error: - prom_printf("PSYCHO: Fatal memory allocation error.\n"); - prom_halt(); + return 0; + +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + kfree(p); + } + return err; +} + +static struct of_device_id psycho_match[] = { + { + .name = "pci", + .compatible = "pci108e,8000", + }, + {}, +}; + +static struct of_platform_driver psycho_driver = { + .name = DRIVER_NAME, + .match_table = psycho_match, + .probe = psycho_probe, +}; + +static int __init psycho_init(void) +{ + return of_register_driver(&psycho_driver, &of_bus_type); } + +subsys_initcall(psycho_init); -- cgit v1.2.3 From edbe805b2b1044659e0727136213bdf42bd1b9d0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:14:01 -0700 Subject: sparc64: Convert SABRE PCI controller driver into a real driver. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 -- arch/sparc64/kernel/pci_sabre.c | 126 +++++++++++++++++++++++++++------------- 2 files changed, 85 insertions(+), 45 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c66c9bbc975..c2ff2de4da5 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -165,16 +165,12 @@ void pci_config_write32(u32 *addr, u32 val) } /* Probe for all PCI controllers in the system. */ -extern void sabre_init(struct device_node *, const char *); extern void fire_pci_init(struct device_node *, const char *); static struct { char *model_name; void (*init)(struct device_node *, const char *); } pci_controller_table[] __initdata = { - { "SUNW,sabre", sabre_init }, - { "pci108e,a000", sabre_init }, - { "pci108e,a001", sabre_init }, { "pciex108e,80f0", fire_pci_init }, }; #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ade5184e75d..7cce4d8f4aa 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -16,13 +16,14 @@ #include #include #include -#include -#include #include #include "pci_impl.h" #include "iommu_common.h" +#define DRIVER_NAME "sabre" +#define PFX DRIVER_NAME ": " + /* All SABRE registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. @@ -656,8 +657,8 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) * to live at bus 0. */ if (once != 0) { - prom_printf("SABRE: Multiple controllers unsupported.\n"); - prom_halt(); + printk(KERN_ERR PFX "Multiple controllers unsupported.\n"); + return; } once++; @@ -705,8 +706,10 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, */ err = iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask, pbm->numa_node); - if (err) + if (err) { + printk(KERN_ERR PFX "iommu_table_init() failed\n"); return err; + } sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, __pa(iommu->page_table)); @@ -722,9 +725,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, control |= SABRE_IOMMU_TSBSZ_128K; break; default: - prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); - prom_halt(); - break; + printk(KERN_ERR PFX "Illegal TSB size %d\n", tsbsize); + return -EINVAL; } sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); @@ -739,7 +741,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = sabre_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; @@ -751,46 +752,49 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pci_get_pbm_props(pbm); pci_determine_mem_io_space(pbm); + + sabre_scan_bus(pbm); } -void __init sabre_init(struct device_node *dp, char *model_name) +static int __devinit sabre_probe(struct of_device *op, + const struct of_device_id *match) { const struct linux_prom64_registers *pr_regs; + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; + u32 upa_portid, dma_mask; struct iommu *iommu; - int tsbsize; + int tsbsize, err; const u32 *vdma; - u32 upa_portid, dma_mask; u64 clear_irq; - hummingbird_p = 0; - if (!strcmp(model_name, "pci108e,a001")) - hummingbird_p = 1; - else if (!strcmp(model_name, "SUNW,sabre")) { - const char *compat = of_get_property(dp, "compatible", NULL); - if (compat && !strcmp(compat, "pci108e,a001")) - hummingbird_p = 1; - if (!hummingbird_p) { - struct device_node *dp; - - /* Of course, Sun has to encode things a thousand - * different ways, inconsistently. - */ - for_each_node_by_type(dp, "cpu") { - if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) - hummingbird_p = 1; - } + hummingbird_p = (match->data != NULL); + if (!hummingbird_p) { + struct device_node *cpu_dp; + + /* Of course, Sun has to encode things a thousand + * different ways, inconsistently. + */ + for_each_node_by_type(cpu_dp, "cpu") { + if (!strcmp(cpu_dp->name, "SUNW,UltraSPARC-IIe")) + hummingbird_p = 1; } } + err = -ENOMEM; p = kzalloc(sizeof(*p), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free; + } + pbm = &p->pbm_A; pbm->iommu = iommu; @@ -806,6 +810,11 @@ void __init sabre_init(struct device_node *dp, char *model_name) */ pr_regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; + if (!pr_regs) { + printk(KERN_ERR PFX "No reg property\n"); + goto out_free; + } /* * First REG in property is base of entire SABRE register space. @@ -832,6 +841,10 @@ void __init sabre_init(struct device_node *dp, char *model_name) (pbm->controller_regs + SABRE_CONFIGSPACE); vdma = of_get_property(dp, "virtual-dma", NULL); + if (!vdma) { + printk(KERN_ERR PFX "No virtual-dma property\n"); + goto out_free; + } dma_mask = vdma[0]; switch(vdma[1]) { @@ -849,20 +862,51 @@ void __init sabre_init(struct device_node *dp, char *model_name) tsbsize = 128; break; default: - prom_printf("SABRE: strange virtual-dma size.\n"); - prom_halt(); + printk(KERN_ERR PFX "Strange virtual-dma size.\n"); + goto out_free; } - if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask)) - goto fatal_memory_error; + err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); + if (err) + goto out_free; /* * Look for APB underneath. */ sabre_pbm_init(p, pbm, dp); - return; + return 0; -fatal_memory_error: - prom_printf("SABRE: Fatal memory allocation error.\n"); - prom_halt(); +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + kfree(p); + } + return err; } + +static struct of_device_id sabre_match[] = { + { + .name = "pci", + .compatible = "pci108e,a001", + .data = (void *) 1, + }, + { + .name = "pci", + .compatible = "pci108e,a000", + }, + {}, +}; + +static struct of_platform_driver sabre_driver = { + .name = DRIVER_NAME, + .match_table = sabre_match, + .probe = sabre_probe, +}; + +static int __init sabre_init(void) +{ + return of_register_driver(&sabre_driver, &of_bus_type); +} + +subsys_initcall(sabre_init); -- cgit v1.2.3 From c8049966b7f903ce61e94efbbddf581cf8860b85 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 30 Aug 2008 03:12:38 -0700 Subject: sparc64: Convert FIRE PCI controller driver into a real driver. And now all the by-hand PCI controller probing junk in pci.c can die too. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 96 ------------------------------------------ arch/sparc64/kernel/pci_fire.c | 80 +++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 118 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c2ff2de4da5..2da32e4c985 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -164,79 +164,6 @@ void pci_config_write32(u32 *addr, u32 val) spin_unlock_irqrestore(&pci_poke_lock, flags); } -/* Probe for all PCI controllers in the system. */ -extern void fire_pci_init(struct device_node *, const char *); - -static struct { - char *model_name; - void (*init)(struct device_node *, const char *); -} pci_controller_table[] __initdata = { - { "pciex108e,80f0", fire_pci_init }, -}; -#define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) - -static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) -{ - int i; - - for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { - if (!strncmp(model_name, - pci_controller_table[i].model_name, - namelen)) { - pci_controller_table[i].init(dp, model_name); - return 1; - } - } - - return 0; -} - -static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) -{ - struct device_node *dp; - int count = 0; - - for_each_node_by_name(dp, "pci") { - struct property *prop; - int len; - - prop = of_find_property(dp, "model", &len); - if (!prop) - prop = of_find_property(dp, "compatible", &len); - - if (prop) { - const char *model = prop->value; - int item_len = 0; - - /* Our value may be a multi-valued string in the - * case of some compatible properties. For sanity, - * only try the first one. - */ - while (model[item_len] && len) { - len--; - item_len++; - } - - if (handler(model, item_len, dp)) - count++; - } - } - - return count; -} - -/* Find each controller in the system, attach and initialize - * software state structure for each and link into the - * pci_pbm_root. Setup the controller enough such - * that bus scanning can be done. - */ -static void __init pci_controller_probe(void) -{ - printk("PCI: Probing for controllers.\n"); - - pci_controller_scan(pci_controller_init); -} - static int ofpci_verbose; static int __init ofpci_debug(char *str) @@ -773,29 +700,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) return bus; } -static void __init pci_scan_each_controller_bus(void) -{ - struct pci_pbm_info *pbm; - - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (pbm->scan_bus) - pbm->scan_bus(pbm); - } -} - -static int __init pcibios_init(void) -{ - pci_controller_probe(); - if (pci_pbm_root == NULL) - return 0; - - pci_scan_each_controller_bus(); - - return 0; -} - -subsys_initcall(pcibios_init); - void __devinit pcibios_fixup_bus(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index d23bb6f53cd..adc3fe44b08 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -8,13 +8,16 @@ #include #include #include +#include -#include #include #include #include "pci_impl.h" +#define DRIVER_NAME "fire" +#define PFX DRIVER_NAME ": " + #define fire_read(__reg) \ ({ u64 __ret; \ __asm__ __volatile__("ldxa [%1] %2, %0" \ @@ -452,7 +455,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pbm->numa_node = -1; - pbm->scan_bus = pci_fire_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 12; @@ -481,6 +483,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pci_fire_msi_init(pbm); + pci_fire_scan_bus(pbm); + return 0; } @@ -491,43 +495,75 @@ static inline int portid_compare(u32 x, u32 y) return 0; } -void __init fire_pci_init(struct device_node *dp, const char *model_name) +static int __devinit fire_probe(struct of_device *op, + const struct of_device_id *match) { + struct device_node *dp = op->node; struct pci_controller_info *p; - u32 portid = of_getintprop_default(dp, "portid", 0xff); - struct iommu *iommu; struct pci_pbm_info *pbm; + struct iommu *iommu; + u32 portid; + int err; + portid = of_getintprop_default(dp, "portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid)) { - if (pci_fire_pbm_init(pbm->parent, dp, portid)) - goto fatal_memory_error; - return; - } + if (portid_compare(pbm->portid, portid)) + return pci_fire_pbm_init(pbm->parent, dp, portid); } + err = -ENOMEM; p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) - goto fatal_memory_error; + if (!p) { + printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + goto out_free; + } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_A.iommu = iommu; iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) - goto fatal_memory_error; + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + goto out_free; + } p->pbm_B.iommu = iommu; - if (pci_fire_pbm_init(p, dp, portid)) - goto fatal_memory_error; + return pci_fire_pbm_init(p, dp, portid); - return; +out_free: + if (p) { + if (p->pbm_A.iommu) + kfree(p->pbm_A.iommu); + if (p->pbm_B.iommu) + kfree(p->pbm_B.iommu); + kfree(p); + } + return err; +} + +static struct of_device_id fire_match[] = { + { + .name = "pci", + .compatible = "pciex108e,80f0", + }, + {}, +}; -fatal_memory_error: - prom_printf("PCI_FIRE: Fatal memory allocation error.\n"); - prom_halt(); +static struct of_platform_driver fire_driver = { + .name = DRIVER_NAME, + .match_table = fire_match, + .probe = fire_probe, +}; + +static int __init fire_init(void) +{ + return of_register_driver(&fire_driver, &of_bus_type); } + +subsys_initcall(fire_init); -- cgit v1.2.3 From fd098316ef533e8441576f020ead4beab93154ce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:23:17 -0700 Subject: sparc: Annotate of_device_id arrays with const or __initdata. As suggested by Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/auxio.c | 2 +- arch/sparc64/kernel/chmc.c | 2 +- arch/sparc64/kernel/pci_fire.c | 2 +- arch/sparc64/kernel/pci_psycho.c | 2 +- arch/sparc64/kernel/pci_sabre.c | 2 +- arch/sparc64/kernel/pci_schizo.c | 2 +- arch/sparc64/kernel/pci_sun4v.c | 2 +- arch/sparc64/kernel/power.c | 2 +- arch/sparc64/kernel/time.c | 6 +++--- 9 files changed, 11 insertions(+), 11 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index dd5c7bf8761..858beda8652 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -109,7 +109,7 @@ void auxio_set_lte(int on) } } -static struct of_device_id auxio_match[] = { +static struct of_device_id __initdata auxio_match[] = { { .name = "auxio", }, diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 3e14952e940..2ed401087ca 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -801,7 +801,7 @@ static int __devexit us3mc_remove(struct of_device *op) return 0; } -static struct of_device_id us3mc_match[] = { +static const struct of_device_id us3mc_match[] = { { .name = "memory-controller", }, diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index adc3fe44b08..477928aad53 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -547,7 +547,7 @@ out_free: return err; } -static struct of_device_id fire_match[] = { +static struct of_device_id __initdata fire_match[] = { { .name = "pci", .compatible = "pciex108e,80f0", diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4e8f87aad20..708212a6e7e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1099,7 +1099,7 @@ out_free: return err; } -static struct of_device_id psycho_match[] = { +static struct of_device_id __initdata psycho_match[] = { { .name = "pci", .compatible = "pci108e,8000", diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 7cce4d8f4aa..cc476e9a275 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -885,7 +885,7 @@ out_free: return err; } -static struct of_device_id sabre_match[] = { +static struct of_device_id __initdata sabre_match[] = { { .name = "pci", .compatible = "pci108e,a001", diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index b95dd548583..18fdd887b4a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1504,7 +1504,7 @@ static int __devinit schizo_probe(struct of_device *op, * and pci108e,8001. So list the chips in reverse chronological * order. */ -static struct of_device_id schizo_match[] = { +static struct of_device_id __initdata schizo_match[] = { { .name = "pci", .compatible = "pci108e,a801", diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index c1e72beade2..fea51a054be 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -1026,7 +1026,7 @@ out_free: return -ENOMEM; } -static struct of_device_id pci_sun4v_match[] = { +static struct of_device_id __initdata pci_sun4v_match[] = { { .name = "pci", .compatible = "SUNW,sun4v-pci", diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 7536255ab57..7559ad395a3 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -89,7 +89,7 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id return 0; } -static struct of_device_id power_match[] = { +static struct of_device_id __initdata power_match[] = { { .name = "power", }, diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index ea05038a8c1..209e7d28c3a 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -438,7 +438,7 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id * return platform_device_register(&rtc_cmos_device); } -static struct of_device_id rtc_match[] = { +static struct of_device_id __initdata rtc_match[] = { { .name = "rtc", .compatible = "m5819", @@ -482,7 +482,7 @@ static int __devinit bq4802_probe(struct of_device *op, const struct of_device_i return platform_device_register(&rtc_bq4802_device); } -static struct of_device_id bq4802_match[] = { +static struct of_device_id __initdata bq4802_match[] = { { .name = "rtc", .compatible = "bq4802", @@ -566,7 +566,7 @@ static int __devinit mostek_probe(struct of_device *op, const struct of_device_i return platform_device_register(&m48t59_rtc); } -static struct of_device_id mostek_match[] = { +static struct of_device_id __initdata mostek_match[] = { { .name = "eeprom", }, -- cgit v1.2.3 From d7472c389ee1044d04af8a5b7c51aa7af96ed2db Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:33:52 -0700 Subject: sparc64: Simplify error handling in PCI controller probing. Based upon suggestions from Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_fire.c | 21 ++++++++++----------- arch/sparc64/kernel/pci_psycho.c | 21 +++++++++++---------- arch/sparc64/kernel/pci_sabre.c | 25 +++++++++++++------------ arch/sparc64/kernel/pci_schizo.c | 32 ++++++++++++++++++-------------- arch/sparc64/kernel/pci_sun4v.c | 31 ++++++++++++++++--------------- 5 files changed, 68 insertions(+), 62 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 477928aad53..4fb1ef92cb1 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -515,13 +515,13 @@ static int __devinit fire_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -529,21 +529,20 @@ static int __devinit fire_probe(struct of_device *op, iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; return pci_fire_pbm_init(p, dp, portid); -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 708212a6e7e..5ee84c5b963 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1051,13 +1051,13 @@ static int __devinit psycho_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = p->pbm_B.iommu = iommu; @@ -1069,7 +1069,7 @@ static int __devinit psycho_probe(struct of_device *op, err = -ENODEV; if (!pr_regs) { printk(KERN_ERR PFX "No reg property.\n"); - goto out_free; + goto out_free_iommu; } p->pbm_A.controller_regs = pr_regs[2].phys_addr; @@ -1082,7 +1082,7 @@ static int __devinit psycho_probe(struct of_device *op, err = psycho_iommu_init(&p->pbm_A); if (err) - goto out_free; + goto out_free_iommu; is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); @@ -1090,12 +1090,13 @@ static int __devinit psycho_probe(struct of_device *op, return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - kfree(p); - } +out_free_iommu: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index cc476e9a275..eee8fdca382 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -786,13 +786,13 @@ static int __devinit sabre_probe(struct of_device *op, p = kzalloc(sizeof(*p), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free; + goto out_free_controller; } pbm = &p->pbm_A; @@ -813,7 +813,7 @@ static int __devinit sabre_probe(struct of_device *op, err = -ENODEV; if (!pr_regs) { printk(KERN_ERR PFX "No reg property\n"); - goto out_free; + goto out_free_iommu; } /* @@ -843,7 +843,7 @@ static int __devinit sabre_probe(struct of_device *op, vdma = of_get_property(dp, "virtual-dma", NULL); if (!vdma) { printk(KERN_ERR PFX "No virtual-dma property\n"); - goto out_free; + goto out_free_iommu; } dma_mask = vdma[0]; @@ -863,12 +863,12 @@ static int __devinit sabre_probe(struct of_device *op, break; default: printk(KERN_ERR PFX "Strange virtual-dma size.\n"); - goto out_free; + goto out_free_iommu; } err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); if (err) - goto out_free; + goto out_free_iommu; /* * Look for APB underneath. @@ -876,12 +876,13 @@ static int __devinit sabre_probe(struct of_device *op, sabre_pbm_init(p, pbm, dp); return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - kfree(p); - } +out_free_iommu: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: return err; } diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 18fdd887b4a..bd7612aae17 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1443,14 +1443,16 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; + int err; portid = of_getintprop_default(dp, "portid", 0xff); + err = -ENOMEM; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid, chip_type)) { if (schizo_pbm_init(pbm->parent, dp, portid, chip_type)) - return -ENOMEM; + goto out_err; return 0; } } @@ -1458,13 +1460,13 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Cannot allocate controller info.\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -1472,25 +1474,27 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; if (schizo_pbm_init(p, dp, portid, chip_type)) - goto out_free; + goto out_free_iommu_B; return 0; -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } - return -ENOMEM; +out_free_iommu_B: + kfree(p->pbm_B.iommu); + +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: + return err; } static int __devinit schizo_probe(struct of_device *op, diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index fea51a054be..21864f06532 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -949,7 +949,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, struct device_node *dp; struct iommu *iommu; u32 devhandle; - int i; + int i, err; dp = op->node; @@ -970,9 +970,10 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } regs = of_get_property(dp, "reg", NULL); + err = -ENODEV; if (!regs) { printk(KERN_ERR PFX "Could not find config registers\n"); - return -ENODEV; + goto out_err; } devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; @@ -982,11 +983,12 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } } + err = -ENOMEM; for_each_possible_cpu(i) { unsigned long page = get_zeroed_page(GFP_ATOMIC); if (!page) - return -ENOMEM; + goto out_err; per_cpu(iommu_batch, i).pglist = (u64 *) page; } @@ -994,13 +996,13 @@ static int __devinit pci_sun4v_probe(struct of_device *op, p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); if (!p) { printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); - goto out_free; + goto out_err; } iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); - goto out_free; + goto out_free_controller; } p->pbm_A.iommu = iommu; @@ -1008,22 +1010,21 @@ static int __devinit pci_sun4v_probe(struct of_device *op, iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); if (!iommu) { printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); - goto out_free; + goto out_free_iommu_A; } p->pbm_B.iommu = iommu; return pci_sun4v_pbm_init(p, dp, devhandle); -out_free: - if (p) { - if (p->pbm_A.iommu) - kfree(p->pbm_A.iommu); - if (p->pbm_B.iommu) - kfree(p->pbm_B.iommu); - kfree(p); - } - return -ENOMEM; +out_free_iommu_A: + kfree(p->pbm_A.iommu); + +out_free_controller: + kfree(p); + +out_err: + return err; } static struct of_device_id __initdata pci_sun4v_match[] = { -- cgit v1.2.3 From 10d29ff9070caf5810d37ab06e30f7acad278f1e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 01:40:12 -0700 Subject: sparc64: Delete starfire_cpu_setup(). It does nothing. Signed-off-by: David S. Miller --- arch/sparc64/kernel/central.c | 5 +---- arch/sparc64/kernel/starfire.c | 5 ----- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index f2e87d0d7e1..68c91b232be 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -306,11 +306,8 @@ void __init central_probe(void) int err; dp = of_find_node_by_name(NULL, "central"); - if (!dp) { - if (this_is_starfire) - starfire_cpu_setup(); + if (!dp) return; - } /* Ok we got one, grab some memory for software state. */ central_bus = (struct linux_central *) diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c index 7461581b3bb..060d0f3a615 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc64/kernel/starfire.c @@ -28,11 +28,6 @@ void check_if_starfire(void) this_is_starfire = 1; } -void starfire_cpu_setup(void) -{ - /* Currently, nothing to do. */ -} - int starfire_hard_smp_processor_id(void) { return upa_readl(0x1fff40000d0UL); -- cgit v1.2.3 From b69416b51be0757c82f1c5a0a3f0995a4484dab4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 20:56:15 -0700 Subject: sparc64: Rewrite central driver. This driver is now limited to just doing the basic clock board and FHC chip initialization and registering the platform devices for the per-board LEDs, which are driven by the new LEDS_STARFIRE driver. The IRQ register handling is already confined purely to the device tree code. Signed-off-by: David S. Miller --- arch/sparc64/kernel/central.c | 616 +++++++++++++++--------------------------- arch/sparc64/kernel/sbus.c | 3 - 2 files changed, 213 insertions(+), 406 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index 68c91b232be..05f1c916db0 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c @@ -1,458 +1,268 @@ /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. * - * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net) */ #include #include #include -#include -#include -#include #include -#include +#include +#include -#include #include -#include - -static struct linux_central *central_bus = NULL; -static struct linux_fhc *fhc_list = NULL; +#include + +struct clock_board { + void __iomem *clock_freq_regs; + void __iomem *clock_regs; + void __iomem *clock_ver_reg; + int num_slots; + struct resource leds_resource; + struct platform_device leds_pdev; +}; + +struct fhc { + void __iomem *pregs; + bool central; + bool jtag_master; + int board_num; + struct resource leds_resource; + struct platform_device leds_pdev; +}; + +static int __devinit clock_board_calc_nslots(struct clock_board *p) +{ + u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0; -#define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) + switch (reg) { + case 0x40: + return 16; -static void central_probe_failure(int line) -{ - prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", - line); - prom_halt(); -} + case 0xc0: + return 8; -static void central_ranges_init(struct linux_central *central) -{ - struct device_node *dp = central->prom_node; - const void *pval; - int len; - - central->num_central_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(central->central_ranges, pval, len); - central->num_central_ranges = - (len / sizeof(struct linux_prom_ranges)); + case 0x80: + reg = 0; + if (p->clock_ver_reg) + reg = upa_readb(p->clock_ver_reg); + if (reg) { + if (reg & 0x80) + return 4; + else + return 5; + } + /* Fallthrough */ + default: + return 4; } } -static void fhc_ranges_init(struct linux_fhc *fhc) +static int __devinit clock_board_probe(struct of_device *op, + const struct of_device_id *match) { - struct device_node *dp = fhc->prom_node; - const void *pval; - int len; - - fhc->num_fhc_ranges = 0; - pval = of_get_property(dp, "ranges", &len); - if (pval) { - memcpy(fhc->fhc_ranges, pval, len); - fhc->num_fhc_ranges = - (len / sizeof(struct linux_prom_ranges)); - } -} + struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); + int err = -ENOMEM; -/* Range application routines are exported to various drivers, - * so do not __init this. - */ -static void adjust_regs(struct linux_prom_registers *regp, int nregs, - struct linux_prom_ranges *rangep, int nranges) -{ - int regc, rngc; - - for (regc = 0; regc < nregs; regc++) { - for (rngc = 0; rngc < nranges; rngc++) - if (regp[regc].which_io == rangep[rngc].ot_child_space) - break; /* Fount it */ - if (rngc == nranges) /* oops */ - central_probe_failure(__LINE__); - regp[regc].which_io = rangep[rngc].ot_parent_space; - regp[regc].phys_addr -= rangep[rngc].ot_child_base; - regp[regc].phys_addr += rangep[rngc].ot_parent_base; + if (!p) { + printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n"); + goto out; } -} -/* Apply probed fhc ranges to registers passed, if no ranges return. */ -static void apply_fhc_ranges(struct linux_fhc *fhc, - struct linux_prom_registers *regs, - int nregs) -{ - if (fhc->num_fhc_ranges) - adjust_regs(regs, nregs, fhc->fhc_ranges, - fhc->num_fhc_ranges); -} + p->clock_freq_regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), + "clock_board_freq"); + if (!p->clock_freq_regs) { + printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n"); + goto out_free; + } -/* Apply probed central ranges to registers passed, if no ranges return. */ -static void apply_central_ranges(struct linux_central *central, - struct linux_prom_registers *regs, int nregs) -{ - if (central->num_central_ranges) - adjust_regs(regs, nregs, central->central_ranges, - central->num_central_ranges); -} + p->clock_regs = of_ioremap(&op->resource[1], 0, + resource_size(&op->resource[1]), + "clock_board_regs"); + if (!p->clock_regs) { + printk(KERN_ERR "clock_board: Cannot map clock_regs\n"); + goto out_unmap_clock_freq_regs; + } -static void * __init central_alloc_bootmem(unsigned long size) -{ - void *ret; + if (op->resource[2].flags) { + p->clock_ver_reg = of_ioremap(&op->resource[2], 0, + resource_size(&op->resource[2]), + "clock_ver_reg"); + if (!p->clock_ver_reg) { + printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n"); + goto out_unmap_clock_regs; + } + } - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); + p->num_slots = clock_board_calc_nslots(p); - return ret; -} + p->leds_resource.start = (unsigned long) + (p->clock_regs + CLOCK_CTRL); + p->leds_resource.end = p->leds_resource.end; + p->leds_resource.name = "leds"; -static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) -{ - unsigned long ret = ((unsigned long) r->which_io) << 32; + p->leds_pdev.name = "sunfire-clockboard-leds"; + p->leds_pdev.resource = &p->leds_resource; + p->leds_pdev.num_resources = 1; + p->leds_pdev.dev.parent = &op->dev; - return ret | (unsigned long) r->phys_addr; -} - -static void __init probe_other_fhcs(void) -{ - struct device_node *dp; - const struct linux_prom64_registers *fpregs; - - for_each_node_by_name(dp, "fhc") { - struct linux_fhc *fhc; - int board; - u32 tmp; - - if (dp->parent && - dp->parent->parent != NULL) - continue; - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* Link it into the FHC chain. */ - fhc->next = fhc_list; - fhc_list = fhc; - - /* Toplevel FHCs have no parent. */ - fhc->parent = NULL; - - fhc->prom_node = dp; - fhc_ranges_init(fhc); - - /* Non-central FHC's have 64-bit OBP format registers. */ - fpregs = of_get_property(dp, "reg", NULL); - if (!fpregs) - central_probe_failure(__LINE__); - - /* Only central FHC needs special ranges applied. */ - fhc->fhc_regs.pregs = fpregs[0].phys_addr; - fhc->fhc_regs.ireg = fpregs[1].phys_addr; - fhc->fhc_regs.ffregs = fpregs[2].phys_addr; - fhc->fhc_regs.sregs = fpregs[3].phys_addr; - fhc->fhc_regs.uregs = fpregs[4].phys_addr; - fhc->fhc_regs.tregs = fpregs[5].phys_addr; - - board = of_getintprop_default(dp, "board#", -1); - fhc->board = board; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); - if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) - fhc->jtag_master = 1; - else - fhc->jtag_master = 0; - - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", - board, - (tmp & FHC_ID_VERS) >> 28, - (tmp & FHC_ID_PARTID) >> 12, - (tmp & FHC_ID_MANUF) >> 1, - (fhc->jtag_master ? "(JTAG Master)" : "")); - - /* This bit must be set in all non-central FHC's in - * the system. When it is clear, this identifies - * the central board. - */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - tmp |= FHC_CONTROL_IXIST; - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + err = platform_device_register(&p->leds_pdev); + if (err) { + printk(KERN_ERR "clock_board: Could not register LEDS " + "platform device\n"); + goto out_unmap_clock_ver_reg; } -} -static void probe_clock_board(struct linux_central *central, - struct linux_fhc *fhc, - struct device_node *fp) -{ - struct device_node *dp; - struct linux_prom_registers cregs[3]; - const struct linux_prom_registers *pr; - int nslots, tmp, nregs; - - dp = fp->child; - while (dp) { - if (!strcmp(dp->name, "clock-board")) - break; - dp = dp->sibling; - } - if (!dp) - central_probe_failure(__LINE__); + printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n", + p->num_slots); - pr = of_get_property(dp, "reg", &nregs); - if (!pr) - central_probe_failure(__LINE__); + err = 0; +out: + return err; - memcpy(cregs, pr, nregs); - nregs /= sizeof(struct linux_prom_registers); +out_unmap_clock_ver_reg: + if (p->clock_ver_reg) + of_iounmap(&op->resource[2], p->clock_ver_reg, + resource_size(&op->resource[2])); - apply_fhc_ranges(fhc, &cregs[0], nregs); - apply_central_ranges(central, &cregs[0], nregs); - central->cfreg = prom_reg_to_paddr(&cregs[0]); - central->clkregs = prom_reg_to_paddr(&cregs[1]); +out_unmap_clock_regs: + of_iounmap(&op->resource[1], p->clock_regs, + resource_size(&op->resource[1])); - if (nregs == 2) - central->clkver = 0UL; - else - central->clkver = prom_reg_to_paddr(&cregs[2]); +out_unmap_clock_freq_regs: + of_iounmap(&op->resource[0], p->clock_freq_regs, + resource_size(&op->resource[0])); - tmp = upa_readb(central->clkregs + CLOCK_STAT1); - tmp &= 0xc0; - switch(tmp) { - case 0x40: - nslots = 16; - break; - case 0xc0: - nslots = 8; - break; - case 0x80: - if (central->clkver != 0UL && - upa_readb(central->clkver) != 0) { - if ((upa_readb(central->clkver) & 0x80) != 0) - nslots = 4; - else - nslots = 5; - break; - } - default: - nslots = 4; - break; - }; - central->slots = nslots; - printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", - central->slots, upa_readb(central->cfreg), - (central->clkver ? upa_readb(central->clkver) : 0x00)); +out_free: + kfree(p); + goto out; } -static void ZAP(unsigned long iclr, unsigned long imap) +static struct of_device_id __initdata clock_board_match[] = { + { + .name = "clock-board", + }, + {}, +}; + +static struct of_platform_driver clock_board_driver = { + .match_table = clock_board_match, + .probe = clock_board_probe, + .driver = { + .name = "clock_board", + }, +}; + +static int __devinit fhc_probe(struct of_device *op, + const struct of_device_id *match) { - u32 imap_tmp; - - upa_writel(0, iclr); - upa_readl(iclr); - imap_tmp = upa_readl(imap); - imap_tmp &= ~(0x80000000); - upa_writel(imap_tmp, imap); - upa_readl(imap); -} + struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); + int err = -ENOMEM; + u32 reg; -static void init_all_fhc_hw(void) -{ - struct linux_fhc *fhc; - - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { - u32 tmp; - - /* Clear all of the interrupt mapping registers - * just in case OBP left them in a foul state. - */ - ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, - fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); - ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, - fhc->fhc_regs.sregs + FHC_SREGS_IMAP); - ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, - fhc->fhc_regs.uregs + FHC_UREGS_IMAP); - ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, - fhc->fhc_regs.tregs + FHC_TREGS_IMAP); - - /* Setup FHC control register. */ - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - - /* All non-central boards have this bit set. */ - if (! IS_CENTRAL_FHC(fhc)) - tmp |= FHC_CONTROL_IXIST; - - /* For all FHCs, clear the firmware synchronization - * line and both low power mode enables. - */ - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | - FHC_CONTROL_SLINE); - - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + if (!p) { + printk(KERN_ERR "fhc: Cannot allocate struct fhc\n"); + goto out; } -} + if (!strcmp(op->node->parent->name, "central")) + p->central = true; -void __init central_probe(void) -{ - struct linux_prom_registers fpregs[6]; - const struct linux_prom_registers *pr; - struct linux_fhc *fhc; - struct device_node *dp, *fp; - int err; - - dp = of_find_node_by_name(NULL, "central"); - if (!dp) - return; - - /* Ok we got one, grab some memory for software state. */ - central_bus = (struct linux_central *) - central_alloc_bootmem(sizeof(struct linux_central)); - if (central_bus == NULL) - central_probe_failure(__LINE__); - - fhc = (struct linux_fhc *) - central_alloc_bootmem(sizeof(struct linux_fhc)); - if (fhc == NULL) - central_probe_failure(__LINE__); - - /* First init central. */ - central_bus->child = fhc; - central_bus->prom_node = dp; - central_ranges_init(central_bus); - - /* And then central's FHC. */ - fhc->next = fhc_list; - fhc_list = fhc; - - fhc->parent = central_bus; - fp = dp->child; - while (fp) { - if (!strcmp(fp->name, "fhc")) - break; - fp = fp->sibling; + p->pregs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), + "fhc_pregs"); + if (!p->pregs) { + printk(KERN_ERR "fhc: Cannot map pregs\n"); + goto out_free; } - if (!fp) - central_probe_failure(__LINE__); - - fhc->prom_node = fp; - fhc_ranges_init(fhc); - - /* Now, map in FHC register set. */ - pr = of_get_property(fp, "reg", NULL); - if (!pr) - central_probe_failure(__LINE__); - memcpy(fpregs, pr, sizeof(fpregs)); - - apply_central_ranges(central_bus, &fpregs[0], 6); - - fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); - fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); - fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); - fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); - fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); - fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); - - /* Obtain board number from board status register, Central's - * FHC lacks "board#" property. - */ - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); - fhc->board = (((err >> 16) & 0x01) | - ((err >> 12) & 0x0e)); - - fhc->jtag_master = 0; - - /* Attach the clock board registers for CENTRAL. */ - probe_clock_board(central_bus, fhc, fp); - - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", - fhc->board, - ((err & FHC_ID_VERS) >> 28), - ((err & FHC_ID_PARTID) >> 12), - ((err & FHC_ID_MANUF) >> 1)); - - probe_other_fhcs(); - - init_all_fhc_hw(); -} -static inline void fhc_ledblink(struct linux_fhc *fhc, int on) -{ - u32 tmp; + if (p->central) { + reg = upa_readl(p->pregs + FHC_PREGS_BSR); + p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e); + } else { + p->board_num = of_getintprop_default(op->node, "board#", -1); + if (p->board_num == -1) { + printk(KERN_ERR "fhc: No board# property\n"); + goto out_unmap_pregs; + } + if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB) + p->jtag_master = true; + } - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); + if (!p->central) { + p->leds_resource.start = (unsigned long) + (p->pregs + FHC_PREGS_CTRL); + p->leds_resource.end = p->leds_resource.end; + p->leds_resource.name = "leds"; + + p->leds_pdev.name = "sunfire-fhc-leds"; + p->leds_pdev.resource = &p->leds_resource; + p->leds_pdev.num_resources = 1; + p->leds_pdev.dev.parent = &op->dev; + + err = platform_device_register(&p->leds_pdev); + if (err) { + printk(KERN_ERR "fhc: Could not register LEDS " + "platform device\n"); + goto out_unmap_pregs; + } + } + reg = upa_readl(p->pregs + FHC_PREGS_CTRL); - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(FHC_CONTROL_RLED); - else - tmp |= FHC_CONTROL_RLED; - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); + if (!p->central) + reg |= FHC_CONTROL_IXIST; - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); -} + reg &= ~(FHC_CONTROL_AOFF | + FHC_CONTROL_BOFF | + FHC_CONTROL_SLINE); -static inline void central_ledblink(struct linux_central *central, int on) -{ - u8 tmp; + upa_writel(reg, p->pregs + FHC_PREGS_CTRL); + upa_readl(p->pregs + FHC_PREGS_CTRL); - tmp = upa_readb(central->clkregs + CLOCK_CTRL); + reg = upa_readl(p->pregs + FHC_PREGS_ID); + printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n", + p->board_num, + (reg & FHC_ID_VERS) >> 28, + (reg & FHC_ID_PARTID) >> 12, + (reg & FHC_ID_MANUF) >> 1, + (p->jtag_master ? + "(JTAG Master)" : + (p->central ? "(Central)" : ""))); - /* NOTE: reverse logic on this bit */ - if (on) - tmp &= ~(CLOCK_CTRL_RLED); - else - tmp |= CLOCK_CTRL_RLED; + err = 0; - upa_writeb(tmp, central->clkregs + CLOCK_CTRL); - upa_readb(central->clkregs + CLOCK_CTRL); -} +out: + return err; -static struct timer_list sftimer; -static int led_state; +out_unmap_pregs: + of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0])); -static void sunfire_timer(unsigned long __ignored) -{ - struct linux_fhc *fhc; - - central_ledblink(central_bus, led_state); - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) - if (! IS_CENTRAL_FHC(fhc)) - fhc_ledblink(fhc, led_state); - led_state = ! led_state; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); +out_free: + kfree(p); + goto out; } -/* After PCI/SBUS busses have been probed, this is called to perform - * final initialization of all FireHose Controllers in the system. - */ -void firetruck_init(void) +static struct of_device_id __initdata fhc_match[] = { + { + .name = "fhc", + }, + {}, +}; + +static struct of_platform_driver fhc_driver = { + .match_table = fhc_match, + .probe = fhc_probe, + .driver = { + .name = "fhc", + }, +}; + +static int __init sunfire_init(void) { - struct linux_central *central = central_bus; - u8 ctrl; - - /* No central bus, nothing to do. */ - if (central == NULL) - return; - - /* OBP leaves it on, turn it off so clock board timer LED - * is in sync with FHC ones. - */ - ctrl = upa_readb(central->clkregs + CLOCK_CTRL); - ctrl &= ~(CLOCK_CTRL_RLED); - upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); - - led_state = 0; - init_timer(&sftimer); - sftimer.data = 0; - sftimer.function = &sunfire_timer; - sftimer.expires = jiffies + (HZ >> 1); - add_timer(&sftimer); + (void) of_register_driver(&fhc_driver, &of_platform_bus_type); + (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); + return 0; } + +subsys_initcall(sunfire_init); diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index 9d7dfb8cc27..2ead310066d 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -659,7 +659,6 @@ fatal_memory_error: static int __init sbus_init(void) { - extern void firetruck_init(void); struct device_node *dp; for_each_node_by_name(dp, "sbus") { @@ -669,8 +668,6 @@ static int __init sbus_init(void) of_propagate_archdata(op); } - firetruck_init(); - return 0; } -- cgit v1.2.3 From ba4962d7a6a10c82e55c14589d4ec635bef8446f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 31 Aug 2008 21:48:12 -0700 Subject: sparc64: Clean up CPU chip type probing code. Three main things: 1) Make prober an arch initcall instead of using hard-coded invocation from paging_init() 2) Shrink table size, the fpu ident stuff was never used. 3) Use named struct initialized in table. Signed-off-by: David S. Miller --- arch/sparc64/kernel/cpu.c | 208 +++++++++++++++++++++++--------------------- arch/sparc64/kernel/entry.h | 4 +- 2 files changed, 111 insertions(+), 101 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index 0097c08dc60..0c9ac83ed0a 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c @@ -1,7 +1,7 @@ /* cpu.c: Dinky routines to look for the kind of Sparc cpu * we are on. * - * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) */ #include @@ -19,53 +19,86 @@ DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; -struct cpu_iu_info { - short manuf; - short impl; - char* cpu_name; /* should be enough I hope... */ +struct cpu_chip_info { + unsigned short manuf; + unsigned short impl; + const char *cpu_name; + const char *fp_name; }; -struct cpu_fp_info { - short manuf; - short impl; - char fpu_vers; - char* fp_name; +static const struct cpu_chip_info cpu_chips[] = { + { + .manuf = 0x17, + .impl = 0x10, + .cpu_name = "TI UltraSparc I (SpitFire)", + .fp_name = "UltraSparc I integrated FPU", + }, + { + .manuf = 0x22, + .impl = 0x10, + .cpu_name = "TI UltraSparc I (SpitFire)", + .fp_name = "UltraSparc I integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x11, + .cpu_name = "TI UltraSparc II (BlackBird)", + .fp_name = "UltraSparc II integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x12, + .cpu_name = "TI UltraSparc IIi (Sabre)", + .fp_name = "UltraSparc IIi integrated FPU", + }, + { + .manuf = 0x17, + .impl = 0x13, + .cpu_name = "TI UltraSparc IIe (Hummingbird)", + .fp_name = "UltraSparc IIe integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x14, + .cpu_name = "TI UltraSparc III (Cheetah)", + .fp_name = "UltraSparc III integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x15, + .cpu_name = "TI UltraSparc III+ (Cheetah+)", + .fp_name = "UltraSparc III+ integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x16, + .cpu_name = "TI UltraSparc IIIi (Jalapeno)", + .fp_name = "UltraSparc IIIi integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x18, + .cpu_name = "TI UltraSparc IV (Jaguar)", + .fp_name = "UltraSparc IV integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x19, + .cpu_name = "TI UltraSparc IV+ (Panther)", + .fp_name = "UltraSparc IV+ integrated FPU", + }, + { + .manuf = 0x3e, + .impl = 0x22, + .cpu_name = "TI UltraSparc IIIi+ (Serrano)", + .fp_name = "UltraSparc IIIi+ integrated FPU", + }, }; -static struct cpu_fp_info linux_sparc_fpu[] = { - { 0x17, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x22, 0x10, 0, "UltraSparc I integrated FPU"}, - { 0x17, 0x11, 0, "UltraSparc II integrated FPU"}, - { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, - { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, - { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, - { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, - { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, - { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, - { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, - { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, -}; - -#define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) - -static struct cpu_iu_info linux_sparc_chips[] = { - { 0x17, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x22, 0x10, "TI UltraSparc I (SpitFire)"}, - { 0x17, 0x11, "TI UltraSparc II (BlackBird)"}, - { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"}, - { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"}, - { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, - { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, - { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, - { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, - { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, - { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, -}; +#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) -#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) - -char *sparc_cpu_type; -char *sparc_fpu_type; +const char *sparc_cpu_type; +const char *sparc_fpu_type; static void __init sun4v_cpu_probe(void) { @@ -89,68 +122,45 @@ static void __init sun4v_cpu_probe(void) } } -void __init cpu_probe(void) +static const struct cpu_chip_info * __init find_cpu_chip(unsigned short manuf, + unsigned short impl) { - unsigned long ver, fpu_vers, manuf, impl, fprs; int i; - - if (tlb_type == hypervisor) { - sun4v_cpu_probe(); - return; - } - fprs = fprs_read(); - fprs_write(FPRS_FEF); - __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" - : "=&r" (ver) - : "r" (&fpu_vers)); - fprs_write(fprs); - - manuf = ((ver >> 48) & 0xffff); - impl = ((ver >> 32) & 0xffff); - - fpu_vers = ((fpu_vers >> 17) & 0x7); - -retry: - for (i = 0; i < NSPARCCHIPS; i++) { - if (linux_sparc_chips[i].manuf == manuf) { - if (linux_sparc_chips[i].impl == impl) { - sparc_cpu_type = - linux_sparc_chips[i].cpu_name; - break; - } - } - } + for (i = 0; i < ARRAY_SIZE(cpu_chips); i++) { + const struct cpu_chip_info *p = &cpu_chips[i]; - if (i == NSPARCCHIPS) { - /* Maybe it is a cheetah+ derivative, report it as cheetah+ - * in that case until we learn the real names. - */ - if (manuf == 0x3e && - impl > 0x15) { - impl = 0x15; - goto retry; - } else { - printk("DEBUG: manuf[%lx] impl[%lx]\n", - manuf, impl); - } - sparc_cpu_type = "Unknown CPU"; + if (p->manuf == manuf && p->impl == impl) + return p; } + return NULL; +} - for (i = 0; i < NSPARCFPU; i++) { - if (linux_sparc_fpu[i].manuf == manuf && - linux_sparc_fpu[i].impl == impl) { - if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { - sparc_fpu_type = - linux_sparc_fpu[i].fp_name; - break; - } +static int __init cpu_type_probe(void) +{ + if (tlb_type == hypervisor) { + sun4v_cpu_probe(); + } else { + unsigned long ver, manuf, impl; + const struct cpu_chip_info *p; + + __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); + + manuf = ((ver >> 48) & 0xffff); + impl = ((ver >> 32) & 0xffff); + + p = find_cpu_chip(manuf, impl); + if (p) { + sparc_cpu_type = p->cpu_name; + sparc_fpu_type = p->fp_name; + } else { + printk(KERN_ERR "CPU: Unknown chip, manuf[%lx] impl[%lx]\n", + manuf, impl); + sparc_cpu_type = "Unknown CPU"; + sparc_fpu_type = "Unknown FPU"; } } - - if (i == NSPARCFPU) { - printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", - manuf, impl, fpu_vers); - sparc_fpu_type = "Unknown FPU"; - } + return 0; } + +arch_initcall(cpu_type_probe); diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index 2255244442f..34d7ab5e10d 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -5,8 +5,8 @@ #include #include -extern char *sparc_cpu_type; -extern char *sparc_fpu_type; +extern const char *sparc_cpu_type; +extern const char *sparc_fpu_type; extern void __init per_cpu_patch(void); extern void __init sun4v_patch(void); -- cgit v1.2.3 From 3d452e55ef905fc6fbf813a66c16de1293e243a1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 01:48:52 -0700 Subject: sparc64: Apply const or __initdata to vio_device_id[] This mirrors the of_device_id[] changes done in fd098316ef533e8441576f020ead4beab93154ce ("sparc: Annotate of_device_id arrays with const or __initdata.") Signed-off-by: David S. Miller --- arch/sparc64/kernel/ds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index d0fa5aa3893..f52e0534d91 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c @@ -1,6 +1,6 @@ /* ds.c: Domain Services driver for Logical Domains * - * Copyright (C) 2007 David S. Miller + * Copyright (C) 2007, 2008 David S. Miller */ #include @@ -1217,7 +1217,7 @@ static int ds_remove(struct vio_dev *vdev) return 0; } -static struct vio_device_id ds_match[] = { +static struct vio_device_id __initdata ds_match[] = { { .type = "domain-services-port", }, -- cgit v1.2.3 From 687124dda0beeb8503ae27a1588e4705b3a588c2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 03:13:17 -0700 Subject: sparc64: Use ENTRY/ENDPROC in hypervisor asm. Signed-off-by: David S. Miller --- arch/sparc64/kernel/head.S | 1 + arch/sparc64/kernel/hvcalls.S | 354 ++++++++++++++---------------------------- 2 files changed, 119 insertions(+), 236 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index c9afef093d5..353226fa023 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc64/kernel/hvcalls.S index a2810f3ac70..e066269d159 100644 --- a/arch/sparc64/kernel/hvcalls.S +++ b/arch/sparc64/kernel/hvcalls.S @@ -3,89 +3,75 @@ * * returns %o0: sysino */ - .globl sun4v_devino_to_sysino - .type sun4v_devino_to_sysino,#function -sun4v_devino_to_sysino: +ENTRY(sun4v_devino_to_sysino) mov HV_FAST_INTR_DEVINO2SYSINO, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino +ENDPROC(sun4v_devino_to_sysino) /* %o0: sysino * * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) */ - .globl sun4v_intr_getenabled - .type sun4v_intr_getenabled,#function -sun4v_intr_getenabled: +ENTRY(sun4v_intr_getenabled) mov HV_FAST_INTR_GETENABLED, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_getenabled, .-sun4v_intr_getenabled +ENDPROC(sun4v_intr_getenabled) /* %o0: sysino * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) */ - .globl sun4v_intr_setenabled - .type sun4v_intr_setenabled,#function -sun4v_intr_setenabled: +ENTRY(sun4v_intr_setenabled) mov HV_FAST_INTR_SETENABLED, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_setenabled, .-sun4v_intr_setenabled +ENDPROC(sun4v_intr_setenabled) /* %o0: sysino * * returns %o0: intr_state (HV_INTR_STATE_*) */ - .globl sun4v_intr_getstate - .type sun4v_intr_getstate,#function -sun4v_intr_getstate: +ENTRY(sun4v_intr_getstate) mov HV_FAST_INTR_GETSTATE, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_getstate, .-sun4v_intr_getstate +ENDPROC(sun4v_intr_getstate) /* %o0: sysino * %o1: intr_state (HV_INTR_STATE_*) */ - .globl sun4v_intr_setstate - .type sun4v_intr_setstate,#function -sun4v_intr_setstate: +ENTRY(sun4v_intr_setstate) mov HV_FAST_INTR_SETSTATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_setstate, .-sun4v_intr_setstate +ENDPROC(sun4v_intr_setstate) /* %o0: sysino * * returns %o0: cpuid */ - .globl sun4v_intr_gettarget - .type sun4v_intr_gettarget,#function -sun4v_intr_gettarget: +ENTRY(sun4v_intr_gettarget) mov HV_FAST_INTR_GETTARGET, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 - .size sun4v_intr_gettarget, .-sun4v_intr_gettarget +ENDPROC(sun4v_intr_gettarget) /* %o0: sysino * %o1: cpuid */ - .globl sun4v_intr_settarget - .type sun4v_intr_settarget,#function -sun4v_intr_settarget: +ENTRY(sun4v_intr_settarget) mov HV_FAST_INTR_SETTARGET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_intr_settarget, .-sun4v_intr_settarget +ENDPROC(sun4v_intr_settarget) /* %o0: cpuid * %o1: pc @@ -94,37 +80,31 @@ sun4v_intr_settarget: * * returns %o0: status */ - .globl sun4v_cpu_start - .type sun4v_cpu_start,#function -sun4v_cpu_start: +ENTRY(sun4v_cpu_start) mov HV_FAST_CPU_START, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_start, .-sun4v_cpu_start +ENDPROC(sun4v_cpu_start) /* %o0: cpuid * * returns %o0: status */ - .globl sun4v_cpu_stop - .type sun4v_cpu_stop,#function -sun4v_cpu_stop: +ENTRY(sun4v_cpu_stop) mov HV_FAST_CPU_STOP, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_stop, .-sun4v_cpu_stop +ENDPROC(sun4v_cpu_stop) /* returns %o0: status */ - .globl sun4v_cpu_yield - .type sun4v_cpu_yield, #function -sun4v_cpu_yield: +ENTRY(sun4v_cpu_yield) mov HV_FAST_CPU_YIELD, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_yield, .-sun4v_cpu_yield +ENDPROC(sun4v_cpu_yield) /* %o0: type * %o1: queue paddr @@ -132,14 +112,12 @@ sun4v_cpu_yield: * * returns %o0: status */ - .globl sun4v_cpu_qconf - .type sun4v_cpu_qconf,#function -sun4v_cpu_qconf: +ENTRY(sun4v_cpu_qconf) mov HV_FAST_CPU_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_qconf, .-sun4v_cpu_qconf +ENDPROC(sun4v_cpu_qconf) /* %o0: num cpus in cpu list * %o1: cpu list paddr @@ -147,23 +125,19 @@ sun4v_cpu_qconf: * * returns %o0: status */ - .globl sun4v_cpu_mondo_send - .type sun4v_cpu_mondo_send,#function -sun4v_cpu_mondo_send: +ENTRY(sun4v_cpu_mondo_send) mov HV_FAST_CPU_MONDO_SEND, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send +ENDPROC(sun4v_cpu_mondo_send) /* %o0: CPU ID * * returns %o0: -status if status non-zero, else * %o0: cpu state as HV_CPU_STATE_* */ - .globl sun4v_cpu_state - .type sun4v_cpu_state,#function -sun4v_cpu_state: +ENTRY(sun4v_cpu_state) mov HV_FAST_CPU_STATE, %o5 ta HV_FAST_TRAP brnz,pn %o0, 1f @@ -171,7 +145,7 @@ sun4v_cpu_state: mov %o1, %o0 1: retl nop - .size sun4v_cpu_state, .-sun4v_cpu_state +ENDPROC(sun4v_cpu_state) /* %o0: virtual address * %o1: must be zero @@ -180,28 +154,24 @@ sun4v_cpu_state: * * returns %o0: status */ - .globl sun4v_mmu_map_perm_addr - .type sun4v_mmu_map_perm_addr,#function -sun4v_mmu_map_perm_addr: +ENTRY(sun4v_mmu_map_perm_addr) mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr +ENDPROC(sun4v_mmu_map_perm_addr) /* %o0: number of TSB descriptions * %o1: TSB descriptions real address * * returns %o0: status */ - .globl sun4v_mmu_tsb_ctx0 - .type sun4v_mmu_tsb_ctx0,#function -sun4v_mmu_tsb_ctx0: +ENTRY(sun4v_mmu_tsb_ctx0) mov HV_FAST_MMU_TSB_CTX0, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0 +ENDPROC(sun4v_mmu_tsb_ctx0) /* %o0: API group number * %o1: pointer to unsigned long major number storage @@ -209,9 +179,7 @@ sun4v_mmu_tsb_ctx0: * * returns %o0: status */ - .globl sun4v_get_version - .type sun4v_get_version,#function -sun4v_get_version: +ENTRY(sun4v_get_version) mov HV_CORE_GET_VER, %o5 mov %o1, %o3 mov %o2, %o4 @@ -219,7 +187,7 @@ sun4v_get_version: stx %o1, [%o3] retl stx %o2, [%o4] - .size sun4v_get_version, .-sun4v_get_version +ENDPROC(sun4v_get_version) /* %o0: API group number * %o1: desired major number @@ -228,51 +196,43 @@ sun4v_get_version: * * returns %o0: status */ - .globl sun4v_set_version - .type sun4v_set_version,#function -sun4v_set_version: +ENTRY(sun4v_set_version) mov HV_CORE_SET_VER, %o5 mov %o3, %o4 ta HV_CORE_TRAP retl stx %o1, [%o4] - .size sun4v_set_version, .-sun4v_set_version +ENDPROC(sun4v_set_version) /* %o0: pointer to unsigned long time * * returns %o0: status */ - .globl sun4v_tod_get - .type sun4v_tod_get,#function -sun4v_tod_get: +ENTRY(sun4v_tod_get) mov %o0, %o4 mov HV_FAST_TOD_GET, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_tod_get, .-sun4v_tod_get +ENDPROC(sun4v_tod_get) /* %o0: time * * returns %o0: status */ - .globl sun4v_tod_set - .type sun4v_tod_set,#function -sun4v_tod_set: +ENTRY(sun4v_tod_set) mov HV_FAST_TOD_SET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_tod_set, .-sun4v_tod_set +ENDPROC(sun4v_tod_set) /* %o0: pointer to unsigned long status * * returns %o0: signed character */ - .globl sun4v_con_getchar - .type sun4v_con_getchar,#function -sun4v_con_getchar: +ENTRY(sun4v_con_getchar) mov %o0, %o4 mov HV_FAST_CONS_GETCHAR, %o5 clr %o0 @@ -281,20 +241,18 @@ sun4v_con_getchar: stx %o0, [%o4] retl sra %o1, 0, %o0 - .size sun4v_con_getchar, .-sun4v_con_getchar +ENDPROC(sun4v_con_getchar) /* %o0: signed long character * * returns %o0: status */ - .globl sun4v_con_putchar - .type sun4v_con_putchar,#function -sun4v_con_putchar: +ENTRY(sun4v_con_putchar) mov HV_FAST_CONS_PUTCHAR, %o5 ta HV_FAST_TRAP retl sra %o0, 0, %o0 - .size sun4v_con_putchar, .-sun4v_con_putchar +ENDPROC(sun4v_con_putchar) /* %o0: buffer real address * %o1: buffer size @@ -302,9 +260,7 @@ sun4v_con_putchar: * * returns %o0: status */ - .globl sun4v_con_read - .type sun4v_con_read,#function -sun4v_con_read: +ENTRY(sun4v_con_read) mov %o2, %o4 mov HV_FAST_CONS_READ, %o5 ta HV_FAST_TRAP @@ -318,7 +274,7 @@ sun4v_con_read: stx %o1, [%o4] 1: retl nop - .size sun4v_con_read, .-sun4v_con_read +ENDPROC(sun4v_con_read) /* %o0: buffer real address * %o1: buffer size @@ -326,43 +282,37 @@ sun4v_con_read: * * returns %o0: status */ - .globl sun4v_con_write - .type sun4v_con_write,#function -sun4v_con_write: +ENTRY(sun4v_con_write) mov %o2, %o4 mov HV_FAST_CONS_WRITE, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_con_write, .-sun4v_con_write +ENDPROC(sun4v_con_write) /* %o0: soft state * %o1: address of description string * * returns %o0: status */ - .globl sun4v_mach_set_soft_state - .type sun4v_mach_set_soft_state,#function -sun4v_mach_set_soft_state: +ENTRY(sun4v_mach_set_soft_state) mov HV_FAST_MACH_SET_SOFT_STATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state +ENDPROC(sun4v_mach_set_soft_state) /* %o0: exit code * * Does not return. */ - .globl sun4v_mach_exit - .type sun4v_mach_exit,#function -sun4v_mach_exit: +ENTRY(sun4v_mach_exit) mov HV_FAST_MACH_EXIT, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_mach_exit, .-sun4v_mach_exit +ENDPROC(sun4v_mach_exit) /* %o0: buffer real address * %o1: buffer length @@ -370,44 +320,38 @@ sun4v_mach_exit: * * returns %o0: status */ - .globl sun4v_mach_desc - .type sun4v_mach_desc,#function -sun4v_mach_desc: +ENTRY(sun4v_mach_desc) mov %o2, %o4 mov HV_FAST_MACH_DESC, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_desc, .-sun4v_mach_desc +ENDPROC(sun4v_mach_desc) /* %o0: new timeout in milliseconds * %o1: pointer to unsigned long orig_timeout * * returns %o0: status */ - .globl sun4v_mach_set_watchdog - .type sun4v_mach_set_watchdog,#function -sun4v_mach_set_watchdog: +ENTRY(sun4v_mach_set_watchdog) mov %o1, %o4 mov HV_FAST_MACH_SET_WATCHDOG, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog +ENDPROC(sun4v_mach_set_watchdog) /* No inputs and does not return. */ - .globl sun4v_mach_sir - .type sun4v_mach_sir,#function -sun4v_mach_sir: +ENTRY(sun4v_mach_sir) mov %o1, %o4 mov HV_FAST_MACH_SIR, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mach_sir, .-sun4v_mach_sir +ENDPROC(sun4v_mach_sir) /* %o0: channel * %o1: ra @@ -415,14 +359,12 @@ sun4v_mach_sir: * * returns %o0: status */ - .globl sun4v_ldc_tx_qconf - .type sun4v_ldc_tx_qconf,#function -sun4v_ldc_tx_qconf: +ENTRY(sun4v_ldc_tx_qconf) mov HV_FAST_LDC_TX_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf +ENDPROC(sun4v_ldc_tx_qconf) /* %o0: channel * %o1: pointer to unsigned long ra @@ -430,9 +372,7 @@ sun4v_ldc_tx_qconf: * * returns %o0: status */ - .globl sun4v_ldc_tx_qinfo - .type sun4v_ldc_tx_qinfo,#function -sun4v_ldc_tx_qinfo: +ENTRY(sun4v_ldc_tx_qinfo) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_TX_QINFO, %o5 @@ -441,7 +381,7 @@ sun4v_ldc_tx_qinfo: stx %o2, [%g2] retl nop - .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo +ENDPROC(sun4v_ldc_tx_qinfo) /* %o0: channel * %o1: pointer to unsigned long head_off @@ -450,9 +390,7 @@ sun4v_ldc_tx_qinfo: * * returns %o0: status */ - .globl sun4v_ldc_tx_get_state - .type sun4v_ldc_tx_get_state,#function -sun4v_ldc_tx_get_state: +ENTRY(sun4v_ldc_tx_get_state) mov %o1, %g1 mov %o2, %g2 mov %o3, %g3 @@ -463,21 +401,19 @@ sun4v_ldc_tx_get_state: stx %o3, [%g3] retl nop - .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state +ENDPROC(sun4v_ldc_tx_get_state) /* %o0: channel * %o1: tail_off * * returns %o0: status */ - .globl sun4v_ldc_tx_set_qtail - .type sun4v_ldc_tx_set_qtail,#function -sun4v_ldc_tx_set_qtail: +ENTRY(sun4v_ldc_tx_set_qtail) mov HV_FAST_LDC_TX_SET_QTAIL, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail +ENDPROC(sun4v_ldc_tx_set_qtail) /* %o0: channel * %o1: ra @@ -485,14 +421,12 @@ sun4v_ldc_tx_set_qtail: * * returns %o0: status */ - .globl sun4v_ldc_rx_qconf - .type sun4v_ldc_rx_qconf,#function -sun4v_ldc_rx_qconf: +ENTRY(sun4v_ldc_rx_qconf) mov HV_FAST_LDC_RX_QCONF, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf +ENDPROC(sun4v_ldc_rx_qconf) /* %o0: channel * %o1: pointer to unsigned long ra @@ -500,9 +434,7 @@ sun4v_ldc_rx_qconf: * * returns %o0: status */ - .globl sun4v_ldc_rx_qinfo - .type sun4v_ldc_rx_qinfo,#function -sun4v_ldc_rx_qinfo: +ENTRY(sun4v_ldc_rx_qinfo) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_RX_QINFO, %o5 @@ -511,7 +443,7 @@ sun4v_ldc_rx_qinfo: stx %o2, [%g2] retl nop - .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo +ENDPROC(sun4v_ldc_rx_qinfo) /* %o0: channel * %o1: pointer to unsigned long head_off @@ -520,9 +452,7 @@ sun4v_ldc_rx_qinfo: * * returns %o0: status */ - .globl sun4v_ldc_rx_get_state - .type sun4v_ldc_rx_get_state,#function -sun4v_ldc_rx_get_state: +ENTRY(sun4v_ldc_rx_get_state) mov %o1, %g1 mov %o2, %g2 mov %o3, %g3 @@ -533,21 +463,19 @@ sun4v_ldc_rx_get_state: stx %o3, [%g3] retl nop - .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state +ENDPROC(sun4v_ldc_rx_get_state) /* %o0: channel * %o1: head_off * * returns %o0: status */ - .globl sun4v_ldc_rx_set_qhead - .type sun4v_ldc_rx_set_qhead,#function -sun4v_ldc_rx_set_qhead: +ENTRY(sun4v_ldc_rx_set_qhead) mov HV_FAST_LDC_RX_SET_QHEAD, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead +ENDPROC(sun4v_ldc_rx_set_qhead) /* %o0: channel * %o1: ra @@ -555,14 +483,12 @@ sun4v_ldc_rx_set_qhead: * * returns %o0: status */ - .globl sun4v_ldc_set_map_table - .type sun4v_ldc_set_map_table,#function -sun4v_ldc_set_map_table: +ENTRY(sun4v_ldc_set_map_table) mov HV_FAST_LDC_SET_MAP_TABLE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table +ENDPROC(sun4v_ldc_set_map_table) /* %o0: channel * %o1: pointer to unsigned long ra @@ -570,9 +496,7 @@ sun4v_ldc_set_map_table: * * returns %o0: status */ - .globl sun4v_ldc_get_map_table - .type sun4v_ldc_get_map_table,#function -sun4v_ldc_get_map_table: +ENTRY(sun4v_ldc_get_map_table) mov %o1, %g1 mov %o2, %g2 mov HV_FAST_LDC_GET_MAP_TABLE, %o5 @@ -581,7 +505,7 @@ sun4v_ldc_get_map_table: stx %o2, [%g2] retl nop - .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table +ENDPROC(sun4v_ldc_get_map_table) /* %o0: channel * %o1: dir_code @@ -592,16 +516,14 @@ sun4v_ldc_get_map_table: * * returns %o0: status */ - .globl sun4v_ldc_copy - .type sun4v_ldc_copy,#function -sun4v_ldc_copy: +ENTRY(sun4v_ldc_copy) mov %o5, %g1 mov HV_FAST_LDC_COPY, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_ldc_copy, .-sun4v_ldc_copy +ENDPROC(sun4v_ldc_copy) /* %o0: channel * %o1: cookie @@ -610,9 +532,7 @@ sun4v_ldc_copy: * * returns %o0: status */ - .globl sun4v_ldc_mapin - .type sun4v_ldc_mapin,#function -sun4v_ldc_mapin: +ENTRY(sun4v_ldc_mapin) mov %o2, %g1 mov %o3, %g2 mov HV_FAST_LDC_MAPIN, %o5 @@ -621,20 +541,18 @@ sun4v_ldc_mapin: stx %o2, [%g2] retl nop - .size sun4v_ldc_mapin, .-sun4v_ldc_mapin +ENDPROC(sun4v_ldc_mapin) /* %o0: ra * * returns %o0: status */ - .globl sun4v_ldc_unmap - .type sun4v_ldc_unmap,#function -sun4v_ldc_unmap: +ENTRY(sun4v_ldc_unmap) mov HV_FAST_LDC_UNMAP, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_unmap, .-sun4v_ldc_unmap +ENDPROC(sun4v_ldc_unmap) /* %o0: channel * %o1: cookie @@ -642,14 +560,12 @@ sun4v_ldc_unmap: * * returns %o0: status */ - .globl sun4v_ldc_revoke - .type sun4v_ldc_revoke,#function -sun4v_ldc_revoke: +ENTRY(sun4v_ldc_revoke) mov HV_FAST_LDC_REVOKE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ldc_revoke, .-sun4v_ldc_revoke +ENDPROC(sun4v_ldc_revoke) /* %o0: device handle * %o1: device INO @@ -657,16 +573,14 @@ sun4v_ldc_revoke: * * returns %o0: status */ - .globl sun4v_vintr_get_cookie - .type sun4v_vintr_get_cookie,#function -sun4v_vintr_get_cookie: +ENTRY(sun4v_vintr_get_cookie) mov %o2, %g1 mov HV_FAST_VINTR_GET_COOKIE, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie +ENDPROC(sun4v_vintr_get_cookie) /* %o0: device handle * %o1: device INO @@ -674,14 +588,12 @@ sun4v_vintr_get_cookie: * * returns %o0: status */ - .globl sun4v_vintr_set_cookie - .type sun4v_vintr_set_cookie,#function -sun4v_vintr_set_cookie: +ENTRY(sun4v_vintr_set_cookie) mov HV_FAST_VINTR_SET_COOKIE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie +ENDPROC(sun4v_vintr_set_cookie) /* %o0: device handle * %o1: device INO @@ -689,16 +601,14 @@ sun4v_vintr_set_cookie: * * returns %o0: status */ - .globl sun4v_vintr_get_valid - .type sun4v_vintr_get_valid,#function -sun4v_vintr_get_valid: +ENTRY(sun4v_vintr_get_valid) mov %o2, %g1 mov HV_FAST_VINTR_GET_VALID, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid +ENDPROC(sun4v_vintr_get_valid) /* %o0: device handle * %o1: device INO @@ -706,14 +616,12 @@ sun4v_vintr_get_valid: * * returns %o0: status */ - .globl sun4v_vintr_set_valid - .type sun4v_vintr_set_valid,#function -sun4v_vintr_set_valid: +ENTRY(sun4v_vintr_set_valid) mov HV_FAST_VINTR_SET_VALID, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid +ENDPROC(sun4v_vintr_set_valid) /* %o0: device handle * %o1: device INO @@ -721,16 +629,14 @@ sun4v_vintr_set_valid: * * returns %o0: status */ - .globl sun4v_vintr_get_state - .type sun4v_vintr_get_state,#function -sun4v_vintr_get_state: +ENTRY(sun4v_vintr_get_state) mov %o2, %g1 mov HV_FAST_VINTR_GET_STATE, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_state, .-sun4v_vintr_get_state +ENDPROC(sun4v_vintr_get_state) /* %o0: device handle * %o1: device INO @@ -738,14 +644,12 @@ sun4v_vintr_get_state: * * returns %o0: status */ - .globl sun4v_vintr_set_state - .type sun4v_vintr_set_state,#function -sun4v_vintr_set_state: +ENTRY(sun4v_vintr_set_state) mov HV_FAST_VINTR_SET_STATE, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_state, .-sun4v_vintr_set_state +ENDPROC(sun4v_vintr_set_state) /* %o0: device handle * %o1: device INO @@ -753,16 +657,14 @@ sun4v_vintr_set_state: * * returns %o0: status */ - .globl sun4v_vintr_get_target - .type sun4v_vintr_get_target,#function -sun4v_vintr_get_target: +ENTRY(sun4v_vintr_get_target) mov %o2, %g1 mov HV_FAST_VINTR_GET_TARGET, %o5 ta HV_FAST_TRAP stx %o1, [%g1] retl nop - .size sun4v_vintr_get_target, .-sun4v_vintr_get_target +ENDPROC(sun4v_vintr_get_target) /* %o0: device handle * %o1: device INO @@ -770,14 +672,12 @@ sun4v_vintr_get_target: * * returns %o0: status */ - .globl sun4v_vintr_set_target - .type sun4v_vintr_set_target,#function -sun4v_vintr_set_target: +ENTRY(sun4v_vintr_set_target) mov HV_FAST_VINTR_SET_TARGET, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_vintr_set_target, .-sun4v_vintr_set_target +ENDPROC(sun4v_vintr_set_target) /* %o0: NCS sub-function * %o1: sub-function arg real-address @@ -785,18 +685,14 @@ sun4v_vintr_set_target: * * returns %o0: status */ - .globl sun4v_ncs_request - .type sun4v_ncs_request,#function -sun4v_ncs_request: +ENTRY(sun4v_ncs_request) mov HV_FAST_NCS_REQUEST, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_ncs_request, .-sun4v_ncs_request +ENDPROC(sun4v_ncs_request) - .globl sun4v_svc_send - .type sun4v_svc_send,#function -sun4v_svc_send: +ENTRY(sun4v_svc_send) save %sp, -192, %sp mov %i0, %o0 mov %i1, %o1 @@ -806,11 +702,9 @@ sun4v_svc_send: stx %o1, [%i3] ret restore - .size sun4v_svc_send, .-sun4v_svc_send +ENDPROC(sun4v_svc_send) - .globl sun4v_svc_recv - .type sun4v_svc_recv,#function -sun4v_svc_recv: +ENTRY(sun4v_svc_recv) save %sp, -192, %sp mov %i0, %o0 mov %i1, %o1 @@ -820,62 +714,50 @@ sun4v_svc_recv: stx %o1, [%i3] ret restore - .size sun4v_svc_recv, .-sun4v_svc_recv +ENDPROC(sun4v_svc_recv) - .globl sun4v_svc_getstatus - .type sun4v_svc_getstatus,#function -sun4v_svc_getstatus: +ENTRY(sun4v_svc_getstatus) mov HV_FAST_SVC_GETSTATUS, %o5 mov %o1, %o4 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_svc_getstatus, .-sun4v_svc_getstatus +ENDPROC(sun4v_svc_getstatus) - .globl sun4v_svc_setstatus - .type sun4v_svc_setstatus,#function -sun4v_svc_setstatus: +ENTRY(sun4v_svc_setstatus) mov HV_FAST_SVC_SETSTATUS, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_svc_setstatus, .-sun4v_svc_setstatus +ENDPROC(sun4v_svc_setstatus) - .globl sun4v_svc_clrstatus - .type sun4v_svc_clrstatus,#function -sun4v_svc_clrstatus: +ENTRY(sun4v_svc_clrstatus) mov HV_FAST_SVC_CLRSTATUS, %o5 ta HV_FAST_TRAP retl nop - .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus +ENDPROC(sun4v_svc_clrstatus) - .globl sun4v_mmustat_conf - .type sun4v_mmustat_conf,#function -sun4v_mmustat_conf: +ENTRY(sun4v_mmustat_conf) mov %o1, %o4 mov HV_FAST_MMUSTAT_CONF, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mmustat_conf, .-sun4v_mmustat_conf +ENDPROC(sun4v_mmustat_conf) - .globl sun4v_mmustat_info - .type sun4v_mmustat_info,#function -sun4v_mmustat_info: +ENTRY(sun4v_mmustat_info) mov %o0, %o4 mov HV_FAST_MMUSTAT_INFO, %o5 ta HV_FAST_TRAP stx %o1, [%o4] retl nop - .size sun4v_mmustat_info, .-sun4v_mmustat_info +ENDPROC(sun4v_mmustat_info) - .globl sun4v_mmu_demap_all - .type sun4v_mmu_demap_all,#function -sun4v_mmu_demap_all: +ENTRY(sun4v_mmu_demap_all) clr %o0 clr %o1 mov HV_MMU_ALL, %o2 @@ -883,4 +765,4 @@ sun4v_mmu_demap_all: ta HV_FAST_TRAP retl nop - .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all +ENDPROC(sun4v_mmu_demap_all) -- cgit v1.2.3 From fefbbc73cac6f7360460cee45e3d4cc209d8d607 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 03:18:49 -0700 Subject: sparc64: Use ENTRY/ENDPROC in PCI SUN4V asm. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v_asm.S | 99 +++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 49 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S index ecb81f389b0..e606d46c681 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc64/kernel/pci_sun4v_asm.S @@ -1,8 +1,9 @@ /* pci_sun4v_asm: Hypervisor calls for PCI support. * - * Copyright (C) 2006 David S. Miller + * Copyright (C) 2006, 2008 David S. Miller */ +#include #include /* %o0: devhandle @@ -14,8 +15,7 @@ * returns %o0: -status if status was non-zero, else * %o0: num pages mapped */ - .globl pci_sun4v_iommu_map -pci_sun4v_iommu_map: +ENTRY(pci_sun4v_iommu_map) mov %o5, %g1 mov HV_FAST_PCI_IOMMU_MAP, %o5 ta HV_FAST_TRAP @@ -24,6 +24,7 @@ pci_sun4v_iommu_map: mov %o1, %o0 1: retl nop +ENDPROC(pci_sun4v_iommu_map) /* %o0: devhandle * %o1: tsbid @@ -31,12 +32,12 @@ pci_sun4v_iommu_map: * * returns %o0: num ttes demapped */ - .globl pci_sun4v_iommu_demap -pci_sun4v_iommu_demap: +ENTRY(pci_sun4v_iommu_demap) mov HV_FAST_PCI_IOMMU_DEMAP, %o5 ta HV_FAST_TRAP retl mov %o1, %o0 +ENDPROC(pci_sun4v_iommu_demap) /* %o0: devhandle * %o1: tsbid @@ -45,8 +46,7 @@ pci_sun4v_iommu_demap: * * returns %o0: status */ - .globl pci_sun4v_iommu_getmap -pci_sun4v_iommu_getmap: +ENTRY(pci_sun4v_iommu_getmap) mov %o2, %o4 mov HV_FAST_PCI_IOMMU_GETMAP, %o5 ta HV_FAST_TRAP @@ -54,6 +54,7 @@ pci_sun4v_iommu_getmap: stx %o2, [%o3] retl mov %o0, %o0 +ENDPROC(pci_sun4v_iommu_getmap) /* %o0: devhandle * %o1: pci_device @@ -65,14 +66,14 @@ pci_sun4v_iommu_getmap: * If there is an error, the data will be returned * as all 1's. */ - .globl pci_sun4v_config_get -pci_sun4v_config_get: +ENTRY(pci_sun4v_config_get) mov HV_FAST_PCI_CONFIG_GET, %o5 ta HV_FAST_TRAP brnz,a,pn %o1, 1f mov -1, %o2 1: retl mov %o2, %o0 +ENDPROC(pci_sun4v_config_get) /* %o0: devhandle * %o1: pci_device @@ -85,14 +86,14 @@ pci_sun4v_config_get: * status will be zero if the operation completed * successfully, else -1 if not */ - .globl pci_sun4v_config_put -pci_sun4v_config_put: +ENTRY(pci_sun4v_config_put) mov HV_FAST_PCI_CONFIG_PUT, %o5 ta HV_FAST_TRAP brnz,a,pn %o1, 1f mov -1, %o1 1: retl mov %o1, %o0 +ENDPROC(pci_sun4v_config_put) /* %o0: devhandle * %o1: msiqid @@ -104,12 +105,12 @@ pci_sun4v_config_put: * status will be zero if the operation completed * successfully, else -1 if not */ - .globl pci_sun4v_msiq_conf -pci_sun4v_msiq_conf: +ENTRY(pci_sun4v_msiq_conf) mov HV_FAST_PCI_MSIQ_CONF, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_conf) /* %o0: devhandle * %o1: msiqid @@ -118,8 +119,7 @@ pci_sun4v_msiq_conf: * * returns %o0: status */ - .globl pci_sun4v_msiq_info -pci_sun4v_msiq_info: +ENTRY(pci_sun4v_msiq_info) mov %o2, %o4 mov HV_FAST_PCI_MSIQ_INFO, %o5 ta HV_FAST_TRAP @@ -127,6 +127,7 @@ pci_sun4v_msiq_info: stx %o2, [%o3] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_info) /* %o0: devhandle * %o1: msiqid @@ -134,13 +135,13 @@ pci_sun4v_msiq_info: * * returns %o0: status */ - .globl pci_sun4v_msiq_getvalid -pci_sun4v_msiq_getvalid: +ENTRY(pci_sun4v_msiq_getvalid) mov HV_FAST_PCI_MSIQ_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_getvalid) /* %o0: devhandle * %o1: msiqid @@ -148,12 +149,12 @@ pci_sun4v_msiq_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msiq_setvalid -pci_sun4v_msiq_setvalid: +ENTRY(pci_sun4v_msiq_setvalid) mov HV_FAST_PCI_MSIQ_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_setvalid) /* %o0: devhandle * %o1: msiqid @@ -161,13 +162,13 @@ pci_sun4v_msiq_setvalid: * * returns %o0: status */ - .globl pci_sun4v_msiq_getstate -pci_sun4v_msiq_getstate: +ENTRY(pci_sun4v_msiq_getstate) mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_getstate) /* %o0: devhandle * %o1: msiqid @@ -175,12 +176,12 @@ pci_sun4v_msiq_getstate: * * returns %o0: status */ - .globl pci_sun4v_msiq_setstate -pci_sun4v_msiq_setstate: +ENTRY(pci_sun4v_msiq_setstate) mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_setstate) /* %o0: devhandle * %o1: msiqid @@ -188,13 +189,13 @@ pci_sun4v_msiq_setstate: * * returns %o0: status */ - .globl pci_sun4v_msiq_gethead -pci_sun4v_msiq_gethead: +ENTRY(pci_sun4v_msiq_gethead) mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_gethead) /* %o0: devhandle * %o1: msiqid @@ -202,12 +203,12 @@ pci_sun4v_msiq_gethead: * * returns %o0: status */ - .globl pci_sun4v_msiq_sethead -pci_sun4v_msiq_sethead: +ENTRY(pci_sun4v_msiq_sethead) mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_sethead) /* %o0: devhandle * %o1: msiqid @@ -215,13 +216,13 @@ pci_sun4v_msiq_sethead: * * returns %o0: status */ - .globl pci_sun4v_msiq_gettail -pci_sun4v_msiq_gettail: +ENTRY(pci_sun4v_msiq_gettail) mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msiq_gettail) /* %o0: devhandle * %o1: msinum @@ -229,13 +230,13 @@ pci_sun4v_msiq_gettail: * * returns %o0: status */ - .globl pci_sun4v_msi_getvalid -pci_sun4v_msi_getvalid: +ENTRY(pci_sun4v_msi_getvalid) mov HV_FAST_PCI_MSI_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getvalid) /* %o0: devhandle * %o1: msinum @@ -243,12 +244,12 @@ pci_sun4v_msi_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msi_setvalid -pci_sun4v_msi_setvalid: +ENTRY(pci_sun4v_msi_setvalid) mov HV_FAST_PCI_MSI_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setvalid) /* %o0: devhandle * %o1: msinum @@ -256,13 +257,13 @@ pci_sun4v_msi_setvalid: * * returns %o0: status */ - .globl pci_sun4v_msi_getmsiq -pci_sun4v_msi_getmsiq: +ENTRY(pci_sun4v_msi_getmsiq) mov HV_FAST_PCI_MSI_GETMSIQ, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getmsiq) /* %o0: devhandle * %o1: msinum @@ -271,12 +272,12 @@ pci_sun4v_msi_getmsiq: * * returns %o0: status */ - .globl pci_sun4v_msi_setmsiq -pci_sun4v_msi_setmsiq: +ENTRY(pci_sun4v_msi_setmsiq) mov HV_FAST_PCI_MSI_SETMSIQ, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setmsiq) /* %o0: devhandle * %o1: msinum @@ -284,13 +285,13 @@ pci_sun4v_msi_setmsiq: * * returns %o0: status */ - .globl pci_sun4v_msi_getstate -pci_sun4v_msi_getstate: +ENTRY(pci_sun4v_msi_getstate) mov HV_FAST_PCI_MSI_GETSTATE, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_getstate) /* %o0: devhandle * %o1: msinum @@ -298,12 +299,12 @@ pci_sun4v_msi_getstate: * * returns %o0: status */ - .globl pci_sun4v_msi_setstate -pci_sun4v_msi_setstate: +ENTRY(pci_sun4v_msi_setstate) mov HV_FAST_PCI_MSI_SETSTATE, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msi_setstate) /* %o0: devhandle * %o1: msinum @@ -311,13 +312,13 @@ pci_sun4v_msi_setstate: * * returns %o0: status */ - .globl pci_sun4v_msg_getmsiq -pci_sun4v_msg_getmsiq: +ENTRY(pci_sun4v_msg_getmsiq) mov HV_FAST_PCI_MSG_GETMSIQ, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_getmsiq) /* %o0: devhandle * %o1: msinum @@ -325,12 +326,12 @@ pci_sun4v_msg_getmsiq: * * returns %o0: status */ - .globl pci_sun4v_msg_setmsiq -pci_sun4v_msg_setmsiq: +ENTRY(pci_sun4v_msg_setmsiq) mov HV_FAST_PCI_MSG_SETMSIQ, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_setmsiq) /* %o0: devhandle * %o1: msinum @@ -338,13 +339,13 @@ pci_sun4v_msg_setmsiq: * * returns %o0: status */ - .globl pci_sun4v_msg_getvalid -pci_sun4v_msg_getvalid: +ENTRY(pci_sun4v_msg_getvalid) mov HV_FAST_PCI_MSG_GETVALID, %o5 ta HV_FAST_TRAP stx %o1, [%o2] retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_getvalid) /* %o0: devhandle * %o1: msinum @@ -352,10 +353,10 @@ pci_sun4v_msg_getvalid: * * returns %o0: status */ - .globl pci_sun4v_msg_setvalid -pci_sun4v_msg_setvalid: +ENTRY(pci_sun4v_msg_setvalid) mov HV_FAST_PCI_MSG_SETVALID, %o5 ta HV_FAST_TRAP retl mov %o0, %o0 +ENDPROC(pci_sun4v_msg_setvalid) -- cgit v1.2.3 From 7cc288add44c392dfc8c1dbf0e3a26a69a14fa70 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 18:32:13 -0700 Subject: sparc64: Kill the scan_bus function pointer in struct pci_pbm_info. No longer used. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c385d126be1..4125f7513c6 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -146,7 +146,6 @@ struct pci_pbm_info { unsigned int pci_first_busno; unsigned int pci_last_busno; struct pci_bus *pci_bus; - void (*scan_bus)(struct pci_pbm_info *); struct pci_ops *pci_ops; int numa_node; @@ -164,7 +163,8 @@ extern int pci_num_pbms; /* PCI bus scanning and fixup support. */ extern void pci_get_pbm_props(struct pci_pbm_info *pbm); -extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); +extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, + struct device *parent); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); /* Error reporting support. */ -- cgit v1.2.3 From e822358ac24550d889895d5866797ae8c9b188c2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 18:32:22 -0700 Subject: sparc64: Pass proper parent device down into root pci_create_bus() call. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 6 +++--- arch/sparc64/kernel/pci_fire.c | 18 +++++++----------- arch/sparc64/kernel/pci_psycho.c | 14 ++++++++------ arch/sparc64/kernel/pci_sabre.c | 13 ++++++++----- arch/sparc64/kernel/pci_schizo.c | 19 +++++++++++-------- arch/sparc64/kernel/pci_sun4v.c | 14 ++++++++------ 6 files changed, 45 insertions(+), 39 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 2da32e4c985..8e18fdf32a6 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -673,15 +673,15 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) pci_bus_register_of_sysfs(child_bus); } -struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) +struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, + struct device *parent) { struct device_node *node = pbm->prom_node; struct pci_bus *bus; printk("PCI: Scanning PBM %s\n", node->full_name); - /* XXX parent device? XXX */ - bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); + bus = pci_create_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm); if (!bus) { printk(KERN_ERR "Failed to create bus for %s\n", node->full_name); diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 4fb1ef92cb1..1b44153f907 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -33,13 +33,6 @@ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory") -static void __init pci_fire_scan_bus(struct pci_pbm_info *pbm) -{ - pbm->pci_bus = pci_scan_one_pbm(pbm); - - /* XXX register error interrupt handlers XXX */ -} - #define FIRE_IOMMU_CONTROL 0x40000UL #define FIRE_IOMMU_TSBBASE 0x40008UL #define FIRE_IOMMU_FLUSH 0x40100UL @@ -439,9 +432,10 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) } static int __init pci_fire_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid) + struct of_device *op, u32 portid) { const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; struct pci_pbm_info *pbm; int err; @@ -483,7 +477,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pci_fire_msi_init(pbm); - pci_fire_scan_bus(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, &op->dev); + + /* XXX register error interrupt handlers XXX */ return 0; } @@ -508,7 +504,7 @@ static int __devinit fire_probe(struct of_device *op, portid = of_getintprop_default(dp, "portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid)) - return pci_fire_pbm_init(pbm->parent, dp, portid); + return pci_fire_pbm_init(pbm->parent, op, portid); } err = -ENOMEM; @@ -534,7 +530,7 @@ static int __devinit fire_probe(struct of_device *op, p->pbm_B.iommu = iommu; - return pci_fire_pbm_init(p, dp, portid); + return pci_fire_pbm_init(p, op, portid); out_free_iommu_A: kfree(p->pbm_A.iommu); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 5ee84c5b963..47db875d023 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -803,11 +803,12 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __init psycho_scan_bus(struct pci_pbm_info *pbm) +static void __init psycho_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = 0; - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); /* After the PCI bus scan is complete, we can register * the error interrupt handlers. @@ -971,8 +972,9 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL static void __init psycho_pbm_init(struct pci_controller_info *p, - struct device_node *dp, int is_pbm_a) + struct of_device *op, int is_pbm_a) { + struct device_node *dp = op->node; struct property *prop; struct pci_pbm_info *pbm; @@ -1015,7 +1017,7 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, psycho_pbm_strbuf_init(pbm, is_pbm_a); - psycho_scan_bus(pbm); + psycho_scan_bus(pbm, &op->dev); } #define PSYCHO_CONFIGSPACE 0x001000000UL @@ -1042,7 +1044,7 @@ static int __devinit psycho_probe(struct of_device *op, if (p->pbm_A.portid == upa_portid) { is_pbm_a = (p->pbm_A.prom_node == NULL); - psycho_pbm_init(p, dp, is_pbm_a); + psycho_pbm_init(p, op, is_pbm_a); return 0; } } @@ -1086,7 +1088,7 @@ static int __devinit psycho_probe(struct of_device *op, is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); - psycho_pbm_init(p, dp, is_pbm_a); + psycho_pbm_init(p, op, is_pbm_a); return 0; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index eee8fdca382..707d6d6130f 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -634,7 +634,8 @@ static void apb_init(struct pci_bus *sabre_bus) } } -static void __init sabre_scan_bus(struct pci_pbm_info *pbm) +static void __init sabre_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { static int once; @@ -662,7 +663,7 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) } once++; - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); if (!pbm->pci_bus) return; @@ -734,8 +735,10 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, } static void __init sabre_pbm_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, struct device_node *dp) + struct pci_pbm_info *pbm, struct of_device *op) { + struct device_node *dp = op->node; + pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); @@ -753,7 +756,7 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pci_determine_mem_io_space(pbm); - sabre_scan_bus(pbm); + sabre_scan_bus(pbm, &op->dev); } static int __devinit sabre_probe(struct of_device *op, @@ -873,7 +876,7 @@ static int __devinit sabre_probe(struct of_device *op, /* * Look for APB underneath. */ - sabre_pbm_init(p, pbm, dp); + sabre_pbm_init(p, pbm, op); return 0; out_free_iommu: diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index bd7612aae17..64904b180f4 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1085,14 +1085,15 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) pci_config_write8(addr, 64); } -static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm) +static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = (of_find_property(pbm->prom_node, "66mhz-capable", NULL) != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) tomatillo_register_error_handlers(pbm); @@ -1338,10 +1339,11 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } static int __devinit schizo_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 portid, + struct of_device *op, u32 portid, int chip_type) { const struct linux_prom64_registers *regs; + struct device_node *dp = op->node; struct pci_pbm_info *pbm; const char *chipset_name; int is_pbm_a, err; @@ -1422,7 +1424,7 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, schizo_pbm_strbuf_init(pbm); - schizo_scan_bus(pbm); + schizo_scan_bus(pbm, &op->dev); return 0; } @@ -1437,8 +1439,9 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } -static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_type) +static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) { + struct device_node *dp = op->node; struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; @@ -1450,7 +1453,7 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty err = -ENOMEM; for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (portid_compare(pbm->portid, portid, chip_type)) { - if (schizo_pbm_init(pbm->parent, dp, + if (schizo_pbm_init(pbm->parent, op, portid, chip_type)) goto out_err; return 0; @@ -1479,7 +1482,7 @@ static int __devinit __schizo_init(struct device_node *dp, unsigned long chip_ty p->pbm_B.iommu = iommu; - if (schizo_pbm_init(p, dp, portid, chip_type)) + if (schizo_pbm_init(p, op, portid, chip_type)) goto out_free_iommu_B; return 0; @@ -1500,7 +1503,7 @@ out_err: static int __devinit schizo_probe(struct of_device *op, const struct of_device_id *match) { - return __schizo_init(op->node, (unsigned long) match->data); + return __schizo_init(op, (unsigned long) match->data); } /* The ordering of this table is very important. Some Tomatillo diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 21864f06532..4839c503c88 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -543,7 +543,8 @@ static const struct dma_ops sun4v_dma_ops = { .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, }; -static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) +static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, + struct device *parent) { struct property *prop; struct device_node *dp; @@ -551,7 +552,7 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) dp = pbm->prom_node; prop = of_find_property(dp, "66mhz-capable", NULL); pbm->is_66mhz_capable = (prop != NULL); - pbm->pci_bus = pci_scan_one_pbm(pbm); + pbm->pci_bus = pci_scan_one_pbm(pbm, parent); /* XXX register error interrupt handlers XXX */ } @@ -894,8 +895,9 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) #endif /* !(CONFIG_PCI_MSI) */ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, - struct device_node *dp, u32 devhandle) + struct of_device *op, u32 devhandle) { + struct device_node *dp = op->node; struct pci_pbm_info *pbm; int err; @@ -934,7 +936,7 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_sun4v_msi_init(pbm); - pci_sun4v_scan_bus(pbm); + pci_sun4v_scan_bus(pbm, &op->dev); return 0; } @@ -979,7 +981,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { if (pbm->devhandle == (devhandle ^ 0x40)) { - return pci_sun4v_pbm_init(pbm->parent, dp, devhandle); + return pci_sun4v_pbm_init(pbm->parent, op, devhandle); } } @@ -1015,7 +1017,7 @@ static int __devinit pci_sun4v_probe(struct of_device *op, p->pbm_B.iommu = iommu; - return pci_sun4v_pbm_init(p, dp, devhandle); + return pci_sun4v_pbm_init(p, op, devhandle); out_free_iommu_A: kfree(p->pbm_A.iommu); -- cgit v1.2.3 From cdb3592a20b41377a28a0737dc9af95e53024470 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 19:31:16 -0700 Subject: sparc64: Move reboot handling into seperate file and kill power reg programming. We should always use prom_power_off(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/power.c | 37 ---------------------------- arch/sparc64/kernel/process.c | 33 ------------------------- arch/sparc64/kernel/reboot.c | 56 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 71 deletions(-) create mode 100644 arch/sparc64/kernel/reboot.c (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 928aa7c8058..fb02807167e 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -7,7 +7,7 @@ EXTRA_CFLAGS := -Werror extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o setup.o cpu.o idprom.o \ +obj-y := process.o setup.o cpu.o idprom.o reboot.o \ traps.o auxio.o una_asm.o sysfs.o iommu.o \ irq.o ptrace.o time.o sys_sparc.o signal.o \ unaligned.o central.o starfire.o \ diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 7559ad395a3..076cad7f975 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -7,21 +7,11 @@ #include #include #include -#include #include #include -#include #include #include -#include -#include - -/* - * sysctl - toggle power-off restriction for serial console - * systems in machine_power_off() - */ -int scons_pwroff = 1; static void __iomem *power_reg; @@ -33,31 +23,6 @@ static irqreturn_t power_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void (*poweroff_method)(void) = machine_alt_power_off; - -void machine_power_off(void) -{ - sstate_poweroff(); - if (strcmp(of_console_device->type, "serial") || scons_pwroff) { - if (power_reg) { - /* Both register bits seem to have the - * same effect, so until I figure out - * what the difference is... - */ - writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg); - } else { - if (poweroff_method != NULL) { - poweroff_method(); - /* not reached */ - } - } - } - machine_halt(); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) { if (irq == 0xffffffff) @@ -78,8 +43,6 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id printk(KERN_INFO "%s: Control reg at %lx\n", op->node->name, res->start); - poweroff_method = machine_halt; /* able to use the standard halt */ - if (has_button_interrupt(irq, op->node)) { if (request_irq(irq, power_handler, 0, "power", NULL) < 0) diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 15f4178592e..11bb6c4612d 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,6 @@ #include #include -#include #include #include #include @@ -46,8 +44,6 @@ #include #include #include -#include -#include #include #include #include @@ -115,35 +111,6 @@ void cpu_idle(void) } } -void machine_halt(void) -{ - sstate_halt(); - prom_halt(); - panic("Halt failed!"); -} - -void machine_alt_power_off(void) -{ - sstate_poweroff(); - prom_halt_power_off(); - panic("Power-off failed!"); -} - -void machine_restart(char * cmd) -{ - char *p; - - sstate_reboot(); - p = strchr (reboot_command, '\n'); - if (p) *p = 0; - if (cmd) - prom_reboot(cmd); - if (*reboot_command) - prom_reboot(reboot_command); - prom_reboot(""); - panic("Reboot failed!"); -} - #ifdef CONFIG_COMPAT static void show_regwindow32(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c new file mode 100644 index 00000000000..04dd34cbb87 --- /dev/null +++ b/arch/sparc64/kernel/reboot.c @@ -0,0 +1,56 @@ +/* reboot.c: reboot/shutdown/halt/poweroff handling + * + * Copyright (C) 2008 David S. Miller + */ +#include +#include +#include +#include + +#include +#include +#include + +/* sysctl - toggle power-off restriction for serial console + * systems in machine_power_off() + */ +int scons_pwroff = 1; + +/* This isn't actually used, it exists merely to satisfy the + * reference in kernel/sys.c + */ +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); + +void machine_power_off(void) +{ + sstate_poweroff(); + if (strcmp(of_console_device->type, "serial") || scons_pwroff) + prom_halt_power_off(); + + prom_halt(); +} + +void machine_halt(void) +{ + sstate_halt(); + prom_halt(); + panic("Halt failed!"); +} + +void machine_restart(char *cmd) +{ + char *p; + + sstate_reboot(); + p = strchr(reboot_command, '\n'); + if (p) + *p = 0; + if (cmd) + prom_reboot(cmd); + if (*reboot_command) + prom_reboot(reboot_command); + prom_reboot(""); + panic("Reboot failed!"); +} + -- cgit v1.2.3 From 446139a8f7078d96159a936fd6059660db425405 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Sep 2008 00:49:38 -0700 Subject: sparc64: Implement SSTATE purely using notifiers and initcalls. Don't clutter up the tree with sstate_blah() scattered all over the place. Signed-off-by: David S. Miller --- arch/sparc64/kernel/hvapi.c | 3 -- arch/sparc64/kernel/reboot.c | 4 --- arch/sparc64/kernel/sstate.c | 67 +++++++++++++++++++++++++++++--------------- 3 files changed, 45 insertions(+), 29 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c index 691760b5b01..1d272c3b574 100644 --- a/arch/sparc64/kernel/hvapi.c +++ b/arch/sparc64/kernel/hvapi.c @@ -9,7 +9,6 @@ #include #include -#include /* If the hypervisor indicates that the API setting * calls are unsupported, by returning HV_EBADTRAP or @@ -184,8 +183,6 @@ void __init sun4v_hvapi_init(void) if (sun4v_hvapi_register(group, major, &minor)) goto bad; - sun4v_sstate_init(); - return; bad: diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c index 04dd34cbb87..11f24966063 100644 --- a/arch/sparc64/kernel/reboot.c +++ b/arch/sparc64/kernel/reboot.c @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -24,7 +23,6 @@ EXPORT_SYMBOL(pm_power_off); void machine_power_off(void) { - sstate_poweroff(); if (strcmp(of_console_device->type, "serial") || scons_pwroff) prom_halt_power_off(); @@ -33,7 +31,6 @@ void machine_power_off(void) void machine_halt(void) { - sstate_halt(); prom_halt(); panic("Halt failed!"); } @@ -42,7 +39,6 @@ void machine_restart(char *cmd) { char *p; - sstate_reboot(); p = strchr(reboot_command, '\n'); if (p) *p = 0; diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c index 5b6e75b7f05..8cdbe5946b4 100644 --- a/arch/sparc64/kernel/sstate.c +++ b/arch/sparc64/kernel/sstate.c @@ -1,14 +1,15 @@ /* sstate.c: System soft state support. * - * Copyright (C) 2007 David S. Miller + * Copyright (C) 2007, 2008 David S. Miller */ #include #include +#include #include #include -#include +#include #include #include #include @@ -50,31 +51,34 @@ static const char rebooting_msg[32] __attribute__((aligned(32))) = static const char panicing_msg[32] __attribute__((aligned(32))) = "Linux panicing"; -void sstate_booting(void) +static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused) { - do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); -} + const char *msg; -void sstate_running(void) -{ - do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); -} + switch (type) { + case SYS_DOWN: + default: + msg = rebooting_msg; + break; -void sstate_halt(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg); -} + case SYS_HALT: + msg = halting_msg; + break; -void sstate_poweroff(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg); -} + case SYS_POWER_OFF: + msg = poweroff_msg; + break; + } -void sstate_reboot(void) -{ - do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg); + do_set_sstate(HV_SOFT_STATE_TRANSITION, msg); + + return NOTIFY_OK; } +static struct notifier_block sstate_reboot_notifier = { + .notifier_call = sstate_reboot_call, +}; + static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) { do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); @@ -87,18 +91,37 @@ static struct notifier_block sstate_panic_block = { .priority = INT_MAX, }; -void __init sun4v_sstate_init(void) +static int __init sstate_init(void) { unsigned long major, minor; + if (tlb_type != hypervisor) + return 0; + major = 1; minor = 0; if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) - return; + return 0; hv_supports_soft_state = 1; prom_sun4v_guest_soft_state(); + + do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); + atomic_notifier_chain_register(&panic_notifier_list, &sstate_panic_block); + register_reboot_notifier(&sstate_reboot_notifier); + + return 0; } + +core_initcall(sstate_init); + +static int __init sstate_running(void) +{ + do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); + return 0; +} + +late_initcall(sstate_running); -- cgit v1.2.3 From 0f73d1bbe6240bcdf14c221bbe2ece63540c5c44 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:18:04 -0700 Subject: pci_psycho: Use of_getintprop_default(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 47db875d023..0be850e6e58 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -975,7 +975,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, struct of_device *op, int is_pbm_a) { struct device_node *dp = op->node; - struct property *prop; struct pci_pbm_info *pbm; if (is_pbm_a) @@ -994,14 +993,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = 0; - prop = of_find_property(dp, "version#", NULL); - if (prop) - pbm->chip_version = *(int *) prop->value; - pbm->chip_revision = 0; - prop = of_find_property(dp, "module-revision#", NULL); - if (prop) - pbm->chip_revision = *(int *) prop->value; + pbm->chip_version = of_getintprop_default(dp, "version#", 0); + pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); pbm->parent = p; pbm->prom_node = dp; @@ -1031,13 +1024,9 @@ static int __devinit psycho_probe(struct of_device *op, struct pci_pbm_info *pbm; struct iommu *iommu; int is_pbm_a, err; - const u32 *p32; u32 upa_portid; - upa_portid = 0xff; - p32 = of_get_property(dp, "upa-portid", NULL); - if (p32) - upa_portid = *p32; + upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { struct pci_controller_info *p = pbm->parent; -- cgit v1.2.3 From 463801b3ae97fe1c652ce8da5a61367405d6ec3e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:21:15 -0700 Subject: pci_schizo: Use of_get_property() and delete spurious local vars. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_schizo.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 64904b180f4..e1c565744d3 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1152,24 +1152,17 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) { - struct iommu *iommu = pbm->iommu; + static const u32 vdma_default[] = { 0xc0000000, 0x40000000 }; unsigned long i, tagbase, database; - struct property *prop; - u32 vdma[2], dma_mask; + struct iommu *iommu = pbm->iommu; int tsbsize, err; + const u32 *vdma; + u32 dma_mask; u64 control; - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; - - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { - /* No property, use default values. */ - vdma[0] = 0xc0000000; - vdma[1] = 0x40000000; - } + vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + if (!vdma) + vdma = vdma_default; dma_mask = vdma[0]; switch (vdma[1]) { @@ -1284,7 +1277,6 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { - struct property *prop; u64 tmp; schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); @@ -1298,8 +1290,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); - if (!prop) + if (!of_find_property(pbm->prom_node, "no-bus-parking", NULL)) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; -- cgit v1.2.3 From 8aef72786192a46e20791b2e854ea3ed047bc15c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 1 Sep 2008 20:23:18 -0700 Subject: pci_sun4v: Use of_get_property(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 4839c503c88..6bed2f6bf7c 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -587,22 +587,15 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) { + static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; struct iommu *iommu = pbm->iommu; - struct property *prop; unsigned long num_tsb_entries, sz, tsbsize; - u32 vdma[2], dma_mask, dma_offset; - - prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); - if (prop) { - u32 *val = prop->value; - - vdma[0] = val[0]; - vdma[1] = val[1]; - } else { - /* No property, use default values. */ - vdma[0] = 0x80000000; - vdma[1] = 0x80000000; - } + u32 dma_mask, dma_offset; + const u32 *vdma; + + vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + if (!vdma) + vdma = vdma_default; if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", -- cgit v1.2.3 From 5280267c1dddb8d413595b87dc406624bb497946 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Sep 2008 02:04:41 -0700 Subject: sparc: Fix handling of LANCE and ESP parent nodes in of_device.c The device nodes that sit above 'esp' and 'le' on SBUS lack a 'ranges' property, but we should pass the translation up to the parent node so that the SBUS level ranges get applied. Based upon a bug report from Robert Reif. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index e427086e3b5..c15bcdf75c0 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -438,8 +438,17 @@ static int __init use_1to1_mapping(struct device_node *pp) /* If the parent is the dma node of an ISA bus, pass * the translation up to the root. + * + * Some SBUS devices use intermediate nodes to express + * hierarchy within the device itself. These aren't + * real bus nodes, and don't have a 'ranges' property. + * But, we should still pass the translation work up + * to the SBUS itself. */ - if (!strcmp(pp->name, "dma")) + if (!strcmp(pp->name, "dma") || + !strcmp(pp->name, "espdma") || + !strcmp(pp->name, "ledma") || + !strcmp(pp->name, "lebuffer")) return 0; /* Similarly for all PCI bridges, if we get this far -- cgit v1.2.3 From 3baca76f5653482f4b7fe1fc400b01877f6b2d92 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 7 Sep 2008 18:12:59 -0700 Subject: sparc64: fix wrong m48t59 RTC year Correctly calculate offset to the year register for Mostek RTC. Signed-off-by: Krzysztof Helt Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 209e7d28c3a..226a0042d87 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -500,6 +500,7 @@ static struct of_platform_driver bq4802_driver = { static unsigned char mostek_read_byte(struct device *dev, u32 ofs) { struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; void __iomem *regs; unsigned char val; @@ -507,7 +508,7 @@ static unsigned char mostek_read_byte(struct device *dev, u32 ofs) val = readb(regs + ofs); /* the year 0 is 1968 */ - if (ofs == M48T59_YEAR) { + if (ofs == pdata->offset + M48T59_YEAR) { val += 0x68; if ((val & 0xf) > 9) val += 6; @@ -518,10 +519,11 @@ static unsigned char mostek_read_byte(struct device *dev, u32 ofs) static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) { struct platform_device *pdev = to_platform_device(dev); + struct m48t59_plat_data *pdata = pdev->dev.platform_data; void __iomem *regs; regs = (void __iomem *) pdev->resource[0].start; - if (ofs == M48T59_YEAR) { + if (ofs == pdata->offset + M48T59_YEAR) { if (val < 0x68) val += 0x32; else -- cgit v1.2.3 From 088a39623660f2875aaf15649bf663bbb5a8a219 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 8 Sep 2008 19:53:28 -0700 Subject: sparc64: Add missing rtc_close() in update_persistent_clock() Noticed by David Brownell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 226a0042d87..8a2fa0eb660 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -396,9 +396,12 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { struct rtc_device *rtc = rtc_class_open("rtc0"); + int err; - if (rtc) - return rtc_set_mmss(rtc, now.tv_sec); + if (rtc) { + err = rtc_set_mmss(rtc, now.tv_sec); + rtc_class_close(rtc); + } return -1; } -- cgit v1.2.3 From 90158d84eb20fa15e3c8010b570f3ea2c925121d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 13:35:08 -0700 Subject: sparc64: Fix return value in update_persistent_clock(). Noticed by Stephen Rothwell. Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 8a2fa0eb660..8d2ca04d309 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -396,14 +396,14 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; int update_persistent_clock(struct timespec now) { struct rtc_device *rtc = rtc_class_open("rtc0"); - int err; + int err = -1; if (rtc) { err = rtc_set_mmss(rtc, now.tv_sec); rtc_class_close(rtc); } - return -1; + return err; } unsigned long cmos_regs; -- cgit v1.2.3 From d3ae4b5bc7186a53731d35187ad4ba3bca147cf6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Sep 2008 23:54:02 -0700 Subject: sparc64: Get rid of pci_controller_info. It is just used as a parent to encapsulate two PBM objects. But that layout is only really relevant and necessary for psycho PCI controllers, which unlike all the others share a single IOMMU instance between sibling PCI busses. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 4 +- arch/sparc64/kernel/pci_fire.c | 55 +++++-------- arch/sparc64/kernel/pci_impl.h | 16 ++-- arch/sparc64/kernel/pci_psycho.c | 161 ++++++++++++++++++--------------------- arch/sparc64/kernel/pci_sabre.c | 33 ++++---- arch/sparc64/kernel/pci_schizo.c | 84 +++++++++----------- arch/sparc64/kernel/pci_sun4v.c | 66 +++++++--------- 7 files changed, 178 insertions(+), 241 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 8e18fdf32a6..3070f6faecc 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -977,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus) EXPORT_SYMBOL(pcibus_to_node); #endif -/* Return the domain nuber for this pci bus */ +/* Return the domain number for this pci bus */ int pci_domain_nr(struct pci_bus *pbus) { struct pci_pbm_info *pbm = pbus->sysdata; int ret; - if (pbm == NULL || pbm->parent == NULL) { + if (!pbm) { ret = -ENXIO; } else { ret = pbm->index; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 1b44153f907..b538bfb0a47 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -431,22 +431,13 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); } -static int __init pci_fire_pbm_init(struct pci_controller_info *p, +static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 portid) { const struct linux_prom64_registers *regs; struct device_node *dp = op->node; - struct pci_pbm_info *pbm; int err; - if ((portid & 1) == 0) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->numa_node = -1; pbm->pci_ops = &sun4u_pci_ops; @@ -455,7 +446,6 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->parent = p; pbm->prom_node = dp; pbm->name = dp->full_name; @@ -481,13 +471,9 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, /* XXX register error interrupt handlers XXX */ - return 0; -} + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; -static inline int portid_compare(u32 x, u32 y) -{ - if (x == (y ^ 1)) - return 1; return 0; } @@ -495,48 +481,41 @@ static int __devinit fire_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; int err; portid = of_getintprop_default(dp, "portid", 0xff); - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid)) - return pci_fire_pbm_init(pbm->parent, op, portid); - } err = -ENOMEM; - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); goto out_free_controller; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free_iommu_A; - } + err = pci_fire_pbm_init(pbm, op, portid); + if (err) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + dev_set_drvdata(&op->dev, pbm); - return pci_fire_pbm_init(p, op, portid); + return 0; -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 4125f7513c6..4937ce903a8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -56,15 +56,11 @@ struct sparc64_msiq_cookie { }; #endif -struct pci_controller_info; - struct pci_pbm_info { struct pci_pbm_info *next; + struct pci_pbm_info *sibling; int index; - /* PCI controller we sit under. */ - struct pci_controller_info *parent; - /* Physical address base of controller registers. */ unsigned long controller_regs; @@ -107,6 +103,10 @@ struct pci_pbm_info { /* This will be 12 on PCI-E controllers, 8 elsewhere. */ unsigned long config_space_reg_bits; + unsigned long pci_afsr; + unsigned long pci_afar; + unsigned long pci_csr; + /* State of 66MHz capabilities on this PBM. */ int is_66mhz_capable; int all_devs_66mhz; @@ -151,12 +151,6 @@ struct pci_pbm_info { int numa_node; }; -struct pci_controller_info { - /* The PCI bus modules controlled by us. */ - struct pci_pbm_info pbm_A; - struct pci_pbm_info pbm_B; -}; - extern struct pci_pbm_info *pci_pbm_root; extern int pci_num_pbms; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0be850e6e58..70a7af092be 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -146,24 +146,16 @@ static unsigned long stc_error_buf[128]; static unsigned long stc_tag_buf[16]; static unsigned long stc_line_buf[16]; -static void __psycho_check_one_stc(struct pci_pbm_info *pbm, - int is_pbm_a) +static void psycho_check_stc_error(struct pci_pbm_info *pbm) { struct strbuf *strbuf = &pbm->stc; - unsigned long regbase = pbm->controller_regs; unsigned long err_base, tag_base, line_base; u64 control; int i; - if (is_pbm_a) { - err_base = regbase + PSYCHO_STC_ERR_A; - tag_base = regbase + PSYCHO_STC_TAG_A; - line_base = regbase + PSYCHO_STC_LINE_A; - } else { - err_base = regbase + PSYCHO_STC_ERR_B; - tag_base = regbase + PSYCHO_STC_TAG_B; - line_base = regbase + PSYCHO_STC_LINE_B; - } + err_base = strbuf->strbuf_err_stat; + tag_base = strbuf->strbuf_tag_diag; + line_base = strbuf->strbuf_line_diag; spin_lock(&stc_buf_lock); @@ -239,15 +231,6 @@ static void __psycho_check_one_stc(struct pci_pbm_info *pbm, spin_unlock(&stc_buf_lock); } -static void __psycho_check_stc_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - __psycho_check_one_stc(pbm, - (pbm == &pbm->parent->pbm_A)); -} - /* When an Uncorrectable Error or a PCI Error happens, we * interrogate the IOMMU state to see if it is the cause. */ @@ -386,7 +369,7 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); } } - __psycho_check_stc_error(pbm, afsr, afar, type); + psycho_check_stc_error(pbm); spin_unlock_irqrestore(&iommu->lock, flags); } @@ -412,7 +395,6 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, static irqreturn_t psycho_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; unsigned long afsr, afar, error_bits; @@ -465,8 +447,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate both IOMMUs for error status. */ - psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); - psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); + psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); + if (pbm->sibling) + psycho_check_iommu_error(pbm->sibling, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -573,23 +556,18 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) #define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_B 0x4018UL -static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) +static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) { - unsigned long csr_reg, csr, csr_error_bits; + unsigned long csr, csr_error_bits; irqreturn_t ret = IRQ_NONE; u16 stat; - if (is_pbm_a) { - csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; - } else { - csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL; - } - csr = psycho_read(csr_reg); + csr = psycho_read(pbm->pci_csr); csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); if (csr_error_bits) { /* Clear the errors. */ - psycho_write(csr_reg, csr); + psycho_write(pbm->pci_csr, csr); /* Log 'em. */ if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) @@ -616,19 +594,12 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg, afar_reg; unsigned long afsr, afar, error_bits; - int is_pbm_a, reported; + int reported; - is_pbm_a = (pbm == &pbm->parent->pbm_A); - if (is_pbm_a) { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A; - } else { - afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B; - afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B; - } + afsr_reg = pbm->pci_afsr; + afar_reg = pbm->pci_afar; /* Latch error status. */ afar = psycho_read(afar_reg); @@ -641,7 +612,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); if (!error_bits) - return psycho_pcierr_intr_other(pbm, is_pbm_a); + return psycho_pcierr_intr_other(pbm); psycho_write(afsr_reg, error_bits); /* Log the error. */ @@ -923,10 +894,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; + pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_A; + pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_A; + pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_A; } else { pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; + pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_B; + pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_B; + pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_B; } /* PSYCHO's streaming buffer lacks ctx flushing. */ pbm->stc.strbuf_ctxflush = 0; @@ -971,16 +948,10 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, #define PSYCHO_MEMSPACE_B 0x180000000UL #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL -static void __init psycho_pbm_init(struct pci_controller_info *p, +static void __init psycho_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, int is_pbm_a) { struct device_node *dp = op->node; - struct pci_pbm_info *pbm; - - if (is_pbm_a) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; pbm->next = pci_pbm_root; pci_pbm_root = pbm; @@ -996,7 +967,6 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->chip_version = of_getintprop_default(dp, "version#", 0); pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - pbm->parent = p; pbm->prom_node = dp; pbm->name = dp->full_name; @@ -1013,6 +983,17 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, psycho_scan_bus(pbm, &op->dev); } +static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) +{ + struct pci_pbm_info *pbm; + + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (pbm->portid == upa_portid) + return pbm; + } + return NULL; +} + #define PSYCHO_CONFIGSPACE 0x001000000UL static int __devinit psycho_probe(struct of_device *op, @@ -1020,7 +1001,6 @@ static int __devinit psycho_probe(struct of_device *op, { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; int is_pbm_a, err; @@ -1028,33 +1008,26 @@ static int __devinit psycho_probe(struct of_device *op, upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - struct pci_controller_info *p = pbm->parent; - - if (p->pbm_A.portid == upa_portid) { - is_pbm_a = (p->pbm_A.prom_node == NULL); - psycho_pbm_init(p, op, is_pbm_a); - return 0; - } - } - err = -ENOMEM; - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); - goto out_free_controller; + pbm->sibling = psycho_find_sibling(upa_portid); + if (pbm->sibling) { + iommu = pbm->sibling->iommu; + } else { + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); + if (!iommu) { + printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); + goto out_free_controller; + } } - p->pbm_A.iommu = p->pbm_B.iommu = iommu; - - p->pbm_A.portid = upa_portid; - p->pbm_B.portid = upa_portid; + pbm->iommu = iommu; + pbm->portid = upa_portid; pr_regs = of_get_property(dp, "reg", NULL); err = -ENODEV; @@ -1063,29 +1036,43 @@ static int __devinit psycho_probe(struct of_device *op, goto out_free_iommu; } - p->pbm_A.controller_regs = pr_regs[2].phys_addr; - p->pbm_B.controller_regs = pr_regs[2].phys_addr; + is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + + pbm->controller_regs = pr_regs[2].phys_addr; + pbm->config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); - p->pbm_A.config_space = p->pbm_B.config_space = - (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); + if (is_pbm_a) { + pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_A; + pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_A; + pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIA_CTRL; + } else { + pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_B; + pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_B; + pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIB_CTRL; + } - psycho_controller_hwinit(&p->pbm_A); + psycho_controller_hwinit(pbm); + if (!pbm->sibling) { + err = psycho_iommu_init(pbm); + if (err) + goto out_free_iommu; + } - err = psycho_iommu_init(&p->pbm_A); - if (err) - goto out_free_iommu; + psycho_pbm_init(pbm, op, is_pbm_a); - is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); + if (pbm->sibling) + pbm->sibling->sibling = pbm; - psycho_pbm_init(p, op, is_pbm_a); + dev_set_drvdata(&op->dev, pbm); return 0; out_free_iommu: - kfree(p->pbm_A.iommu); + if (!pbm->sibling) + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 707d6d6130f..8f779b58d65 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -734,8 +734,8 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, return 0; } -static void __init sabre_pbm_init(struct pci_controller_info *p, - struct pci_pbm_info *pbm, struct of_device *op) +static void __init sabre_pbm_init(struct pci_pbm_info *pbm, + struct of_device *op) { struct device_node *dp = op->node; @@ -750,7 +750,6 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->parent = p; pbm->prom_node = dp; pci_get_pbm_props(pbm); @@ -764,7 +763,6 @@ static int __devinit sabre_probe(struct of_device *op, { const struct linux_prom64_registers *pr_regs; struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; u32 upa_portid, dma_mask; struct iommu *iommu; @@ -786,26 +784,22 @@ static int __devinit sabre_probe(struct of_device *op, } err = -ENOMEM; - p = kzalloc(sizeof(*p), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); goto out_free_controller; } - pbm = &p->pbm_A; pbm->iommu = iommu; upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->portid = upa_portid; /* @@ -840,8 +834,7 @@ static int __devinit sabre_probe(struct of_device *op, SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); /* Now map in PCI config space for entire SABRE. */ - pbm->config_space = - (pbm->controller_regs + SABRE_CONFIGSPACE); + pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; vdma = of_get_property(dp, "virtual-dma", NULL); if (!vdma) { @@ -876,14 +869,20 @@ static int __devinit sabre_probe(struct of_device *op, /* * Look for APB underneath. */ - sabre_pbm_init(p, pbm, op); + sabre_pbm_init(pbm, op); + + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + + dev_set_drvdata(&op->dev, pbm); + return 0; out_free_iommu: - kfree(p->pbm_A.iommu); + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e1c565744d3..67e3640bc69 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -358,11 +358,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, spin_unlock_irqrestore(&iommu->lock, flags); } -static void schizo_check_iommu_error(struct pci_controller_info *p, +static void schizo_check_iommu_error(struct pci_pbm_info *pbm, enum schizo_error_type type) { - schizo_check_iommu_error_pbm(&p->pbm_A, type); - schizo_check_iommu_error_pbm(&p->pbm_B, type); + schizo_check_iommu_error_pbm(pbm, type); + if (pbm->sibling) + schizo_check_iommu_error_pbm(pbm->sibling, type); } /* Uncorrectable ECC error status gathering. */ @@ -387,7 +388,6 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, static irqreturn_t schizo_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; unsigned long afsr, afar, error_bits; @@ -450,7 +450,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - schizo_check_iommu_error(p, UE_ERR); + schizo_check_iommu_error(pbm, UE_ERR); return IRQ_HANDLED; } @@ -651,7 +651,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; unsigned long afsr_reg, afar_reg, base; unsigned long afsr, afar, error_bits; int reported; @@ -745,7 +744,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) * a bug in the IOMMU support code or a PCI device driver. */ if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { - schizo_check_iommu_error(p, PCI_ERR); + schizo_check_iommu_error(pbm, PCI_ERR); pci_scan_for_target_abort(pbm, pbm->pci_bus); } if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) @@ -806,7 +805,6 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; - struct pci_controller_info *p = pbm->parent; u64 errlog; errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); @@ -822,7 +820,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", pbm->name); - schizo_check_iommu_error(p, SAFARI_ERR); + schizo_check_iommu_error(pbm, SAFARI_ERR); return IRQ_HANDLED; } @@ -1329,13 +1327,12 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) } } -static int __devinit schizo_pbm_init(struct pci_controller_info *p, +static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 portid, int chip_type) { const struct linux_prom64_registers *regs; struct device_node *dp = op->node; - struct pci_pbm_info *pbm; const char *chipset_name; int is_pbm_a, err; @@ -1368,10 +1365,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, regs = of_get_property(dp, "reg", NULL); is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); - if (is_pbm_a) - pbm = &p->pbm_A; - else - pbm = &p->pbm_B; pbm->next = pci_pbm_root; pci_pbm_root = pbm; @@ -1384,7 +1377,6 @@ static int __devinit schizo_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->parent = p; pbm->prom_node = dp; pbm->chip_type = chip_type; @@ -1430,10 +1422,21 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) return (x == y); } +static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid, + int chip_type) +{ + struct pci_pbm_info *pbm; + + for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { + if (portid_compare(pbm->portid, portid, chip_type)) + return pbm; + } + return NULL; +} + static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) { struct device_node *dp = op->node; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct iommu *iommu; u32 portid; @@ -1442,50 +1445,37 @@ static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type portid = of_getintprop_default(dp, "portid", 0xff); err = -ENOMEM; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (portid_compare(pbm->portid, portid, chip_type)) { - if (schizo_pbm_init(pbm->parent, op, - portid, chip_type)) - goto out_err; - return 0; - } - } - - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Cannot allocate controller info.\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + pbm->sibling = schizo_find_sibling(portid, chip_type); + + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); - goto out_free_controller; + goto out_free_pbm; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Cannot allocate PBM B iommu.\n"); - goto out_free_iommu_A; - } + if (schizo_pbm_init(pbm, op, portid, chip_type)) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + if (pbm->sibling) + pbm->sibling->sibling = pbm; - if (schizo_pbm_init(p, op, portid, chip_type)) - goto out_free_iommu_B; + dev_set_drvdata(&op->dev, pbm); return 0; -out_free_iommu_B: - kfree(p->pbm_B.iommu); - -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); -out_free_controller: - kfree(p); +out_free_pbm: + kfree(pbm); out_err: return err; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 6bed2f6bf7c..233b22b8b57 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -42,6 +42,7 @@ struct iommu_batch { }; static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); +static int iommu_batch_initialized; /* Interrupts must be disabled. */ static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) @@ -887,21 +888,12 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) } #endif /* !(CONFIG_PCI_MSI) */ -static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, +static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, u32 devhandle) { struct device_node *dp = op->node; - struct pci_pbm_info *pbm; int err; - if (devhandle & 0x40) - pbm = &p->pbm_B; - else - pbm = &p->pbm_A; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - pbm->numa_node = of_node_to_nid(dp); pbm->pci_ops = &sun4v_pci_ops; @@ -909,7 +901,6 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->index = pci_num_pbms++; - pbm->parent = p; pbm->prom_node = dp; pbm->devhandle = devhandle; @@ -931,6 +922,9 @@ static int __init pci_sun4v_pbm_init(struct pci_controller_info *p, pci_sun4v_scan_bus(pbm, &op->dev); + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + return 0; } @@ -939,7 +933,6 @@ static int __devinit pci_sun4v_probe(struct of_device *op, { const struct linux_prom64_registers *regs; static int hvapi_negotiated = 0; - struct pci_controller_info *p; struct pci_pbm_info *pbm; struct device_node *dp; struct iommu *iommu; @@ -972,51 +965,46 @@ static int __devinit pci_sun4v_probe(struct of_device *op, } devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; - for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { - if (pbm->devhandle == (devhandle ^ 0x40)) { - return pci_sun4v_pbm_init(pbm->parent, op, devhandle); - } - } - err = -ENOMEM; - for_each_possible_cpu(i) { - unsigned long page = get_zeroed_page(GFP_ATOMIC); + if (!iommu_batch_initialized) { + for_each_possible_cpu(i) { + unsigned long page = get_zeroed_page(GFP_KERNEL); - if (!page) - goto out_err; + if (!page) + goto out_err; - per_cpu(iommu_batch, i).pglist = (u64 *) page; + per_cpu(iommu_batch, i).pglist = (u64 *) page; + } + iommu_batch_initialized = 1; } - p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); - if (!p) { - printk(KERN_ERR PFX "Could not allocate pci_controller_info\n"); + pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); + if (!pbm) { + printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n"); goto out_err; } - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); + iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); if (!iommu) { - printk(KERN_ERR PFX "Could not allocate pbm A iommu\n"); + printk(KERN_ERR PFX "Could not allocate pbm iommu\n"); goto out_free_controller; } - p->pbm_A.iommu = iommu; + pbm->iommu = iommu; - iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); - if (!iommu) { - printk(KERN_ERR PFX "Could not allocate pbm B iommu\n"); - goto out_free_iommu_A; - } + err = pci_sun4v_pbm_init(pbm, op, devhandle); + if (err) + goto out_free_iommu; - p->pbm_B.iommu = iommu; + dev_set_drvdata(&op->dev, pbm); - return pci_sun4v_pbm_init(p, op, devhandle); + return 0; -out_free_iommu_A: - kfree(p->pbm_A.iommu); +out_free_iommu: + kfree(pbm->iommu); out_free_controller: - kfree(p); + kfree(pbm); out_err: return err; -- cgit v1.2.3 From 22fecbae4446ad470b9237ee9b79f80f343b3838 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 00:19:28 -0700 Subject: sparc64: Record OF device instead of device node pointer in pci_pbm_info. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 2 +- arch/sparc64/kernel/pci_common.c | 8 ++++---- arch/sparc64/kernel/pci_fire.c | 2 +- arch/sparc64/kernel/pci_impl.h | 3 ++- arch/sparc64/kernel/pci_msi.c | 18 +++++++++--------- arch/sparc64/kernel/pci_psycho.c | 4 ++-- arch/sparc64/kernel/pci_sabre.c | 4 ++-- arch/sparc64/kernel/pci_schizo.c | 12 ++++++------ arch/sparc64/kernel/pci_sun4v.c | 6 +++--- 9 files changed, 30 insertions(+), 29 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 3070f6faecc..c6e81dea2cf 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -676,7 +676,7 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, struct device *parent) { - struct device_node *node = pbm->prom_node; + struct device_node *node = pbm->op->node; struct pci_bus *bus; printk("PCI: Scanning PBM %s\n", node->full_name); diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 09a5ec200c6..23b88082d0b 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -314,12 +314,12 @@ struct pci_ops sun4v_pci_ops = { void pci_get_pbm_props(struct pci_pbm_info *pbm) { - const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); + const u32 *val = of_get_property(pbm->op->node, "bus-range", NULL); pbm->pci_first_busno = val[0]; pbm->pci_last_busno = val[1]; - val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); + val = of_get_property(pbm->op->node, "ino-bitmap", NULL); if (val) { pbm->ino_bitmap = (((u64)val[1] << 32UL) | ((u64)val[0] << 0UL)); @@ -365,7 +365,7 @@ static void pci_register_legacy_regions(struct resource *io_res, static void pci_register_iommu_region(struct pci_pbm_info *pbm) { - const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (vdma) { struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); @@ -389,7 +389,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) int num_pbm_ranges; saw_mem = saw_io = 0; - pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); + pbm_ranges = of_get_property(pbm->op->node, "ranges", &i); if (!pbm_ranges) { prom_printf("PCI: Fatal error, missing PBM ranges property " " for %s\n", diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index b538bfb0a47..7e1a9b6717b 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -446,7 +446,7 @@ static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->prom_node = dp; + pbm->op = op; pbm->name = dp->full_name; regs = of_get_property(dp, "reg", NULL); diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 4937ce903a8..b300f39e9e8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ struct pci_pbm_info { char *name; /* OBP specific information. */ - struct device_node *prom_node; + struct of_device *op; u64 ino_bitmap; /* PBM I/O and Memory space resources. */ diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index 60c71e35021..2e680f34f72 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c @@ -323,7 +323,7 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, const u32 *val; int len; - val = of_get_property(pbm->prom_node, "#msi-eqs", &len); + val = of_get_property(pbm->op->node, "#msi-eqs", &len); if (!val || len != 4) goto no_msi; pbm->msiq_num = *val; @@ -346,16 +346,16 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, u32 msi64_len; } *arng; - val = of_get_property(pbm->prom_node, "msi-eq-size", &len); + val = of_get_property(pbm->op->node, "msi-eq-size", &len); if (!val || len != 4) goto no_msi; pbm->msiq_ent_count = *val; - mqp = of_get_property(pbm->prom_node, + mqp = of_get_property(pbm->op->node, "msi-eq-to-devino", &len); if (!mqp) - mqp = of_get_property(pbm->prom_node, + mqp = of_get_property(pbm->op->node, "msi-eq-devino", &len); if (!mqp || len != sizeof(struct msiq_prop)) goto no_msi; @@ -363,27 +363,27 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, pbm->msiq_first = mqp->first_msiq; pbm->msiq_first_devino = mqp->first_devino; - val = of_get_property(pbm->prom_node, "#msi", &len); + val = of_get_property(pbm->op->node, "#msi", &len); if (!val || len != 4) goto no_msi; pbm->msi_num = *val; - mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); + mrng = of_get_property(pbm->op->node, "msi-ranges", &len); if (!mrng || len != sizeof(struct msi_range_prop)) goto no_msi; pbm->msi_first = mrng->first_msi; - val = of_get_property(pbm->prom_node, "msi-data-mask", &len); + val = of_get_property(pbm->op->node, "msi-data-mask", &len); if (!val || len != 4) goto no_msi; pbm->msi_data_mask = *val; - val = of_get_property(pbm->prom_node, "msix-data-width", &len); + val = of_get_property(pbm->op->node, "msix-data-width", &len); if (!val || len != 4) goto no_msi; pbm->msix_data_width = *val; - arng = of_get_property(pbm->prom_node, "msi-address-ranges", + arng = of_get_property(pbm->op->node, "msi-address-ranges", &len); if (!arng || len != sizeof(struct addr_range_prop)) goto no_msi; diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 70a7af092be..4562b3e0b54 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -690,7 +690,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); unsigned long base = pbm->controller_regs; u64 tmp; int err; @@ -967,7 +967,7 @@ static void __init psycho_pbm_init(struct pci_pbm_info *pbm, pbm->chip_version = of_getintprop_default(dp, "version#", 0); pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - pbm->prom_node = dp; + pbm->op = op; pbm->name = dp->full_name; printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 8f779b58d65..196049bb14b 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -543,7 +543,7 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { - struct device_node *dp = pbm->prom_node; + struct device_node *dp = pbm->op->node; struct of_device *op; unsigned long base = pbm->controller_regs; u64 tmp; @@ -750,7 +750,7 @@ static void __init sabre_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->prom_node = dp; + pbm->op = op; pci_get_pbm_props(pbm); pci_determine_mem_io_space(pbm); diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 67e3640bc69..c30856541bb 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -862,7 +862,7 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) */ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); u64 tmp, err_mask, err_no_mask; int err; @@ -958,7 +958,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) static void schizo_register_error_handlers(struct pci_pbm_info *pbm) { - struct of_device *op = of_find_device_by_node(pbm->prom_node); + struct of_device *op = of_find_device_by_node(pbm->op->node); u64 tmp, err_mask, err_no_mask; int err; @@ -1088,7 +1088,7 @@ static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, { pbm_config_busmastering(pbm); pbm->is_66mhz_capable = - (of_find_property(pbm->prom_node, "66mhz-capable", NULL) + (of_find_property(pbm->op->node, "66mhz-capable", NULL) != NULL); pbm->pci_bus = pci_scan_one_pbm(pbm, parent); @@ -1158,7 +1158,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) u32 dma_mask; u64 control; - vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (!vdma) vdma = vdma_default; @@ -1288,7 +1288,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) pbm->chip_version >= 0x2) tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; - if (!of_find_property(pbm->prom_node, "no-bus-parking", NULL)) + if (!of_find_property(pbm->op->node, "no-bus-parking", NULL)) tmp |= SCHIZO_PCICTRL_PARK; else tmp &= ~SCHIZO_PCICTRL_PARK; @@ -1377,7 +1377,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; pbm->portid = portid; - pbm->prom_node = dp; + pbm->op = op; pbm->chip_type = chip_type; pbm->chip_version = of_getintprop_default(dp, "version#", 0); diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 233b22b8b57..97a77bcd255 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -550,7 +550,7 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, struct property *prop; struct device_node *dp; - dp = pbm->prom_node; + dp = pbm->op->node; prop = of_find_property(dp, "66mhz-capable", NULL); pbm->is_66mhz_capable = (prop != NULL); pbm->pci_bus = pci_scan_one_pbm(pbm, parent); @@ -594,7 +594,7 @@ static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) u32 dma_mask, dma_offset; const u32 *vdma; - vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); + vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); if (!vdma) vdma = vdma_default; @@ -901,7 +901,7 @@ static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, pbm->index = pci_num_pbms++; - pbm->prom_node = dp; + pbm->op = op; pbm->devhandle = devhandle; -- cgit v1.2.3 From a21cff3e5e39c087b5a4c5efb20f1744475c556e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:07:03 -0700 Subject: sparc64: Start commonizing code common between SABRE and PSYCHO. These are very similar chips, in fact they are identical in some macro blocks. So start commonizing code which they can share. We begin with the IOMMU initialization sequence. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/pci_psycho.c | 65 +++----------------------- arch/sparc64/kernel/pci_sabre.c | 63 +------------------------ arch/sparc64/kernel/psycho_common.c | 93 +++++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 8 ++++ 5 files changed, 111 insertions(+), 120 deletions(-) create mode 100644 arch/sparc64/kernel/psycho_common.c create mode 100644 arch/sparc64/kernel/psycho_common.h (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index fb02807167e..c0b8009ab19 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -16,7 +16,7 @@ obj-y := process.o setup.o cpu.o idprom.o reboot.o \ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += pci.o pci_common.o \ +obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4562b3e0b54..4681e3d8b5f 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -20,6 +20,7 @@ #include "pci_impl.h" #include "iommu_common.h" +#include "psycho_common.h" #define DRIVER_NAME "psycho" #define PFX DRIVER_NAME ": " @@ -787,63 +788,6 @@ static void __init psycho_scan_bus(struct pci_pbm_info *pbm, psycho_register_error_handlers(pbm); } -static int psycho_iommu_init(struct pci_pbm_info *pbm) -{ - struct iommu *iommu = pbm->iommu; - unsigned long i; - u64 control; - int err; - - /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; - iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); - - /* PSYCHO's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* We use the main control register of PSYCHO as the write - * completion register. - */ - iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; - - /* - * Invalidate TLB Entries. - */ - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); - control |= PSYCHO_IOMMU_CTRL_DENAB; - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - for (i = 0; i < 16; i++) { - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, - pbm->numa_node); - if (err) { - printk(KERN_ERR PFX "iommu_table_init() fails\n"); - return err; - } - - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); - control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); - control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); - psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); - - /* If necessary, hook us up for starfire IRQ translations. */ - if (this_is_starfire) - starfire_hookup(pbm->portid); - - return 0; -} - #define PSYCHO_IRQ_RETRY 0x1a00UL #define PSYCHO_PCIA_DIAG 0x2020UL #define PSYCHO_PCIB_DIAG 0x4020UL @@ -1053,9 +997,14 @@ static int __devinit psycho_probe(struct of_device *op, psycho_controller_hwinit(pbm); if (!pbm->sibling) { - err = psycho_iommu_init(pbm); + err = psycho_iommu_init(pbm, 128, 0xc0000000, + 0xffffffff, PSYCHO_CONTROL); if (err) goto out_free_iommu; + + /* If necessary, hook us up for starfire IRQ translations. */ + if (this_is_starfire) + starfire_hookup(pbm->portid); } psycho_pbm_init(pbm, op, is_pbm_a); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 196049bb14b..a3a276de75a 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -20,6 +20,7 @@ #include "pci_impl.h" #include "iommu_common.h" +#include "psycho_common.h" #define DRIVER_NAME "sabre" #define PFX DRIVER_NAME ": " @@ -674,66 +675,6 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm, sabre_register_error_handlers(pbm); } -static int sabre_iommu_init(struct pci_pbm_info *pbm, - int tsbsize, unsigned long dvma_offset, - u32 dma_mask) -{ - struct iommu *iommu = pbm->iommu; - unsigned long i; - u64 control; - int err; - - /* Register addresses. */ - iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; - iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; - iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; - iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); - iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; - /* Sabre's IOMMU lacks ctx flushing. */ - iommu->iommu_ctxflush = 0; - - /* Invalidate TLB Entries. */ - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); - control |= SABRE_IOMMUCTRL_DENAB; - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); - - for(i = 0; i < 16; i++) { - sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diag mode enabled for full-flushing done - * in pci_iommu.c - */ - err = iommu_table_init(iommu, tsbsize * 1024 * 8, - dvma_offset, dma_mask, pbm->numa_node); - if (err) { - printk(KERN_ERR PFX "iommu_table_init() failed\n"); - return err; - } - - sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, - __pa(iommu->page_table)); - - control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); - control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); - control |= SABRE_IOMMUCTRL_ENAB; - switch(tsbsize) { - case 64: - control |= SABRE_IOMMU_TSBSZ_64K; - break; - case 128: - control |= SABRE_IOMMU_TSBSZ_128K; - break; - default: - printk(KERN_ERR PFX "Illegal TSB size %d\n", tsbsize); - return -EINVAL; - } - sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); - - return 0; -} - static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { @@ -862,7 +803,7 @@ static int __devinit sabre_probe(struct of_device *op, goto out_free_iommu; } - err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); + err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC); if (err) goto out_free_iommu; diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c new file mode 100644 index 00000000000..07acc13637b --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.c @@ -0,0 +1,93 @@ +/* psycho_common.c: Code common to PSYCHO and derivative PCI controllers. + * + * Copyright (C) 2008 David S. Miller + */ +#include + +#include + +#include "pci_impl.h" +#include "psycho_common.h" + +#define PSYCHO_IOMMU_TAG 0xa580UL +#define PSYCHO_IOMMU_DATA 0xa600UL + +static void psycho_iommu_flush(struct pci_pbm_info *pbm) +{ + int i; + + for (i = 0; i < 16; i++) { + unsigned long off = i * 8; + + upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off); + upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off); + } +} + +#define PSYCHO_IOMMU_CONTROL 0x0200UL +#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL +#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL +#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL +#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL +#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL +#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL +#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL +#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL +#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL +#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL +#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL +#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL +#define PSYCHO_IOMMU_FLUSH 0x0210UL +#define PSYCHO_IOMMU_TSBBASE 0x0208UL + +int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, + u32 dvma_offset, u32 dma_mask, + unsigned long write_complete_offset) +{ + struct iommu *iommu = pbm->iommu; + u64 control; + int err; + + iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; + iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; + iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; + iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG; + iommu->write_complete_reg = (pbm->controller_regs + + write_complete_offset); + + iommu->iommu_ctxflush = 0; + + control = upa_readq(iommu->iommu_control); + control |= PSYCHO_IOMMU_CTRL_DENAB; + upa_writeq(control, iommu->iommu_control); + + psycho_iommu_flush(pbm); + + /* Leave diag mode enabled for full-flushing done in pci_iommu.c */ + err = iommu_table_init(iommu, tsbsize * 1024 * 8, + dvma_offset, dma_mask, pbm->numa_node); + if (err) + return err; + + upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); + + control = upa_readq(iommu->iommu_control); + control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); + control |= PSYCHO_IOMMU_CTRL_ENAB; + + switch (tsbsize) { + case 64: + control |= PSYCHO_IOMMU_TSBSZ_64K; + break; + case 128: + control |= PSYCHO_IOMMU_TSBSZ_128K; + break; + default: + return -EINVAL; + } + + upa_writeq(control, iommu->iommu_control); + + return 0; + +} diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h new file mode 100644 index 00000000000..bffaff57d5e --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.h @@ -0,0 +1,8 @@ +#ifndef _PSYCHO_COMMON_H +#define _PSYCHO_COMMON_H + +extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, + u32 dvma_offset, u32 dma_mask, + unsigned long write_complete_offset); + +#endif /* _PSYCHO_COMMON_H */ -- cgit v1.2.3 From 1c03a55cdf309d0939e881b313abbe7e9a67d95e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:15:56 -0700 Subject: sparc64: Create and use psycho_pbm_init_common(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 32 ++++---------------------------- arch/sparc64/kernel/pci_sabre.c | 19 +------------------ arch/sparc64/kernel/psycho_common.c | 22 ++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 4 ++++ 4 files changed, 31 insertions(+), 46 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 4681e3d8b5f..2de51fb34ee 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -895,35 +895,8 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, static void __init psycho_pbm_init(struct pci_pbm_info *pbm, struct of_device *op, int is_pbm_a) { - struct device_node *dp = op->node; - - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - - pbm->numa_node = -1; - - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - - pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; - pbm->chip_version = of_getintprop_default(dp, "version#", 0); - pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); - - pbm->op = op; - pbm->name = dp->full_name; - - printk(KERN_INFO "%s: PSYCHO PCI Bus Module ver[%x:%x]\n", - pbm->name, - pbm->chip_version, pbm->chip_revision); - - pci_determine_mem_io_space(pbm); - - pci_get_pbm_props(pbm); - + psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO); psycho_pbm_strbuf_init(pbm, is_pbm_a); - psycho_scan_bus(pbm, &op->dev); } @@ -1009,6 +982,9 @@ static int __devinit psycho_probe(struct of_device *op, psycho_pbm_init(pbm, op, is_pbm_a); + pbm->next = pci_pbm_root; + pci_pbm_root = pbm; + if (pbm->sibling) pbm->sibling->sibling = pbm; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index a3a276de75a..ae11d67388e 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -678,24 +678,7 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm, static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { - struct device_node *dp = op->node; - - pbm->name = dp->full_name; - printk("%s: SABRE PCI Bus Module\n", pbm->name); - - pbm->numa_node = -1; - - pbm->pci_ops = &sun4u_pci_ops; - pbm->config_space_reg_bits = 8; - - pbm->index = pci_num_pbms++; - - pbm->chip_type = PBM_CHIP_TYPE_SABRE; - pbm->op = op; - pci_get_pbm_props(pbm); - - pci_determine_mem_io_space(pbm); - + psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); sabre_scan_bus(pbm, &op->dev); } diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c index 07acc13637b..1b4d462513d 100644 --- a/arch/sparc64/kernel/psycho_common.c +++ b/arch/sparc64/kernel/psycho_common.c @@ -91,3 +91,25 @@ int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, return 0; } + +void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct of_device *op, + const char *chip_name, int chip_type) +{ + struct device_node *dp = op->node; + + pbm->name = dp->full_name; + pbm->numa_node = -1; + pbm->chip_type = chip_type; + pbm->chip_version = of_getintprop_default(dp, "version#", 0); + pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); + pbm->op = op; + pbm->pci_ops = &sun4u_pci_ops; + pbm->config_space_reg_bits = 8; + pbm->index = pci_num_pbms++; + pci_get_pbm_props(pbm); + pci_determine_mem_io_space(pbm); + + printk(KERN_INFO "%s: %s PCI Bus Module ver[%x:%x]\n", + pbm->name, chip_name, + pbm->chip_version, pbm->chip_revision); +} diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h index bffaff57d5e..adfbadb6986 100644 --- a/arch/sparc64/kernel/psycho_common.h +++ b/arch/sparc64/kernel/psycho_common.h @@ -5,4 +5,8 @@ extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, u32 dvma_offset, u32 dma_mask, unsigned long write_complete_offset); +extern void psycho_pbm_init_common(struct pci_pbm_info *pbm, + struct of_device *op, + const char *chip_name, int chip_type); + #endif /* _PSYCHO_COMMON_H */ -- cgit v1.2.3 From e6e003720fd7123482f77dcec19e930d272937fe Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 03:52:51 -0700 Subject: sparc64: Commonize large portions of PSYCHO error handling. The IOMMU and streaming cache error interrogation is moved here as well as the PCI error interrupt handler. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_psycho.c | 361 ------------------------------------ arch/sparc64/kernel/pci_sabre.c | 223 +--------------------- arch/sparc64/kernel/psycho_common.c | 353 +++++++++++++++++++++++++++++++++++ arch/sparc64/kernel/psycho_common.h | 11 ++ 4 files changed, 369 insertions(+), 579 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 2de51fb34ee..bac9c1ba40e 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -98,9 +98,6 @@ static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, } /* PSYCHO error handling support. */ -enum psycho_error_type { - UE_ERR, CE_ERR, PCI_ERR -}; /* Helper function of IOMMU error checking, which checks out * the state of the streaming buffers. The IOMMU lock is @@ -125,112 +122,10 @@ enum psycho_error_type { #define PSYCHO_STC_DATA_B 0xc000UL #define PSYCHO_STC_ERR_A 0xb400UL #define PSYCHO_STC_ERR_B 0xc400UL -#define PSYCHO_STCERR_WRITE 0x0000000000000002UL /* Write Error */ -#define PSYCHO_STCERR_READ 0x0000000000000001UL /* Read Error */ #define PSYCHO_STC_TAG_A 0xb800UL #define PSYCHO_STC_TAG_B 0xc800UL -#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL /* Physical Page Number */ -#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL /* Virtual Page Number */ -#define PSYCHO_STCTAG_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL /* Writable */ #define PSYCHO_STC_LINE_A 0xb900UL #define PSYCHO_STC_LINE_B 0xc900UL -#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL /* LRU Index */ -#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL /* Dirty Data Start Pointer */ -#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL /* Line Address */ -#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL /* Dirty Data End Pointer */ -#define PSYCHO_STCLINE_VALID 0x0000000000000002UL /* Valid */ -#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL /* Fetch Outstanding / Flush Necessary */ - -static DEFINE_SPINLOCK(stc_buf_lock); -static unsigned long stc_error_buf[128]; -static unsigned long stc_tag_buf[16]; -static unsigned long stc_line_buf[16]; - -static void psycho_check_stc_error(struct pci_pbm_info *pbm) -{ - struct strbuf *strbuf = &pbm->stc; - unsigned long err_base, tag_base, line_base; - u64 control; - int i; - - err_base = strbuf->strbuf_err_stat; - tag_base = strbuf->strbuf_tag_diag; - line_base = strbuf->strbuf_line_diag; - - spin_lock(&stc_buf_lock); - - /* This is __REALLY__ dangerous. When we put the - * streaming buffer into diagnostic mode to probe - * it's tags and error status, we _must_ clear all - * of the line tag valid bits before re-enabling - * the streaming buffer. If any dirty data lives - * in the STC when we do this, we will end up - * invalidating it before it has a chance to reach - * main memory. - */ - control = psycho_read(strbuf->strbuf_control); - psycho_write(strbuf->strbuf_control, - (control | PSYCHO_STRBUF_CTRL_DENAB)); - for (i = 0; i < 128; i++) { - unsigned long val; - - val = psycho_read(err_base + (i * 8UL)); - psycho_write(err_base + (i * 8UL), 0UL); - stc_error_buf[i] = val; - } - for (i = 0; i < 16; i++) { - stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL)); - stc_line_buf[i] = psycho_read(line_base + (i * 8UL)); - psycho_write(tag_base + (i * 8UL), 0UL); - psycho_write(line_base + (i * 8UL), 0UL); - } - - /* OK, state is logged, exit diagnostic mode. */ - psycho_write(strbuf->strbuf_control, control); - - for (i = 0; i < 16; i++) { - int j, saw_error, first, last; - - saw_error = 0; - first = i * 8; - last = first + 8; - for (j = first; j < last; j++) { - unsigned long errval = stc_error_buf[j]; - if (errval != 0) { - saw_error++; - printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", - pbm->name, - j, - (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, - (errval & PSYCHO_STCERR_READ) ? 1 : 0); - } - } - if (saw_error != 0) { - unsigned long tagval = stc_tag_buf[i]; - unsigned long lineval = stc_line_buf[i]; - printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", - pbm->name, - i, - ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), - (tagval & PSYCHO_STCTAG_VPN), - ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), - ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); - printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" - "V(%d)FOFN(%d)]\n", - pbm->name, - i, - ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), - ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), - ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), - ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), - ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), - ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); - } - } - - spin_unlock(&stc_buf_lock); -} /* When an Uncorrectable Error or a PCI Error happens, we * interrogate the IOMMU state to see if it is the cause. @@ -257,122 +152,7 @@ static void psycho_check_stc_error(struct pci_pbm_info *pbm) #define PSYCHO_IOMMU_TSBBASE 0x0208UL #define PSYCHO_IOMMU_FLUSH 0x0210UL #define PSYCHO_IOMMU_TAG 0xa580UL -#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) -#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) -#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) -#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) -#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) -#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL #define PSYCHO_IOMMU_DATA 0xa600UL -#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) -#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) -#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL -static void psycho_check_iommu_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar, - enum psycho_error_type type) -{ - struct iommu *iommu = pbm->iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = psycho_read(iommu->iommu_control); - if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { - char *type_string; - - /* Clear the error encountered bit. */ - control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; - psycho_write(iommu->iommu_control, control); - - switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); - - /* Put the IOMMU into diagnostic mode and probe - * it's TLB for entries with error status. - * - * It is very possible for another DVMA to occur - * while we do this probe, and corrupt the system - * further. But we are so screwed at this point - * that we are likely to crash hard anyways, so - * get as much diagnostic information to the - * console as we can. - */ - psycho_write(iommu->iommu_control, - control | PSYCHO_IOMMU_CTRL_DENAB); - for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; - - iommu_tag[i] = - psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL)); - - /* Now clear out the entry. */ - psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0); - psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0); - } - - /* Leave diagnostic mode. */ - psycho_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & PSYCHO_IOMMU_TAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { - case 0: - type_string = "Protection Error"; - break; - case 1: - type_string = "Invalid Error"; - break; - case 2: - type_string = "TimeOut Error"; - break; - case 3: - default: - type_string = "ECC Error"; - break; - }; - printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", - pbm->name, i, type_string, - ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), - ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), - (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); - printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", - pbm->name, i, - ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), - ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), - (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); - } - } - psycho_check_stc_error(pbm); - spin_unlock_irqrestore(&iommu->lock, flags); -} /* Uncorrectable Errors. Cause of the error and the address are * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors @@ -540,150 +320,9 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) */ #define PSYCHO_PCI_AFSR_A 0x2010UL #define PSYCHO_PCI_AFSR_B 0x4010UL -#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL /* Primary Master Abort Error */ -#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL /* Primary Target Abort Error */ -#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ -#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ -#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort Error */ -#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL /* Secondary Target Abort Error */ -#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ -#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ -#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ -#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL /* Trans was block operation */ -#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL /* Reserved */ -#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL /* MID causing the error */ -#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL /* Reserved */ #define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_B 0x4018UL -static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) -{ - unsigned long csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr = psycho_read(pbm->pci_csr); - csr_error_bits = - csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); - if (csr_error_bits) { - /* Clear the errors. */ - psycho_write(pbm->pci_csr, csr); - - /* Log 'em. */ - if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) - printk("%s: PCI streaming byte hole error asserted.\n", - pbm->name); - if (csr_error_bits & PSYCHO_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", pbm->name); - ret = IRQ_HANDLED; - } - pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) -{ - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = pbm->pci_afsr; - afar_reg = pbm->pci_afar; - - /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | - PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | - PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | - PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); - if (!error_bits) - return psycho_pcierr_intr_other(pbm); - psycho_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, - (((error_bits & PSYCHO_PCIAFSR_PMA) ? - "Master Abort" : - ((error_bits & PSYCHO_PCIAFSR_PTA) ? - "Target Abort" : - ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & PSYCHO_PCIAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", - pbm->name, - (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, - (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, - (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); - reported = 0; - if (afsr & PSYCHO_PCIAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & PSYCHO_PCIAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & PSYCHO_PCIAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan PBM's PCI bus for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { - psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); - pci_scan_for_target_abort(pbm, pbm->pci_bus); - } - if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); - - /* For excessive retries, PSYCHO/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); - - return IRQ_HANDLED; -} - /* XXX What about PowerFail/PowerManagement??? -DaveM */ #define PSYCHO_ECC_CTRL 0x0020 #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ae11d67388e..f8089aa84f6 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -210,95 +210,6 @@ static int hummingbird_p; static struct pci_bus *sabre_root_bus; -/* SABRE error handling support. */ -static void sabre_check_iommu_error(struct pci_pbm_info *pbm, - unsigned long afsr, - unsigned long afar) -{ - struct iommu *iommu = pbm->iommu; - unsigned long iommu_tag[16]; - unsigned long iommu_data[16]; - unsigned long flags; - u64 control; - int i; - - spin_lock_irqsave(&iommu->lock, flags); - control = sabre_read(iommu->iommu_control); - if (control & SABRE_IOMMUCTRL_ERR) { - char *type_string; - - /* Clear the error encountered bit. - * NOTE: On Sabre this is write 1 to clear, - * which is different from Psycho. - */ - sabre_write(iommu->iommu_control, control); - switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("%s: IOMMU Error, type[%s]\n", - pbm->name, type_string); - - /* Enter diagnostic mode and probe for error'd - * entries in the IOTLB. - */ - control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR); - sabre_write(iommu->iommu_control, - (control | SABRE_IOMMUCTRL_DENAB)); - for (i = 0; i < 16; i++) { - unsigned long base = pbm->controller_regs; - - iommu_tag[i] = - sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); - iommu_data[i] = - sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL)); - sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0); - sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0); - } - sabre_write(iommu->iommu_control, control); - - for (i = 0; i < 16; i++) { - unsigned long tag, data; - - tag = iommu_tag[i]; - if (!(tag & SABRE_IOMMUTAG_ERR)) - continue; - - data = iommu_data[i]; - switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) { - case 1: - type_string = "Invalid Error"; - break; - case 3: - type_string = "ECC Error"; - break; - default: - type_string = "Unknown"; - break; - }; - printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", - pbm->name, i, tag, type_string, - ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), - ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), - ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); - printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", - pbm->name, i, data, - ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), - ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), - ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), - ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); - } - } - spin_unlock_irqrestore(&iommu->lock, flags); -} - static irqreturn_t sabre_ue_intr(int irq, void *dev_id) { struct pci_pbm_info *pbm = dev_id; @@ -354,7 +265,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) printk("]\n"); /* Interrogate IOMMU for error status. */ - sabre_check_iommu_error(pbm, afsr, afar); + psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); return IRQ_HANDLED; } @@ -415,133 +326,6 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) -{ - unsigned long csr_reg, csr, csr_error_bits; - irqreturn_t ret = IRQ_NONE; - u16 stat; - - csr_reg = pbm->controller_regs + SABRE_PCICTRL; - csr = sabre_read(csr_reg); - csr_error_bits = - csr & SABRE_PCICTRL_SERR; - if (csr_error_bits) { - /* Clear the errors. */ - sabre_write(csr_reg, csr); - - /* Log 'em. */ - if (csr_error_bits & SABRE_PCICTRL_SERR) - printk("%s: PCI SERR signal asserted.\n", - pbm->name); - ret = IRQ_HANDLED; - } - pci_bus_read_config_word(sabre_root_bus, 0, - PCI_STATUS, &stat); - if (stat & (PCI_STATUS_PARITY | - PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | - PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR)) { - printk("%s: PCI bus error, PCI_STATUS[%04x]\n", - pbm->name, stat); - pci_bus_write_config_word(sabre_root_bus, 0, - PCI_STATUS, 0xffff); - ret = IRQ_HANDLED; - } - return ret; -} - -static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) -{ - struct pci_pbm_info *pbm = dev_id; - unsigned long afsr_reg, afar_reg; - unsigned long afsr, afar, error_bits; - int reported; - - afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; - afar_reg = pbm->controller_regs + SABRE_PIOAFAR; - - /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); - - /* Clear primary/secondary error status bits. */ - error_bits = afsr & - (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA | - SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR | - SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | - SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); - if (!error_bits) - return sabre_pcierr_intr_other(pbm); - sabre_write(afsr_reg, error_bits); - - /* Log the error. */ - printk("%s: PCI Error, primary error type[%s]\n", - pbm->name, - (((error_bits & SABRE_PIOAFSR_PMA) ? - "Master Abort" : - ((error_bits & SABRE_PIOAFSR_PTA) ? - "Target Abort" : - ((error_bits & SABRE_PIOAFSR_PRTRY) ? - "Excessive Retries" : - ((error_bits & SABRE_PIOAFSR_PPERR) ? - "Parity Error" : "???")))))); - printk("%s: bytemask[%04lx] was_block(%d)\n", - pbm->name, - (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, - (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); - printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); - printk("%s: PCI Secondary errors [", pbm->name); - reported = 0; - if (afsr & SABRE_PIOAFSR_SMA) { - reported++; - printk("(Master Abort)"); - } - if (afsr & SABRE_PIOAFSR_STA) { - reported++; - printk("(Target Abort)"); - } - if (afsr & SABRE_PIOAFSR_SRTRY) { - reported++; - printk("(Excessive Retries)"); - } - if (afsr & SABRE_PIOAFSR_SPERR) { - reported++; - printk("(Parity Error)"); - } - if (!reported) - printk("(none)"); - printk("]\n"); - - /* For the error types shown, scan both PCI buses for devices - * which have logged that error type. - */ - - /* If we see a Target Abort, this could be the result of an - * IOMMU translation error of some sort. It is extremely - * useful to log this information as usually it indicates - * a bug in the IOMMU support code or a PCI device driver. - */ - if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { - sabre_check_iommu_error(pbm, afsr, afar); - pci_scan_for_target_abort(pbm, pbm->pci_bus); - } - if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) - pci_scan_for_master_abort(pbm, pbm->pci_bus); - - /* For excessive retries, SABRE/PBM will abort the device - * and there is no way to specifically check for excessive - * retries in the config space status registers. So what - * we hope is that we'll catch it via the master/target - * abort events. - */ - - if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) - pci_scan_for_parity_error(pbm, pbm->pci_bus); - - return IRQ_HANDLED; -} - static void sabre_register_error_handlers(struct pci_pbm_info *pbm) { struct device_node *dp = pbm->op->node; @@ -588,7 +372,7 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) if (err) printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", pbm->name, err); - err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, + err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, "SABRE_PCIERR", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", @@ -679,6 +463,9 @@ static void __init sabre_pbm_init(struct pci_pbm_info *pbm, struct of_device *op) { psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); + pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; + pbm->pci_afar = pbm->controller_regs + SABRE_PIOAFAR; + pbm->pci_csr = pbm->controller_regs + SABRE_PCICTRL; sabre_scan_bus(pbm, &op->dev); } diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c index 1b4d462513d..6b188dfeeb9 100644 --- a/arch/sparc64/kernel/psycho_common.c +++ b/arch/sparc64/kernel/psycho_common.c @@ -3,15 +3,368 @@ * Copyright (C) 2008 David S. Miller */ #include +#include #include #include "pci_impl.h" +#include "iommu_common.h" #include "psycho_common.h" +#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL +#define PSYCHO_STCERR_WRITE 0x0000000000000002UL +#define PSYCHO_STCERR_READ 0x0000000000000001UL +#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL +#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL +#define PSYCHO_STCTAG_VALID 0x0000000000000002UL +#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL +#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL +#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL +#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL +#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL +#define PSYCHO_STCLINE_VALID 0x0000000000000002UL +#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL + +static DEFINE_SPINLOCK(stc_buf_lock); +static unsigned long stc_error_buf[128]; +static unsigned long stc_tag_buf[16]; +static unsigned long stc_line_buf[16]; + +static void psycho_check_stc_error(struct pci_pbm_info *pbm) +{ + unsigned long err_base, tag_base, line_base; + struct strbuf *strbuf = &pbm->stc; + u64 control; + int i; + + if (!strbuf->strbuf_control) + return; + + err_base = strbuf->strbuf_err_stat; + tag_base = strbuf->strbuf_tag_diag; + line_base = strbuf->strbuf_line_diag; + + spin_lock(&stc_buf_lock); + + /* This is __REALLY__ dangerous. When we put the streaming + * buffer into diagnostic mode to probe it's tags and error + * status, we _must_ clear all of the line tag valid bits + * before re-enabling the streaming buffer. If any dirty data + * lives in the STC when we do this, we will end up + * invalidating it before it has a chance to reach main + * memory. + */ + control = upa_readq(strbuf->strbuf_control); + upa_writeq(control | PSYCHO_STRBUF_CTRL_DENAB, strbuf->strbuf_control); + for (i = 0; i < 128; i++) { + u64 val; + + val = upa_readq(err_base + (i * 8UL)); + upa_writeq(0UL, err_base + (i * 8UL)); + stc_error_buf[i] = val; + } + for (i = 0; i < 16; i++) { + stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); + stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); + upa_writeq(0UL, tag_base + (i * 8UL)); + upa_writeq(0UL, line_base + (i * 8UL)); + } + + /* OK, state is logged, exit diagnostic mode. */ + upa_writeq(control, strbuf->strbuf_control); + + for (i = 0; i < 16; i++) { + int j, saw_error, first, last; + + saw_error = 0; + first = i * 8; + last = first + 8; + for (j = first; j < last; j++) { + u64 errval = stc_error_buf[j]; + if (errval != 0) { + saw_error++; + printk(KERN_ERR "%s: STC_ERR(%d)[wr(%d)" + "rd(%d)]\n", + pbm->name, + j, + (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, + (errval & PSYCHO_STCERR_READ) ? 1 : 0); + } + } + if (saw_error != 0) { + u64 tagval = stc_tag_buf[i]; + u64 lineval = stc_line_buf[i]; + printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)" + "V(%d)W(%d)]\n", + pbm->name, + i, + ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), + (tagval & PSYCHO_STCTAG_VPN), + ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), + ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); + printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)" + "LADDR(%lx)EP(%lx)V(%d)FOFN(%d)]\n", + pbm->name, + i, + ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), + ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), + ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), + ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), + ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), + ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); + } + } + + spin_unlock(&stc_buf_lock); +} + #define PSYCHO_IOMMU_TAG 0xa580UL #define PSYCHO_IOMMU_DATA 0xa600UL +static void psycho_record_iommu_tags_and_data(struct pci_pbm_info *pbm, + u64 *tag, u64 *data) +{ + int i; + + for (i = 0; i < 16; i++) { + unsigned long base = pbm->controller_regs; + unsigned long off = i * 8UL; + + tag[i] = upa_readq(base + PSYCHO_IOMMU_TAG+off); + data[i] = upa_readq(base + PSYCHO_IOMMU_DATA+off); + + /* Now clear out the entry. */ + upa_writeq(0, base + PSYCHO_IOMMU_TAG + off); + upa_writeq(0, base + PSYCHO_IOMMU_DATA + off); + } +} + +#define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) +#define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) +#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) +#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) +#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) +#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL +#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) +#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) +#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL + +static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm, + u64 *tag, u64 *data) +{ + int i; + + for (i = 0; i < 16; i++) { + u64 tag_val, data_val; + const char *type_str; + tag_val = tag[i]; + if (!(tag_val & PSYCHO_IOMMU_TAG_ERR)) + continue; + + data_val = data[i]; + switch((tag_val & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { + case 0: + type_str = "Protection Error"; + break; + case 1: + type_str = "Invalid Error"; + break; + case 2: + type_str = "TimeOut Error"; + break; + case 3: + default: + type_str = "ECC Error"; + break; + } + + printk(KERN_ERR "%s: IOMMU TAG(%d)[error(%s) wr(%d) " + "str(%d) sz(%dK) vpg(%08lx)]\n", + pbm->name, i, type_str, + ((tag_val & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), + ((tag_val & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), + ((tag_val & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), + (tag_val & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); + printk(KERN_ERR "%s: IOMMU DATA(%d)[valid(%d) cache(%d) " + "ppg(%016lx)]\n", + pbm->name, i, + ((data_val & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), + ((data_val & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), + (data_val & PSYCHO_IOMMU_DATA_PPAGE)<iommu; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + control = upa_readq(iommu->iommu_control); + if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { + const char *type_str; + + control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; + upa_writeq(control, iommu->iommu_control); + + switch ((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { + case 0: + type_str = "Protection Error"; + break; + case 1: + type_str = "Invalid Error"; + break; + case 2: + type_str = "TimeOut Error"; + break; + case 3: + default: + type_str = "ECC Error"; + break; + }; + printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", + pbm->name, type_str); + + /* It is very possible for another DVMA to occur while + * we do this probe, and corrupt the system further. + * But we are so screwed at this point that we are + * likely to crash hard anyways, so get as much + * diagnostic information to the console as we can. + */ + psycho_record_iommu_tags_and_data(pbm, iommu_tag, iommu_data); + psycho_dump_iommu_tags_and_data(pbm, iommu_tag, iommu_data); + } + psycho_check_stc_error(pbm); + spin_unlock_irqrestore(&iommu->lock, flags); +} + +#define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000UL +#define PSYCHO_PCICTRL_SERR 0x0000000400000000UL + +static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) +{ + irqreturn_t ret = IRQ_NONE; + u64 csr, csr_error_bits; + u16 stat; + + csr = upa_readq(pbm->pci_csr); + csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); + if (csr_error_bits) { + /* Clear the errors. */ + upa_writeq(csr, pbm->pci_csr); + + /* Log 'em. */ + if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) + printk(KERN_ERR "%s: PCI streaming byte hole " + "error asserted.\n", pbm->name); + if (csr_error_bits & PSYCHO_PCICTRL_SERR) + printk(KERN_ERR "%s: PCI SERR signal asserted.\n", + pbm->name); + ret = IRQ_HANDLED; + } + pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat); + if (stat & (PCI_STATUS_PARITY | + PCI_STATUS_SIG_TARGET_ABORT | + PCI_STATUS_REC_TARGET_ABORT | + PCI_STATUS_REC_MASTER_ABORT | + PCI_STATUS_SIG_SYSTEM_ERROR)) { + printk(KERN_ERR "%s: PCI bus error, PCI_STATUS[%04x]\n", + pbm->name, stat); + pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff); + ret = IRQ_HANDLED; + } + return ret; +} + +#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL +#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL +#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL +#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL +#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL +#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL +#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL +#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL +#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL +#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL +#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL +#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL +#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL +#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL + +irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) +{ + struct pci_pbm_info *pbm = dev_id; + u64 afsr, afar, error_bits; + int reported; + + afsr = upa_readq(pbm->pci_afsr); + afar = upa_readq(pbm->pci_afar); + error_bits = afsr & + (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | + PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | + PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | + PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); + if (!error_bits) + return psycho_pcierr_intr_other(pbm); + upa_writeq(error_bits, pbm->pci_afsr); + printk(KERN_ERR "%s: PCI Error, primary error type[%s]\n", + pbm->name, + (((error_bits & PSYCHO_PCIAFSR_PMA) ? + "Master Abort" : + ((error_bits & PSYCHO_PCIAFSR_PTA) ? + "Target Abort" : + ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? + "Excessive Retries" : + ((error_bits & PSYCHO_PCIAFSR_PPERR) ? + "Parity Error" : "???")))))); + printk(KERN_ERR "%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", + pbm->name, + (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, + (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, + (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); + printk(KERN_ERR "%s: PCI AFAR [%016lx]\n", pbm->name, afar); + printk(KERN_ERR "%s: PCI Secondary errors [", pbm->name); + reported = 0; + if (afsr & PSYCHO_PCIAFSR_SMA) { + reported++; + printk("(Master Abort)"); + } + if (afsr & PSYCHO_PCIAFSR_STA) { + reported++; + printk("(Target Abort)"); + } + if (afsr & PSYCHO_PCIAFSR_SRTRY) { + reported++; + printk("(Excessive Retries)"); + } + if (afsr & PSYCHO_PCIAFSR_SPERR) { + reported++; + printk("(Parity Error)"); + } + if (!reported) + printk("(none)"); + printk("]\n"); + + if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { + psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); + pci_scan_for_target_abort(pbm, pbm->pci_bus); + } + if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) + pci_scan_for_master_abort(pbm, pbm->pci_bus); + + if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) + pci_scan_for_parity_error(pbm, pbm->pci_bus); + + return IRQ_HANDLED; +} + static void psycho_iommu_flush(struct pci_pbm_info *pbm) { int i; diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h index adfbadb6986..b53aa8dcad2 100644 --- a/arch/sparc64/kernel/psycho_common.h +++ b/arch/sparc64/kernel/psycho_common.h @@ -1,6 +1,17 @@ #ifndef _PSYCHO_COMMON_H #define _PSYCHO_COMMON_H +enum psycho_error_type { + UE_ERR, CE_ERR, PCI_ERR +}; + +extern void psycho_check_iommu_error(struct pci_pbm_info *pbm, + unsigned long afsr, + unsigned long afar, + enum psycho_error_type type); + +extern irqreturn_t psycho_pcierr_intr(int irq, void *dev_id); + extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, u32 dvma_offset, u32 dma_mask, unsigned long write_complete_offset); -- cgit v1.2.3 From 87395fc6781ff269bad7f972b8abf2312a8ccdf6 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 10 Sep 2008 04:13:10 -0700 Subject: sparc64: Kill hand-crafted I/O accessors in PCI controller drivers. Use existing upa_{read,write}q() interfaces instead. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_fire.c | 136 +++++++++++++------------------ arch/sparc64/kernel/pci_psycho.c | 69 ++++++---------- arch/sparc64/kernel/pci_sabre.c | 61 ++++++-------- arch/sparc64/kernel/pci_schizo.c | 167 +++++++++++++++++---------------------- 4 files changed, 177 insertions(+), 256 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7e1a9b6717b..9462b68f489 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -12,27 +12,13 @@ #include #include +#include #include "pci_impl.h" #define DRIVER_NAME "fire" #define PFX DRIVER_NAME ": " -#define fire_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define fire_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - #define FIRE_IOMMU_CONTROL 0x40000UL #define FIRE_IOMMU_TSBBASE 0x40008UL #define FIRE_IOMMU_FLUSH 0x40100UL @@ -65,21 +51,21 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) /* * Invalidate TLB Entries. */ - fire_write(iommu->iommu_flushinv, ~(u64)0); + upa_writeq(~(u64)0, iommu->iommu_flushinv); err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, pbm->numa_node); if (err) return err; - fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); + upa_writeq(__pa(iommu->page_table) | 0x7UL, iommu->iommu_tsbbase); - control = fire_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control |= (0x00000400 /* TSB cache snoop enable */ | 0x00000300 /* Cache mode */ | 0x00000002 /* Bypass enable */ | 0x00000001 /* Translation enable */); - fire_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); return 0; } @@ -161,7 +147,7 @@ struct pci_msiq_entry { static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, unsigned long *head) { - *head = fire_read(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); + *head = upa_readq(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); return 0; } @@ -187,8 +173,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> MSIQ_WORD0_DATA0_SHIFT); - fire_write(pbm->pbm_regs + MSI_CLEAR(msi_num), - MSI_CLEAR_EQWR_N); + upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi_num)); /* Clear the entry. */ ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; @@ -204,7 +189,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, unsigned long head) { - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid), head); + upa_writeq(head, pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); return 0; } @@ -213,17 +198,16 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, { u64 val; - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); val &= ~(MSI_MAP_EQNUM); val |= msiqid; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); - fire_write(pbm->pbm_regs + MSI_CLEAR(msi), - MSI_CLEAR_EQWR_N); + upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi)); - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); val |= MSI_MAP_VALID; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); return 0; } @@ -233,12 +217,12 @@ static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) unsigned long msiqid; u64 val; - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); + val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); msiqid = (val & MSI_MAP_EQNUM); val &= ~MSI_MAP_VALID; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); + upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); return 0; } @@ -257,22 +241,19 @@ static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) memset((char *)pages, 0, PAGE_SIZE << order); pbm->msi_queues = (void *) pages; - fire_write(pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG, - (EVENT_QUEUE_BASE_ADDR_ALL_ONES | - __pa(pbm->msi_queues))); + upa_writeq((EVENT_QUEUE_BASE_ADDR_ALL_ONES | + __pa(pbm->msi_queues)), + pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG); - fire_write(pbm->pbm_regs + IMONDO_DATA0, - pbm->portid << 6); - fire_write(pbm->pbm_regs + IMONDO_DATA1, 0); + upa_writeq(pbm->portid << 6, pbm->pbm_regs + IMONDO_DATA0); + upa_writeq(0, pbm->pbm_regs + IMONDO_DATA1); - fire_write(pbm->pbm_regs + MSI_32BIT_ADDR, - pbm->msi32_start); - fire_write(pbm->pbm_regs + MSI_64BIT_ADDR, - pbm->msi64_start); + upa_writeq(pbm->msi32_start, pbm->pbm_regs + MSI_32BIT_ADDR); + upa_writeq(pbm->msi64_start, pbm->pbm_regs + MSI_64BIT_ADDR); for (i = 0; i < pbm->msiq_num; i++) { - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(i), 0); - fire_write(pbm->pbm_regs + EVENT_QUEUE_TAIL(i), 0); + upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_HEAD(i)); + upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_TAIL(i)); } return 0; @@ -306,9 +287,9 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, /* XXX iterate amongst the 4 IRQ controllers XXX */ int_ctrlr = (1UL << 6); - val = fire_read(imap_reg); + val = upa_readq(imap_reg); val |= (1UL << 63) | int_ctrlr; - fire_write(imap_reg, val); + upa_writeq(val, imap_reg); fixup = ((pbm->portid << 6) | devino) - int_ctrlr; @@ -316,9 +297,8 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, if (!virt_irq) return -ENOMEM; - fire_write(pbm->pbm_regs + - EVENT_QUEUE_CONTROL_SET(msiqid), - EVENT_QUEUE_CONTROL_SET_EN); + upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, + pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); return virt_irq; } @@ -386,49 +366,47 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) { u64 val; - fire_write(pbm->controller_regs + FIRE_PARITY_CONTROL, - FIRE_PARITY_ENAB); + upa_writeq(FIRE_PARITY_ENAB, + pbm->controller_regs + FIRE_PARITY_CONTROL); - fire_write(pbm->controller_regs + FIRE_FATAL_RESET_CTL, - (FIRE_FATAL_RESET_SPARE | + upa_writeq((FIRE_FATAL_RESET_SPARE | FIRE_FATAL_RESET_MB | FIRE_FATAL_RESET_CPE | FIRE_FATAL_RESET_APE | FIRE_FATAL_RESET_PIO | FIRE_FATAL_RESET_JW | FIRE_FATAL_RESET_JI | - FIRE_FATAL_RESET_JR)); + FIRE_FATAL_RESET_JR), + pbm->controller_regs + FIRE_FATAL_RESET_CTL); - fire_write(pbm->controller_regs + FIRE_CORE_INTR_ENABLE, ~(u64)0); + upa_writeq(~(u64)0, pbm->controller_regs + FIRE_CORE_INTR_ENABLE); - val = fire_read(pbm->pbm_regs + FIRE_TLU_CTRL); + val = upa_readq(pbm->pbm_regs + FIRE_TLU_CTRL); val |= (FIRE_TLU_CTRL_TIM | FIRE_TLU_CTRL_QDET | FIRE_TLU_CTRL_CFG); - fire_write(pbm->pbm_regs + FIRE_TLU_CTRL, val); - fire_write(pbm->pbm_regs + FIRE_TLU_DEV_CTRL, 0); - fire_write(pbm->pbm_regs + FIRE_TLU_LINK_CTRL, - FIRE_TLU_LINK_CTRL_CLK); - - fire_write(pbm->pbm_regs + FIRE_LPU_RESET, 0); - fire_write(pbm->pbm_regs + FIRE_LPU_LLCFG, - FIRE_LPU_LLCFG_VC0); - fire_write(pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL, - (FIRE_LPU_FCTRL_UCTRL_N | - FIRE_LPU_FCTRL_UCTRL_P)); - fire_write(pbm->pbm_regs + FIRE_LPU_TXL_FIFOP, - ((0xffff << 16) | (0x0000 << 0))); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2, 3000000); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3, 500000); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4, - (2 << 16) | (140 << 8)); - fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5, 0); - - fire_write(pbm->pbm_regs + FIRE_DMC_IENAB, ~(u64)0); - fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_A, 0); - fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_B, 0); - - fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); + upa_writeq(val, pbm->pbm_regs + FIRE_TLU_CTRL); + upa_writeq(0, pbm->pbm_regs + FIRE_TLU_DEV_CTRL); + upa_writeq(FIRE_TLU_LINK_CTRL_CLK, + pbm->pbm_regs + FIRE_TLU_LINK_CTRL); + + upa_writeq(0, pbm->pbm_regs + FIRE_LPU_RESET); + upa_writeq(FIRE_LPU_LLCFG_VC0, pbm->pbm_regs + FIRE_LPU_LLCFG); + upa_writeq((FIRE_LPU_FCTRL_UCTRL_N | FIRE_LPU_FCTRL_UCTRL_P), + pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL); + upa_writeq(((0xffff << 16) | (0x0000 << 0)), + pbm->pbm_regs + FIRE_LPU_TXL_FIFOP); + upa_writeq(3000000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2); + upa_writeq(500000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3); + upa_writeq((2 << 16) | (140 << 8), + pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4); + upa_writeq(0, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5); + + upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_DMC_IENAB); + upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_A); + upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_B); + + upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB); } static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index bac9c1ba40e..89733468065 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -25,25 +26,6 @@ #define DRIVER_NAME "psycho" #define PFX DRIVER_NAME ": " -/* All PSYCHO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define psycho_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define psycho_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* Misc. PSYCHO PCI controller register offsets and definitions. */ #define PSYCHO_CONTROL 0x0010UL #define PSYCHO_CONTROL_IMPL 0xf000000000000000UL /* Implementation of this PSYCHO*/ @@ -182,8 +164,8 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) int reported; /* Latch uncorrectable error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear the primary/secondary error status bits. */ error_bits = afsr & @@ -191,7 +173,7 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - psycho_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s]\n", @@ -261,8 +243,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) int reported; /* Latch error status. */ - afar = psycho_read(afar_reg); - afsr = psycho_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -270,7 +252,7 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - psycho_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -373,27 +355,26 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) "err=%d\n", pbm->name, err); /* Enable UE and CE interrupts for controller. */ - psycho_write(base + PSYCHO_ECC_CTRL, - (PSYCHO_ECCCTRL_EE | - PSYCHO_ECCCTRL_UE | - PSYCHO_ECCCTRL_CE)); + upa_writeq((PSYCHO_ECCCTRL_EE | + PSYCHO_ECCCTRL_UE | + PSYCHO_ECCCTRL_CE), base + PSYCHO_ECC_CTRL); /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = psycho_read(base + PSYCHO_PCIA_CTRL); + tmp = upa_readq(base + PSYCHO_PCIA_CTRL); tmp |= (PSYCHO_PCICTRL_SERR | PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIA_CTRL, tmp); + upa_writeq(tmp, base + PSYCHO_PCIA_CTRL); - tmp = psycho_read(base + PSYCHO_PCIB_CTRL); + tmp = upa_readq(base + PSYCHO_PCIB_CTRL); tmp |= (PSYCHO_PCICTRL_SERR | PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_EEN); tmp &= ~(PSYCHO_PCICTRL_SBH_INT); - psycho_write(base + PSYCHO_PCIB_CTRL, tmp); + upa_writeq(tmp, base + PSYCHO_PCIB_CTRL); } /* PSYCHO boot time probing and initialization. */ @@ -443,28 +424,28 @@ static void psycho_controller_hwinit(struct pci_pbm_info *pbm) { u64 tmp; - psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); + upa_writeq(5, pbm->controller_regs + PSYCHO_IRQ_RETRY); /* Enable arbiter for all PCI slots. */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_CTRL); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_CTRL); tmp |= PSYCHO_PCICTRL_AEN; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_CTRL); /* Disable DMA write / PIO read synchronization on * both PCI bus segments. * [ U2P Erratum 1243770, STP2223BGA data sheet ] */ - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_DIAG); - tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); + tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_DIAG); tmp |= PSYCHO_PCIDIAG_DDWSYNC; - psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); + upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_DIAG); } static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, @@ -509,7 +490,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, */ #undef PSYCHO_STRBUF_RERUN_ENABLE #undef PSYCHO_STRBUF_RERUN_DISABLE - control = psycho_read(pbm->stc.strbuf_control); + control = upa_readq(pbm->stc.strbuf_control); control |= PSYCHO_STRBUF_CTRL_ENAB; control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); #ifdef PSYCHO_STRBUF_RERUN_ENABLE @@ -519,7 +500,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, control |= PSYCHO_STRBUF_CTRL_RRDIS; #endif #endif - psycho_write(pbm->stc.strbuf_control, control); + upa_writeq(control, pbm->stc.strbuf_control); pbm->stc.strbuf_enabled = 1; } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index f8089aa84f6..713257b6963 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -25,25 +26,6 @@ #define DRIVER_NAME "sabre" #define PFX DRIVER_NAME ": " -/* All SABRE registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define sabre_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define sabre_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* SABRE PCI controller register offsets and definitions. */ #define SABRE_UE_AFSR 0x0030UL #define SABRE_UEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */ @@ -219,8 +201,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) int reported; /* Latch uncorrectable error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear the primary/secondary error status bits. */ error_bits = afsr & @@ -229,7 +211,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); if (!error_bits) return IRQ_NONE; - sabre_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s%s]\n", @@ -279,8 +261,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) int reported; /* Latch error status. */ - afar = sabre_read(afar_reg); - afsr = sabre_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -288,7 +270,7 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); if (!error_bits) return IRQ_NONE; - sabre_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -354,19 +336,20 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) * registering the handler so that we don't get spurious * interrupts. */ - sabre_write(base + SABRE_UE_AFSR, - (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | - SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | - SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); + upa_writeq((SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | + SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | + SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), + base + SABRE_UE_AFSR); err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); if (err) printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", pbm->name, err); - sabre_write(base + SABRE_CE_AFSR, - (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | - SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); + upa_writeq((SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | + SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR), + base + SABRE_CE_AFSR); + err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); if (err) @@ -378,9 +361,9 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", pbm->name, err); - tmp = sabre_read(base + SABRE_PCICTRL); + tmp = upa_readq(base + SABRE_PCICTRL); tmp |= SABRE_PCICTRL_ERREN; - sabre_write(base + SABRE_PCICTRL, tmp); + upa_writeq(tmp, base + SABRE_PCICTRL); } static void apb_init(struct pci_bus *sabre_bus) @@ -533,16 +516,16 @@ static int __devinit sabre_probe(struct of_device *op, /* PCI first */ for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + upa_writeq(0x0UL, pbm->controller_regs + clear_irq); /* Then OBIO */ for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) - sabre_write(pbm->controller_regs + clear_irq, 0x0UL); + upa_writeq(0x0UL, pbm->controller_regs + clear_irq); /* Error interrupts are enabled later after the bus scan. */ - sabre_write(pbm->controller_regs + SABRE_PCICTRL, - (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | - SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); + upa_writeq((SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | + SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN), + pbm->controller_regs + SABRE_PCICTRL); /* Now map in PCI config space for entire SABRE. */ pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index c30856541bb..45d9dba1ba1 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "pci_impl.h" #include "iommu_common.h" @@ -22,25 +23,6 @@ #define DRIVER_NAME "schizo" #define PFX DRIVER_NAME ": " -/* All SCHIZO registers are 64-bits. The following accessor - * routines are how they are accessed. The REG parameter - * is a physical address. - */ -#define schizo_read(__reg) \ -({ u64 __ret; \ - __asm__ __volatile__("ldxa [%1] %2, %0" \ - : "=r" (__ret) \ - : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory"); \ - __ret; \ -}) -#define schizo_write(__reg, __val) \ - __asm__ __volatile__("stxa %0, [%1] %2" \ - : /* no outputs */ \ - : "r" (__val), "r" (__reg), \ - "i" (ASI_PHYS_BYPASS_EC_E) \ - : "memory") - /* This is a convention that at least Excalibur and Merlin * follow. I suppose the SCHIZO used in Starcat and friends * will do similar. @@ -164,25 +146,25 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, * invalidating it before it has a chance to reach * main memory. */ - control = schizo_read(strbuf->strbuf_control); - schizo_write(strbuf->strbuf_control, - (control | SCHIZO_STRBUF_CTRL_DENAB)); + control = upa_readq(strbuf->strbuf_control); + upa_writeq((control | SCHIZO_STRBUF_CTRL_DENAB), + strbuf->strbuf_control); for (i = 0; i < 128; i++) { unsigned long val; - val = schizo_read(err_base + (i * 8UL)); - schizo_write(err_base + (i * 8UL), 0UL); + val = upa_readq(err_base + (i * 8UL)); + upa_writeq(0UL, err_base + (i * 8UL)); stc_error_buf[i] = val; } for (i = 0; i < 16; i++) { - stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL)); - stc_line_buf[i] = schizo_read(line_base + (i * 8UL)); - schizo_write(tag_base + (i * 8UL), 0UL); - schizo_write(line_base + (i * 8UL), 0UL); + stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); + stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); + upa_writeq(0UL, tag_base + (i * 8UL)); + upa_writeq(0UL, line_base + (i * 8UL)); } /* OK, state is logged, exit diagnostic mode. */ - schizo_write(strbuf->strbuf_control, control); + upa_writeq(control, strbuf->strbuf_control); for (i = 0; i < 16; i++) { int j, saw_error, first, last; @@ -259,14 +241,14 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, int i; spin_lock_irqsave(&iommu->lock, flags); - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { unsigned long base; char *type_string; /* Clear the error encountered bit. */ control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { case 0: @@ -296,24 +278,24 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, * get as much diagnostic information to the * console as we can. */ - schizo_write(iommu->iommu_control, - control | SCHIZO_IOMMU_CTRL_DENAB); + upa_writeq(control | SCHIZO_IOMMU_CTRL_DENAB, + iommu->iommu_control); base = pbm->pbm_regs; for (i = 0; i < 16; i++) { iommu_tag[i] = - schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL)); + upa_readq(base + SCHIZO_IOMMU_TAG + (i * 8UL)); iommu_data[i] = - schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL)); + upa_readq(base + SCHIZO_IOMMU_DATA + (i * 8UL)); /* Now clear out the entry. */ - schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0); - schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0); + upa_writeq(0, base + SCHIZO_IOMMU_TAG + (i * 8UL)); + upa_writeq(0, base + SCHIZO_IOMMU_DATA + (i * 8UL)); } /* Leave diagnostic mode. */ - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); for (i = 0; i < 16; i++) { unsigned long tag, data; @@ -394,7 +376,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) int reported, limit; /* Latch uncorrectable error status. */ - afar = schizo_read(afar_reg); + afar = upa_readq(afar_reg); /* If either of the error pending bits are set in the * AFSR, the error status is being actively updated by @@ -402,7 +384,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) */ limit = 1000; do { - afsr = schizo_read(afsr_reg); + afsr = upa_readq(afsr_reg); } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); /* Clear the primary/secondary error status bits. */ @@ -411,7 +393,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); if (!error_bits) return IRQ_NONE; - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Uncorrectable Error, primary error type[%s]\n", @@ -482,7 +464,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) int reported, limit; /* Latch error status. */ - afar = schizo_read(afar_reg); + afar = upa_readq(afar_reg); /* If either of the error pending bits are set in the * AFSR, the error status is being actively updated by @@ -490,7 +472,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) */ limit = 1000; do { - afsr = schizo_read(afsr_reg); + afsr = upa_readq(afsr_reg); } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); /* Clear primary/secondary error status bits. */ @@ -499,7 +481,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); if (!error_bits) return IRQ_NONE; - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: Correctable Error, primary error type[%s]\n", @@ -601,7 +583,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) u16 stat; csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; - csr = schizo_read(csr_reg); + csr = upa_readq(csr_reg); csr_error_bits = csr & (SCHIZO_PCICTRL_BUS_UNUS | SCHIZO_PCICTRL_TTO_ERR | @@ -611,7 +593,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) SCHIZO_PCICTRL_SERR); if (csr_error_bits) { /* Clear the errors. */ - schizo_write(csr_reg, csr); + upa_writeq(csr, csr_reg); /* Log 'em. */ if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) @@ -661,8 +643,8 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) afar_reg = base + SCHIZO_PCI_AFAR; /* Latch error status. */ - afar = schizo_read(afar_reg); - afsr = schizo_read(afsr_reg); + afar = upa_readq(afar_reg); + afsr = upa_readq(afsr_reg); /* Clear primary/secondary error status bits. */ error_bits = afsr & @@ -674,7 +656,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); if (!error_bits) return schizo_pcierr_intr_other(pbm); - schizo_write(afsr_reg, error_bits); + upa_writeq(error_bits, afsr_reg); /* Log the error. */ printk("%s: PCI Error, primary error type[%s]\n", @@ -807,9 +789,9 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) struct pci_pbm_info *pbm = dev_id; u64 errlog; - errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, - errlog & ~(SAFARI_ERRLOG_ERROUT)); + errlog = upa_readq(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); + upa_writeq(errlog & ~(SAFARI_ERRLOG_ERROUT), + pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); if (!(errlog & BUS_ERROR_UNMAP)) { printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", @@ -909,10 +891,9 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) } /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); + upa_writeq((SCHIZO_ECCCTRL_EE | + SCHIZO_ECCCTRL_UE | + SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); /* Enable PCI Error interrupts and clear error * bits. @@ -925,10 +906,10 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) err_no_mask = SCHIZO_PCICTRL_DTO_ERR; - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | @@ -937,7 +918,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | SCHIZO_PCIAFSR_STTO); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); + upa_writeq(err_mask, pbm->pbm_regs + SCHIZO_PCI_AFSR); err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | @@ -949,11 +930,11 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_APERR | BUS_ERROR_UNMAP | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); + upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), + pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, - (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); + upa_writeq((SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)), + pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL); } static void schizo_register_error_handlers(struct pci_pbm_info *pbm) @@ -1005,10 +986,9 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) } /* Enable UE and CE interrupts for controller. */ - schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, - (SCHIZO_ECCCTRL_EE | - SCHIZO_ECCCTRL_UE | - SCHIZO_ECCCTRL_CE)); + upa_writeq((SCHIZO_ECCCTRL_EE | + SCHIZO_ECCCTRL_UE | + SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); err_mask = (SCHIZO_PCICTRL_BUS_UNUS | SCHIZO_PCICTRL_ESLCK | @@ -1024,18 +1004,18 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) /* Enable PCI Error interrupts and clear error * bits for each PBM. */ - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); tmp |= err_mask; tmp &= ~err_no_mask; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, - (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | - SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | - SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | - SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | - SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | - SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); + upa_writeq((SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | + SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | + SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | + SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | + SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | + SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS), + pbm->pbm_regs + SCHIZO_PCI_AFSR); /* Make all Safari error conditions fatal except unmapped * errors which we make generate interrupts. @@ -1062,8 +1042,8 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); #endif - schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, - (SCHIZO_SAFERRCTRL_EN | err_mask)); + upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), + pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); } static void pbm_config_busmastering(struct pci_pbm_info *pbm) @@ -1133,12 +1113,12 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) * streaming buffer and leave the rerun-disable * setting however OBP set it. */ - control = schizo_read(pbm->stc.strbuf_control); + control = upa_readq(pbm->stc.strbuf_control); control &= ~(SCHIZO_STRBUF_CTRL_LPTR | SCHIZO_STRBUF_CTRL_LENAB | SCHIZO_STRBUF_CTRL_DENAB); control |= SCHIZO_STRBUF_CTRL_ENAB; - schizo_write(pbm->stc.strbuf_control, control); + upa_writeq(control, pbm->stc.strbuf_control); pbm->stc.strbuf_enabled = 1; } @@ -1199,15 +1179,15 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) /* * Invalidate TLB Entries. */ - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control |= SCHIZO_IOMMU_CTRL_DENAB; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; for (i = 0; i < 16; i++) { - schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); - schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); + upa_writeq(0, pbm->pbm_regs + tagbase + (i * 8UL)); + upa_writeq(0, pbm->pbm_regs + database + (i * 8UL)); } /* Leave diag mode enabled for full-flushing done @@ -1220,9 +1200,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) return err; } - schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); + upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); - control = schizo_read(iommu->iommu_control); + control = upa_readq(iommu->iommu_control); control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); switch (tsbsize) { case 64: @@ -1234,7 +1214,7 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) } control |= SCHIZO_IOMMU_CTRL_ENAB; - schizo_write(iommu->iommu_control, control); + upa_writeq(control, iommu->iommu_control); return 0; } @@ -1277,9 +1257,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) { u64 tmp; - schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); + upa_writeq(5, pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY); - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); /* Enable arbiter for all PCI slots. */ tmp |= 0xff; @@ -1304,13 +1284,13 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) SCHIZO_PCICTRL_RDO_PREF | SCHIZO_PCICTRL_RDL_PREF); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); - tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); + tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_DIAG); tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | SCHIZO_PCIDIAG_D_RETRY | SCHIZO_PCIDIAG_D_INTSYNC); - schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); + upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_DIAG); if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { /* Clear prefetch lengths to workaround a bug in @@ -1322,8 +1302,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) TOMATILLO_IOC_RDONE_CPENAB | TOMATILLO_IOC_RDLINE_CPENAB); - schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, - tmp); + upa_writeq(tmp, pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR); } } -- cgit v1.2.3 From 8f20b20de73eeabe3d35e67e0ce993eceef07492 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:19:22 -0700 Subject: sparc64: Fix sparse warnings in global reg snapshotting. Lots of shadowed local variables and global_reg_snapshot[] needs an extern declaration in asm/ptrace_64.h. Signed-off-by: David S. Miller --- arch/sparc64/kernel/process.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 11bb6c4612d..d5e2acef987 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -215,7 +215,6 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; if (regs->tstate & TSTATE_PRIV) { - struct thread_info *tp = current_thread_info(); struct reg_window *rw; rw = (struct reg_window *) @@ -271,7 +270,6 @@ void __trigger_all_cpu_backtrace(void) for_each_online_cpu(cpu) { struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; - struct thread_info *tp; __global_reg_poll(gp); -- cgit v1.2.3 From 17f04fbb0f7153d95ec33da81189b113cc778157 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:33:53 -0700 Subject: sysctl: Use header file for sysctl knob declarations on sparc. This also takes care of a sparse warning as scons_pwroff's definition point. Signed-off-by: David S. Miller --- arch/sparc64/kernel/reboot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c index 11f24966063..ef89d3d6974 100644 --- a/arch/sparc64/kernel/reboot.c +++ b/arch/sparc64/kernel/reboot.c @@ -7,6 +7,7 @@ #include #include +#include #include #include -- cgit v1.2.3 From d8ada0a2cd11c991d8193a3f7d37f1806c93c4a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:39:11 -0700 Subject: sparc64: Fix sparse warnings in kernel/time.c 1) Using "clock" as a local variable shadows a global variable of the same name declared in linux/clocksource.h 2) rtc_cmos_resource should be static Signed-off-by: David S. Miller --- arch/sparc64/kernel/time.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 8d2ca04d309..80d71a5ce1e 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -409,7 +409,7 @@ int update_persistent_clock(struct timespec now) unsigned long cmos_regs; EXPORT_SYMBOL(cmos_regs); -struct resource rtc_cmos_resource; +static struct resource rtc_cmos_resource; static struct platform_device rtc_cmos_device = { .name = "rtc_cmos", @@ -621,7 +621,7 @@ fs_initcall(clock_init); static unsigned long sparc64_init_timers(void) { struct device_node *dp; - unsigned long clock; + unsigned long freq; dp = of_find_node_by_path("/"); if (tlb_type == spitfire) { @@ -634,17 +634,17 @@ static unsigned long sparc64_init_timers(void) if (manuf == 0x17 && impl == 0x13) { /* Hummingbird, aka Ultra-IIe */ tick_ops = &hbtick_operations; - clock = of_getintprop_default(dp, "stick-frequency", 0); + freq = of_getintprop_default(dp, "stick-frequency", 0); } else { tick_ops = &tick_operations; - clock = local_cpu_data().clock_tick; + freq = local_cpu_data().clock_tick; } } else { tick_ops = &stick_operations; - clock = of_getintprop_default(dp, "stick-frequency", 0); + freq = of_getintprop_default(dp, "stick-frequency", 0); } - return clock; + return freq; } struct freq_table { @@ -836,16 +836,16 @@ EXPORT_SYMBOL(udelay); void __init time_init(void) { - unsigned long clock = sparc64_init_timers(); + unsigned long freq = sparc64_init_timers(); - tb_ticks_per_usec = clock / USEC_PER_SEC; + tb_ticks_per_usec = freq / USEC_PER_SEC; timer_ticks_per_nsec_quotient = - clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT); + clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); clocksource_tick.name = tick_ops->name; clocksource_tick.mult = - clocksource_hz2mult(clock, + clocksource_hz2mult(freq, clocksource_tick.shift); clocksource_tick.read = tick_ops->get_tick; @@ -856,7 +856,7 @@ void __init time_init(void) sparc64_clockevent.name = tick_ops->name; - setup_clockevent_multiplier(clock); + setup_clockevent_multiplier(freq); sparc64_clockevent.max_delta_ns = clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); -- cgit v1.2.3 From 7e0b1e6186c755becf8b19c844c63db1a551898b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:46:40 -0700 Subject: sparc64: Fix sparse warnings in visemul.c 1) edge8 tables should be static 2) add vis_emul() extern decl. to asm/visasm.h Signed-off-by: David S. Miller --- arch/sparc64/kernel/traps.c | 1 - arch/sparc64/kernel/visemul.c | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 71644da6cad..9378896589f 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2270,7 +2270,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) extern int handle_popc(u32 insn, struct pt_regs *regs); extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); -extern int vis_emul(struct pt_regs *, unsigned int); void do_illegal_instruction(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c index c3fd64706b5..9e05cb5cb85 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc64/kernel/visemul.c @@ -243,7 +243,7 @@ static inline unsigned int *fps_regaddr(struct fpustate *f, struct edge_tab { u16 left, right; }; -struct edge_tab edge8_tab[8] = { +static struct edge_tab edge8_tab[8] = { { 0xff, 0x80 }, { 0x7f, 0xc0 }, { 0x3f, 0xe0 }, @@ -253,7 +253,7 @@ struct edge_tab edge8_tab[8] = { { 0x03, 0xfe }, { 0x01, 0xff }, }; -struct edge_tab edge8_tab_l[8] = { +static struct edge_tab edge8_tab_l[8] = { { 0xff, 0x01 }, { 0xfe, 0x03 }, { 0xfc, 0x07 }, @@ -263,23 +263,23 @@ struct edge_tab edge8_tab_l[8] = { { 0xc0, 0x7f }, { 0x80, 0xff }, }; -struct edge_tab edge16_tab[4] = { +static struct edge_tab edge16_tab[4] = { { 0xf, 0x8 }, { 0x7, 0xc }, { 0x3, 0xe }, { 0x1, 0xf }, }; -struct edge_tab edge16_tab_l[4] = { +static struct edge_tab edge16_tab_l[4] = { { 0xf, 0x1 }, { 0xe, 0x3 }, { 0xc, 0x7 }, { 0x8, 0xf }, }; -struct edge_tab edge32_tab[2] = { +static struct edge_tab edge32_tab[2] = { { 0x3, 0x2 }, { 0x1, 0x3 }, }; -struct edge_tab edge32_tab_l[2] = { +static struct edge_tab edge32_tab_l[2] = { { 0x3, 0x1 }, { 0x2, 0x3 }, }; -- cgit v1.2.3 From c91e2ecad0a392604ece6e53d38b484918060825 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:52:35 -0700 Subject: sparc64: Fix sparse warnings in prom.c 1) Testing null with '0' 2) returning void-valued expression Signed-off-by: David S. Miller --- arch/sparc64/kernel/prom.c | 85 ++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 30 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 922dd612612..5f50e2b17a8 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -38,7 +38,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) { struct device_node *np; - for (np = allnodes; np != 0; np = np->allnext) + for (np = allnodes; np; np = np->allnext) if (np->node == handle) break; @@ -1043,22 +1043,30 @@ static void __init irq_trans_init(struct device_node *dp) for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { struct irq_trans *t = &pci_irq_trans_table[i]; - if (!strcmp(model, t->name)) - return t->init(dp); + if (!strcmp(model, t->name)) { + t->init(dp); + return; + } } } #endif #ifdef CONFIG_SBUS if (!strcmp(dp->name, "sbus") || - !strcmp(dp->name, "sbi")) - return sbus_irq_trans_init(dp); + !strcmp(dp->name, "sbi")) { + sbus_irq_trans_init(dp); + return; + } #endif if (!strcmp(dp->name, "fhc") && - !strcmp(dp->parent->name, "central")) - return central_irq_trans_init(dp); + !strcmp(dp->parent->name, "central")) { + central_irq_trans_init(dp); + return; + } if (!strcmp(dp->name, "virtual-devices") || - !strcmp(dp->name, "niu")) - return sun4v_vdev_irq_trans_init(dp); + !strcmp(dp->name, "niu")) { + sun4v_vdev_irq_trans_init(dp); + return; + } } static int is_root_node(const struct device_node *dp) @@ -1329,32 +1337,49 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf) if (parent != NULL) { if (!strcmp(parent->type, "pci") || - !strcmp(parent->type, "pciex")) - return pci_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "sbus")) - return sbus_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "upa")) - return upa_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "ebus")) - return ebus_path_component(dp, tmp_buf); + !strcmp(parent->type, "pciex")) { + pci_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "sbus")) { + sbus_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "upa")) { + upa_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "ebus")) { + ebus_path_component(dp, tmp_buf); + return; + } if (!strcmp(parent->name, "usb") || - !strcmp(parent->name, "hub")) - return usb_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "i2c")) - return i2c_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "firewire")) - return ieee1394_path_component(dp, tmp_buf); - if (!strcmp(parent->type, "virtual-devices")) - return vdev_path_component(dp, tmp_buf); - + !strcmp(parent->name, "hub")) { + usb_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "i2c")) { + i2c_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "firewire")) { + ieee1394_path_component(dp, tmp_buf); + return; + } + if (!strcmp(parent->type, "virtual-devices")) { + vdev_path_component(dp, tmp_buf); + return; + } /* "isa" is handled with platform naming */ } /* Use platform naming convention. */ - if (tlb_type == hypervisor) - return sun4v_path_component(dp, tmp_buf); - else - return sun4u_path_component(dp, tmp_buf); + if (tlb_type == hypervisor) { + sun4v_path_component(dp, tmp_buf); + return; + } else { + sun4u_path_component(dp, tmp_buf); + } } static char * __init build_path_component(struct device_node *dp) -- cgit v1.2.3 From 21cd8833933ef20a0bbb368ea00876cbfc06141b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:53:41 -0700 Subject: sparc64: Fix sparse warnings in of_device.c Passing unsigned int pointer where plain int pointer is expected. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 5c4fbc23aee..ef05d14bd7f 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -401,8 +401,7 @@ static int __init build_one_resource(struct device_node *parent, int na, int ns, int pna) { const u32 *ranges; - unsigned int rlen; - int rone; + int rone, rlen; ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { -- cgit v1.2.3 From 77d10d0e63dcc4f961cb416447d64281300e5a01 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 11 Sep 2008 23:57:40 -0700 Subject: sparc64: Fix sparse warnings in pci.c 1) Declare pci_poke_* in pci_impl.h 2) of_create_pci_dev() should be static 3) ->setup_msi_irq() wants an unsigned int pointer not a plain int one 4) void value expression return in arch_teardown_msi_irq() Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci.c | 14 ++++++-------- arch/sparc64/kernel/pci_impl.h | 4 ++++ arch/sparc64/kernel/traps.c | 5 +---- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c6e81dea2cf..e12a0586b43 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -242,9 +242,9 @@ static void pci_parse_of_addrs(struct of_device *op, } } -struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, - struct device_node *node, - struct pci_bus *bus, int devfn) +static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, + struct device_node *node, + struct pci_bus *bus, int devfn) { struct dev_archdata *sd; struct of_device *op; @@ -998,7 +998,7 @@ EXPORT_SYMBOL(pci_domain_nr); int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) { struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - int virt_irq; + unsigned int virt_irq; if (!pbm->setup_msi_irq) return -EINVAL; @@ -1012,10 +1012,8 @@ void arch_teardown_msi_irq(unsigned int virt_irq) struct pci_dev *pdev = entry->dev; struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - if (!pbm->teardown_msi_irq) - return; - - return pbm->teardown_msi_irq(virt_irq, pdev); + if (pbm->teardown_msi_irq) + pbm->teardown_msi_irq(virt_irq, pdev); } #endif /* !(CONFIG_PCI_MSI) */ diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index b300f39e9e8..03186824327 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -178,4 +178,8 @@ extern void pci_config_write32(u32 *addr, u32 val); extern struct pci_ops sun4u_pci_ops; extern struct pci_ops sun4v_pci_ops; +extern volatile int pci_poke_in_progress; +extern volatile int pci_poke_cpu; +extern volatile int pci_poke_faulted; + #endif /* !(PCI_IMPL_H) */ diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 9378896589f..342da216423 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -341,10 +341,7 @@ void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, u } #ifdef CONFIG_PCI -/* This is really pathetic... */ -extern volatile int pci_poke_in_progress; -extern volatile int pci_poke_cpu; -extern volatile int pci_poke_faulted; +#include "pci_impl.h" #endif /* When access exceptions happen, we must do this. */ -- cgit v1.2.3 From 8d2aec512304144cbb4f7dbb484626fb598b698e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:01:03 -0700 Subject: sparc64: Fix sparse warnings in pci_sun4v.c 'err' variable shadowing in pci_sun4v_probe() Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_sun4v.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 97a77bcd255..e86c73ec167 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -942,9 +942,9 @@ static int __devinit pci_sun4v_probe(struct of_device *op, dp = op->node; if (!hvapi_negotiated++) { - int err = sun4v_hvapi_register(HV_GRP_PCI, - vpci_major, - &vpci_minor); + err = sun4v_hvapi_register(HV_GRP_PCI, + vpci_major, + &vpci_minor); if (err) { printk(KERN_ERR PFX "Could not register hvapi, " -- cgit v1.2.3 From 7694b024f145c4a598cde5fcccfd3fe5eac4027b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:04:33 -0700 Subject: sparc64: Fix sparse warnings in vio.c Several variables should be marked static. Signed-off-by: David S. Miller --- arch/sparc64/kernel/vio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index a490077891a..92b1f8ec01d 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c @@ -152,7 +152,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); -struct device_node *cdev_node; +static struct device_node *cdev_node; static struct vio_dev *root_vdev; static u64 cdev_cfg_handle; @@ -371,9 +371,9 @@ static struct mdesc_notifier_client vio_ds_notifier = { .node_name = "domain-services-port", }; -const char *channel_devices_node = "channel-devices"; -const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; -const char *cfg_handle_prop = "cfg-handle"; +static const char *channel_devices_node = "channel-devices"; +static const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; +static const char *cfg_handle_prop = "cfg-handle"; static int __init vio_init(void) { -- cgit v1.2.3 From 3ab5827eb0fefbfa7234f3f91f78b50f2dfcf8e4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 00:22:42 -0700 Subject: sparc64: Fix sparse warnings in chmc.c Several constants are larger than 32-bit and need "UL" markers. Signed-off-by: David S. Miller --- arch/sparc64/kernel/chmc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 2ed401087ca..967b0488682 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c @@ -104,20 +104,20 @@ struct chmc { #define JBUSMC_REGS_SIZE 8 -#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000 -#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000 -#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000 -#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000 -#define JB_MC_REG1_XOR 0x0000010000000000 -#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000 +#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000UL +#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000UL +#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000UL +#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000UL +#define JB_MC_REG1_XOR 0x0000010000000000UL +#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000UL #define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 -#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000 +#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000UL #define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 -#define JB_MC_REG1_INTERLEAVE 0x0000000001800000 +#define JB_MC_REG1_INTERLEAVE 0x0000000001800000UL #define JB_MC_REG1_INTERLEAVE_SHIFT 23 -#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000 +#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000UL #define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 -#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000 +#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000UL #define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 #define PART_TYPE_X8 0 -- cgit v1.2.3 From 3c503701038ac161c269ea43cd67805a3c5669fb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 12 Sep 2008 15:01:31 -0700 Subject: sparc: Fix user_regset 'n' field values. As noticed by Russell King, we were not setting this properly to the number of entries, but rather the total size. This results in the core dumping code allocating waayyyy too much memory. Signed-off-by: David S. Miller --- arch/sparc64/kernel/ptrace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index db2ddf2e829..f43adbc773c 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -443,7 +443,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 36 * sizeof(u64), + .n = 36, .size = sizeof(u64), .align = sizeof(u64), .get = genregs64_get, .set = genregs64_set }, @@ -455,7 +455,7 @@ static const struct user_regset sparc64_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 35 * sizeof(u64), + .n = 35, .size = sizeof(u64), .align = sizeof(u64), .get = fpregs64_get, .set = fpregs64_set }, @@ -801,7 +801,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, - .n = 38 * sizeof(u32), + .n = 38, .size = sizeof(u32), .align = sizeof(u32), .get = genregs32_get, .set = genregs32_set }, @@ -817,7 +817,7 @@ static const struct user_regset sparc32_regsets[] = { */ [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = 99 * sizeof(u32), + .n = 99, .size = sizeof(u32), .align = sizeof(u32), .get = fpregs32_get, .set = fpregs32_set }, -- cgit v1.2.3