From ee1858d3122dedd2e82a61b6ab56b229aefd9447 Mon Sep 17 00:00:00 2001 From: Lars Kotthoff Date: Mon, 7 Nov 2005 14:08:04 -0800 Subject: [SPARC]: Add sun4m LED driver. This is a forward port of a 2.4.x sun4m LED driver written by Lars Kotthoff. Signed-off-by: Lars Kotthoff Signed-off-by: David S. Miller --- arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/led.c | 139 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 arch/sparc/kernel/led.c (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 3d22ba2af01c..1b83e21841b5 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_SUN_AUXIO) += auxio.o obj-$(CONFIG_PCI) += ebus.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o +obj-$(CONFIG_SPARC_LED) += led.o ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos.o sunos_ioctl.o diff --git a/arch/sparc/kernel/led.c b/arch/sparc/kernel/led.c new file mode 100644 index 000000000000..2a3afca453c9 --- /dev/null +++ b/arch/sparc/kernel/led.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include + +#include + +#define LED_MAX_LENGTH 8 /* maximum chars written to proc file */ + +static inline void led_toggle(void) +{ + unsigned char val = get_auxio(); + unsigned char on, off; + + if (val & AUXIO_LED) { + on = 0; + off = AUXIO_LED; + } else { + on = AUXIO_LED; + off = 0; + } + + set_auxio(on, off); +} + +static struct timer_list led_blink_timer; + +static void led_blink(unsigned long timeout) +{ + led_toggle(); + + /* reschedule */ + if (!timeout) { /* blink according to load */ + led_blink_timer.expires = jiffies + + ((1 + (avenrun[0] >> FSHIFT)) * HZ); + led_blink_timer.data = 0; + } else { /* blink at user specified interval */ + led_blink_timer.expires = jiffies + (timeout * HZ); + led_blink_timer.data = timeout; + } + add_timer(&led_blink_timer); +} + +static int led_read_proc(char *buf, char **start, off_t offset, int count, + int *eof, void *data) +{ + int len = 0; + + if (get_auxio() & AUXIO_LED) + len = sprintf(buf, "on\n"); + else + len = sprintf(buf, "off\n"); + + return len; +} + +static int led_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char *buf = NULL; + + if (count > LED_MAX_LENGTH) + count = LED_MAX_LENGTH; + + buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, buffer, count)) { + kfree(buf); + return -EFAULT; + } + + buf[count] = '\0'; + + /* work around \n when echo'ing into proc */ + if (buf[count - 1] == '\n') + buf[count - 1] = '\0'; + + /* before we change anything we want to stop any running timers, + * otherwise calls such as on will have no persistent effect + */ + del_timer_sync(&led_blink_timer); + + if (!strcmp(buf, "on")) { + auxio_set_led(AUXIO_LED_ON); + } else if (!strcmp(buf, "toggle")) { + led_toggle(); + } else if ((*buf > '0') && (*buf <= '9')) { + led_blink(simple_strtoul(buf, NULL, 10)); + } else if (!strcmp(buf, "load")) { + led_blink(0); + } else { + auxio_set_led(AUXIO_LED_OFF); + } + + kfree(buf); + + return count; +} + +static struct proc_dir_entry *led; + +#define LED_VERSION "0.1" + +static int __init led_init(void) +{ + init_timer(&led_blink_timer); + led_blink_timer.function = led_blink; + + led = create_proc_entry("led", 0, NULL); + if (!led) + return -ENOMEM; + + led->read_proc = led_read_proc; /* reader function */ + led->write_proc = led_write_proc; /* writer function */ + led->owner = THIS_MODULE; + + printk(KERN_INFO + "led: version %s, Lars Kotthoff \n", + LED_VERSION); + + return 0; +} + +static void __exit led_exit(void) +{ + remove_proc_entry("led", NULL); + del_timer_sync(&led_blink_timer); +} + +module_init(led_init); +module_exit(led_exit); + +MODULE_AUTHOR("Lars Kotthoff "); +MODULE_DESCRIPTION("Provides control of the front LED on SPARC systems."); +MODULE_LICENSE("GPL"); +MODULE_VERSION(LED_VERSION); -- cgit From 16cf0d816541fde06ed8f37c0f5cf9940cdfc145 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 14:12:21 -0800 Subject: [SPARC]: Kill remaining kbio.h references. Would you mind applying the following patch that kills those two + the m68k and Documentation/ references? Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- arch/sparc/kernel/sunos_ioctl.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c index df1c0b31a930..a6ba3d26222c 100644 --- a/arch/sparc/kernel/sunos_ioctl.c +++ b/arch/sparc/kernel/sunos_ioctl.c @@ -23,7 +23,6 @@ #include #include #include -#include #if 0 extern char sunkbd_type; -- cgit From 5bfb5d690f36d316a5f3b4f7775fda996faa6b12 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 8 Nov 2005 21:39:01 -0800 Subject: [PATCH] sched: disable preempt in idle tasks Run idle threads with preempt disabled. Also corrected a bugs in arm26's cpu_idle (make it actually call schedule()). How did it ever work before? Might fix the CPU hotplugging hang which Nigel Cunningham noted. We think the bug hits if the idle thread is preempted after checking need_resched() and before going to sleep, then the CPU offlined. After calling stop_machine_run, the CPU eventually returns from preemption and into the idle thread and goes to sleep. The CPU will continue executing previous idle and have no chance to call play_dead. By disabling preemption until we are ready to explicitly schedule, this bug is fixed and the idle threads generally become more robust. From: alexs PPC build fix From: Yoichi Yuasa MIPS build fix Signed-off-by: Nick Piggin Signed-off-by: Yoichi Yuasa Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/process.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 29e72b57d4fd..c39f4d01096d 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -120,7 +120,9 @@ void cpu_idle(void) (*pm_idle)(); } + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } } @@ -133,7 +135,9 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while(1) { if(need_resched()) { + preempt_enable_no_resched(); schedule(); + preempt_disable(); check_pgt_cache(); } barrier(); /* or else gcc optimizes... */ -- cgit From 64c7c8f88559624abdbe12b5da6502e8879f8d28 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Tue, 8 Nov 2005 21:39:04 -0800 Subject: [PATCH] sched: resched and cpu_idle rework Make some changes to the NEED_RESCHED and POLLING_NRFLAG to reduce confusion, and make their semantics rigid. Improves efficiency of resched_task and some cpu_idle routines. * In resched_task: - TIF_NEED_RESCHED is only cleared with the task's runqueue lock held, and as we hold it during resched_task, then there is no need for an atomic test and set there. The only other time this should be set is when the task's quantum expires, in the timer interrupt - this is protected against because the rq lock is irq-safe. - If TIF_NEED_RESCHED is set, then we don't need to do anything. It won't get unset until the task get's schedule()d off. - If we are running on the same CPU as the task we resched, then set TIF_NEED_RESCHED and no further action is required. - If we are running on another CPU, and TIF_POLLING_NRFLAG is *not* set after TIF_NEED_RESCHED has been set, then we need to send an IPI. Using these rules, we are able to remove the test and set operation in resched_task, and make clear the previously vague semantics of POLLING_NRFLAG. * In idle routines: - Enter cpu_idle with preempt disabled. When the need_resched() condition becomes true, explicitly call schedule(). This makes things a bit clearer (IMO), but haven't updated all architectures yet. - Many do a test and clear of TIF_NEED_RESCHED for some reason. According to the resched_task rules, this isn't needed (and actually breaks the assumption that TIF_NEED_RESCHED is only cleared with the runqueue lock held). So remove that. Generally one less locked memory op when switching to the idle thread. - Many idle routines clear TIF_POLLING_NRFLAG, and only set it in the inner most polling idle loops. The above resched_task semantics allow it to be set until before the last time need_resched() is checked before going into a halt requiring interrupt wakeup. Many idle routines simply never enter such a halt, and so POLLING_NRFLAG can be always left set, completely eliminating resched IPIs when rescheduling the idle task. POLLING_NRFLAG width can be increased, to reduce the chance of resched IPIs. Signed-off-by: Nick Piggin Cc: Ingo Molnar Cc: Con Kolivas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/process.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index c39f4d01096d..ea8647411462 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -67,13 +67,6 @@ extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *); struct task_struct *last_task_used_math = NULL; struct thread_info *current_set[NR_CPUS]; -/* - * default_idle is new in 2.5. XXX Review, currently stolen from sparc64. - */ -void default_idle(void) -{ -} - #ifndef CONFIG_SMP #define SUN4C_FAULT_HIGH 100 @@ -92,12 +85,11 @@ void cpu_idle(void) static unsigned long fps; unsigned long now; unsigned long faults; - unsigned long flags; extern unsigned long sun4c_kernel_faults; extern void sun4c_grow_kernel_ring(void); - local_irq_save(flags); + local_irq_disable(); now = jiffies; count -= (now - last_jiffies); last_jiffies = now; @@ -113,13 +105,16 @@ void cpu_idle(void) sun4c_grow_kernel_ring(); } } - local_irq_restore(flags); + local_irq_enable(); } - while((!need_resched()) && pm_idle) { - (*pm_idle)(); + if (pm_idle) { + while (!need_resched()) + (*pm_idle)(); + } else { + while (!need_resched()) + cpu_relax(); } - preempt_enable_no_resched(); schedule(); preempt_disable(); @@ -132,15 +127,15 @@ void cpu_idle(void) /* This is being executed in task 0 'user space'. */ void cpu_idle(void) { + set_thread_flag(TIF_POLLING_NRFLAG); /* endless idle loop with no priority at all */ while(1) { - if(need_resched()) { - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } - barrier(); /* or else gcc optimizes... */ + while (!need_resched()) + cpu_relax(); + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); } } -- cgit From 940fdc6e1223f1323b88b7f1e7ae09a93a76b74d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 9 Nov 2005 12:03:05 -0800 Subject: [SPARC]: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) and remove a duplicate of ARRAY_SIZE which is never used anyways. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- arch/sparc/kernel/cpu.c | 4 ++-- arch/sparc/kernel/pcic.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 6a4ebc62193e..d7bfc61d2879 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -75,7 +75,7 @@ struct cpu_fp_info linux_sparc_fpu[] = { { 9, 3, "Fujitsu or Weitek on-chip FPU"}, }; -#define NSPARCFPU (sizeof(linux_sparc_fpu)/sizeof(struct cpu_fp_info)) +#define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) struct cpu_iu_info linux_sparc_chips[] = { /* Sun4/100, 4/200, SLC */ @@ -120,7 +120,7 @@ struct cpu_iu_info linux_sparc_chips[] = { { 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"}, }; -#define NSPARCCHIPS (sizeof(linux_sparc_chips)/sizeof(struct cpu_iu_info)) +#define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) char *sparc_cpu_type; char *sparc_fpu_type; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 25e31d5ec99b..cccfc12802ed 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -143,7 +143,7 @@ static struct pcic_ca2irq pcic_i_jk[] = { * as several PROMs may be installed on the same physical board. */ #define SN2L_INIT(name, map) \ - { name, map, sizeof(map)/sizeof(struct pcic_ca2irq) } + { name, map, ARRAY_SIZE(map) } static struct pcic_sn2list pcic_known_sysnames[] = { SN2L_INIT("SUNW,JavaEngine1", pcic_i_je1a), /* JE1, PROM 2.32 */ -- cgit