watchdog: hpwdt: add next gen HP servers
This patch is required to enable hpwdt to work on next generation HP servers with iLO. Signed-off-by: Thomas Mingarelli <thomas.mingarelli@hp.com> Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
parent
2260286886
commit
5efc7a6222
1 changed files with 77 additions and 27 deletions
|
@ -36,7 +36,7 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#endif /* CONFIG_HPWDT_NMI_DECODING */
|
#endif /* CONFIG_HPWDT_NMI_DECODING */
|
||||||
|
|
||||||
#define HPWDT_VERSION "1.2.0"
|
#define HPWDT_VERSION "1.3.0"
|
||||||
#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
|
#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
|
||||||
#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
|
#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
|
||||||
#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
|
#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
|
||||||
|
@ -87,6 +87,19 @@ struct smbios_cru64_info {
|
||||||
};
|
};
|
||||||
#define SMBIOS_CRU64_INFORMATION 212
|
#define SMBIOS_CRU64_INFORMATION 212
|
||||||
|
|
||||||
|
/* type 219 */
|
||||||
|
struct smbios_proliant_info {
|
||||||
|
u8 type;
|
||||||
|
u8 byte_length;
|
||||||
|
u16 handle;
|
||||||
|
u32 power_features;
|
||||||
|
u32 omega_features;
|
||||||
|
u32 reserved;
|
||||||
|
u32 misc_features;
|
||||||
|
};
|
||||||
|
#define SMBIOS_ICRU_INFORMATION 219
|
||||||
|
|
||||||
|
|
||||||
struct cmn_registers {
|
struct cmn_registers {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -132,6 +145,7 @@ struct cmn_registers {
|
||||||
static unsigned int hpwdt_nmi_decoding;
|
static unsigned int hpwdt_nmi_decoding;
|
||||||
static unsigned int allow_kdump;
|
static unsigned int allow_kdump;
|
||||||
static unsigned int priority; /* hpwdt at end of die_notify list */
|
static unsigned int priority; /* hpwdt at end of die_notify list */
|
||||||
|
static unsigned int is_icru;
|
||||||
static DEFINE_SPINLOCK(rom_lock);
|
static DEFINE_SPINLOCK(rom_lock);
|
||||||
static void *cru_rom_addr;
|
static void *cru_rom_addr;
|
||||||
static struct cmn_registers cmn_regs;
|
static struct cmn_registers cmn_regs;
|
||||||
|
@ -476,19 +490,22 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock_irqsave(&rom_lock, rom_pl);
|
spin_lock_irqsave(&rom_lock, rom_pl);
|
||||||
if (!die_nmi_called)
|
if (!die_nmi_called && !is_icru)
|
||||||
asminline_call(&cmn_regs, cru_rom_addr);
|
asminline_call(&cmn_regs, cru_rom_addr);
|
||||||
die_nmi_called = 1;
|
die_nmi_called = 1;
|
||||||
spin_unlock_irqrestore(&rom_lock, rom_pl);
|
spin_unlock_irqrestore(&rom_lock, rom_pl);
|
||||||
|
if (!is_icru) {
|
||||||
if (cmn_regs.u1.ral == 0) {
|
if (cmn_regs.u1.ral == 0) {
|
||||||
printk(KERN_WARNING "hpwdt: An NMI occurred, "
|
printk(KERN_WARNING "hpwdt: An NMI occurred, "
|
||||||
"but unable to determine source.\n");
|
"but unable to determine source.\n");
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (allow_kdump)
|
if (allow_kdump)
|
||||||
hpwdt_stop();
|
hpwdt_stop();
|
||||||
panic("An NMI occurred, please see the Integrated "
|
panic("An NMI occurred, please see the Integrated "
|
||||||
"Management Log for details.\n");
|
"Management Log for details.\n");
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
@ -659,10 +676,42 @@ static void __devinit hpwdt_check_nmi_decoding(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dmi_find_icru
|
||||||
|
*
|
||||||
|
* Routine Description:
|
||||||
|
* This function checks whether or not we are on an iCRU-based server.
|
||||||
|
* This check is independent of architecture and needs to be made for
|
||||||
|
* any ProLiant system.
|
||||||
|
*/
|
||||||
|
static void __devinit dmi_find_icru(const struct dmi_header *dm, void *dummy)
|
||||||
|
{
|
||||||
|
struct smbios_proliant_info *smbios_proliant_ptr;
|
||||||
|
|
||||||
|
if (dm->type == SMBIOS_ICRU_INFORMATION) {
|
||||||
|
smbios_proliant_ptr = (struct smbios_proliant_info *) dm;
|
||||||
|
if (smbios_proliant_ptr->misc_features & 0x01)
|
||||||
|
is_icru = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
|
static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On typical CRU-based systems we need to map that service in
|
||||||
|
* the BIOS. For 32 bit Operating Systems we need to go through
|
||||||
|
* the 32 Bit BIOS Service Directory. For 64 bit Operating
|
||||||
|
* Systems we get that service through SMBIOS.
|
||||||
|
*
|
||||||
|
* On systems that support the new iCRU service all we need to
|
||||||
|
* do is call dmi_walk to get the supported flag value and skip
|
||||||
|
* the old cru detect code.
|
||||||
|
*/
|
||||||
|
dmi_walk(dmi_find_icru, NULL);
|
||||||
|
if (!is_icru) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to map the ROM to get the CRU service.
|
* We need to map the ROM to get the CRU service.
|
||||||
* For 32 bit Operating Systems we need to go through the 32 Bit
|
* For 32 bit Operating Systems we need to go through the 32 Bit
|
||||||
|
@ -683,6 +732,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev)
|
||||||
*/
|
*/
|
||||||
cmn_regs.u1.rah = 0x0D;
|
cmn_regs.u1.rah = 0x0D;
|
||||||
cmn_regs.u1.ral = 0x02;
|
cmn_regs.u1.ral = 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the priority is set to 1, then we will be put first on the
|
* If the priority is set to 1, then we will be put first on the
|
||||||
|
|
Loading…
Add table
Reference in a new issue