All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: "Steven J. Hill" <steven.hill@cavium.com>
Cc: linux-mips@linux-mips.org, linux-watchdog@vger.kernel.org,
	ralf@linux-mips.org
Subject: Re: [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs.
Date: Tue, 29 Aug 2017 21:34:16 -0700	[thread overview]
Message-ID: <20170830043416.GD14791@roeck-us.net> (raw)
In-Reply-To: <1504021238-3184-9-git-send-email-steven.hill@cavium.com>

On Tue, Aug 29, 2017 at 10:40:38AM -0500, Steven J. Hill wrote:
> From: Carlos Munoz <carlos.munoz@caviumnetworks.com>
> 
> Signed-off-by: Carlos Munoz <carlos.munoz@caviumnetworks.com>
> Signed-off-by: Steven J. Hill <steven.hill@cavium.com>
> Acked-by: David Daney <david.daney@cavium.com>

Acked-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/watchdog/octeon-wdt-main.c | 133 ++++++++++++++++++++++++++++---------
>  1 file changed, 103 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
> index 410800f..0ec419a 100644
> --- a/drivers/watchdog/octeon-wdt-main.c
> +++ b/drivers/watchdog/octeon-wdt-main.c
> @@ -70,6 +70,10 @@
>  #include <asm/octeon/octeon.h>
>  #include <asm/octeon/cvmx-boot-vector.h>
>  #include <asm/octeon/cvmx-ciu2-defs.h>
> +#include <asm/octeon/cvmx-rst-defs.h>
> +
> +/* Watchdog interrupt major block number (8 MSBs of intsn) */
> +#define WD_BLOCK_NUMBER		0x01
>  
>  static int divisor;
>  
> @@ -91,6 +95,8 @@ static cpumask_t irq_enabled_cpus;
>  
>  #define WD_TIMO 60			/* Default heartbeat = 60 seconds */
>  
> +#define CVMX_GSERX_SCRATCH(offset) (CVMX_ADD_IO_SEG(0x0001180090000020ull) + ((offset) & 15) * 0x1000000ull)
> +
>  static int heartbeat = WD_TIMO;
>  module_param(heartbeat, int, 0444);
>  MODULE_PARM_DESC(heartbeat,
> @@ -115,21 +121,12 @@ void octeon_wdt_nmi_stage2(void);
>  static int cpu2core(int cpu)
>  {
>  #ifdef CONFIG_SMP
> -	return cpu_logical_map(cpu);
> +	return cpu_logical_map(cpu) & 0x3f;
>  #else
>  	return cvmx_get_core_num();
>  #endif
>  }
>  
> -static int core2cpu(int coreid)
> -{
> -#ifdef CONFIG_SMP
> -	return cpu_number_map(coreid);
> -#else
> -	return 0;
> -#endif
> -}
> -
>  /**
>   * Poke the watchdog when an interrupt is received
>   *
> @@ -140,13 +137,14 @@ static int core2cpu(int coreid)
>   */
>  static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
>  {
> -	unsigned int core = cvmx_get_core_num();
> -	int cpu = core2cpu(core);
> +	int cpu = raw_smp_processor_id();
> +	unsigned int core = cpu2core(cpu);
> +	int node = cpu_to_node(cpu);
>  
>  	if (do_countdown) {
>  		if (per_cpu_countdown[cpu] > 0) {
>  			/* We're alive, poke the watchdog */
> -			cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> +			cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>  			per_cpu_countdown[cpu]--;
>  		} else {
>  			/* Bad news, you are about to reboot. */
> @@ -155,7 +153,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id)
>  		}
>  	} else {
>  		/* Not open, just ping away... */
> -		cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> +		cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>  	}
>  	return IRQ_HANDLED;
>  }
> @@ -280,26 +278,74 @@ void octeon_wdt_nmi_stage3(u64 reg[32])
>  	}
>  
>  	octeon_wdt_write_string("*** Chip soft reset soon ***\r\n");
> +
> +	/*
> +	 * G-30204: We must trigger a soft reset before watchdog
> +	 * does an incomplete job of doing it.
> +	 */
> +	if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX)) {
> +		u64 scr;
> +		unsigned int node = cvmx_get_node_num();
> +		unsigned int lcore = cvmx_get_local_core_num();
> +		union cvmx_ciu_wdogx ciu_wdog;
> +
> +		/*
> +		 * Wait for other cores to print out information, but
> +		 * not too long.  Do the soft reset before watchdog
> +		 * can trigger it.
> +		 */
> +		do {
> +			ciu_wdog.u64 = cvmx_read_csr_node(node, CVMX_CIU_WDOGX(lcore));
> +		} while (ciu_wdog.s.cnt > 0x10000);
> +
> +		scr = cvmx_read_csr_node(0, CVMX_GSERX_SCRATCH(0));
> +		scr |= 1 << 11; /* Indicate watchdog in bit 11 */
> +		cvmx_write_csr_node(0, CVMX_GSERX_SCRATCH(0), scr);
> +		cvmx_write_csr_node(0, CVMX_RST_SOFT_RST, 1);
> +	}
> +}
> +
> +static int octeon_wdt_cpu_to_irq(int cpu)
> +{
> +	unsigned int coreid;
> +	int node;
> +	int irq;
> +
> +	coreid = cpu2core(cpu);
> +	node = cpu_to_node(cpu);
> +
> +	if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> +		struct irq_domain *domain;
> +		int hwirq;
> +
> +		domain = octeon_irq_get_block_domain(node,
> +						     WD_BLOCK_NUMBER);
> +		hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | coreid;
> +		irq = irq_find_mapping(domain, hwirq);
> +	} else {
> +		irq = OCTEON_IRQ_WDOG0 + coreid;
> +	}
> +	return irq;
>  }
>  
>  static int octeon_wdt_cpu_pre_down(unsigned int cpu)
>  {
>  	unsigned int core;
> -	unsigned int irq;
> +	int node;
>  	union cvmx_ciu_wdogx ciu_wdog;
>  
>  	core = cpu2core(cpu);
>  
> -	irq = OCTEON_IRQ_WDOG0 + core;
> +	node = cpu_to_node(cpu);
>  
>  	/* Poke the watchdog to clear out its state */
> -	cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> +	cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>  
>  	/* Disable the hardware. */
>  	ciu_wdog.u64 = 0;
> -	cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
> +	cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>  
> -	free_irq(irq, octeon_wdt_poke_irq);
> +	free_irq(octeon_wdt_cpu_to_irq(cpu), octeon_wdt_poke_irq);
>  	return 0;
>  }
>  
> @@ -308,33 +354,56 @@ static int octeon_wdt_cpu_online(unsigned int cpu)
>  	unsigned int core;
>  	unsigned int irq;
>  	union cvmx_ciu_wdogx ciu_wdog;
> +	int node;
> +	struct irq_domain *domain;
> +	int hwirq;
>  
>  	core = cpu2core(cpu);
> +	node = cpu_to_node(cpu);
>  
>  	octeon_wdt_bootvector[core].target_ptr = (u64)octeon_wdt_nmi_stage2;
>  
>  	/* Disable it before doing anything with the interrupts. */
>  	ciu_wdog.u64 = 0;
> -	cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
> +	cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>  
>  	per_cpu_countdown[cpu] = countdown_reset;
>  
> -	irq = OCTEON_IRQ_WDOG0 + core;
> +	if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> +		/* Must get the domain for the watchdog block */
> +		domain = octeon_irq_get_block_domain(node, WD_BLOCK_NUMBER);
> +
> +		/* Get a irq for the wd intsn (hardware interrupt) */
> +		hwirq = WD_BLOCK_NUMBER << 12 | 0x200 | core;
> +		irq = irq_create_mapping(domain, hwirq);
> +		irqd_set_trigger_type(irq_get_irq_data(irq),
> +				      IRQ_TYPE_EDGE_RISING);
> +	} else
> +		irq = OCTEON_IRQ_WDOG0 + core;
>  
>  	if (request_irq(irq, octeon_wdt_poke_irq,
>  			IRQF_NO_THREAD, "octeon_wdt", octeon_wdt_poke_irq))
>  		panic("octeon_wdt: Couldn't obtain irq %d", irq);
>  
> +	/* Must set the irq affinity here */
> +	if (octeon_has_feature(OCTEON_FEATURE_CIU3)) {
> +		cpumask_t mask;
> +
> +		cpumask_clear(&mask);
> +		cpumask_set_cpu(cpu, &mask);
> +		irq_set_affinity(irq, &mask);
> +	}
> +
>  	cpumask_set_cpu(cpu, &irq_enabled_cpus);
>  
>  	/* Poke the watchdog to clear out its state */
> -	cvmx_write_csr(CVMX_CIU_PP_POKEX(core), 1);
> +	cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(core), 1);
>  
>  	/* Finally enable the watchdog now that all handlers are installed */
>  	ciu_wdog.u64 = 0;
>  	ciu_wdog.s.len = timeout_cnt;
>  	ciu_wdog.s.mode = 3;	/* 3 = Interrupt + NMI + Soft-Reset */
> -	cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64);
> +	cvmx_write_csr_node(node, CVMX_CIU_WDOGX(core), ciu_wdog.u64);
>  
>  	return 0;
>  }
> @@ -343,20 +412,20 @@ static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
>  {
>  	int cpu;
>  	int coreid;
> +	int node;
>  
>  	if (disable)
>  		return 0;
>  
>  	for_each_online_cpu(cpu) {
>  		coreid = cpu2core(cpu);
> -		cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> +		node = cpu_to_node(cpu);
> +		cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
>  		per_cpu_countdown[cpu] = countdown_reset;
>  		if ((countdown_reset || !do_countdown) &&
>  		    !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
>  			/* We have to enable the irq */
> -			int irq = OCTEON_IRQ_WDOG0 + coreid;
> -
> -			enable_irq(irq);
> +			enable_irq(octeon_wdt_cpu_to_irq(cpu));
>  			cpumask_set_cpu(cpu, &irq_enabled_cpus);
>  		}
>  	}
> @@ -395,6 +464,7 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
>  	int cpu;
>  	int coreid;
>  	union cvmx_ciu_wdogx ciu_wdog;
> +	int node;
>  
>  	if (t <= 0)
>  		return -1;
> @@ -406,12 +476,13 @@ static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
>  
>  	for_each_online_cpu(cpu) {
>  		coreid = cpu2core(cpu);
> -		cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> +		node = cpu_to_node(cpu);
> +		cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
>  		ciu_wdog.u64 = 0;
>  		ciu_wdog.s.len = timeout_cnt;
>  		ciu_wdog.s.mode = 3;	/* 3 = Interrupt + NMI + Soft-Reset */
> -		cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
> -		cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
> +		cvmx_write_csr_node(node, CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
> +		cvmx_write_csr_node(node, CVMX_CIU_PP_POKEX(coreid), 1);
>  	}
>  	octeon_wdt_ping(wdog); /* Get the irqs back on. */
>  	return 0;
> @@ -467,6 +538,8 @@ static int __init octeon_wdt_init(void)
>  
>  	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
>  		divisor = 0x200;
> +	else if (OCTEON_IS_MODEL(OCTEON_CN78XX))
> +		divisor = 0x400;
>  	else
>  		divisor = 0x100;
>  
> -- 
> 2.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

      reply	other threads:[~2017-08-30  4:34 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-29 15:40 [PATCH 0/8] Update Octeon watchdog driver Steven J. Hill
2017-08-29 15:40 ` [PATCH 1/8] MIPS: Octeon: Add support for accessing the boot vector Steven J. Hill
2017-08-29 15:40 ` [PATCH 2/8] watchdog: octeon-wdt: Remove old boot vector code Steven J. Hill
2017-08-30  4:33   ` Guenter Roeck
2017-08-30 14:16     ` Steven J. Hill
2017-08-29 15:40 ` [PATCH 3/8] MIPS: Octeon: Watchdog registers for 70xx, 73xx, 78xx, F75xx Steven J. Hill
2017-08-29 15:40 ` [PATCH 4/8] MIPS: Octeon: Make CSR functions node aware Steven J. Hill
2017-08-29 15:40 ` [PATCH 5/8] MIPS: Octeon: Allow access to CIU3 IRQ domains Steven J. Hill
2017-08-29 15:40 ` [PATCH 6/8] watchdog: octeon-wdt: File cleaning Steven J. Hill
2017-08-30  4:33   ` Guenter Roeck
2017-08-29 15:40 ` [PATCH 7/8] watchdog: octeon-wdt: Add support for cn68XX SOCs Steven J. Hill
2017-08-30  4:34   ` Guenter Roeck
2017-08-29 15:40 ` [PATCH 8/8] watchdog: octeon-wdt: Add support for 78XX SOCs Steven J. Hill
2017-08-30  4:34   ` Guenter Roeck [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170830043416.GD14791@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=linux-mips@linux-mips.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=ralf@linux-mips.org \
    --cc=steven.hill@cavium.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.