Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Au1x PM fixes.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Pete Popov and committed by
Ralf Baechle
3ce86ee1 7ab1261f

+37 -29
+17 -15
arch/mips/au1000/common/irq.c
··· 83 83 void (*board_init_irq)(void); 84 84 85 85 #ifdef CONFIG_PM 86 - extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); 86 + extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs); 87 87 #endif 88 88 89 89 static DEFINE_SPINLOCK(irq_lock); ··· 293 293 }; 294 294 295 295 #ifdef CONFIG_PM 296 - void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) 296 + void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)) 297 297 { 298 + struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; 299 + 298 300 static struct irqaction action; 301 + memset(&action, 0, sizeof(struct irqaction)); 302 + 299 303 /* This is a big problem.... since we didn't use request_irq 300 - when kernel/irq.c calls probe_irq_xxx this interrupt will 301 - be probed for usage. This will end up disabling the device :( 302 - 303 - Give it a bogus "action" pointer -- this will keep it from 304 - getting auto-probed! 305 - 306 - By setting the status to match that of request_irq() we 307 - can avoid it. --cgray 304 + * when kernel/irq.c calls probe_irq_xxx this interrupt will 305 + * be probed for usage. This will end up disabling the device :( 306 + * Give it a bogus "action" pointer -- this will keep it from 307 + * getting auto-probed! 308 + * 309 + * By setting the status to match that of request_irq() we 310 + * can avoid it. --cgray 308 311 */ 309 312 action.dev_id = handler; 310 - action.flags = 0; 311 - action.mask = 0; 313 + action.flags = SA_INTERRUPT; 314 + cpus_clear(action.mask); 312 315 action.name = "Au1xxx TOY"; 313 316 action.handler = handler; 314 317 action.next = NULL; 315 318 316 - irq_desc[AU1000_TOY_MATCH2_INT].action = &action; 317 - irq_desc[AU1000_TOY_MATCH2_INT].status 318 - &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); 319 + desc->action = &action; 320 + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); 319 321 320 322 local_enable_irq(AU1000_TOY_MATCH2_INT); 321 323 }
+9 -7
arch/mips/au1000/common/power.c
··· 34 34 #include <linux/pm.h> 35 35 #include <linux/slab.h> 36 36 #include <linux/sysctl.h> 37 + #include <linux/jiffies.h> 37 38 38 39 #include <asm/string.h> 39 40 #include <asm/uaccess.h> 40 41 #include <asm/io.h> 41 42 #include <asm/system.h> 43 + #include <asm/cacheflush.h> 42 44 #include <asm/mach-au1x00/au1000.h> 43 45 44 46 #ifdef CONFIG_PM ··· 52 50 # define DPRINTK(fmt, args...) 53 51 #endif 54 52 55 - static void calibrate_delay(void); 53 + static void au1000_calibrate_delay(void); 56 54 57 55 extern void set_au1x00_speed(unsigned int new_freq); 58 56 extern unsigned int get_au1x00_speed(void); ··· 262 260 } 263 261 264 262 static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, 265 - void *buffer, size_t * len) 263 + void __user *buffer, size_t * len, loff_t *ppos) 266 264 { 267 265 int retval = 0; 268 266 #ifdef SLEEP_TEST_TIMEOUT ··· 296 294 } 297 295 298 296 static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, 299 - void *buffer, size_t * len) 297 + void __user *buffer, size_t * len, loff_t *ppos) 300 298 { 301 299 int retval = 0; 302 300 ··· 315 313 316 314 317 315 static int pm_do_freq(ctl_table * ctl, int write, struct file *file, 318 - void *buffer, size_t * len) 316 + void __user *buffer, size_t * len, loff_t *ppos) 319 317 { 320 318 int retval = 0, i; 321 319 unsigned long val, pll; ··· 410 408 411 409 412 410 /* We don't want _any_ interrupts other than 413 - * match20. Otherwise our calibrate_delay() 411 + * match20. Otherwise our au1000_calibrate_delay() 414 412 * calculation will be off, potentially a lot. 415 413 */ 416 414 intc0_mask = save_local_and_disable(0); 417 415 intc1_mask = save_local_and_disable(1); 418 416 local_enable_irq(AU1000_TOY_MATCH2_INT); 419 417 spin_unlock_irqrestore(&pm_lock, flags); 420 - calibrate_delay(); 418 + au1000_calibrate_delay(); 421 419 restore_local_and_enable(0, intc0_mask); 422 420 restore_local_and_enable(1, intc1_mask); 423 421 return retval; ··· 457 455 better than 1% */ 458 456 #define LPS_PREC 8 459 457 460 - static void calibrate_delay(void) 458 + static void au1000_calibrate_delay(void) 461 459 { 462 460 unsigned long ticks, loopbit; 463 461 int lps_precision = LPS_PREC;
+11 -7
arch/mips/au1000/common/time.c
··· 63 63 static unsigned int timerhi = 0, timerlo = 0; 64 64 65 65 #ifdef CONFIG_PM 66 - #define MATCH20_INC 328 67 - extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); 66 + #if HZ < 100 || HZ > 1000 67 + #error "unsupported HZ value! Must be in [100,1000]" 68 + #endif 69 + #define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */ 70 + extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)); 68 71 static unsigned long last_pc0, last_match20; 69 72 #endif 70 73 ··· 119 116 } 120 117 121 118 #ifdef CONFIG_PM 122 - void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) 119 + irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs) 123 120 { 124 121 unsigned long pc0; 125 122 int time_elapsed; 126 123 static int jiffie_drift = 0; 127 124 128 - kstat.irqs[0][irq]++; 129 125 if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { 130 126 /* should never happen! */ 131 - printk(KERN_WARNING "counter 0 w status eror\n"); 132 - return; 127 + printk(KERN_WARNING "counter 0 w status error\n"); 128 + return IRQ_NONE; 133 129 } 134 130 135 131 pc0 = au_readl(SYS_TOYREAD); ··· 165 163 update_process_times(user_mode(regs)); 166 164 #endif 167 165 } 166 + 167 + return IRQ_HANDLED; 168 168 } 169 169 170 170 /* When we wakeup from sleep, we have to "catch up" on all of the ··· 443 439 au_sync(); 444 440 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); 445 441 446 - /* setup match20 to interrupt once every 10ms */ 442 + /* setup match20 to interrupt once every HZ */ 447 443 last_pc0 = last_match20 = au_readl(SYS_TOYREAD); 448 444 au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); 449 445 au_sync();