[PATCH v1 13/13] sparc32: drop use of sparc_config

From: Sam Ravnborg
Date: Fri Dec 18 2020 - 13:46:02 EST


sparc_config were used to handle the differences between the machines.
With only LEON supported sparc_config is no longer required.

This has the added benefit that we get rid of a rw variable
with several function pointers thus reducing our attack surface.

Signed-off-by: Sam Ravnborg <sam@xxxxxxxxxxxx>
Cc: Sam Ravnborg <sam@xxxxxxxxxxxx>
Cc: Arnd Bergmann <arnd@xxxxxxxxxx>
Cc: Andreas Larsson <andreas@xxxxxxxxxxx>
---
arch/sparc/include/asm/timer_32.h | 1 +
arch/sparc/kernel/irq.h | 32 ++-------
arch/sparc/kernel/irq_32.c | 3 -
arch/sparc/kernel/leon_kernel.c | 27 ++------
arch/sparc/kernel/of_device_32.c | 4 +-
arch/sparc/kernel/time_32.c | 110 +++++++++++++-----------------
6 files changed, 61 insertions(+), 116 deletions(-)

diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h
index eecd2696922d..1cd89a99966f 100644
--- a/arch/sparc/include/asm/timer_32.h
+++ b/arch/sparc/include/asm/timer_32.h
@@ -17,6 +17,7 @@
#include <asm/cpu_type.h> /* For SUN4M_NCPUS */

#define SBUS_CLOCK_RATE 2000000 /* 2MHz */
+#define LEON_CLOCK_RATE 1000000
#define TIMER_VALUE_SHIFT 9
#define TIMER_VALUE_MASK 0x3fffff
#define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index 0d9b740725b4..ba0db1e4df6f 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -49,33 +49,6 @@ extern struct sun4m_irq_global __iomem *sun4m_irq_global;
#define FEAT_L10_CLOCKEVENT (1 << 1) /* L10 timer is used as a clockevent */
#define FEAT_L14_ONESHOT (1 << 2) /* L14 timer clockevent can oneshot */

-/*
- * Platform specific configuration
- * The individual platforms assign their platform
- * specifics in their init functions.
- */
-struct sparc_config {
- void (*init_timers)(void);
- unsigned int (*build_device_irq)(struct platform_device *op,
- unsigned int real_irq);
-
- /* generic clockevent features - see FEAT_* above */
- int features;
-
- /* clock rate used for clock event timer */
- int clock_rate;
-
- /* one period for clock source timer */
- unsigned int cs_period;
-
- /* function to obtain offsett for cs period */
- unsigned int (*get_cycles_offset)(void);
-
- void (*clear_clock_irq)(void);
- void (*load_profile_irq)(int cpu, unsigned int limit);
-};
-extern struct sparc_config sparc_config;
-
unsigned int irq_alloc(unsigned int real_irq, unsigned int pil);
void irq_link(unsigned int irq);
void irq_unlink(unsigned int irq);
@@ -89,6 +62,11 @@ void sun4m_nmi(struct pt_regs *regs);
/* sun4d_irq.c */
void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs);

+/* leon_kernel.c */
+void leon_clear_clock_irq(void);
+void leon_load_profile_irq(int cpu, unsigned int limit);
+u32 leon_cycles_offset(void);
+
#ifdef CONFIG_SMP

/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index a6af08fce796..f76f57073323 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -24,9 +24,6 @@
#include "kernel.h"
#include "irq.h"

-/* platform specific irq setup */
-struct sparc_config sparc_config;
-
unsigned long arch_local_irq_save(void)
{
unsigned long retval;
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 49b37a0dcc2b..491dff89f52c 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -239,12 +239,6 @@ unsigned int leon_build_device_irq(unsigned int real_irq,
return irq;
}

-static unsigned int _leon_build_device_irq(struct platform_device *op,
- unsigned int real_irq)
-{
- return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0);
-}
-
void leon_update_virq_handling(unsigned int virq,
irq_flow_handler_t flow_handler,
const char *name, int do_ack)
@@ -260,7 +254,7 @@ void leon_update_virq_handling(unsigned int virq,
irq_set_chip_data(virq, (void *)mask);
}

-static u32 leon_cycles_offset(void)
+u32 leon_cycles_offset(void)
{
u32 rld, val, ctrl, off;

@@ -314,14 +308,6 @@ void __init leon_init_timers(void)
u32 config;
u32 ctrl;

- sparc_config.get_cycles_offset = leon_cycles_offset;
- sparc_config.cs_period = 1000000 / HZ;
- sparc_config.features |= FEAT_L10_CLOCKSOURCE;
-
-#ifndef CONFIG_SMP
- sparc_config.features |= FEAT_L10_CLOCKEVENT;
-#endif
-
leondebug_irq_disable = 0;
leon_debug_irqout = 0;
master_l10_counter = (u32 __iomem *)&dummy_master_l10_counter;
@@ -436,7 +422,7 @@ void __init leon_init_timers(void)
err = request_irq(irq, leon_percpu_timer_ce_interrupt,
IRQF_PERCPU | IRQF_TIMER, "timer", NULL);
#else
- irq = _leon_build_device_irq(NULL, leon3_gptimer_irq);
+ irq = leon_build_device_irq(leon3_gptimer_irq, handle_simple_irq, "edge", 0);
err = request_irq(irq, timer_interrupt, IRQF_TIMER, "timer", NULL);
#endif
if (err) {
@@ -455,7 +441,7 @@ void __init leon_init_timers(void)
return;
}

-static void leon_clear_clock_irq(void)
+void leon_clear_clock_irq(void)
{
u32 ctrl;

@@ -464,7 +450,7 @@ static void leon_clear_clock_irq(void)
ctrl & leon3_gptimer_ackmask);
}

-static void leon_load_profile_irq(int cpu, unsigned int limit)
+void leon_load_profile_irq(int cpu, unsigned int limit)
{
}

@@ -487,9 +473,4 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)

void __init leon_init_IRQ(void)
{
- sparc_config.init_timers = leon_init_timers;
- sparc_config.build_device_irq = _leon_build_device_irq;
- sparc_config.clock_rate = 1000000;
- sparc_config.clear_clock_irq = leon_clear_clock_irq;
- sparc_config.load_profile_irq = leon_load_profile_irq;
}
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4ebf51e6e78e..c846acdb4455 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -358,7 +358,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
for (i = 0; i < op->archdata.num_irqs; i++)
op->archdata.irqs[i] =
- sparc_config.build_device_irq(op, intr[i].pri);
+ leon_build_device_irq(intr[i].pri, handle_simple_irq, "edge", 0);
} else {
const unsigned int *irq =
of_get_property(dp, "interrupts", &len);
@@ -367,7 +367,7 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
op->archdata.num_irqs = len / sizeof(unsigned int);
for (i = 0; i < op->archdata.num_irqs; i++)
op->archdata.irqs[i] =
- sparc_config.build_device_irq(op, irq[i]);
+ leon_build_device_irq(irq[i], handle_simple_irq, "edge", 0);
} else {
op->archdata.num_irqs = 0;
}
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 0093cf4ecb06..8619a3d9953f 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -45,6 +45,7 @@
#include <asm/idprom.h>
#include <asm/page.h>
#include <asm/irq_regs.h>
+#include <asm/leon.h>
#include <asm/setup.h>

#include "kernel.h"
@@ -89,10 +90,10 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
if (timer_cs_enabled) {
write_seqlock(&timer_cs_lock);
timer_cs_internal_counter++;
- sparc_config.clear_clock_irq();
+ leon_clear_clock_irq();
write_sequnlock(&timer_cs_lock);
} else {
- sparc_config.clear_clock_irq();
+ leon_clear_clock_irq();
}

if (timer_ce_enabled)
@@ -101,39 +102,6 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id)
return IRQ_HANDLED;
}

-static int timer_ce_shutdown(struct clock_event_device *evt)
-{
- timer_ce_enabled = 0;
- smp_mb();
- return 0;
-}
-
-static int timer_ce_set_periodic(struct clock_event_device *evt)
-{
- timer_ce_enabled = 1;
- smp_mb();
- return 0;
-}
-
-static __init void setup_timer_ce(void)
-{
- struct clock_event_device *ce = &timer_ce;
-
- BUG_ON(smp_processor_id() != boot_cpu_id);
-
- ce->name = "timer_ce";
- ce->rating = 100;
- ce->features = CLOCK_EVT_FEAT_PERIODIC;
- ce->set_state_shutdown = timer_ce_shutdown;
- ce->set_state_periodic = timer_ce_set_periodic;
- ce->tick_resume = timer_ce_set_periodic;
- ce->cpumask = cpu_possible_mask;
- ce->shift = 32;
- ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
- ce->shift);
- clockevents_register_device(ce);
-}
-
static unsigned int sbus_cycles_offset(void)
{
u32 val, offset;
@@ -143,7 +111,7 @@ static unsigned int sbus_cycles_offset(void)

/* Limit hit? */
if (val & TIMER_LIMIT_BIT)
- offset += sparc_config.cs_period;
+ offset += 1000000 / HZ;

return offset;
}
@@ -157,11 +125,11 @@ static u64 timer_cs_read(struct clocksource *cs)
seq = read_seqbegin(&timer_cs_lock);

cycles = timer_cs_internal_counter;
- offset = sparc_config.get_cycles_offset();
+ offset = sbus_cycles_offset();
} while (read_seqretry(&timer_cs_lock, seq));

/* Count absolute cycles */
- cycles *= sparc_config.cs_period;
+ cycles *= LEON_CLOCK_RATE / HZ;
cycles += offset;

return cycles;
@@ -178,15 +146,47 @@ static struct clocksource timer_cs = {
static __init int setup_timer_cs(void)
{
timer_cs_enabled = 1;
- return clocksource_register_hz(&timer_cs, sparc_config.clock_rate);
+ return clocksource_register_hz(&timer_cs, LEON_CLOCK_RATE);
}

#ifdef CONFIG_SMP
+static int timer_ce_shutdown(struct clock_event_device *evt)
+{
+ timer_ce_enabled = 0;
+ smp_mb();
+ return 0;
+}
+
+static int timer_ce_set_periodic(struct clock_event_device *evt)
+{
+ timer_ce_enabled = 1;
+ smp_mb();
+ return 0;
+}
+
+static __init void setup_timer_ce(void)
+{
+ struct clock_event_device *ce = &timer_ce;
+
+ BUG_ON(smp_processor_id() != boot_cpu_id);
+
+ ce->name = "timer_ce";
+ ce->rating = 100;
+ ce->features = CLOCK_EVT_FEAT_PERIODIC;
+ ce->set_state_shutdown = timer_ce_shutdown;
+ ce->set_state_periodic = timer_ce_set_periodic;
+ ce->tick_resume = timer_ce_set_periodic;
+ ce->cpumask = cpu_possible_mask;
+ ce->shift = 32;
+ ce->mult = div_sc(LEON_CLOCK_RATE, NSEC_PER_SEC, ce->shift);
+ clockevents_register_device(ce);
+}
+
static int percpu_ce_shutdown(struct clock_event_device *evt)
{
int cpu = cpumask_first(evt->cpumask);

- sparc_config.load_profile_irq(cpu, 0);
+ leon_load_profile_irq(cpu, 0);
return 0;
}

@@ -194,7 +194,7 @@ static int percpu_ce_set_periodic(struct clock_event_device *evt)
{
int cpu = cpumask_first(evt->cpumask);

- sparc_config.load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ);
+ leon_load_profile_irq(cpu, SBUS_CLOCK_RATE / HZ);
return 0;
}

@@ -204,7 +204,7 @@ static int percpu_ce_set_next_event(unsigned long delta,
int cpu = cpumask_first(evt->cpumask);
unsigned int next = (unsigned int)delta;

- sparc_config.load_profile_irq(cpu, next);
+ leon_load_profile_irq(cpu, next);
return 0;
}

@@ -213,9 +213,6 @@ void register_percpu_ce(int cpu)
struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
unsigned int features = CLOCK_EVT_FEAT_PERIODIC;

- if (sparc_config.features & FEAT_L14_ONESHOT)
- features |= CLOCK_EVT_FEAT_ONESHOT;
-
ce->name = "percpu_ce";
ce->rating = 200;
ce->features = features;
@@ -225,10 +222,9 @@ void register_percpu_ce(int cpu)
ce->set_next_event = percpu_ce_set_next_event;
ce->cpumask = cpumask_of(cpu);
ce->shift = 32;
- ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC,
- ce->shift);
- ce->max_delta_ns = clockevent_delta2ns(sparc_config.clock_rate, ce);
- ce->max_delta_ticks = (unsigned long)sparc_config.clock_rate;
+ ce->mult = div_sc(LEON_CLOCK_RATE, NSEC_PER_SEC, ce->shift);
+ ce->max_delta_ns = clockevent_delta2ns(LEON_CLOCK_RATE, ce);
+ ce->max_delta_ticks = (unsigned long)LEON_CLOCK_RATE;
ce->min_delta_ns = clockevent_delta2ns(100, ce);
ce->min_delta_ticks = 100;

@@ -327,26 +323,18 @@ fs_initcall(clock_init);

static void __init sparc32_late_time_init(void)
{
- if (sparc_config.features & FEAT_L10_CLOCKEVENT)
- setup_timer_ce();
- if (sparc_config.features & FEAT_L10_CLOCKSOURCE)
- setup_timer_cs();
+ setup_timer_cs();
+
#ifdef CONFIG_SMP
+ setup_timer_ce();
register_percpu_ce(smp_processor_id());
#endif
}

-static void __init sbus_time_init(void)
-{
- sparc_config.get_cycles_offset = sbus_cycles_offset;
- sparc_config.init_timers();
-}
-
void __init time_init(void)
{
- sparc_config.features = 0;
late_time_init = sparc32_late_time_init;

- sbus_time_init();
+ leon_init_timers();
}

--
2.27.0