X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmacintosh%2Fsmu.c;h=d86d57af282abde6bca52d369e480ca543651746;hb=537388bb6563bfde7c0307b95ecc1f7a1ae39b02;hp=8ba49385c3ff4fd149c21980eabf0cc1996ee32b;hpb=93890b71a34f9490673a6edd56b61c2124215e46;p=linux-2.6 diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 8ba49385c3..d86d57af28 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -85,6 +85,7 @@ struct smu_device { u32 cmd_buf_abs; /* command buffer absolute */ struct list_head cmd_list; struct smu_cmd *cmd_cur; /* pending command */ + int broken_nap; struct list_head cmd_i2c_list; struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ struct timer_list i2c_timer; @@ -135,6 +136,19 @@ static void smu_start_cmd(void) fend = faddr + smu->cmd_buf->length + 2; flush_inval_dcache_range(faddr, fend); + + /* We also disable NAP mode for the duration of the command + * on U3 based machines. + * This is slightly racy as it can be written back to 1 by a sysctl + * but that never happens in practice. There seem to be an issue with + * U3 based machines such as the iMac G5 where napping for the + * whole duration of the command prevents the SMU from fetching it + * from memory. This might be related to the strange i2c based + * mechanism the SMU uses to access memory. + */ + if (smu->broken_nap) + powersave_nap = 0; + /* This isn't exactly a DMA mapping here, I suspect * the SMU is actually communicating with us via i2c to the * northbridge or the CPU to access RAM. @@ -211,6 +225,10 @@ static irqreturn_t smu_db_intr(int irq, void *arg) misc = cmd->misc; mb(); cmd->status = rc; + + /* Re-enable NAP mode */ + if (smu->broken_nap) + powersave_nap = 1; bail: /* Start next command if any */ smu_start_cmd(); @@ -461,16 +479,19 @@ int __init smu_init (void) if (np == NULL) return -ENODEV; - printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); + printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR); if (smu_cmdbuf_abs == 0) { printk(KERN_ERR "SMU: Command buffer not allocated !\n"); + of_node_put(np); return -EINVAL; } smu = alloc_bootmem(sizeof(struct smu_device)); - if (smu == NULL) + if (smu == NULL) { + of_node_put(np); return -ENOMEM; + } memset(smu, 0, sizeof(*smu)); spin_lock_init(&smu->lock); @@ -533,6 +554,11 @@ int __init smu_init (void) goto fail; } + /* U3 has an issue with NAP mode when issuing SMU commands */ + smu->broken_nap = pmac_get_uninorth_variant() < 4; + if (smu->broken_nap) + printk(KERN_INFO "SMU: using NAP mode workaround\n"); + sys_ctrler = SYS_CTRLER_SMU; return 0;