Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90d241ed authored by Yinghai Lu's avatar Yinghai Lu Committed by Wim Van Sebroeck
Browse files

watchdog: sp5100_tco.c: Check if firmware has set correct value in tcobase.



Stefano found SP5100 TCO watchdog driver using wrong address.

[    9.148536] SP5100 TCO timer: SP5100 TCO WatchDog Timer Driver v0.01
[    9.148628] DEBUG __ioremap_caller WARNING address=b8fe00 size=8 valid=1 reserved=1

and e820 said that range is RAM.

We should check if we can use that reading out. BIOS could just program wrong address there.

Reported-by: default avatarStefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Acked-by: default avatarMike Waychison <mikew@google.com>
Tested-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
Cc: stable <stable@kernel.org>
parent f712eacf
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#define PFX TCO_MODULE_NAME ": "

/* internal variables */
static u32 tcobase_phys;
static void __iomem *tcobase;
static unsigned int pm_iobase;
static DEFINE_SPINLOCK(tco_lock);	/* Guards the hardware */
@@ -305,10 +306,18 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
	/* Low three bits of BASE0 are reserved. */
	val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);

	if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
								"SP5100 TCO")) {
		printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
			val);
		goto unreg_region;
	}
	tcobase_phys = val;

	tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
	if (tcobase == 0) {
		printk(KERN_ERR PFX "failed to get tcobase address\n");
		goto unreg_region;
		goto unreg_mem_region;
	}

	/* Enable watchdog decode bit */
@@ -346,7 +355,8 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
	/* Done */
	return 1;

	iounmap(tcobase);
unreg_mem_region:
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
unreg_region:
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
exit:
@@ -401,6 +411,7 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)

exit:
	iounmap(tcobase);
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
	return ret;
}
@@ -414,6 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
	/* Deregister */
	misc_deregister(&sp5100_tco_miscdev);
	iounmap(tcobase);
	release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
	release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
}