Blame view

drivers/watchdog/hpwdt.c 9.96 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
2
  /*
ca22e79f5   Mingarelli, Thomas   watchdog: hpwdt: ...
3
   *	HPE WatchDog Driver
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
4
5
6
7
   *	based on
   *
   *	SoftDog	0.05:	A Software Watchdog Device
   *
9a46fc4ec   Jerry Hoemann   watchdog: hpwdt: ...
8
   *	(c) Copyright 2018 Hewlett Packard Enterprise Development LP
ca22e79f5   Mingarelli, Thomas   watchdog: hpwdt: ...
9
   *	Thomas Mingarelli <thomas.mingarelli@hpe.com>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
10
   */
27c766aaa   Joe Perches   watchdog: Use pr_...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
12
  #include <linux/device.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
13
  #include <linux/io.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
14
  #include <linux/kernel.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
15
  #include <linux/module.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
16
  #include <linux/moduleparam.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
17
18
  #include <linux/pci.h>
  #include <linux/pci_ids.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
19
  #include <linux/types.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
20
  #include <linux/watchdog.h>
d48b0e173   Ingo Molnar   x86, nmi, drivers...
21
  #include <asm/nmi.h>
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
22

f1bb45b93   Jerry Hoemann   watchdog/hpwdt: R...
23
  #define HPWDT_VERSION			"2.0.3"
e802e32d2   dann frazier   watchdog: hpwdt (...
24
  #define SECS_TO_TICKS(secs)		((secs) * 1000 / 128)
6f681c2ea   dann frazier   watchdog: hpwdt (...
25
  #define TICKS_TO_SECS(ticks)		((ticks) * 128 / 1000)
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
26
27
  #define HPWDT_MAX_TICKS			65535
  #define HPWDT_MAX_TIMER			TICKS_TO_SECS(HPWDT_MAX_TICKS)
923410d0b   dann frazier   watchdog: hpwdt (...
28
  #define DEFAULT_MARGIN			30
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
29
  #define PRETIMEOUT_SEC			9
923410d0b   dann frazier   watchdog: hpwdt (...
30

a6c24733d   Jerry Hoemann   watchdog: hpwdt: ...
31
  static bool ilo5;
923410d0b   dann frazier   watchdog: hpwdt (...
32
  static unsigned int soft_margin = DEFAULT_MARGIN;	/* in seconds */
86a1e1896   Wim Van Sebroeck   watchdog: nowayou...
33
  static bool nowayout = WATCHDOG_NOWAYOUT;
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
34
  static bool pretimeout = IS_ENABLED(CONFIG_HPWDT_NMI_DECODING);
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
35
  static int kdumptimeout = -1;
923410d0b   dann frazier   watchdog: hpwdt (...
36
37
  
  static void __iomem *pci_mem_addr;		/* the PCI-memory address */
838534e50   Jerry Hoemann   watchdog: hpwdt: ...
38
  static unsigned long __iomem *hpwdt_nmistat;
923410d0b   dann frazier   watchdog: hpwdt (...
39
40
  static unsigned long __iomem *hpwdt_timer_reg;
  static unsigned long __iomem *hpwdt_timer_con;
bc17f9dcb   Jingoo Han   watchdog: remove ...
41
  static const struct pci_device_id hpwdt_devices[] = {
36e3ff44c   dann frazier   watchdog: hpwdt (...
42
43
  	{ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },	/* iLO2 */
  	{ PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },	/* iLO3 */
923410d0b   dann frazier   watchdog: hpwdt (...
44
45
46
  	{0},			/* terminate list */
  };
  MODULE_DEVICE_TABLE(pci, hpwdt_devices);
94d6b80c4   Jerry Hoemann   watchdog/hpwdt: E...
47
48
  static const struct pci_device_id hpwdt_blacklist[] = {
  	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3306, PCI_VENDOR_ID_HP, 0x1979) }, /* auxilary iLO */
de2cb0cc3   Jerry Hoemann   watchdog/hpwdt: D...
49
  	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_HP, 0x3306, PCI_VENDOR_ID_HP_3PAR, 0x0289) },  /* CL */
94d6b80c4   Jerry Hoemann   watchdog/hpwdt: E...
50
51
  	{0},			/* terminate list */
  };
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
52

be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
53
  static struct watchdog_device hpwdt_dev;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
54
  /*
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
55
56
   *	Watchdog operations
   */
bb721d6b9   Jerry Hoemann   watchdog/hpwdt: H...
57
58
59
60
  static int hpwdt_hw_is_running(void)
  {
  	return ioread8(hpwdt_timer_con) & 0x01;
  }
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
61
  static int hpwdt_start(struct watchdog_device *wdd)
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
62
  {
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
63
  	int control = 0x81 | (pretimeout ? 0x4 : 0);
c22d8e38e   Jerry Hoemann   watchdog/hpwdt: A...
64
  	int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000));
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
65

c22d8e38e   Jerry Hoemann   watchdog/hpwdt: A...
66
67
  	dev_dbg(wdd->parent, "start watchdog 0x%08x:0x%08x:0x%02x
  ", wdd->timeout, reload, control);
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
68
  	iowrite16(reload, hpwdt_timer_reg);
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
69
  	iowrite8(control, hpwdt_timer_con);
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
70
71
  
  	return 0;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
72
73
74
75
76
  }
  
  static void hpwdt_stop(void)
  {
  	unsigned long data;
ccfd69213   Jerry Hoemann   watchdog: hpwdt: ...
77
78
  	pr_debug("stop  watchdog
  ");
d08c9a33b   Mingarelli, Thomas   hpwdt: Only BYTE ...
79
  	data = ioread8(hpwdt_timer_con);
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
80
  	data &= 0xFE;
d08c9a33b   Mingarelli, Thomas   hpwdt: Only BYTE ...
81
  	iowrite8(data, hpwdt_timer_con);
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
82
  }
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
83
  static int hpwdt_stop_core(struct watchdog_device *wdd)
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
84
  {
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
85
86
87
  	hpwdt_stop();
  
  	return 0;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
88
  }
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
89
90
91
92
93
  static void hpwdt_ping_ticks(int val)
  {
  	val = min(val, HPWDT_MAX_TICKS);
  	iowrite16(val, hpwdt_timer_reg);
  }
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
94
  static int hpwdt_ping(struct watchdog_device *wdd)
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
95
  {
c22d8e38e   Jerry Hoemann   watchdog/hpwdt: A...
96
  	int reload = SECS_TO_TICKS(min(wdd->timeout, wdd->max_hw_heartbeat_ms/1000));
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
97

c22d8e38e   Jerry Hoemann   watchdog/hpwdt: A...
98
99
  	dev_dbg(wdd->parent, "ping  watchdog 0x%08x:0x%08x
  ", wdd->timeout, reload);
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
100
  	hpwdt_ping_ticks(reload);
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
101

7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
102
103
  	return 0;
  }
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
104
  static unsigned int hpwdt_gettimeleft(struct watchdog_device *wdd)
aae67f360   dann frazier   watchdog: hpwdt (...
105
106
107
  {
  	return TICKS_TO_SECS(ioread16(hpwdt_timer_reg));
  }
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
108
109
  static int hpwdt_settimeout(struct watchdog_device *wdd, unsigned int val)
  {
ccfd69213   Jerry Hoemann   watchdog: hpwdt: ...
110
111
  	dev_dbg(wdd->parent, "set_timeout = %d
  ", val);
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
112
  	wdd->timeout = val;
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
113
  	if (val <= wdd->pretimeout) {
ccfd69213   Jerry Hoemann   watchdog: hpwdt: ...
114
115
  		dev_dbg(wdd->parent, "pretimeout < timeout. Setting to zero
  ");
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
116
117
118
119
120
  		wdd->pretimeout = 0;
  		pretimeout = 0;
  		if (watchdog_active(wdd))
  			hpwdt_start(wdd);
  	}
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
121
122
123
124
  	hpwdt_ping(wdd);
  
  	return 0;
  }
aeebc6ba8   Arnd Bergmann   watchdog: hpwdt: ...
125
  #ifdef CONFIG_HPWDT_NMI_DECODING
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
126
127
128
  static int hpwdt_set_pretimeout(struct watchdog_device *wdd, unsigned int req)
  {
  	unsigned int val = 0;
ccfd69213   Jerry Hoemann   watchdog: hpwdt: ...
129
130
  	dev_dbg(wdd->parent, "set_pretimeout = %d
  ", req);
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
131
132
133
134
135
  	if (req) {
  		val = PRETIMEOUT_SEC;
  		if (val >= wdd->timeout)
  			return -EINVAL;
  	}
ccfd69213   Jerry Hoemann   watchdog: hpwdt: ...
136
137
138
  	if (val != req)
  		dev_dbg(wdd->parent, "Rounding pretimeout to: %d
  ", val);
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
139
140
141
142
143
144
145
146
  	wdd->pretimeout = val;
  	pretimeout = !!val;
  
  	if (watchdog_active(wdd))
  		hpwdt_start(wdd);
  
  	return 0;
  }
838534e50   Jerry Hoemann   watchdog: hpwdt: ...
147
148
149
150
  static int hpwdt_my_nmi(void)
  {
  	return ioread8(hpwdt_nmistat) & 0x6;
  }
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
151
  /*
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
152
153
   *	NMI Handler
   */
9c48f1c62   Don Zickus   x86, nmi: Wire up...
154
  static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
155
  {
a042229a1   Jerry Hoemann   watchdog: hpwdt: ...
156
157
158
159
160
161
162
163
164
165
166
167
  	unsigned int mynmi = hpwdt_my_nmi();
  	static char panic_msg[] =
  		"00: An NMI occurred. Depending on your system the reason "
  		"for the NMI is logged in any one of the following resources:
  "
  		"1. Integrated Management Log (IML)
  "
  		"2. OA Syslog
  "
  		"3. OA Forward Progress Log
  "
  		"4. iLO Event Log";
62290a5c1   Jerry Hoemann   watchdog: hpwdt: ...
168
  	if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi)
838534e50   Jerry Hoemann   watchdog: hpwdt: ...
169
  		return NMI_DONE;
093d43858   Jerry Hoemann   watchdog: hpwdt: ...
170
  	if (ilo5 && !pretimeout && !mynmi)
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
171
  		return NMI_DONE;
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
172
173
174
175
176
177
178
179
  	if (kdumptimeout < 0)
  		hpwdt_stop();
  	else if (kdumptimeout == 0)
  		;
  	else {
  		unsigned int val = max((unsigned int)kdumptimeout, hpwdt_dev.timeout);
  		hpwdt_ping_ticks(SECS_TO_TICKS(val));
  	}
dbc018eca   Naga Chumbalkar   watchdog: hpwdt: ...
180

a042229a1   Jerry Hoemann   watchdog: hpwdt: ...
181
182
  	hex_byte_pack(panic_msg, mynmi);
  	nmi_panic(regs, panic_msg);
5efc7a622   Thomas Mingarelli   watchdog: hpwdt: ...
183

abc514c58   Hidehiro Kawai   hpwdt: use nmi_pa...
184
  	return NMI_HANDLED;
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
185
  }
86ded1f35   dann frazier   watchdog: hpwdt (...
186
  #endif /* CONFIG_HPWDT_NMI_DECODING */
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
187

7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
188

42747d712   Wim Van Sebroeck   [WATCHDOG] watchd...
189
  static const struct watchdog_info ident = {
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
190
191
  	.options = WDIOF_PRETIMEOUT    |
  		   WDIOF_SETTIMEOUT    |
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
192
193
  		   WDIOF_KEEPALIVEPING |
  		   WDIOF_MAGICCLOSE,
ca22e79f5   Mingarelli, Thomas   watchdog: hpwdt: ...
194
  	.identity = "HPE iLO2+ HW Watchdog Timer",
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
195
  };
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
196
197
198
  /*
   *	Kernel interfaces
   */
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
199
200
201
202
203
204
205
206
  
  static const struct watchdog_ops hpwdt_ops = {
  	.owner		= THIS_MODULE,
  	.start		= hpwdt_start,
  	.stop		= hpwdt_stop_core,
  	.ping		= hpwdt_ping,
  	.set_timeout	= hpwdt_settimeout,
  	.get_timeleft	= hpwdt_gettimeleft,
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
207
208
209
  #ifdef CONFIG_HPWDT_NMI_DECODING
  	.set_pretimeout	= hpwdt_set_pretimeout,
  #endif
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
210
  };
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
211
212
213
214
  static struct watchdog_device hpwdt_dev = {
  	.info		= &ident,
  	.ops		= &hpwdt_ops,
  	.min_timeout	= 1,
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
215
  	.timeout	= DEFAULT_MARGIN,
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
216
  	.pretimeout	= PRETIMEOUT_SEC,
c22d8e38e   Jerry Hoemann   watchdog/hpwdt: A...
217
  	.max_hw_heartbeat_ms	= HPWDT_MAX_TIMER * 1000,
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
218
  };
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
219

7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
220
221
222
  /*
   *	Init & Exit
   */
2d991a164   Bill Pemberton   watchdog: remove ...
223
  static int hpwdt_init_nmi_decoding(struct pci_dev *dev)
2ec7ed67d   dann frazier   watchdog: hpwdt (...
224
  {
2b3d89b40   Jerry Hoemann   watchdog: hpwdt: ...
225
  #ifdef CONFIG_HPWDT_NMI_DECODING
2ec7ed67d   dann frazier   watchdog: hpwdt (...
226
  	int retval;
2ec7ed67d   dann frazier   watchdog: hpwdt (...
227
  	/*
09ee10143   Don Zickus   watchdog, hpwdt: ...
228
  	 * Only one function can register for NMI_UNKNOWN
2ec7ed67d   dann frazier   watchdog: hpwdt (...
229
  	 */
09ee10143   Don Zickus   watchdog, hpwdt: ...
230
  	retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, 0, "hpwdt");
553222f3e   Don Zickus   x86/nmi: Add new ...
231
232
233
234
235
236
237
238
  	if (retval)
  		goto error;
  	retval = register_nmi_handler(NMI_SERR, hpwdt_pretimeout, 0, "hpwdt");
  	if (retval)
  		goto error1;
  	retval = register_nmi_handler(NMI_IO_CHECK, hpwdt_pretimeout, 0, "hpwdt");
  	if (retval)
  		goto error2;
2ec7ed67d   dann frazier   watchdog: hpwdt (...
239
240
  
  	dev_info(&dev->dev,
703fc3df9   Jerry Hoemann   watchdog: hpwdt: ...
241
242
  		"HPE Watchdog Timer Driver: NMI decoding initialized
  ");
2ec7ed67d   dann frazier   watchdog: hpwdt (...
243
  	return 0;
553222f3e   Don Zickus   x86/nmi: Add new ...
244
245
246
247
248
249
250
251
252
253
  
  error2:
  	unregister_nmi_handler(NMI_SERR, "hpwdt");
  error1:
  	unregister_nmi_handler(NMI_UNKNOWN, "hpwdt");
  error:
  	dev_warn(&dev->dev,
  		"Unable to register a die notifier (err=%d).
  ",
  		retval);
553222f3e   Don Zickus   x86/nmi: Add new ...
254
  	return retval;
2b3d89b40   Jerry Hoemann   watchdog: hpwdt: ...
255
256
  #endif	/* CONFIG_HPWDT_NMI_DECODING */
  	return 0;
2ec7ed67d   dann frazier   watchdog: hpwdt (...
257
  }
b77b70886   Axel Lin   watchdog: hpwdt: ...
258
  static void hpwdt_exit_nmi_decoding(void)
2ec7ed67d   dann frazier   watchdog: hpwdt (...
259
  {
2b3d89b40   Jerry Hoemann   watchdog: hpwdt: ...
260
  #ifdef CONFIG_HPWDT_NMI_DECODING
9c48f1c62   Don Zickus   x86, nmi: Wire up...
261
  	unregister_nmi_handler(NMI_UNKNOWN, "hpwdt");
a089361cf   Mingarelli, Thomas   watchdog: hpwdt: ...
262
263
  	unregister_nmi_handler(NMI_SERR, "hpwdt");
  	unregister_nmi_handler(NMI_IO_CHECK, "hpwdt");
2b3d89b40   Jerry Hoemann   watchdog: hpwdt: ...
264
  #endif
86ded1f35   dann frazier   watchdog: hpwdt (...
265
  }
2d991a164   Bill Pemberton   watchdog: remove ...
266
  static int hpwdt_init_one(struct pci_dev *dev,
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
267
  					const struct pci_device_id *ent)
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
268
269
270
271
  {
  	int retval;
  
  	/*
36e3ff44c   dann frazier   watchdog: hpwdt (...
272
  	 * First let's find out if we are on an iLO2+ server. We will
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
273
  	 * not run on a legacy ASM box.
ab4ba3cde   Thomas Mingarelli   [WATCHDOG] hpwdt....
274
  	 * So we only support the G5 ProLiant servers and higher.
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
275
  	 */
fc113d54e   Brian Boylston   watchdog: hpwdt: ...
276
277
  	if (dev->subsystem_vendor != PCI_VENDOR_ID_HP &&
  	    dev->subsystem_vendor != PCI_VENDOR_ID_HP_3PAR) {
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
278
  		dev_warn(&dev->dev,
36e3ff44c   dann frazier   watchdog: hpwdt (...
279
280
  			"This server does not have an iLO2+ ASIC.
  ");
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
281
282
  		return -ENODEV;
  	}
94d6b80c4   Jerry Hoemann   watchdog/hpwdt: E...
283
284
285
  	if (pci_match_id(hpwdt_blacklist, dev)) {
  		dev_dbg(&dev->dev, "Not supported on this device
  ");
0821f20d4   Mingarelli, Thomas   watchdog: hpwdt: ...
286
  		return -ENODEV;
94d6b80c4   Jerry Hoemann   watchdog/hpwdt: E...
287
  	}
0821f20d4   Mingarelli, Thomas   watchdog: hpwdt: ...
288

7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
289
290
291
292
293
294
295
296
297
298
299
  	if (pci_enable_device(dev)) {
  		dev_warn(&dev->dev,
  			"Not possible to enable PCI Device: 0x%x:0x%x.
  ",
  			ent->vendor, ent->device);
  		return -ENODEV;
  	}
  
  	pci_mem_addr = pci_iomap(dev, 1, 0x80);
  	if (!pci_mem_addr) {
  		dev_warn(&dev->dev,
36e3ff44c   dann frazier   watchdog: hpwdt (...
300
301
  			"Unable to detect the iLO2+ server memory.
  ");
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
302
303
304
  		retval = -ENOMEM;
  		goto error_pci_iomap;
  	}
838534e50   Jerry Hoemann   watchdog: hpwdt: ...
305
  	hpwdt_nmistat	= pci_mem_addr + 0x6e;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
306
307
  	hpwdt_timer_reg = pci_mem_addr + 0x70;
  	hpwdt_timer_con = pci_mem_addr + 0x72;
bb721d6b9   Jerry Hoemann   watchdog/hpwdt: H...
308
309
310
311
312
313
  	/* Have the core update running timer until user space is ready */
  	if (hpwdt_hw_is_running()) {
  		dev_info(&dev->dev, "timer is running
  ");
  		set_bit(WDOG_HW_RUNNING, &hpwdt_dev.status);
  	}
308b135e4   Toshi Kani   hpwdt: Fix kdump ...
314

2ec7ed67d   dann frazier   watchdog: hpwdt (...
315
316
317
318
  	/* Initialize NMI Decoding functionality */
  	retval = hpwdt_init_nmi_decoding(dev);
  	if (retval != 0)
  		goto error_init_nmi_decoding;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
319

48b32199f   Jerry Hoemann   watchdog/hpwdt: S...
320
  	watchdog_stop_on_unregister(&hpwdt_dev);
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
321
  	watchdog_set_nowayout(&hpwdt_dev, nowayout);
87dfe210f   Wolfram Sang   watchdog: hpwdt: ...
322
  	watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL);
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
323

10d790d1f   Jerry Hoemann   watchdog: hpwdt: ...
324
325
326
327
328
  	if (pretimeout && hpwdt_dev.timeout <= PRETIMEOUT_SEC) {
  		dev_warn(&dev->dev, "timeout <= pretimeout. Setting pretimeout to zero
  ");
  		pretimeout = 0;
  	}
4d9186d01   Jerry Hoemann   watchdog: hpwdt: ...
329
  	hpwdt_dev.pretimeout = pretimeout ? PRETIMEOUT_SEC : 0;
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
330
  	kdumptimeout = min(kdumptimeout, HPWDT_MAX_TIMER);
4d9186d01   Jerry Hoemann   watchdog: hpwdt: ...
331

d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
332
333
  	hpwdt_dev.parent = &dev->dev;
  	retval = watchdog_register_device(&hpwdt_dev);
f51540b83   Wolfram Sang   watchdog: hpwdt: ...
334
  	if (retval < 0)
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
335
  		goto error_wd_register;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
336

923014619   Jerry Hoemann   watchdog: hpwdt: ...
337
338
339
340
341
342
343
344
345
  	dev_info(&dev->dev, "HPE Watchdog Timer Driver: Version: %s
  ",
  				HPWDT_VERSION);
  	dev_info(&dev->dev, "timeout: %d seconds (nowayout=%d)
  ",
  				hpwdt_dev.timeout, nowayout);
  	dev_info(&dev->dev, "pretimeout: %s.
  ",
  				pretimeout ? "on" : "off");
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
346
347
  	dev_info(&dev->dev, "kdumptimeout: %d.
  ", kdumptimeout);
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
348

a6c24733d   Jerry Hoemann   watchdog: hpwdt: ...
349
350
  	if (dev->subsystem_vendor == PCI_VENDOR_ID_HP_3PAR)
  		ilo5 = true;
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
351
  	return 0;
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
352
  error_wd_register:
2ec7ed67d   dann frazier   watchdog: hpwdt (...
353
354
  	hpwdt_exit_nmi_decoding();
  error_init_nmi_decoding:
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
355
356
357
358
359
  	pci_iounmap(dev, pci_mem_addr);
  error_pci_iomap:
  	pci_disable_device(dev);
  	return retval;
  }
4b12b896c   Bill Pemberton   watchdog: remove ...
360
  static void hpwdt_exit(struct pci_dev *dev)
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
361
  {
d0a4027f2   Jerry Hoemann   watchdog: hpwdt: ...
362
  	watchdog_unregister_device(&hpwdt_dev);
2ec7ed67d   dann frazier   watchdog: hpwdt (...
363
  	hpwdt_exit_nmi_decoding();
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
364
365
366
367
368
369
370
371
  	pci_iounmap(dev, pci_mem_addr);
  	pci_disable_device(dev);
  }
  
  static struct pci_driver hpwdt_driver = {
  	.name = "hpwdt",
  	.id_table = hpwdt_devices,
  	.probe = hpwdt_init_one,
82268714b   Bill Pemberton   watchdog: remove ...
372
  	.remove = hpwdt_exit,
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
373
  };
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
374
  MODULE_AUTHOR("Tom Mingarelli");
9a46fc4ec   Jerry Hoemann   watchdog: hpwdt: ...
375
  MODULE_DESCRIPTION("hpe watchdog driver");
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
376
  MODULE_LICENSE("GPL");
d8100c3ab   Thomas Mingarelli   [WATCHDOG] hpwdt....
377
  MODULE_VERSION(HPWDT_VERSION);
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
378
379
380
  
  module_param(soft_margin, int, 0);
  MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds");
397a35d41   Jerry Hoemann   watchdog: hpwdt: ...
381
382
  module_param_named(timeout, soft_margin, int, 0);
  MODULE_PARM_DESC(timeout, "Alias of soft_margin");
86a1e1896   Wim Van Sebroeck   watchdog: nowayou...
383
  module_param(nowayout, bool, 0);
7f4da4745   Thomas Mingarelli   [WATCHDOG] HP Pro...
384
385
  MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  		__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
be3d7f7cb   Jerry Hoemann   watchdog/hpwdt: A...
386
387
  module_param(kdumptimeout, int, 0444);
  MODULE_PARM_DESC(kdumptimeout, "Timeout applied for crash kernel transition in seconds");
0458f403f   Jerry Hoemann   watchdog: hpwdt: ...
388
389
390
391
  #ifdef CONFIG_HPWDT_NMI_DECODING
  module_param(pretimeout, bool, 0);
  MODULE_PARM_DESC(pretimeout, "Watchdog pretimeout enabled");
  #endif
5ce9c371c   Wim Van Sebroeck   watchdog: Use mod...
392
  module_pci_driver(hpwdt_driver);