Re: hpwdt oops in clflush_cache_range

From: Roland Dreier
Date: Wed Feb 27 2008 - 16:35:30 EST


> the ioremap there is trying to remap 0x7b6 bytes at an address of
> 0x240047000ee000 -- either the BIOS data is bogus or the driver is
> getting at it the wrong way.

Looking at the code, it seems that maybe only the low 32 bits of the
address are supposed to be used. With a 32-bit kernel the address
in smbios_entry_point.table_address would be silently truncated to 32
bits, and on my 64-bit kernel, the patch below seems to make things
work... (ie the driver seems happy -- I didn't actually try the
watchdog, and in fact this whole exercise just started with me seeing
the new config option and saying "Hey I've got an HP box with ilo2!"
rather than any desire to actually use the feature)

I have to say this driver looks a little iffy -- a huge chunk of the
code is inside a big

#ifndef CONFIG_X86_64
...
#else
...
#endif

and the code where the crash happens has:

static int __devinit smbios_present(const char __iomem *p)
{
struct smbios_entry_point *eps =
(struct smbios_entry_point *) p;

and then blithely dereferences the eps pointer, which I guess works
fine on x86 but is not exactly how we encourage people to use __iomem
pointers.

- R.

diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a2e174b..21efdfa 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -511,7 +511,7 @@ static int __devinit smbios_present(const char __iomem *p)
(strncmp((char *)eps->intermediate_anchor, "_DMI_",
sizeof(eps->intermediate_anchor)) == 0) &&
(bios_checksum(p+0x10, 15))) {
- buf = ioremap(eps->table_address, eps->table_length);
+ buf = ioremap(eps->table_address & 0xffffffff, eps->table_length);
if (buf == NULL)
return -ENODEV;

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/