aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/macintosh
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-02-06 22:29:43 -0500
committerPaul Mackerras <paulus@samba.org>2008-02-08 03:52:35 -0500
commit592a607bbc053bc6f614a0e619326009f4b3829e (patch)
treef6deedbe40c525c8fe088e08f620cd76cb865591 /drivers/macintosh
parenta4ffc0a0b240a29cbe489f6db9dae112a49ef1c1 (diff)
[POWERPC] Disable G5 NAP mode during SMU commands on U3
It appears that with the U3 northbridge, if the processor is in NAP mode the whole time while waiting for an SMU command to complete, then the SMU will fail. It could be related to the weird backward mechanism the SMU uses to get to system memory via i2c to the northbridge that doesn't operate properly when the said bridge is in napping along with the CPU. That is on U3 at least, U4 doesn't seem to be affected. This didn't show before NO_HZ as the timer wakeup was enough to make it work it seems, but that is no longer the case. This fixes it by disabling NAP mode on those machines while an SMU command is in flight. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers/macintosh')
-rw-r--r--drivers/macintosh/smu.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 8ba49385c3ff..77ad192962c5 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -85,6 +85,7 @@ struct smu_device {
85 u32 cmd_buf_abs; /* command buffer absolute */ 85 u32 cmd_buf_abs; /* command buffer absolute */
86 struct list_head cmd_list; 86 struct list_head cmd_list;
87 struct smu_cmd *cmd_cur; /* pending command */ 87 struct smu_cmd *cmd_cur; /* pending command */
88 int broken_nap;
88 struct list_head cmd_i2c_list; 89 struct list_head cmd_i2c_list;
89 struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ 90 struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */
90 struct timer_list i2c_timer; 91 struct timer_list i2c_timer;
@@ -135,6 +136,19 @@ static void smu_start_cmd(void)
135 fend = faddr + smu->cmd_buf->length + 2; 136 fend = faddr + smu->cmd_buf->length + 2;
136 flush_inval_dcache_range(faddr, fend); 137 flush_inval_dcache_range(faddr, fend);
137 138
139
140 /* We also disable NAP mode for the duration of the command
141 * on U3 based machines.
142 * This is slightly racy as it can be written back to 1 by a sysctl
143 * but that never happens in practice. There seem to be an issue with
144 * U3 based machines such as the iMac G5 where napping for the
145 * whole duration of the command prevents the SMU from fetching it
146 * from memory. This might be related to the strange i2c based
147 * mechanism the SMU uses to access memory.
148 */
149 if (smu->broken_nap)
150 powersave_nap = 0;
151
138 /* This isn't exactly a DMA mapping here, I suspect 152 /* This isn't exactly a DMA mapping here, I suspect
139 * the SMU is actually communicating with us via i2c to the 153 * the SMU is actually communicating with us via i2c to the
140 * northbridge or the CPU to access RAM. 154 * northbridge or the CPU to access RAM.
@@ -211,6 +225,10 @@ static irqreturn_t smu_db_intr(int irq, void *arg)
211 misc = cmd->misc; 225 misc = cmd->misc;
212 mb(); 226 mb();
213 cmd->status = rc; 227 cmd->status = rc;
228
229 /* Re-enable NAP mode */
230 if (smu->broken_nap)
231 powersave_nap = 1;
214 bail: 232 bail:
215 /* Start next command if any */ 233 /* Start next command if any */
216 smu_start_cmd(); 234 smu_start_cmd();
@@ -461,7 +479,7 @@ int __init smu_init (void)
461 if (np == NULL) 479 if (np == NULL)
462 return -ENODEV; 480 return -ENODEV;
463 481
464 printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); 482 printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR);
465 483
466 if (smu_cmdbuf_abs == 0) { 484 if (smu_cmdbuf_abs == 0) {
467 printk(KERN_ERR "SMU: Command buffer not allocated !\n"); 485 printk(KERN_ERR "SMU: Command buffer not allocated !\n");
@@ -533,6 +551,11 @@ int __init smu_init (void)
533 goto fail; 551 goto fail;
534 } 552 }
535 553
554 /* U3 has an issue with NAP mode when issuing SMU commands */
555 smu->broken_nap = pmac_get_uninorth_variant() < 4;
556 if (smu->broken_nap)
557 printk(KERN_INFO "SMU: using NAP mode workaround\n");
558
536 sys_ctrler = SYS_CTRLER_SMU; 559 sys_ctrler = SYS_CTRLER_SMU;
537 return 0; 560 return 0;
538 561