diff options
Diffstat (limited to 'arch/ia64/sn/kernel/sn2')
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/Makefile | 2 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/prominfo_proc.c | 152 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/sn2_smp.c | 119 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_hwperf.c | 99 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/sn_proc_fs.c | 120 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/timer.c | 23 | ||||
| -rw-r--r-- | arch/ia64/sn/kernel/sn2/timer_interrupt.c | 2 |
7 files changed, 262 insertions, 255 deletions
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile index 99e17769323..3d09108d427 100644 --- a/arch/ia64/sn/kernel/sn2/Makefile +++ b/arch/ia64/sn/kernel/sn2/Makefile @@ -9,7 +9,7 @@ # sn2 specific kernel files # -CPPFLAGS += -I$(srctree)/arch/ia64/sn/include +ccflags-y := -Iarch/ia64/sn/include obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c index 4dcce3d0e04..ec4de2b0965 100644 --- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c +++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c @@ -11,8 +11,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/nodemask.h> -#include <asm/system.h> #include <asm/io.h> #include <asm/sn/sn_sal.h> #include <asm/sn/sn_cpuid.h> @@ -102,18 +102,18 @@ get_fit_entry(unsigned long nasid, int index, unsigned long *fentry, /* * These two routines display the FIT table for each node. */ -static int dump_fit_entry(char *page, unsigned long *fentry) +static void dump_fit_entry(struct seq_file *m, unsigned long *fentry) { unsigned type; type = FIT_TYPE(fentry[1]); - return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n", - type, - fit_type_name(type), - FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]), - fentry[0], - /* mult by sixteen to get size in bytes */ - (unsigned)(fentry[1] & 0xffffff) * 16); + seq_printf(m, "%02x %-25s %x.%02x %016lx %u\n", + type, + fit_type_name(type), + FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]), + fentry[0], + /* mult by sixteen to get size in bytes */ + (unsigned)(fentry[1] & 0xffffff) * 16); } @@ -125,31 +125,39 @@ static int dump_fit_entry(char *page, unsigned long *fentry) * OK except for 4kB pages (and no one is going to do that on SN * anyway). */ -static int -dump_fit(char *page, unsigned long nasid) +static int proc_fit_show(struct seq_file *m, void *v) { + unsigned long nasid = (unsigned long)m->private; unsigned long fentry[2]; int index; - char *p; - p = page; for (index=0;;index++) { BUG_ON(index * 60 > PAGE_SIZE); if (get_fit_entry(nasid, index, fentry, NULL, 0)) break; - p += dump_fit_entry(p, fentry); + dump_fit_entry(m, fentry); } + return 0; +} - return p - page; +static int proc_fit_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_fit_show, PDE_DATA(inode)); } -static int -dump_version(char *page, unsigned long nasid) +static const struct file_operations proc_fit_fops = { + .open = proc_fit_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int proc_version_show(struct seq_file *m, void *v) { + unsigned long nasid = (unsigned long)m->private; unsigned long fentry[2]; char banner[128]; int index; - int len; for (index = 0; ; index++) { if (get_fit_entry(nasid, index, fentry, banner, @@ -159,56 +167,24 @@ dump_version(char *page, unsigned long nasid) break; } - len = sprintf(page, "%x.%02x\n", FIT_MAJOR(fentry[1]), - FIT_MINOR(fentry[1])); - page += len; + seq_printf(m, "%x.%02x\n", FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1])); if (banner[0]) - len += snprintf(page, PAGE_SIZE-len, "%s\n", banner); - - return len; -} - -/* same as in proc_misc.c */ -static int -proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, - int len) -{ - if (len <= off + count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; + seq_printf(m, "%s\n", banner); + return 0; } -static int -read_version_entry(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int proc_version_open(struct inode *inode, struct file *file) { - int len; - - /* data holds the NASID of the node */ - len = dump_version(page, (unsigned long)data); - len = proc_calc_metrics(page, start, off, count, eof, len); - return len; + return single_open(file, proc_version_show, PDE_DATA(inode)); } -static int -read_fit_entry(char *page, char **start, off_t off, int count, int *eof, - void *data) -{ - int len; - - /* data holds the NASID of the node */ - len = dump_fit(page, (unsigned long)data); - len = proc_calc_metrics(page, start, off, count, eof, len); - - return len; -} +static const struct file_operations proc_version_fops = { + .open = proc_version_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* module entry points */ int __init prominfo_init(void); @@ -217,63 +193,39 @@ void __exit prominfo_exit(void); module_init(prominfo_init); module_exit(prominfo_exit); -static struct proc_dir_entry **proc_entries; -static struct proc_dir_entry *sgi_prominfo_entry; - #define NODE_NAME_LEN 11 int __init prominfo_init(void) { - struct proc_dir_entry **entp; - struct proc_dir_entry *p; + struct proc_dir_entry *sgi_prominfo_entry; cnodeid_t cnodeid; - unsigned long nasid; - int size; - char name[NODE_NAME_LEN]; if (!ia64_platform_is("sn2")) return 0; - size = num_online_nodes() * sizeof(struct proc_dir_entry *); - proc_entries = kzalloc(size, GFP_KERNEL); - if (!proc_entries) - return -ENOMEM; - sgi_prominfo_entry = proc_mkdir("sgi_prominfo", NULL); + if (!sgi_prominfo_entry) + return -ENOMEM; - entp = proc_entries; for_each_online_node(cnodeid) { + struct proc_dir_entry *dir; + unsigned long nasid; + char name[NODE_NAME_LEN]; + sprintf(name, "node%d", cnodeid); - *entp = proc_mkdir(name, sgi_prominfo_entry); + dir = proc_mkdir(name, sgi_prominfo_entry); + if (!dir) + continue; nasid = cnodeid_to_nasid(cnodeid); - p = create_proc_read_entry("fit", 0, *entp, read_fit_entry, - (void *)nasid); - if (p) - p->owner = THIS_MODULE; - p = create_proc_read_entry("version", 0, *entp, - read_version_entry, (void *)nasid); - if (p) - p->owner = THIS_MODULE; - entp++; + proc_create_data("fit", 0, dir, + &proc_fit_fops, (void *)nasid); + proc_create_data("version", 0, dir, + &proc_version_fops, (void *)nasid); } - return 0; } void __exit prominfo_exit(void) { - struct proc_dir_entry **entp; - unsigned int cnodeid; - char name[NODE_NAME_LEN]; - - entp = proc_entries; - for_each_online_node(cnodeid) { - remove_proc_entry("fit", *entp); - remove_proc_entry("version", *entp); - sprintf(name, "node%d", cnodeid); - remove_proc_entry(name, sgi_prominfo_entry); - entp++; - } - remove_proc_entry("sgi_prominfo", NULL); - kfree(proc_entries); + remove_proc_subtree("sgi_prominfo", NULL); } diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index d9d306c79f2..68c84541162 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -26,7 +26,6 @@ #include <asm/processor.h> #include <asm/irq.h> #include <asm/sal.h> -#include <asm/system.h> #include <asm/delay.h> #include <asm/io.h> #include <asm/smp.h> @@ -40,12 +39,16 @@ #include <asm/sn/shub_mmr.h> #include <asm/sn/nodepda.h> #include <asm/sn/rw_mmr.h> +#include <asm/sn/sn_feature_sets.h> DEFINE_PER_CPU(struct ptc_stats, ptcstats); DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); +/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */ +static int sn2_flush_opt = 0; + extern unsigned long sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, @@ -76,6 +79,8 @@ struct ptc_stats { unsigned long shub_itc_clocks; unsigned long shub_itc_clocks_max; unsigned long shub_ptc_flushes_not_my_mm; + unsigned long shub_ipi_flushes; + unsigned long shub_ipi_flushes_itc_clocks; }; #define sn2_ptctest 0 @@ -99,7 +104,7 @@ static inline unsigned long wait_piowc(void) * * SN2 PIO writes from separate CPUs are not guaranteed to arrive in order. * Context switching user threads which have memory-mapped MMIO may cause - * PIOs to issue from seperate CPUs, thus the PIO writes must be drained + * PIOs to issue from separate CPUs, thus the PIO writes must be drained * from the previous CPU's Shub before execution resumes on the new CPU. */ void sn_migrate(struct task_struct *task) @@ -121,6 +126,18 @@ void sn_tlb_migrate_finish(struct mm_struct *mm) flush_tlb_mm(mm); } +static void +sn2_ipi_flush_all_tlb(struct mm_struct *mm) +{ + unsigned long itc; + + itc = ia64_get_itc(); + smp_flush_tlb_cpumask(*mm_cpumask(mm)); + itc = ia64_get_itc() - itc; + __get_cpu_var(ptcstats).shub_ipi_flushes_itc_clocks += itc; + __get_cpu_var(ptcstats).shub_ipi_flushes++; +} + /** * sn2_global_tlb_purge - globally purge translation cache of virtual address range * @mm: mm_struct containing virtual address range @@ -154,12 +171,17 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; - int active, max_active, deadlock; + int active, max_active, deadlock, flush_opt = sn2_flush_opt; + + if (flush_opt > 2) { + sn2_ipi_flush_all_tlb(mm); + return; + } nodes_clear(nodes_flushed); i = 0; - for_each_cpu_mask(cpu, mm->cpu_vm_mask) { + for_each_cpu(cpu, mm_cpumask(mm)) { cnode = cpu_to_node(cpu); node_set(cnode, nodes_flushed); lcpu = cpu; @@ -189,6 +211,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, return; } + if (flush_opt == 2) { + sn2_ipi_flush_all_tlb(mm); + preempt_enable(); + return; + } + itc = ia64_get_itc(); nix = 0; for_each_node_mask(cnode, nodes_flushed) @@ -256,6 +284,8 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, } if (active >= max_active || i == (nix - 1)) { if ((deadlock = wait_piowc())) { + if (flush_opt == 1) + goto done; sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); if (reset_max_active_on_deadlock()) max_active = 1; @@ -267,6 +297,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, start += (1UL << nbits); } while (start < end); +done: itc2 = ia64_get_itc() - itc2; __get_cpu_var(ptcstats).shub_itc_clocks += itc2; if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) @@ -279,6 +310,11 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start, spin_unlock_irqrestore(PTC_LOCK(shub1), flags); + if (flush_opt == 1 && deadlock) { + __get_cpu_var(ptcstats).deadlocks++; + sn2_ipi_flush_all_tlb(mm); + } + preempt_enable(); } @@ -393,13 +429,38 @@ void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect) sn_send_IPI_phys(nasid, physid, vector, delivery_mode); } +#ifdef CONFIG_HOTPLUG_CPU +/** + * sn_cpu_disable_allowed - Determine if a CPU can be disabled. + * @cpu - CPU that is requested to be disabled. + * + * CPU disable is only allowed on SHub2 systems running with a PROM + * that supports CPU disable. It is not permitted to disable the boot processor. + */ +bool sn_cpu_disable_allowed(int cpu) +{ + if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT)) { + if (cpu != 0) + return true; + else + printk(KERN_WARNING + "Disabling the boot processor is not allowed.\n"); + + } else + printk(KERN_WARNING + "CPU disable is not supported on this system.\n"); + + return false; +} +#endif /* CONFIG_HOTPLUG_CPU */ + #ifdef CONFIG_PROC_FS #define PTC_BASENAME "sgi_sn/ptc_statistics" static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset) { - if (*offset < NR_CPUS) + if (*offset < nr_cpu_ids) return offset; return NULL; } @@ -407,7 +468,7 @@ static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset) static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset) { (*offset)++; - if (*offset < NR_CPUS) + if (*offset < nr_cpu_ids) return offset; return NULL; } @@ -425,25 +486,45 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data) if (!cpu) { seq_printf(file, - "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); - seq_printf(file, "# ptctest %d\n", sn2_ptctest); + "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n"); + seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt); } - if (cpu < NR_CPUS && cpu_online(cpu)) { + if (cpu < nr_cpu_ids && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, stat->deadlocks, - 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, - 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, + 1000 * stat->lock_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks_max / per_cpu(ia64_cpu_info, cpu).cyc_per_usec, stat->shub_ptc_flushes_not_my_mm, - stat->deadlocks2); + stat->deadlocks2, + stat->shub_ipi_flushes, + 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(ia64_cpu_info, cpu).cyc_per_usec); } return 0; } -static struct seq_operations sn2_ptc_seq_ops = { +static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data) +{ + int cpu; + char optstr[64]; + + if (count == 0 || count > sizeof(optstr)) + return -EINVAL; + if (copy_from_user(optstr, user, count)) + return -EFAULT; + optstr[count - 1] = '\0'; + sn2_flush_opt = simple_strtoul(optstr, NULL, 0); + + for_each_online_cpu(cpu) + memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats)); + + return count; +} + +static const struct seq_operations sn2_ptc_seq_ops = { .start = sn2_ptc_seq_start, .next = sn2_ptc_seq_next, .stop = sn2_ptc_seq_stop, @@ -455,9 +536,10 @@ static int sn2_ptc_proc_open(struct inode *inode, struct file *file) return seq_open(file, &sn2_ptc_seq_ops); } -static struct file_operations proc_sn2_ptc_operations = { +static const struct file_operations proc_sn2_ptc_operations = { .open = sn2_ptc_proc_open, .read = seq_read, + .write = sn2_ptc_proc_write, .llseek = seq_lseek, .release = seq_release, }; @@ -469,11 +551,12 @@ static int __init sn2_ptc_init(void) if (!ia64_platform_is("sn2")) return 0; - if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { + proc_sn2_ptc = proc_create(PTC_BASENAME, 0444, + NULL, &proc_sn2_ptc_operations); + if (!proc_sn2_ptc) { printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); return -EINVAL; } - proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations; spin_lock_init(&sn2_global_ptc_lock); return 0; } diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index b632b9c1e3b..b9992571c03 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -25,18 +25,18 @@ #include <linux/fs.h> #include <linux/slab.h> +#include <linux/export.h> #include <linux/vmalloc.h> #include <linux/seq_file.h> #include <linux/miscdevice.h> #include <linux/utsname.h> #include <linux/cpumask.h> -#include <linux/smp_lock.h> #include <linux/nodemask.h> #include <linux/smp.h> +#include <linux/mutex.h> #include <asm/processor.h> #include <asm/topology.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <asm/sal.h> #include <asm/sn/io.h> @@ -50,7 +50,7 @@ static void *sn_hwperf_salheap = NULL; static int sn_hwperf_obj_cnt = 0; static nasid_t sn_hwperf_master_nasid = INVALID_NASID; static int sn_hwperf_init(void); -static DECLARE_MUTEX(sn_hwperf_init_mutex); +static DEFINE_MUTEX(sn_hwperf_init_mutex); #define cnode_possible(n) ((n) < num_cnodes) @@ -66,7 +66,8 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) } sz = sn_hwperf_obj_cnt * sizeof(struct sn_hwperf_object_info); - if ((objbuf = (struct sn_hwperf_object_info *) vmalloc(sz)) == NULL) { + objbuf = vmalloc(sz); + if (objbuf == NULL) { printk("sn_hwperf_enum_objects: vmalloc(%d) failed\n", (int)sz); e = -ENOMEM; goto out; @@ -189,7 +190,7 @@ static void print_pci_topology(struct seq_file *s) int e; for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) { - if (!(p = (char *)kmalloc(sz, GFP_KERNEL))) + if (!(p = kmalloc(sz, GFP_KERNEL))) break; e = ia64_sn_ioif_get_pci_topology(__pa(p), sz); if (e == SALRET_OK) @@ -274,8 +275,7 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb /* get it's interconnect topology */ sz = op->ports * sizeof(struct sn_hwperf_port_info); - if (sz > sizeof(ptdata)) - BUG(); + BUG_ON(sz > sizeof(ptdata)); e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_PORTS, nodeobj->id, sz, (u64)&ptdata, 0, 0, NULL); @@ -309,8 +309,7 @@ static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objb if (router && (!found_cpu || !found_mem)) { /* search for a node connected to the same router */ sz = router->ports * sizeof(struct sn_hwperf_port_info); - if (sz > sizeof(ptdata)) - BUG(); + BUG_ON(sz > sizeof(ptdata)); e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_PORTS, router->id, sz, (u64)&ptdata, 0, 0, NULL); @@ -384,7 +383,6 @@ static int sn_topology_show(struct seq_file *s, void *d) int j; const char *slabname; int ordinal; - cpumask_t cpumask; char slice; struct cpuinfo_ia64 *c; struct sn_hwperf_port_info *ptdata; @@ -416,14 +414,14 @@ static int sn_topology_show(struct seq_file *s, void *d) } seq_printf(s, "partition %u %s local " "shubtype %s, " - "nasid_mask 0x%016lx, " + "nasid_mask 0x%016llx, " "nasid_bits %d:%d, " "system_size %d, " "sharing_size %d, " "coherency_domain %d, " "region_size %d\n", - partid, system_utsname.nodename, + partid, utsname()->nodename, shubtype ? "shub2" : "shub1", (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift, system_size, sharing_size, coher, region_size); @@ -472,23 +470,21 @@ static int sn_topology_show(struct seq_file *s, void *d) * CPUs on this node, if any */ if (!SN_HWPERF_IS_IONODE(obj)) { - cpumask = node_to_cpumask(ordinal); - for_each_online_cpu(i) { - if (cpu_isset(i, cpumask)) { - slice = 'a' + cpuid_to_slice(i); - c = cpu_data(i); - seq_printf(s, "cpu %d %s%c local" - " freq %luMHz, arch ia64", - i, obj->location, slice, - c->proc_freq / 1000000); - for_each_online_cpu(j) { - seq_printf(s, j ? ":%d" : ", dist %d", - node_distance( + for_each_cpu_and(i, cpu_online_mask, + cpumask_of_node(ordinal)) { + slice = 'a' + cpuid_to_slice(i); + c = cpu_data(i); + seq_printf(s, "cpu %d %s%c local" + " freq %luMHz, arch ia64", + i, obj->location, slice, + c->proc_freq / 1000000); + for_each_online_cpu(j) { + seq_printf(s, j ? ":%d" : ", dist %d", + node_distance( cpu_to_node(i), cpu_to_node(j))); - } - seq_putc(s, '\n'); } + seq_putc(s, '\n'); } } } @@ -576,7 +572,7 @@ static void sn_topology_stop(struct seq_file *m, void *v) /* * /proc/sgi_sn/sn_topology, read-only using seq_file */ -static struct seq_operations sn_topology_seq_ops = { +static const struct seq_operations sn_topology_seq_ops = { .start = sn_topology_start, .next = sn_topology_next, .stop = sn_topology_stop, @@ -614,28 +610,32 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) op_info->a->arg &= SN_HWPERF_ARG_OBJID_MASK; if (cpu != SN_HWPERF_ARG_ANY_CPU) { - if (cpu >= NR_CPUS || !cpu_online(cpu)) { + if (cpu >= nr_cpu_ids || !cpu_online(cpu)) { r = -EINVAL; goto out; } } - if (cpu == SN_HWPERF_ARG_ANY_CPU || cpu == get_cpu()) { - /* don't care, or already on correct cpu */ + if (cpu == SN_HWPERF_ARG_ANY_CPU) { + /* don't care which cpu */ sn_hwperf_call_sal(op_info); - } - else { + } else if (cpu == get_cpu()) { + /* already on correct cpu */ + sn_hwperf_call_sal(op_info); + put_cpu(); + } else { + put_cpu(); if (use_ipi) { /* use an interprocessor interrupt to call SAL */ smp_call_function_single(cpu, sn_hwperf_call_sal, - op_info, 1, 1); + op_info, 1); } else { /* migrate the task before calling SAL */ save_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); sn_hwperf_call_sal(op_info); - set_cpus_allowed(current, save_allowed); + set_cpus_allowed_ptr(current, &save_allowed); } } r = op_info->ret; @@ -686,8 +686,7 @@ static int sn_hwperf_map_err(int hwperf_err) /* * ioctl for "sn_hwperf" misc device */ -static int -sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) +static long sn_hwperf_ioctl(struct file *fp, u32 op, unsigned long arg) { struct sn_hwperf_ioctl_args a; struct cpuinfo_ia64 *cdata; @@ -703,8 +702,6 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) int i; int j; - unlock_kernel(); - /* only user requests are allowed here */ if ((op & SN_HWPERF_OP_MASK) < 10) { r = -EINVAL; @@ -750,9 +747,10 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) goto error; } else if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { + int cpuobj_index = 0; + memset(p, 0, a.sz); for (i = 0; i < nobj; i++) { - int cpuobj_index = 0; if (!SN_HWPERF_IS_NODE(objs + i)) continue; node = sn_hwperf_obj_to_cnode(objs + i); @@ -789,17 +787,18 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) break; case SN_HWPERF_GET_OBJ_NODE: - if (a.sz != sizeof(u64) || a.arg < 0) { + i = a.arg; + if (a.sz != sizeof(u64) || i < 0) { r = -EINVAL; goto error; } if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { - if (a.arg >= nobj) { + if (i >= nobj) { r = -EINVAL; vfree(objs); goto error; } - if (objs[(i = a.arg)].id != a.arg) { + if (objs[i].id != a.arg) { for (i = 0; i < nobj; i++) { if (objs[i].id == a.arg) break; @@ -861,12 +860,12 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) error: vfree(p); - lock_kernel(); return r; } -static struct file_operations sn_hwperf_fops = { - .ioctl = sn_hwperf_ioctl, +static const struct file_operations sn_hwperf_fops = { + .unlocked_ioctl = sn_hwperf_ioctl, + .llseek = noop_llseek, }; static struct miscdevice sn_hwperf_dev = { @@ -882,10 +881,10 @@ static int sn_hwperf_init(void) int e = 0; /* single threaded, once-only initialization */ - down(&sn_hwperf_init_mutex); + mutex_lock(&sn_hwperf_init_mutex); if (sn_hwperf_salheap) { - up(&sn_hwperf_init_mutex); + mutex_unlock(&sn_hwperf_init_mutex); return e; } @@ -934,7 +933,7 @@ out: sn_hwperf_salheap = NULL; sn_hwperf_obj_cnt = 0; } - up(&sn_hwperf_init_mutex); + mutex_unlock(&sn_hwperf_init_mutex); return e; } @@ -978,7 +977,7 @@ int sn_hwperf_get_nearest_node(cnodeid_t node, return e; } -static int __devinit sn_hwperf_misc_register_init(void) +static int sn_hwperf_misc_register_init(void) { int e; diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index 43ddc2eccb9..7aab87f4806 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c @@ -36,7 +36,7 @@ static int system_serial_number_open(struct inode *inode, struct file *file) static int licenseID_show(struct seq_file *s, void *p) { - seq_printf(s, "0x%lx\n", sn_partition_serial_number_val()); + seq_printf(s, "0x%llx\n", sn_partition_serial_number_val()); return 0; } @@ -45,38 +45,6 @@ static int licenseID_open(struct inode *inode, struct file *file) return single_open(file, licenseID_show, NULL); } -/* - * Enable forced interrupt by default. - * When set, the sn interrupt handler writes the force interrupt register on - * the bridge chip. The hardware will then send an interrupt message if the - * interrupt line is active. This mimics a level sensitive interrupt. - */ -extern int sn_force_interrupt_flag; - -static int sn_force_interrupt_show(struct seq_file *s, void *p) -{ - seq_printf(s, "Force interrupt is %s\n", - sn_force_interrupt_flag ? "enabled" : "disabled"); - return 0; -} - -static ssize_t sn_force_interrupt_write_proc(struct file *file, - const char __user *buffer, size_t count, loff_t *data) -{ - char val; - - if (copy_from_user(&val, buffer, 1)) - return -EFAULT; - - sn_force_interrupt_flag = (val == '0') ? 0 : 1; - return count; -} - -static int sn_force_interrupt_open(struct inode *inode, struct file *file) -{ - return single_open(file, sn_force_interrupt_show, NULL); -} - static int coherence_id_show(struct seq_file *s, void *p) { seq_printf(s, "%d\n", partition_coherence_id()); @@ -89,35 +57,45 @@ static int coherence_id_open(struct inode *inode, struct file *file) return single_open(file, coherence_id_show, NULL); } -static struct proc_dir_entry -*sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, - int (*openfunc)(struct inode *, struct file *), - int (*releasefunc)(struct inode *, struct file *), - ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)) -{ - struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); - - if (e) { - struct file_operations *f; - - f = kzalloc(sizeof(*f), GFP_KERNEL); - if (f) { - f->open = openfunc; - f->read = seq_read; - f->llseek = seq_lseek; - f->release = releasefunc; - f->write = write; - e->proc_fops = f; - } - } - - return e; -} - /* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */ extern int sn_topology_open(struct inode *, struct file *); extern int sn_topology_release(struct inode *, struct file *); +static const struct file_operations proc_partition_id_fops = { + .open = partition_id_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_system_sn_fops = { + .open = system_serial_number_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_license_id_fops = { + .open = licenseID_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_coherence_id_fops = { + .open = coherence_id_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_sn_topo_fops = { + .open = sn_topology_open, + .read = seq_read, + .llseek = seq_lseek, + .release = sn_topology_release, +}; + void register_sn_procfs(void) { static struct proc_dir_entry *sgi_proc_dir = NULL; @@ -126,24 +104,14 @@ void register_sn_procfs(void) if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) return; - sn_procfs_create_entry("partition_id", sgi_proc_dir, - partition_id_open, single_release, NULL); - - sn_procfs_create_entry("system_serial_number", sgi_proc_dir, - system_serial_number_open, single_release, NULL); - - sn_procfs_create_entry("licenseID", sgi_proc_dir, - licenseID_open, single_release, NULL); - - sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, - sn_force_interrupt_open, single_release, - sn_force_interrupt_write_proc); - - sn_procfs_create_entry("coherence_id", sgi_proc_dir, - coherence_id_open, single_release, NULL); - - sn_procfs_create_entry("sn_topology", sgi_proc_dir, - sn_topology_open, sn_topology_release, NULL); + proc_create("partition_id", 0444, sgi_proc_dir, + &proc_partition_id_fops); + proc_create("system_serial_number", 0444, sgi_proc_dir, + &proc_system_sn_fops); + proc_create("licenseID", 0444, sgi_proc_dir, &proc_license_id_fops); + proc_create("coherence_id", 0444, sgi_proc_dir, + &proc_coherence_id_fops); + proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops); } #endif /* CONFIG_PROC_FS */ diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c index 56a88b6df4b..abab8f99e91 100644 --- a/arch/ia64/sn/kernel/sn2/timer.c +++ b/arch/ia64/sn/kernel/sn2/timer.c @@ -11,9 +11,9 @@ #include <linux/sched.h> #include <linux/time.h> #include <linux/interrupt.h> +#include <linux/clocksource.h> #include <asm/hw_irq.h> -#include <asm/system.h> #include <asm/timex.h> #include <asm/sn/leds.h> @@ -22,11 +22,17 @@ extern unsigned long sn_rtc_cycles_per_second; -static struct time_interpolator sn2_interpolator = { - .drift = -1, - .shift = 10, - .mask = (1LL << 55) - 1, - .source = TIME_SOURCE_MMIO64 +static cycle_t read_sn2(struct clocksource *cs) +{ + return (cycle_t)readq(RTC_COUNTER_ADDR); +} + +static struct clocksource clocksource_sn2 = { + .name = "sn2_rtc", + .rating = 450, + .read = read_sn2, + .mask = (1LL << 55) - 1, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; /* @@ -47,9 +53,8 @@ ia64_sn_udelay (unsigned long usecs) void __init sn_timer_init(void) { - sn2_interpolator.frequency = sn_rtc_cycles_per_second; - sn2_interpolator.addr = RTC_COUNTER_ADDR; - register_time_interpolator(&sn2_interpolator); + clocksource_sn2.archdata.fsys_mmio = RTC_COUNTER_ADDR; + clocksource_register_hz(&clocksource_sn2, sn_rtc_cycles_per_second); ia64_udelay = &ia64_sn_udelay; } diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c index fa7f6994591..103d6ea8e94 100644 --- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c +++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c @@ -36,7 +36,7 @@ extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); #define SN_LB_INT_WAR_INTERVAL 100 -void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +void sn_timer_interrupt(int irq, void *dev_id) { /* LED blinking */ if (!pda->hb_count--) { |
