linux/drivers/watchdog/octeon-wdt-main.c
<<
>>
Prefs
   1/*
   2 * Octeon Watchdog driver
   3 *
   4 * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks
   5 *
   6 * Some parts derived from wdt.c
   7 *
   8 *      (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>,
   9 *                                              All Rights Reserved.
  10 *
  11 *      This program is free software; you can redistribute it and/or
  12 *      modify it under the terms of the GNU General Public License
  13 *      as published by the Free Software Foundation; either version
  14 *      2 of the License, or (at your option) any later version.
  15 *
  16 *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
  17 *      warranty for any of this software. This material is provided
  18 *      "AS-IS" and at no charge.
  19 *
  20 *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  21 *
  22 * This file is subject to the terms and conditions of the GNU General Public
  23 * License.  See the file "COPYING" in the main directory of this archive
  24 * for more details.
  25 *
  26 *
  27 * The OCTEON watchdog has a maximum timeout of 2^32 * io_clock.
  28 * For most systems this is less than 10 seconds, so to allow for
  29 * software to request longer watchdog heartbeats, we maintain software
  30 * counters to count multiples of the base rate.  If the system locks
  31 * up in such a manner that we can not run the software counters, the
  32 * only result is a watchdog reset sooner than was requested.  But
  33 * that is OK, because in this case userspace would likely not be able
  34 * to do anything anyhow.
  35 *
  36 * The hardware watchdog interval we call the period.  The OCTEON
  37 * watchdog goes through several stages, after the first period an
  38 * irq is asserted, then if it is not reset, after the next period NMI
  39 * is asserted, then after an additional period a chip wide soft reset.
  40 * So for the software counters, we reset watchdog after each period
  41 * and decrement the counter.  But for the last two periods we need to
  42 * let the watchdog progress to the NMI stage so we disable the irq
  43 * and let it proceed.  Once in the NMI, we print the register state
  44 * to the serial port and then wait for the reset.
  45 *
  46 * A watchdog is maintained for each CPU in the system, that way if
  47 * one CPU suffers a lockup, we also get a register dump and reset.
  48 * The userspace ping resets the watchdog on all CPUs.
  49 *
  50 * Before userspace opens the watchdog device, we still run the
  51 * watchdogs to catch any lockups that may be kernel related.
  52 *
  53 */
  54
  55#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  56
  57#include <linux/miscdevice.h>
  58#include <linux/interrupt.h>
  59#include <linux/watchdog.h>
  60#include <linux/cpumask.h>
  61#include <linux/bitops.h>
  62#include <linux/kernel.h>
  63#include <linux/module.h>
  64#include <linux/string.h>
  65#include <linux/delay.h>
  66#include <linux/cpu.h>
  67#include <linux/smp.h>
  68#include <linux/fs.h>
  69#include <linux/irq.h>
  70
  71#include <asm/mipsregs.h>
  72#include <asm/uasm.h>
  73
  74#include <asm/octeon/octeon.h>
  75
  76/* The count needed to achieve timeout_sec. */
  77static unsigned int timeout_cnt;
  78
  79/* The maximum period supported. */
  80static unsigned int max_timeout_sec;
  81
  82/* The current period.  */
  83static unsigned int timeout_sec;
  84
  85/* Set to non-zero when userspace countdown mode active */
  86static int do_coundown;
  87static unsigned int countdown_reset;
  88static unsigned int per_cpu_countdown[NR_CPUS];
  89
  90static cpumask_t irq_enabled_cpus;
  91
  92#define WD_TIMO 60                      /* Default heartbeat = 60 seconds */
  93
  94static int heartbeat = WD_TIMO;
  95module_param(heartbeat, int, S_IRUGO);
  96MODULE_PARM_DESC(heartbeat,
  97        "Watchdog heartbeat in seconds. (0 < heartbeat, default="
  98                                __MODULE_STRING(WD_TIMO) ")");
  99
 100static bool nowayout = WATCHDOG_NOWAYOUT;
 101module_param(nowayout, bool, S_IRUGO);
 102MODULE_PARM_DESC(nowayout,
 103        "Watchdog cannot be stopped once started (default="
 104                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 105
 106static unsigned long octeon_wdt_is_open;
 107static char expect_close;
 108
 109static u32 __initdata nmi_stage1_insns[64];
 110/* We need one branch and therefore one relocation per target label. */
 111static struct uasm_label __initdata labels[5];
 112static struct uasm_reloc __initdata relocs[5];
 113
 114enum lable_id {
 115        label_enter_bootloader = 1
 116};
 117
 118/* Some CP0 registers */
 119#define K0              26
 120#define C0_CVMMEMCTL 11, 7
 121#define C0_STATUS 12, 0
 122#define C0_EBASE 15, 1
 123#define C0_DESAVE 31, 0
 124
 125void octeon_wdt_nmi_stage2(void);
 126
 127static void __init octeon_wdt_build_stage1(void)
 128{
 129        int i;
 130        int len;
 131        u32 *p = nmi_stage1_insns;
 132#ifdef CONFIG_HOTPLUG_CPU
 133        struct uasm_label *l = labels;
 134        struct uasm_reloc *r = relocs;
 135#endif
 136
 137        /*
 138         * For the next few instructions running the debugger may
 139         * cause corruption of k0 in the saved registers. Since we're
 140         * about to crash, nobody probably cares.
 141         *
 142         * Save K0 into the debug scratch register
 143         */
 144        uasm_i_dmtc0(&p, K0, C0_DESAVE);
 145
 146        uasm_i_mfc0(&p, K0, C0_STATUS);
 147#ifdef CONFIG_HOTPLUG_CPU
 148        uasm_il_bbit0(&p, &r, K0, ilog2(ST0_NMI), label_enter_bootloader);
 149#endif
 150        /* Force 64-bit addressing enabled */
 151        uasm_i_ori(&p, K0, K0, ST0_UX | ST0_SX | ST0_KX);
 152        uasm_i_mtc0(&p, K0, C0_STATUS);
 153
 154#ifdef CONFIG_HOTPLUG_CPU
 155        uasm_i_mfc0(&p, K0, C0_EBASE);
 156        /* Coreid number in K0 */
 157        uasm_i_andi(&p, K0, K0, 0xf);
 158        /* 8 * coreid in bits 16-31 */
 159        uasm_i_dsll_safe(&p, K0, K0, 3 + 16);
 160        uasm_i_ori(&p, K0, K0, 0x8001);
 161        uasm_i_dsll_safe(&p, K0, K0, 16);
 162        uasm_i_ori(&p, K0, K0, 0x0700);
 163        uasm_i_drotr_safe(&p, K0, K0, 32);
 164        /*
 165         * Should result in: 0x8001,0700,0000,8*coreid which is
 166         * CVMX_CIU_WDOGX(coreid) - 0x0500
 167         *
 168         * Now ld K0, CVMX_CIU_WDOGX(coreid)
 169         */
 170        uasm_i_ld(&p, K0, 0x500, K0);
 171        /*
 172         * If bit one set handle the NMI as a watchdog event.
 173         * otherwise transfer control to bootloader.
 174         */
 175        uasm_il_bbit0(&p, &r, K0, 1, label_enter_bootloader);
 176        uasm_i_nop(&p);
 177#endif
 178
 179        /* Clear Dcache so cvmseg works right. */
 180        uasm_i_cache(&p, 1, 0, 0);
 181
 182        /* Use K0 to do a read/modify/write of CVMMEMCTL */
 183        uasm_i_dmfc0(&p, K0, C0_CVMMEMCTL);
 184        /* Clear out the size of CVMSEG */
 185        uasm_i_dins(&p, K0, 0, 0, 6);
 186        /* Set CVMSEG to its largest value */
 187        uasm_i_ori(&p, K0, K0, 0x1c0 | 54);
 188        /* Store the CVMMEMCTL value */
 189        uasm_i_dmtc0(&p, K0, C0_CVMMEMCTL);
 190
 191        /* Load the address of the second stage handler */
 192        UASM_i_LA(&p, K0, (long)octeon_wdt_nmi_stage2);
 193        uasm_i_jr(&p, K0);
 194        uasm_i_dmfc0(&p, K0, C0_DESAVE);
 195
 196#ifdef CONFIG_HOTPLUG_CPU
 197        uasm_build_label(&l, p, label_enter_bootloader);
 198        /* Jump to the bootloader and restore K0 */
 199        UASM_i_LA(&p, K0, (long)octeon_bootloader_entry_addr);
 200        uasm_i_jr(&p, K0);
 201        uasm_i_dmfc0(&p, K0, C0_DESAVE);
 202#endif
 203        uasm_resolve_relocs(relocs, labels);
 204
 205        len = (int)(p - nmi_stage1_insns);
 206        pr_debug("Synthesized NMI stage 1 handler (%d instructions)\n", len);
 207
 208        pr_debug("\t.set push\n");
 209        pr_debug("\t.set noreorder\n");
 210        for (i = 0; i < len; i++)
 211                pr_debug("\t.word 0x%08x\n", nmi_stage1_insns[i]);
 212        pr_debug("\t.set pop\n");
 213
 214        if (len > 32)
 215                panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len);
 216}
 217
 218static int cpu2core(int cpu)
 219{
 220#ifdef CONFIG_SMP
 221        return cpu_logical_map(cpu);
 222#else
 223        return cvmx_get_core_num();
 224#endif
 225}
 226
 227static int core2cpu(int coreid)
 228{
 229#ifdef CONFIG_SMP
 230        return cpu_number_map(coreid);
 231#else
 232        return 0;
 233#endif
 234}
 235
 236/**
 237 * Poke the watchdog when an interrupt is received
 238 *
 239 * @cpl:
 240 * @dev_id:
 241 *
 242 * Returns
 243 */
 244static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
 245{
 246        unsigned int core = cvmx_get_core_num();
 247        int cpu = core2cpu(core);
 248
 249        if (do_coundown) {
 250                if (per_cpu_countdown[cpu] > 0) {
 251                        /* We're alive, poke the watchdog */
 252                        cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
 253                        per_cpu_countdown[cpu]--;
 254                } else {
 255                        /* Bad news, you are about to reboot. */
 256                        disable_irq_nosync(cpl);
 257                        cpumask_clear_cpu(cpu, &irq_enabled_cpus);
 258                }
 259        } else {
 260                /* Not open, just ping away... */
 261                cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
 262        }
 263        return IRQ_HANDLED;
 264}
 265
 266/* From setup.c */
 267extern int prom_putchar(char c);
 268
 269/**
 270 * Write a string to the uart
 271 *
 272 * @str:        String to write
 273 */
 274static void octeon_wdt_write_string(const char *str)
 275{
 276        /* Just loop writing one byte at a time */
 277        while (*str)
 278                prom_putchar(*str++);
 279}
 280
 281/**
 282 * Write a hex number out of the uart
 283 *
 284 * @value:      Number to display
 285 * @digits:     Number of digits to print (1 to 16)
 286 */
 287static void octeon_wdt_write_hex(u64 value, int digits)
 288{
 289        int d;
 290        int v;
 291        for (d = 0; d < digits; d++) {
 292                v = (value >> ((digits - d - 1) * 4)) & 0xf;
 293                if (v >= 10)
 294                        prom_putchar('a' + v - 10);
 295                else
 296                        prom_putchar('0' + v);
 297        }
 298}
 299
 300const char *reg_name[] = {
 301        "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
 302        "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
 303        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
 304        "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
 305};
 306
 307/**
 308 * NMI stage 3 handler. NMIs are handled in the following manner:
 309 * 1) The first NMI handler enables CVMSEG and transfers from
 310 * the bootbus region into normal memory. It is careful to not
 311 * destroy any registers.
 312 * 2) The second stage handler uses CVMSEG to save the registers
 313 * and create a stack for C code. It then calls the third level
 314 * handler with one argument, a pointer to the register values.
 315 * 3) The third, and final, level handler is the following C
 316 * function that prints out some useful infomration.
 317 *
 318 * @reg:    Pointer to register state before the NMI
 319 */
 320void octeon_wdt_nmi_stage3(u64 reg[32])
 321{
 322        u64 i;
 323
 324        unsigned int coreid = cvmx_get_core_num();
 325        /*
 326         * Save status and cause early to get them before any changes
 327         * might happen.
 328         */
 329        u64 cp0_cause = read_c0_cause();
 330        u64 cp0_status = read_c0_status();
 331        u64 cp0_error_epc = read_c0_errorepc();
 332        u64 cp0_epc = read_c0_epc();
 333
 334        /* Delay so output from all cores output is not jumbled together. */
 335        __delay(100000000ull * coreid);
 336
 337        octeon_wdt_write_string("\r\n*** NMI Watchdog interrupt on Core 0x");
 338        octeon_wdt_write_hex(coreid, 1);
 339        octeon_wdt_write_string(" ***\r\n");
 340        for (i = 0; i < 32; i++) {
 341                octeon_wdt_write_string("\t");
 342                octeon_wdt_write_string(reg_name[i]);
 343                octeon_wdt_write_string("\t0x");
 344                octeon_wdt_write_hex(reg[i], 16);
 345                if (i & 1)
 346                        octeon_wdt_write_string("\r\n");
 347        }
 348        octeon_wdt_write_string("\terr_epc\t0x");
 349        octeon_wdt_write_hex(cp0_error_epc, 16);
 350
 351        octeon_wdt_write_string("\tepc\t0x");
 352        octeon_wdt_write_hex(cp0_epc, 16);
 353        octeon_wdt_write_string("\r\n");
 354
 355        octeon_wdt_write_string("\tstatus\t0x");
 356        octeon_wdt_write_hex(cp0_status, 16);
 357        octeon_wdt_write_string("\tcause\t0x");
 358        octeon_wdt_write_hex(cp0_cause, 16);
 359        octeon_wdt_write_string("\r\n");
 360
 361        octeon_wdt_write_string("\tsum0\t0x");
 362        octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_SUM0(coreid * 2)), 16);
 363        octeon_wdt_write_string("\ten0\t0x");
 364        octeon_wdt_write_hex(cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)), 16);
 365        octeon_wdt_write_string("\r\n");
 366
 367        octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
 368}
 369
 370static void octeon_wdt_disable_interrupt(int cpu)
 371{
 372        unsigned int core;
 373        unsigned int irq;
 374        union cvmx_ciu_wdogx ciu_wdog;
 375
 376        core = cpu2core(cpu);
 377
 378        irq = OCTEON_IRQ_WDOG0 + core;
 379
 380        /* Poke the watchdog to clear out its state */
 381        cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
 382
 383        /* Disable the hardware. */
 384        ciu_wdog.u64 = 0;
 385        cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
 386
 387        free_irq(irq, octeon_wdt_poke_irq);
 388}
 389
 390static void octeon_wdt_setup_interrupt(int cpu)
 391{
 392        unsigned int core;
 393        unsigned int irq;
 394        union cvmx_ciu_wdogx ciu_wdog;
 395
 396        core = cpu2core(cpu);
 397
 398        /* Disable it before doing anything with the interrupts. */
 399        ciu_wdog.u64 = 0;
 400        cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
 401
 402        per_cpu_countdown[cpu] = countdown_reset;
 403
 404        irq = OCTEON_IRQ_WDOG0 + core;
 405
 406        if (request_irq(irq, octeon_wdt_poke_irq,
 407                        IRQF_NO_THREAD, "octeon_wdt", octeon_wdt_poke_irq))
 408                panic("octeon_wdt: Couldn't obtain irq %d", irq);
 409
 410        cpumask_set_cpu(cpu, &irq_enabled_cpus);
 411
 412        /* Poke the watchdog to clear out its state */
 413        cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
 414
 415        /* Finally enable the watchdog now that all handlers are installed */
 416        ciu_wdog.u64 = 0;
 417        ciu_wdog.s.len = timeout_cnt;
 418        ciu_wdog.s.mode = 3;    /* 3 = Interrupt + NMI + Soft-Reset */
 419        cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
 420}
 421
 422static int octeon_wdt_cpu_callback(struct notifier_block *nfb,
 423                                           unsigned long action, void *hcpu)
 424{
 425        unsigned int cpu = (unsigned long)hcpu;
 426
 427        switch (action) {
 428        case CPU_DOWN_PREPARE:
 429                octeon_wdt_disable_interrupt(cpu);
 430                break;
 431        case CPU_ONLINE:
 432        case CPU_DOWN_FAILED:
 433                octeon_wdt_setup_interrupt(cpu);
 434                break;
 435        default:
 436                break;
 437        }
 438        return NOTIFY_OK;
 439}
 440
 441static void octeon_wdt_ping(void)
 442{
 443        int cpu;
 444        int coreid;
 445
 446        for_each_online_cpu(cpu) {
 447                coreid = cpu2core(cpu);
 448                cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
 449                per_cpu_countdown[cpu] = countdown_reset;
 450                if ((countdown_reset || !do_coundown) &&
 451                    !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
 452                        /* We have to enable the irq */
 453                        int irq = OCTEON_IRQ_WDOG0 + coreid;
 454                        enable_irq(irq);
 455                        cpumask_set_cpu(cpu, &irq_enabled_cpus);
 456                }
 457        }
 458}
 459
 460static void octeon_wdt_calc_parameters(int t)
 461{
 462        unsigned int periods;
 463
 464        timeout_sec = max_timeout_sec;
 465
 466
 467        /*
 468         * Find the largest interrupt period, that can evenly divide
 469         * the requested heartbeat time.
 470         */
 471        while ((t % timeout_sec) != 0)
 472                timeout_sec--;
 473
 474        periods = t / timeout_sec;
 475
 476        /*
 477         * The last two periods are after the irq is disabled, and
 478         * then to the nmi, so we subtract them off.
 479         */
 480
 481        countdown_reset = periods > 2 ? periods - 2 : 0;
 482        heartbeat = t;
 483        timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
 484}
 485
 486static int octeon_wdt_set_heartbeat(int t)
 487{
 488        int cpu;
 489        int coreid;
 490        union cvmx_ciu_wdogx ciu_wdog;
 491
 492        if (t <= 0)
 493                return -1;
 494
 495        octeon_wdt_calc_parameters(t);
 496
 497        for_each_online_cpu(cpu) {
 498                coreid = cpu2core(cpu);
 499                cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
 500                ciu_wdog.u64 = 0;
 501                ciu_wdog.s.len = timeout_cnt;
 502                ciu_wdog.s.mode = 3;    /* 3 = Interrupt + NMI + Soft-Reset */
 503                cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
 504                cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
 505        }
 506        octeon_wdt_ping(); /* Get the irqs back on. */
 507        return 0;
 508}
 509
 510/**
 511 *      octeon_wdt_write:
 512 *      @file: file handle to the watchdog
 513 *      @buf: buffer to write (unused as data does not matter here
 514 *      @count: count of bytes
 515 *      @ppos: pointer to the position to write. No seeks allowed
 516 *
 517 *      A write to a watchdog device is defined as a keepalive signal. Any
 518 *      write of data will do, as we we don't define content meaning.
 519 */
 520
 521static ssize_t octeon_wdt_write(struct file *file, const char __user *buf,
 522                                size_t count, loff_t *ppos)
 523{
 524        if (count) {
 525                if (!nowayout) {
 526                        size_t i;
 527
 528                        /* In case it was set long ago */
 529                        expect_close = 0;
 530
 531                        for (i = 0; i != count; i++) {
 532                                char c;
 533                                if (get_user(c, buf + i))
 534                                        return -EFAULT;
 535                                if (c == 'V')
 536                                        expect_close = 1;
 537                        }
 538                }
 539                octeon_wdt_ping();
 540        }
 541        return count;
 542}
 543
 544/**
 545 *      octeon_wdt_ioctl:
 546 *      @file: file handle to the device
 547 *      @cmd: watchdog command
 548 *      @arg: argument pointer
 549 *
 550 *      The watchdog API defines a common set of functions for all
 551 *      watchdogs according to their available features. We only
 552 *      actually usefully support querying capabilities and setting
 553 *      the timeout.
 554 */
 555
 556static long octeon_wdt_ioctl(struct file *file, unsigned int cmd,
 557                             unsigned long arg)
 558{
 559        void __user *argp = (void __user *)arg;
 560        int __user *p = argp;
 561        int new_heartbeat;
 562
 563        static struct watchdog_info ident = {
 564                .options =              WDIOF_SETTIMEOUT|
 565                                        WDIOF_MAGICCLOSE|
 566                                        WDIOF_KEEPALIVEPING,
 567                .firmware_version =     1,
 568                .identity =             "OCTEON",
 569        };
 570
 571        switch (cmd) {
 572        case WDIOC_GETSUPPORT:
 573                return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 574        case WDIOC_GETSTATUS:
 575        case WDIOC_GETBOOTSTATUS:
 576                return put_user(0, p);
 577        case WDIOC_KEEPALIVE:
 578                octeon_wdt_ping();
 579                return 0;
 580        case WDIOC_SETTIMEOUT:
 581                if (get_user(new_heartbeat, p))
 582                        return -EFAULT;
 583                if (octeon_wdt_set_heartbeat(new_heartbeat))
 584                        return -EINVAL;
 585                /* Fall through. */
 586        case WDIOC_GETTIMEOUT:
 587                return put_user(heartbeat, p);
 588        default:
 589                return -ENOTTY;
 590        }
 591}
 592
 593/**
 594 *      octeon_wdt_open:
 595 *      @inode: inode of device
 596 *      @file: file handle to device
 597 *
 598 *      The watchdog device has been opened. The watchdog device is single
 599 *      open and on opening we do a ping to reset the counters.
 600 */
 601
 602static int octeon_wdt_open(struct inode *inode, struct file *file)
 603{
 604        if (test_and_set_bit(0, &octeon_wdt_is_open))
 605                return -EBUSY;
 606        /*
 607         *      Activate
 608         */
 609        octeon_wdt_ping();
 610        do_coundown = 1;
 611        return nonseekable_open(inode, file);
 612}
 613
 614/**
 615 *      octeon_wdt_release:
 616 *      @inode: inode to board
 617 *      @file: file handle to board
 618 *
 619 *      The watchdog has a configurable API. There is a religious dispute
 620 *      between people who want their watchdog to be able to shut down and
 621 *      those who want to be sure if the watchdog manager dies the machine
 622 *      reboots. In the former case we disable the counters, in the latter
 623 *      case you have to open it again very soon.
 624 */
 625
 626static int octeon_wdt_release(struct inode *inode, struct file *file)
 627{
 628        if (expect_close) {
 629                do_coundown = 0;
 630                octeon_wdt_ping();
 631        } else {
 632                pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
 633        }
 634        clear_bit(0, &octeon_wdt_is_open);
 635        expect_close = 0;
 636        return 0;
 637}
 638
 639static const struct file_operations octeon_wdt_fops = {
 640        .owner          = THIS_MODULE,
 641        .llseek         = no_llseek,
 642        .write          = octeon_wdt_write,
 643        .unlocked_ioctl = octeon_wdt_ioctl,
 644        .open           = octeon_wdt_open,
 645        .release        = octeon_wdt_release,
 646};
 647
 648static struct miscdevice octeon_wdt_miscdev = {
 649        .minor  = WATCHDOG_MINOR,
 650        .name   = "watchdog",
 651        .fops   = &octeon_wdt_fops,
 652};
 653
 654static struct notifier_block octeon_wdt_cpu_notifier = {
 655        .notifier_call = octeon_wdt_cpu_callback,
 656};
 657
 658
 659/**
 660 * Module/ driver initialization.
 661 *
 662 * Returns Zero on success
 663 */
 664static int __init octeon_wdt_init(void)
 665{
 666        int i;
 667        int ret;
 668        int cpu;
 669        u64 *ptr;
 670
 671        /*
 672         * Watchdog time expiration length = The 16 bits of LEN
 673         * represent the most significant bits of a 24 bit decrementer
 674         * that decrements every 256 cycles.
 675         *
 676         * Try for a timeout of 5 sec, if that fails a smaller number
 677         * of even seconds,
 678         */
 679        max_timeout_sec = 6;
 680        do {
 681                max_timeout_sec--;
 682                timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8;
 683        } while (timeout_cnt > 65535);
 684
 685        BUG_ON(timeout_cnt == 0);
 686
 687        octeon_wdt_calc_parameters(heartbeat);
 688
 689        pr_info("Initial granularity %d Sec\n", timeout_sec);
 690
 691        ret = misc_register(&octeon_wdt_miscdev);
 692        if (ret) {
 693                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
 694                       WATCHDOG_MINOR, ret);
 695                goto out;
 696        }
 697
 698        /* Build the NMI handler ... */
 699        octeon_wdt_build_stage1();
 700
 701        /* ... and install it. */
 702        ptr = (u64 *) nmi_stage1_insns;
 703        for (i = 0; i < 16; i++) {
 704                cvmx_write_csr(CVMX_MIO_BOOT_LOC_ADR, i * 8);
 705                cvmx_write_csr(CVMX_MIO_BOOT_LOC_DAT, ptr[i]);
 706        }
 707        cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0x81fc0000);
 708
 709        cpumask_clear(&irq_enabled_cpus);
 710
 711        for_each_online_cpu(cpu)
 712                octeon_wdt_setup_interrupt(cpu);
 713
 714        register_hotcpu_notifier(&octeon_wdt_cpu_notifier);
 715out:
 716        return ret;
 717}
 718
 719/**
 720 * Module / driver shutdown
 721 */
 722static void __exit octeon_wdt_cleanup(void)
 723{
 724        int cpu;
 725
 726        misc_deregister(&octeon_wdt_miscdev);
 727
 728        unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier);
 729
 730        for_each_online_cpu(cpu) {
 731                int core = cpu2core(cpu);
 732                /* Disable the watchdog */
 733                cvmx_write_csr(CVMX_CIU_WDOGX(core), 0);
 734                /* Free the interrupt handler */
 735                free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq);
 736        }
 737        /*
 738         * Disable the boot-bus memory, the code it points to is soon
 739         * to go missing.
 740         */
 741        cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0);
 742}
 743
 744MODULE_LICENSE("GPL");
 745MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
 746MODULE_DESCRIPTION("Cavium Networks Octeon Watchdog driver.");
 747module_init(octeon_wdt_init);
 748module_exit(octeon_wdt_cleanup);
 749
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.