0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013
0014 #include <linux/device.h>
0015 #include <linux/io.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/moduleparam.h>
0019 #include <linux/pci.h>
0020 #include <linux/pci_ids.h>
0021 #include <linux/types.h>
0022 #include <linux/watchdog.h>
0023 #include <asm/nmi.h>
0024 #include <linux/crash_dump.h>
0025
0026 #define HPWDT_VERSION "2.0.4"
0027 #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
0028 #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
0029 #define HPWDT_MAX_TICKS 65535
0030 #define HPWDT_MAX_TIMER TICKS_TO_SECS(HPWDT_MAX_TICKS)
0031 #define DEFAULT_MARGIN 30
0032 #define PRETIMEOUT_SEC 9
0033
0034 static bool ilo5;
0035 static unsigned int soft_margin = DEFAULT_MARGIN;
0036 static bool nowayout = WATCHDOG_NOWAYOUT;
0037 static bool pretimeout = IS_ENABLED(CONFIG_HPWDT_NMI_DECODING);
0038 static int kdumptimeout = -1;
0039
0040 static void __iomem *pci_mem_addr;
0041 static unsigned long __iomem *hpwdt_nmistat;
0042 static unsigned long __iomem *hpwdt_timer_reg;
0043 static unsigned long __iomem *hpwdt_timer_con;
0044
0045 static const struct pci_device_id hpwdt_devices[] = {
0046 { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },
0047 { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },
0048 { PCI_DEVICE(PCI_VENDOR_ID_HP_3PAR, 0x0389) },
0049 {0},
0050 };
0051 MODULE_DEVICE_TABLE(pci, hpwdt_devices);
0052
0053 static const struct pci_device_id hpwdt_blacklist[] = {
0054 { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3306, PCI_VENDOR_ID_HP, 0x1979) },
0055 { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3306, PCI_VENDOR_ID_HP_3PAR, 0x0289) },
0056 {0},
0057 };
0058
0059 static struct watchdog_device hpwdt_dev;
0060
0061
0062
0063 static int hpwdt_hw_is_running(void)
0064 {
0065 return ioread8(hpwdt_timer_con) & 0x01;
0066 }
0067
0068 static int hpwdt_start(struct watchdog_device *wdd)
0069 {
0070 int control = 0x81 | (pretimeout ? 0x4 : 0);
0071 int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000));
0072
0073 dev_dbg(wdd->parent, "start watchdog 0x%08x:0x%08x:0x%02x\n", wdd->timeout, reload, control);
0074 iowrite16(reload, hpwdt_timer_reg);
0075 iowrite8(control, hpwdt_timer_con);
0076
0077 return 0;
0078 }
0079
0080 static void hpwdt_stop(void)
0081 {
0082 unsigned long data;
0083
0084 pr_debug("stop watchdog\n");
0085
0086 data = ioread8(hpwdt_timer_con);
0087 data &= 0xFE;
0088 iowrite8(data, hpwdt_timer_con);
0089 }
0090
0091 static int hpwdt_stop_core(struct watchdog_device *wdd)
0092 {
0093 hpwdt_stop();
0094
0095 return 0;
0096 }
0097
0098 static void hpwdt_ping_ticks(int val)
0099 {
0100 val = min(val, HPWDT_MAX_TICKS);
0101 iowrite16(val, hpwdt_timer_reg);
0102 }
0103
0104 static int hpwdt_ping(struct watchdog_device *wdd)
0105 {
0106 int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000));
0107
0108 dev_dbg(wdd->parent, "ping watchdog 0x%08x:0x%08x\n", wdd->timeout, reload);
0109 hpwdt_ping_ticks(reload);
0110
0111 return 0;
0112 }
0113
0114 static unsigned int hpwdt_gettimeleft(struct watchdog_device *wdd)
0115 {
0116 return TICKS_TO_SECS(ioread16(hpwdt_timer_reg));
0117 }
0118
0119 static int hpwdt_settimeout(struct watchdog_device *wdd, unsigned int val)
0120 {
0121 dev_dbg(wdd->parent, "set_timeout = %d\n", val);
0122
0123 wdd->timeout = val;
0124 if (val <= wdd->pretimeout) {
0125 dev_dbg(wdd->parent, "pretimeout < timeout. Setting to zero\n");
0126 wdd->pretimeout = 0;
0127 pretimeout = false;
0128 if (watchdog_active(wdd))
0129 hpwdt_start(wdd);
0130 }
0131 hpwdt_ping(wdd);
0132
0133 return 0;
0134 }
0135
0136 #ifdef CONFIG_HPWDT_NMI_DECODING
0137 static int hpwdt_set_pretimeout(struct watchdog_device *wdd, unsigned int req)
0138 {
0139 unsigned int val = 0;
0140
0141 dev_dbg(wdd->parent, "set_pretimeout = %d\n", req);
0142 if (req) {
0143 val = PRETIMEOUT_SEC;
0144 if (val >= wdd->timeout)
0145 return -EINVAL;
0146 }
0147
0148 if (val != req)
0149 dev_dbg(wdd->parent, "Rounding pretimeout to: %d\n", val);
0150
0151 wdd->pretimeout = val;
0152 pretimeout = !!val;
0153
0154 if (watchdog_active(wdd))
0155 hpwdt_start(wdd);
0156
0157 return 0;
0158 }
0159
0160 static int hpwdt_my_nmi(void)
0161 {
0162 return ioread8(hpwdt_nmistat) & 0x6;
0163 }
0164
0165
0166
0167
0168 static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
0169 {
0170 unsigned int mynmi = hpwdt_my_nmi();
0171 static char panic_msg[] =
0172 "00: An NMI occurred. Depending on your system the reason "
0173 "for the NMI is logged in any one of the following resources:\n"
0174 "1. Integrated Management Log (IML)\n"
0175 "2. OA Syslog\n"
0176 "3. OA Forward Progress Log\n"
0177 "4. iLO Event Log";
0178
0179 if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi)
0180 return NMI_DONE;
0181
0182 if (ilo5 && !pretimeout && !mynmi)
0183 return NMI_DONE;
0184
0185 if (kdumptimeout < 0)
0186 hpwdt_stop();
0187 else if (kdumptimeout == 0)
0188 ;
0189 else {
0190 unsigned int val = max((unsigned int)kdumptimeout, hpwdt_dev.timeout);
0191 hpwdt_ping_ticks(SECS_TO_TICKS(val));
0192 }
0193
0194 hex_byte_pack(panic_msg, mynmi);
0195 nmi_panic(regs, panic_msg);
0196
0197 return NMI_HANDLED;
0198 }
0199 #endif
0200
0201
0202 static const struct watchdog_info ident = {
0203 .options = WDIOF_PRETIMEOUT |
0204 WDIOF_SETTIMEOUT |
0205 WDIOF_KEEPALIVEPING |
0206 WDIOF_MAGICCLOSE,
0207 .identity = "HPE iLO2+ HW Watchdog Timer",
0208 };
0209
0210
0211
0212
0213
0214 static const struct watchdog_ops hpwdt_ops = {
0215 .owner = THIS_MODULE,
0216 .start = hpwdt_start,
0217 .stop = hpwdt_stop_core,
0218 .ping = hpwdt_ping,
0219 .set_timeout = hpwdt_settimeout,
0220 .get_timeleft = hpwdt_gettimeleft,
0221 #ifdef CONFIG_HPWDT_NMI_DECODING
0222 .set_pretimeout = hpwdt_set_pretimeout,
0223 #endif
0224 };
0225
0226 static struct watchdog_device hpwdt_dev = {
0227 .info = &ident,
0228 .ops = &hpwdt_ops,
0229 .min_timeout = 1,
0230 .timeout = DEFAULT_MARGIN,
0231 .pretimeout = PRETIMEOUT_SEC,
0232 .max_hw_heartbeat_ms = HPWDT_MAX_TIMER * 1000,
0233 };
0234
0235
0236
0237
0238
0239
0240 static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
0241 {
0242 #ifdef CONFIG_HPWDT_NMI_DECODING
0243 int retval;
0244
0245
0246
0247 retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, 0, "hpwdt");
0248 if (retval)
0249 goto error;
0250 retval = register_nmi_handler(NMI_SERR, hpwdt_pretimeout, 0, "hpwdt");
0251 if (retval)
0252 goto error1;
0253 retval = register_nmi_handler(NMI_IO_CHECK, hpwdt_pretimeout, 0, "hpwdt");
0254 if (retval)
0255 goto error2;
0256
0257 dev_info(&dev->dev,
0258 "HPE Watchdog Timer Driver: NMI decoding initialized\n");
0259
0260 return 0;
0261
0262 error2:
0263 unregister_nmi_handler(NMI_SERR, "hpwdt");
0264 error1:
0265 unregister_nmi_handler(NMI_UNKNOWN, "hpwdt");
0266 error:
0267 dev_warn(&dev->dev,
0268 "Unable to register a die notifier (err=%d).\n",
0269 retval);
0270 return retval;
0271 #endif
0272 return 0;
0273 }
0274
0275 static void hpwdt_exit_nmi_decoding(void)
0276 {
0277 #ifdef CONFIG_HPWDT_NMI_DECODING
0278 unregister_nmi_handler(NMI_UNKNOWN, "hpwdt");
0279 unregister_nmi_handler(NMI_SERR, "hpwdt");
0280 unregister_nmi_handler(NMI_IO_CHECK, "hpwdt");
0281 #endif
0282 }
0283
0284 static int hpwdt_init_one(struct pci_dev *dev,
0285 const struct pci_device_id *ent)
0286 {
0287 int retval;
0288
0289
0290
0291
0292
0293
0294 if (dev->subsystem_vendor != PCI_VENDOR_ID_HP &&
0295 dev->subsystem_vendor != PCI_VENDOR_ID_HP_3PAR) {
0296 dev_warn(&dev->dev,
0297 "This server does not have an iLO2+ ASIC.\n");
0298 return -ENODEV;
0299 }
0300
0301 if (pci_match_id(hpwdt_blacklist, dev)) {
0302 dev_dbg(&dev->dev, "Not supported on this device\n");
0303 return -ENODEV;
0304 }
0305
0306 if (pci_enable_device(dev)) {
0307 dev_warn(&dev->dev,
0308 "Not possible to enable PCI Device: 0x%x:0x%x.\n",
0309 ent->vendor, ent->device);
0310 return -ENODEV;
0311 }
0312
0313 pci_mem_addr = pci_iomap(dev, 1, 0x80);
0314 if (!pci_mem_addr) {
0315 dev_warn(&dev->dev,
0316 "Unable to detect the iLO2+ server memory.\n");
0317 retval = -ENOMEM;
0318 goto error_pci_iomap;
0319 }
0320 hpwdt_nmistat = pci_mem_addr + 0x6e;
0321 hpwdt_timer_reg = pci_mem_addr + 0x70;
0322 hpwdt_timer_con = pci_mem_addr + 0x72;
0323
0324
0325 if (hpwdt_hw_is_running()) {
0326 dev_info(&dev->dev, "timer is running\n");
0327 set_bit(WDOG_HW_RUNNING, &hpwdt_dev.status);
0328 }
0329
0330
0331 retval = hpwdt_init_nmi_decoding(dev);
0332 if (retval != 0)
0333 goto error_init_nmi_decoding;
0334
0335 watchdog_stop_on_unregister(&hpwdt_dev);
0336 watchdog_set_nowayout(&hpwdt_dev, nowayout);
0337 watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL);
0338
0339 if (is_kdump_kernel()) {
0340 pretimeout = false;
0341 kdumptimeout = 0;
0342 }
0343
0344 if (pretimeout && hpwdt_dev.timeout <= PRETIMEOUT_SEC) {
0345 dev_warn(&dev->dev, "timeout <= pretimeout. Setting pretimeout to zero\n");
0346 pretimeout = false;
0347 }
0348 hpwdt_dev.pretimeout = pretimeout ? PRETIMEOUT_SEC : 0;
0349 kdumptimeout = min(kdumptimeout, HPWDT_MAX_TIMER);
0350
0351 hpwdt_dev.parent = &dev->dev;
0352 retval = watchdog_register_device(&hpwdt_dev);
0353 if (retval < 0)
0354 goto error_wd_register;
0355
0356 dev_info(&dev->dev, "HPE Watchdog Timer Driver: Version: %s\n",
0357 HPWDT_VERSION);
0358 dev_info(&dev->dev, "timeout: %d seconds (nowayout=%d)\n",
0359 hpwdt_dev.timeout, nowayout);
0360 dev_info(&dev->dev, "pretimeout: %s.\n",
0361 pretimeout ? "on" : "off");
0362 dev_info(&dev->dev, "kdumptimeout: %d.\n", kdumptimeout);
0363
0364 if (dev->subsystem_vendor == PCI_VENDOR_ID_HP_3PAR)
0365 ilo5 = true;
0366
0367 return 0;
0368
0369 error_wd_register:
0370 hpwdt_exit_nmi_decoding();
0371 error_init_nmi_decoding:
0372 pci_iounmap(dev, pci_mem_addr);
0373 error_pci_iomap:
0374 pci_disable_device(dev);
0375 return retval;
0376 }
0377
0378 static void hpwdt_exit(struct pci_dev *dev)
0379 {
0380 watchdog_unregister_device(&hpwdt_dev);
0381 hpwdt_exit_nmi_decoding();
0382 pci_iounmap(dev, pci_mem_addr);
0383 pci_disable_device(dev);
0384 }
0385
0386 static struct pci_driver hpwdt_driver = {
0387 .name = "hpwdt",
0388 .id_table = hpwdt_devices,
0389 .probe = hpwdt_init_one,
0390 .remove = hpwdt_exit,
0391 };
0392
0393 MODULE_AUTHOR("Tom Mingarelli");
0394 MODULE_DESCRIPTION("hpe watchdog driver");
0395 MODULE_LICENSE("GPL");
0396 MODULE_VERSION(HPWDT_VERSION);
0397
0398 module_param(soft_margin, int, 0);
0399 MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
0400
0401 module_param_named(timeout, soft_margin, int, 0);
0402 MODULE_PARM_DESC(timeout, "Alias of soft_margin");
0403
0404 module_param(nowayout, bool, 0);
0405 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
0406 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0407
0408 module_param(kdumptimeout, int, 0444);
0409 MODULE_PARM_DESC(kdumptimeout, "Timeout applied for crash kernel transition in seconds");
0410
0411 #ifdef CONFIG_HPWDT_NMI_DECODING
0412 module_param(pretimeout, bool, 0);
0413 MODULE_PARM_DESC(pretimeout, "Watchdog pretimeout enabled");
0414 #endif
0415
0416 module_pci_driver(hpwdt_driver);