~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/watchdog/watchdog-test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3 * Watchdog Driver Test Program
  4 * - Tests all ioctls
  5 * - Tests Magic Close - CONFIG_WATCHDOG_NOWAYOUT
  6 * - Could be tested against softdog driver on systems that
  7 *   don't have watchdog hardware.
  8 * - TODO:
  9 * - Enhance test to add coverage for WDIOC_GETTEMP.
 10 *
 11 * Reference: Documentation/watchdog/watchdog-api.rst
 12  */
 13 
 14 #include <errno.h>
 15 #include <stdio.h>
 16 #include <stdlib.h>
 17 #include <string.h>
 18 #include <unistd.h>
 19 #include <fcntl.h>
 20 #include <signal.h>
 21 #include <getopt.h>
 22 #include <sys/ioctl.h>
 23 #include <linux/types.h>
 24 #include <linux/watchdog.h>
 25 
 26 #define DEFAULT_PING_RATE       1
 27 
 28 int fd;
 29 const char v = 'V';
 30 static const char sopts[] = "bdehp:st:Tn:NLf:i";
 31 static const struct option lopts[] = {
 32         {"bootstatus",          no_argument, NULL, 'b'},
 33         {"disable",             no_argument, NULL, 'd'},
 34         {"enable",              no_argument, NULL, 'e'},
 35         {"help",                no_argument, NULL, 'h'},
 36         {"pingrate",      required_argument, NULL, 'p'},
 37         {"status",              no_argument, NULL, 's'},
 38         {"timeout",       required_argument, NULL, 't'},
 39         {"gettimeout",          no_argument, NULL, 'T'},
 40         {"pretimeout",    required_argument, NULL, 'n'},
 41         {"getpretimeout",       no_argument, NULL, 'N'},
 42         {"gettimeleft",         no_argument, NULL, 'L'},
 43         {"file",          required_argument, NULL, 'f'},
 44         {"info",                no_argument, NULL, 'i'},
 45         {NULL,                  no_argument, NULL, 0x0}
 46 };
 47 
 48 /*
 49  * This function simply sends an IOCTL to the driver, which in turn ticks
 50  * the PC Watchdog card to reset its internal timer so it doesn't trigger
 51  * a computer reset.
 52  */
 53 static void keep_alive(void)
 54 {
 55         int dummy;
 56         int ret;
 57 
 58         ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
 59         if (!ret)
 60                 printf(".");
 61 }
 62 
 63 /*
 64  * The main program.  Run the program with "-d" to disable the card,
 65  * or "-e" to enable the card.
 66  */
 67 
 68 static void term(int sig)
 69 {
 70         int ret = write(fd, &v, 1);
 71 
 72         close(fd);
 73         if (ret < 0)
 74                 printf("\nStopping watchdog ticks failed (%d)...\n", errno);
 75         else
 76                 printf("\nStopping watchdog ticks...\n");
 77         exit(0);
 78 }
 79 
 80 static void usage(char *progname)
 81 {
 82         printf("Usage: %s [options]\n", progname);
 83         printf(" -f, --file\t\tOpen watchdog device file\n");
 84         printf("\t\t\tDefault is /dev/watchdog\n");
 85         printf(" -i, --info\t\tShow watchdog_info\n");
 86         printf(" -s, --status\t\tGet status & supported features\n");
 87         printf(" -b, --bootstatus\tGet last boot status (Watchdog/POR)\n");
 88         printf(" -d, --disable\t\tTurn off the watchdog timer\n");
 89         printf(" -e, --enable\t\tTurn on the watchdog timer\n");
 90         printf(" -h, --help\t\tPrint the help message\n");
 91         printf(" -p, --pingrate=P\tSet ping rate to P seconds (default %d)\n",
 92                DEFAULT_PING_RATE);
 93         printf(" -t, --timeout=T\tSet timeout to T seconds\n");
 94         printf(" -T, --gettimeout\tGet the timeout\n");
 95         printf(" -n, --pretimeout=T\tSet the pretimeout to T seconds\n");
 96         printf(" -N, --getpretimeout\tGet the pretimeout\n");
 97         printf(" -L, --gettimeleft\tGet the time left until timer expires\n");
 98         printf("\n");
 99         printf("Parameters are parsed left-to-right in real-time.\n");
100         printf("Example: %s -d -t 10 -p 5 -e\n", progname);
101         printf("Example: %s -t 12 -T -n 7 -N\n", progname);
102 }
103 
104 struct wdiof_status {
105         int flag;
106         const char *status_str;
107 };
108 
109 #define WDIOF_NUM_STATUS 8
110 
111 static const struct wdiof_status wdiof_status[WDIOF_NUM_STATUS] = {
112         {WDIOF_SETTIMEOUT,  "Set timeout (in seconds)"},
113         {WDIOF_MAGICCLOSE,  "Supports magic close char"},
114         {WDIOF_PRETIMEOUT,  "Pretimeout (in seconds), get/set"},
115         {WDIOF_ALARMONLY,  "Watchdog triggers a management or other external alarm not a reboot"},
116         {WDIOF_KEEPALIVEPING,  "Keep alive ping reply"},
117         {WDIOS_DISABLECARD,  "Turn off the watchdog timer"},
118         {WDIOS_ENABLECARD,  "Turn on the watchdog timer"},
119         {WDIOS_TEMPPANIC,  "Kernel panic on temperature trip"},
120 };
121 
122 static void print_status(int flags)
123 {
124         int wdiof = 0;
125 
126         if (flags == WDIOS_UNKNOWN) {
127                 printf("Unknown status error from WDIOC_GETSTATUS\n");
128                 return;
129         }
130 
131         for (wdiof = 0; wdiof < WDIOF_NUM_STATUS; wdiof++) {
132                 if (flags & wdiof_status[wdiof].flag)
133                         printf("Support/Status: %s\n",
134                                 wdiof_status[wdiof].status_str);
135         }
136 }
137 
138 #define WDIOF_NUM_BOOTSTATUS 7
139 
140 static const struct wdiof_status wdiof_bootstatus[WDIOF_NUM_BOOTSTATUS] = {
141         {WDIOF_OVERHEAT, "Reset due to CPU overheat"},
142         {WDIOF_FANFAULT, "Fan failed"},
143         {WDIOF_EXTERN1, "External relay 1"},
144         {WDIOF_EXTERN2, "External relay 2"},
145         {WDIOF_POWERUNDER, "Power bad/power fault"},
146         {WDIOF_CARDRESET, "Card previously reset the CPU"},
147         {WDIOF_POWEROVER,  "Power over voltage"},
148 };
149 
150 static void print_boot_status(int flags)
151 {
152         int wdiof = 0;
153 
154         if (flags == WDIOF_UNKNOWN) {
155                 printf("Unknown flag error from WDIOC_GETBOOTSTATUS\n");
156                 return;
157         }
158 
159         if (flags == 0) {
160                 printf("Last boot is caused by: Power-On-Reset\n");
161                 return;
162         }
163 
164         for (wdiof = 0; wdiof < WDIOF_NUM_BOOTSTATUS; wdiof++) {
165                 if (flags & wdiof_bootstatus[wdiof].flag)
166                         printf("Last boot is caused by: %s\n",
167                                 wdiof_bootstatus[wdiof].status_str);
168         }
169 }
170 
171 int main(int argc, char *argv[])
172 {
173         int flags;
174         unsigned int ping_rate = DEFAULT_PING_RATE;
175         int ret;
176         int c;
177         int oneshot = 0;
178         char *file = "/dev/watchdog";
179         struct watchdog_info info;
180         int temperature;
181 
182         setbuf(stdout, NULL);
183 
184         while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
185                 if (c == 'f')
186                         file = optarg;
187         }
188 
189         fd = open(file, O_WRONLY);
190 
191         if (fd == -1) {
192                 if (errno == ENOENT)
193                         printf("Watchdog device (%s) not found.\n", file);
194                 else if (errno == EACCES)
195                         printf("Run watchdog as root.\n");
196                 else
197                         printf("Watchdog device open failed %s\n",
198                                 strerror(errno));
199                 exit(-1);
200         }
201 
202         /*
203          * Validate that `file` is a watchdog device
204          */
205         ret = ioctl(fd, WDIOC_GETSUPPORT, &info);
206         if (ret) {
207                 printf("WDIOC_GETSUPPORT error '%s'\n", strerror(errno));
208                 close(fd);
209                 exit(ret);
210         }
211 
212         optind = 0;
213 
214         while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
215                 switch (c) {
216                 case 'b':
217                         flags = 0;
218                         oneshot = 1;
219                         ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags);
220                         if (!ret)
221                                 print_boot_status(flags);
222                         else
223                                 printf("WDIOC_GETBOOTSTATUS error '%s'\n", strerror(errno));
224                         break;
225                 case 'd':
226                         flags = WDIOS_DISABLECARD;
227                         ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
228                         if (!ret)
229                                 printf("Watchdog card disabled.\n");
230                         else {
231                                 printf("WDIOS_DISABLECARD error '%s'\n", strerror(errno));
232                                 oneshot = 1;
233                         }
234                         break;
235                 case 'e':
236                         flags = WDIOS_ENABLECARD;
237                         ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
238                         if (!ret)
239                                 printf("Watchdog card enabled.\n");
240                         else {
241                                 printf("WDIOS_ENABLECARD error '%s'\n", strerror(errno));
242                                 oneshot = 1;
243                         }
244                         break;
245                 case 'p':
246                         ping_rate = strtoul(optarg, NULL, 0);
247                         if (!ping_rate)
248                                 ping_rate = DEFAULT_PING_RATE;
249                         printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
250                         break;
251                 case 's':
252                         flags = 0;
253                         oneshot = 1;
254                         ret = ioctl(fd, WDIOC_GETSTATUS, &flags);
255                         if (!ret)
256                                 print_status(flags);
257                         else
258                                 printf("WDIOC_GETSTATUS error '%s'\n", strerror(errno));
259                         ret = ioctl(fd, WDIOC_GETTEMP, &temperature);
260                         if (ret)
261                                 printf("WDIOC_GETTEMP: '%s'\n", strerror(errno));
262                         else
263                                 printf("Temperature %d\n", temperature);
264 
265                         break;
266                 case 't':
267                         flags = strtoul(optarg, NULL, 0);
268                         ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
269                         if (!ret)
270                                 printf("Watchdog timeout set to %u seconds.\n", flags);
271                         else {
272                                 printf("WDIOC_SETTIMEOUT error '%s'\n", strerror(errno));
273                                 oneshot = 1;
274                         }
275                         break;
276                 case 'T':
277                         oneshot = 1;
278                         ret = ioctl(fd, WDIOC_GETTIMEOUT, &flags);
279                         if (!ret)
280                                 printf("WDIOC_GETTIMEOUT returns %u seconds.\n", flags);
281                         else
282                                 printf("WDIOC_GETTIMEOUT error '%s'\n", strerror(errno));
283                         break;
284                 case 'n':
285                         flags = strtoul(optarg, NULL, 0);
286                         ret = ioctl(fd, WDIOC_SETPRETIMEOUT, &flags);
287                         if (!ret)
288                                 printf("Watchdog pretimeout set to %u seconds.\n", flags);
289                         else {
290                                 printf("WDIOC_SETPRETIMEOUT error '%s'\n", strerror(errno));
291                                 oneshot = 1;
292                         }
293                         break;
294                 case 'N':
295                         oneshot = 1;
296                         ret = ioctl(fd, WDIOC_GETPRETIMEOUT, &flags);
297                         if (!ret)
298                                 printf("WDIOC_GETPRETIMEOUT returns %u seconds.\n", flags);
299                         else
300                                 printf("WDIOC_GETPRETIMEOUT error '%s'\n", strerror(errno));
301                         break;
302                 case 'L':
303                         oneshot = 1;
304                         ret = ioctl(fd, WDIOC_GETTIMELEFT, &flags);
305                         if (!ret)
306                                 printf("WDIOC_GETTIMELEFT returns %u seconds.\n", flags);
307                         else
308                                 printf("WDIOC_GETTIMELEFT error '%s'\n", strerror(errno));
309                         break;
310                 case 'f':
311                         /* Handled above */
312                         break;
313                 case 'i':
314                         /*
315                          * watchdog_info was obtained as part of file open
316                          * validation. So we just show it here.
317                          */
318                         oneshot = 1;
319                         printf("watchdog_info:\n");
320                         printf(" identity:\t\t%s\n", info.identity);
321                         printf(" firmware_version:\t%u\n",
322                                info.firmware_version);
323                         print_status(info.options);
324                         break;
325 
326                 default:
327                         usage(argv[0]);
328                         goto end;
329                 }
330         }
331 
332         if (oneshot)
333                 goto end;
334 
335         printf("Watchdog Ticking Away!\n");
336 
337         signal(SIGINT, term);
338 
339         while (1) {
340                 keep_alive();
341                 sleep(ping_rate);
342         }
343 end:
344         /*
345          * Send specific magic character 'V' just in case Magic Close is
346          * enabled to ensure watchdog gets disabled on close.
347          */
348         ret = write(fd, &v, 1);
349         if (ret < 0)
350                 printf("Stopping watchdog ticks failed (%d)...\n", errno);
351         close(fd);
352         return 0;
353 }
354 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php