linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 00/29] x86/hpet: Cleanup the channel management
@ 2019-06-23 13:23 Thomas Gleixner
  2019-06-23 13:23 ` [patch 01/29] x86/hpet: Simplify CPU online code Thomas Gleixner
                   ` (29 more replies)
  0 siblings, 30 replies; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

When reviewing the HPET NMI watchdog series, I stared into the HPET code
and the proposed changes. The latter try to add yet another layer of duct
tape and ifdeffery to the existing maze. No, thanks.

The following series cleans up the channel management and consolidates all
state storage into a single place instead of 3 different ad hoc allocated
places which carry redundant information and make the code hard to follow.

The reservation of a HPET channel for a NMI watchdog becomes a few lines of
code after that series and just fits naturaly into that scheme without glue
and more extra storage and ifdeffery.

For your conveniance the series is also available from git:

    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.x86/hpet

Thanks,

	tglx

8<---------------------
 include/asm/hpet.h |    7 
 kernel/apic/msi.c  |    4 
 kernel/hpet.c      |  937 +++++++++++++++++++++++------------------------------
 3 files changed, 428 insertions(+), 520 deletions(-)




^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 01/29] x86/hpet: Simplify CPU online code
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:34   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 02/29] x86/hpet: Replace printk(KERN...) with pr_...() Thomas Gleixner
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

The indirection via work scheduled on the upcoming CPU was necessary with the
old hotplug code because the online callback was invoked on the control CPU
not on the upcoming CPU. The rework of the CPU hotplug core guarantees that
the online callbacks are invoked on the upcoming CPU.

Remove the now pointless work redirection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   31 ++-----------------------------
 1 file changed, 2 insertions(+), 29 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -547,12 +547,10 @@ static int hpet_setup_irq(struct hpet_de
 	return 0;
 }
 
-/* This should be called in specific @cpu */
 static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 {
 	struct clock_event_device *evt = &hdev->evt;
 
-	WARN_ON(cpu != smp_processor_id());
 	if (!(hdev->flags & HPET_DEV_VALID))
 		return;
 
@@ -684,36 +682,12 @@ static struct hpet_dev *hpet_get_unused_
 	return NULL;
 }
 
-struct hpet_work_struct {
-	struct delayed_work work;
-	struct completion complete;
-};
-
-static void hpet_work(struct work_struct *w)
+static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hdev;
-	int cpu = smp_processor_id();
-	struct hpet_work_struct *hpet_work;
+	struct hpet_dev *hdev = hpet_get_unused_timer();
 
-	hpet_work = container_of(w, struct hpet_work_struct, work.work);
-
-	hdev = hpet_get_unused_timer();
 	if (hdev)
 		init_one_hpet_msi_clockevent(hdev, cpu);
-
-	complete(&hpet_work->complete);
-}
-
-static int hpet_cpuhp_online(unsigned int cpu)
-{
-	struct hpet_work_struct work;
-
-	INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work);
-	init_completion(&work.complete);
-	/* FIXME: add schedule_work_on() */
-	schedule_delayed_work_on(cpu, &work.work, 0);
-	wait_for_completion(&work.complete);
-	destroy_delayed_work_on_stack(&work.work);
 	return 0;
 }
 
@@ -1045,7 +1019,6 @@ static __init int hpet_late_init(void)
 	if (boot_cpu_has(X86_FEATURE_ARAT))
 		return 0;
 
-	/* This notifier should be called after workqueue is ready */
 	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "x86/hpet:online",
 				hpet_cpuhp_online, NULL);
 	if (ret)



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 02/29] x86/hpet: Replace printk(KERN...) with pr_...()
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
  2019-06-23 13:23 ` [patch 01/29] x86/hpet: Simplify CPU online code Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:34   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 03/29] x86/hpet: Restructure init code Thomas Gleixner
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

And sanitize the format strings while at it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   45 +++++++++++++++++++--------------------------
 1 file changed, 19 insertions(+), 26 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -20,6 +20,9 @@
 #include <asm/hpet.h>
 #include <asm/time.h>
 
+#undef  pr_fmt
+#define pr_fmt(fmt) "hpet: " fmt
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -137,31 +140,28 @@ EXPORT_SYMBOL_GPL(is_hpet_enabled);
 static void _hpet_print_config(const char *function, int line)
 {
 	u32 i, timers, l, h;
-	printk(KERN_INFO "hpet: %s(%d):\n", function, line);
+	pr_info("%s(%d):\n", function, line);
 	l = hpet_readl(HPET_ID);
 	h = hpet_readl(HPET_PERIOD);
 	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
-	printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
+	pr_info("ID: 0x%x, PERIOD: 0x%x\n", l, h);
 	l = hpet_readl(HPET_CFG);
 	h = hpet_readl(HPET_STATUS);
-	printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
+	pr_info("CFG: 0x%x, STATUS: 0x%x\n", l, h);
 	l = hpet_readl(HPET_COUNTER);
 	h = hpet_readl(HPET_COUNTER+4);
-	printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
+	pr_info("COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
 
 	for (i = 0; i < timers; i++) {
 		l = hpet_readl(HPET_Tn_CFG(i));
 		h = hpet_readl(HPET_Tn_CFG(i)+4);
-		printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h);
 		l = hpet_readl(HPET_Tn_CMP(i));
 		h = hpet_readl(HPET_Tn_CMP(i)+4);
-		printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h);
 		l = hpet_readl(HPET_Tn_ROUTE(i));
 		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
-		printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h);
 	}
 }
 
@@ -287,7 +287,7 @@ static void hpet_legacy_clockevent_regis
 	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
 					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
 	global_clock_event = &hpet_clockevent;
-	printk(KERN_DEBUG "hpet clockevent registered\n");
+	pr_debug("Clockevent registered\n");
 }
 
 static int hpet_set_periodic(struct clock_event_device *evt, int timer)
@@ -520,8 +520,7 @@ static irqreturn_t hpet_interrupt_handle
 	struct clock_event_device *hevt = &dev->evt;
 
 	if (!hevt->event_handler) {
-		printk(KERN_INFO "Spurious HPET timer interrupt on HPET timer %d\n",
-				dev->num);
+		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
 		return IRQ_HANDLED;
 	}
 
@@ -541,8 +540,7 @@ static int hpet_setup_irq(struct hpet_de
 	irq_set_affinity(dev->irq, cpumask_of(dev->cpu));
 	enable_irq(dev->irq);
 
-	printk(KERN_DEBUG "hpet: %s irq %d for MSI\n",
-			 dev->name, dev->irq);
+	pr_debug("%s irq %d for MSI\n", dev->name, dev->irq);
 
 	return 0;
 }
@@ -638,7 +636,7 @@ static void hpet_msi_capability_lookup(u
 			break;
 	}
 
-	printk(KERN_INFO "HPET: %d timers in total, %d timers will be used for per-cpu timer\n",
+	pr_info("%d channels of %d reserved for per-cpu timers\n",
 		num_timers, num_timers_used);
 }
 
@@ -856,8 +854,7 @@ static int hpet_clocksource_register(voi
 	} while ((now - start) < 200000UL);
 
 	if (t1 == hpet_readl(HPET_COUNTER)) {
-		printk(KERN_WARNING
-		       "HPET counter not counting. HPET disabled\n");
+		pr_warn("Counter not counting. HPET disabled\n");
 		return -ENODEV;
 	}
 
@@ -903,9 +900,7 @@ int __init hpet_enable(void)
 	 */
 	for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) {
 		if (i == 1000) {
-			printk(KERN_WARNING
-			       "HPET config register value = 0xFFFFFFFF. "
-			       "Disabling HPET\n");
+			pr_warn("Config register invalid. Disabling HPET\n");
 			goto out_nohpet;
 		}
 	}
@@ -949,7 +944,7 @@ int __init hpet_enable(void)
 	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
 	hpet_writel(cfg, HPET_CFG);
 	if (cfg)
-		pr_warn("Unrecognized bits %#x set in global cfg\n", cfg);
+		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
 	for (i = 0; i <= last; ++i) {
 		cfg = hpet_readl(HPET_Tn_CFG(i));
@@ -961,8 +956,7 @@ int __init hpet_enable(void)
 			 | HPET_TN_64BIT_CAP | HPET_TN_32BIT | HPET_TN_ROUTE
 			 | HPET_TN_FSB | HPET_TN_FSB_CAP);
 		if (cfg)
-			pr_warn("Unrecognized bits %#x set in cfg#%u\n",
-				cfg, i);
+			pr_warn("Channel #%u config: Unknown bits %#x\n", i, cfg);
 	}
 	hpet_print_config();
 
@@ -1290,8 +1284,7 @@ static void hpet_rtc_timer_reinit(void)
 		if (hpet_rtc_flags & RTC_PIE)
 			hpet_pie_count += lost_ints;
 		if (printk_ratelimit())
-			printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n",
-				lost_ints);
+			pr_warn("Lost %d RTC interrupts\n", lost_ints);
 	}
 }
 



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 03/29] x86/hpet: Restructure init code
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
  2019-06-23 13:23 ` [patch 01/29] x86/hpet: Simplify CPU online code Thomas Gleixner
  2019-06-23 13:23 ` [patch 02/29] x86/hpet: Replace printk(KERN...) with pr_...() Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:35   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 04/29] x86/hpet: Remove pointless x86-64 specific #include Thomas Gleixner
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

As a preparatory change for further consolidation, restructure the HPET
init code so it becomes more readable. Fix up misleading and stale comments
and rename variables so they actually make sense.

No intended functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   81 ++++++++++++++++++++++++++-----------------------
 1 file changed, 43 insertions(+), 38 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -45,6 +45,7 @@ bool					hpet_msi_disable;
 static unsigned int			hpet_num_timers;
 #endif
 static void __iomem			*hpet_virt_address;
+static u32				*hpet_boot_cfg;
 
 struct hpet_dev {
 	struct clock_event_device	evt;
@@ -862,7 +863,34 @@ static int hpet_clocksource_register(voi
 	return 0;
 }
 
-static u32 *hpet_boot_cfg;
+/*
+ * AMD SB700 based systems with spread spectrum enabled use a SMM based
+ * HPET emulation to provide proper frequency setting.
+ *
+ * On such systems the SMM code is initialized with the first HPET register
+ * access and takes some time to complete. During this time the config
+ * register reads 0xffffffff. We check for max 1000 loops whether the
+ * config register reads a non-0xffffffff value to make sure that the
+ * HPET is up and running before we proceed any further.
+ *
+ * A counting loop is safe, as the HPET access takes thousands of CPU cycles.
+ *
+ * On non-SB700 based machines this check is only done once and has no
+ * side effects.
+ */
+static bool __init hpet_cfg_working(void)
+{
+	int i;
+
+	for (i = 0; i < 1000; i++) {
+		if (hpet_readl(HPET_CFG) != 0xFFFFFFFF)
+			return true;
+	}
+
+	pr_warn("Config register invalid. Disabling HPET\n");
+	return false;
+}
+
 
 /**
  * hpet_enable - Try to setup the HPET timer. Returns 1 on success.
@@ -870,8 +898,8 @@ static u32 *hpet_boot_cfg;
 int __init hpet_enable(void)
 {
 	u32 hpet_period, cfg, id;
+	unsigned int i, channels;
 	u64 freq;
-	unsigned int i, last;
 
 	if (!is_hpet_capable())
 		return 0;
@@ -880,38 +908,18 @@ int __init hpet_enable(void)
 	if (!hpet_virt_address)
 		return 0;
 
+	/* Validate that the config register is working */
+	if (!hpet_cfg_working())
+		goto out_nohpet;
+
 	/*
 	 * Read the period and check for a sane value:
 	 */
 	hpet_period = hpet_readl(HPET_PERIOD);
-
-	/*
-	 * AMD SB700 based systems with spread spectrum enabled use a
-	 * SMM based HPET emulation to provide proper frequency
-	 * setting. The SMM code is initialized with the first HPET
-	 * register access and takes some time to complete. During
-	 * this time the config register reads 0xffffffff. We check
-	 * for max. 1000 loops whether the config register reads a non
-	 * 0xffffffff value to make sure that HPET is up and running
-	 * before we go further. A counting loop is safe, as the HPET
-	 * access takes thousands of CPU cycles. On non SB700 based
-	 * machines this check is only done once and has no side
-	 * effects.
-	 */
-	for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) {
-		if (i == 1000) {
-			pr_warn("Config register invalid. Disabling HPET\n");
-			goto out_nohpet;
-		}
-	}
-
 	if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
 		goto out_nohpet;
 
-	/*
-	 * The period is a femto seconds value. Convert it to a
-	 * frequency.
-	 */
+	/* The period is a femtoseconds value. Convert it to a frequency. */
 	freq = FSEC_PER_SEC;
 	do_div(freq, hpet_period);
 	hpet_freq = freq;
@@ -923,19 +931,21 @@ int __init hpet_enable(void)
 	id = hpet_readl(HPET_ID);
 	hpet_print_config();
 
-	last = (id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
+	/* This is the HPET channel number which is zero based */
+	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 	/*
 	 * The legacy routing mode needs at least two channels, tick timer
 	 * and the rtc emulation channel.
 	 */
-	if (!last)
+	if (channels < 2)
 		goto out_nohpet;
 #endif
 
 	cfg = hpet_readl(HPET_CFG);
-	hpet_boot_cfg = kmalloc_array(last + 2, sizeof(*hpet_boot_cfg),
+	/* Allocate entries for the global and the channel configurations */
+	hpet_boot_cfg = kmalloc_array(channels + 1, sizeof(*hpet_boot_cfg),
 				      GFP_KERNEL);
 	if (hpet_boot_cfg)
 		*hpet_boot_cfg = cfg;
@@ -946,7 +956,7 @@ int __init hpet_enable(void)
 	if (cfg)
 		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
-	for (i = 0; i <= last; ++i) {
+	for (i = 0; i < channels; ++i) {
 		cfg = hpet_readl(HPET_Tn_CFG(i));
 		if (hpet_boot_cfg)
 			hpet_boot_cfg[i + 1] = cfg;
@@ -976,18 +986,13 @@ int __init hpet_enable(void)
 }
 
 /*
- * Needs to be late, as the reserve_timer code calls kalloc !
- *
- * Not a problem on i386 as hpet_enable is called from late_time_init,
- * but on x86_64 it is necessary !
+ * The late initialization runs after the PCI quirks have been invoked
+ * which might have detected a system on which the HPET can be enforced.
  */
 static __init int hpet_late_init(void)
 {
 	int ret;
 
-	if (boot_hpet_disable)
-		return -ENODEV;
-
 	if (!hpet_address) {
 		if (!force_hpet_address)
 			return -ENODEV;



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 04/29] x86/hpet: Remove pointless x86-64 specific #include
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (2 preceding siblings ...)
  2019-06-23 13:23 ` [patch 03/29] x86/hpet: Restructure init code Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:36   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 05/29] x86/hpet: Remove unused parameter from hpet_next_event() Thomas Gleixner
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Nothing requires asm/pgtable.h here anymore.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |    4 ----
 1 file changed, 4 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -71,10 +71,6 @@ static inline void hpet_writel(unsigned
 	writel(d, hpet_virt_address + a);
 }
 
-#ifdef CONFIG_X86_64
-#include <asm/pgtable.h>
-#endif
-
 static inline void hpet_set_mapping(void)
 {
 	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 05/29] x86/hpet: Remove unused parameter from hpet_next_event()
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (3 preceding siblings ...)
  2019-06-23 13:23 ` [patch 04/29] x86/hpet: Remove pointless x86-64 specific #include Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:36   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 06/29] x86/hpet: Remove the unused hpet_msi_read() function Thomas Gleixner
                   ` (24 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

The clockevent device pointer is not used in this function.

While at it, rename the misnamed 'timer' parameter to 'channel', which makes it
clear what this parameter means.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -347,15 +347,14 @@ static int hpet_resume(struct clock_even
 	return 0;
 }
 
-static int hpet_next_event(unsigned long delta,
-			   struct clock_event_device *evt, int timer)
+static int hpet_next_event(unsigned long delta, int channel)
 {
 	u32 cnt;
 	s32 res;
 
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += (u32) delta;
-	hpet_writel(cnt, HPET_Tn_CMP(timer));
+	hpet_writel(cnt, HPET_Tn_CMP(channel));
 
 	/*
 	 * HPETs are a complete disaster. The compare register is
@@ -407,7 +406,7 @@ static int hpet_legacy_resume(struct clo
 static int hpet_legacy_next_event(unsigned long delta,
 			struct clock_event_device *evt)
 {
-	return hpet_next_event(delta, evt, 0);
+	return hpet_next_event(delta, 0);
 }
 
 /*
@@ -508,7 +507,8 @@ static int hpet_msi_next_event(unsigned
 				struct clock_event_device *evt)
 {
 	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-	return hpet_next_event(delta, evt, hdev->num);
+
+	return hpet_next_event(delta, hdev->num);
 }
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 06/29] x86/hpet: Remove the unused hpet_msi_read() function
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (4 preceding siblings ...)
  2019-06-23 13:23 ` [patch 05/29] x86/hpet: Remove unused parameter from hpet_next_event() Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:37   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 07/29] x86/hpet: Mark init functions __init Thomas Gleixner
                   ` (23 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

No users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/hpet.h |    1 -
 arch/x86/kernel/hpet.c      |    7 -------
 2 files changed, 8 deletions(-)

--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -81,7 +81,6 @@ struct irq_domain;
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
 extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
-extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
 extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
 			   struct hpet_dev *dev, int dev_num);
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -462,13 +462,6 @@ void hpet_msi_write(struct hpet_dev *hde
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
 }
 
-void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
-{
-	msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
-	msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
-	msg->address_hi = 0;
-}
-
 static int hpet_msi_shutdown(struct clock_event_device *evt)
 {
 	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 07/29] x86/hpet: Mark init functions __init
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (5 preceding siblings ...)
  2019-06-23 13:23 ` [patch 06/29] x86/hpet: Remove the unused hpet_msi_read() function Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:38   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 08/29] x86/hpet: Sanitize stub functions Thomas Gleixner
                   ` (22 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

They are only called from init code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -176,7 +176,7 @@ do {								\
 
 static void hpet_reserve_msi_timers(struct hpet_data *hd);
 
-static void hpet_reserve_platform_timers(unsigned int id)
+static void __init hpet_reserve_platform_timers(unsigned int id)
 {
 	struct hpet __iomem *hpet = hpet_virt_address;
 	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
@@ -572,7 +572,7 @@ static void init_one_hpet_msi_clockevent
 #define RESERVE_TIMERS 0
 #endif
 
-static void hpet_msi_capability_lookup(unsigned int start_timer)
+static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 {
 	unsigned int id;
 	unsigned int num_timers;
@@ -631,7 +631,7 @@ static void hpet_msi_capability_lookup(u
 }
 
 #ifdef CONFIG_HPET
-static void hpet_reserve_msi_timers(struct hpet_data *hd)
+static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 {
 	int i;
 



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 08/29] x86/hpet: Sanitize stub functions
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (6 preceding siblings ...)
  2019-06-23 13:23 ` [patch 07/29] x86/hpet: Mark init functions __init Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:39   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 09/29] x86/hpet: Move static and global variables to one place Thomas Gleixner
                   ` (21 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Mark them inline and remove the pointless 'return;' statement.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -692,16 +692,10 @@ static int hpet_cpuhp_dead(unsigned int
 }
 #else
 
-static void hpet_msi_capability_lookup(unsigned int start_timer)
-{
-	return;
-}
+static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }
 
 #ifdef CONFIG_HPET
-static void hpet_reserve_msi_timers(struct hpet_data *hd)
-{
-	return;
-}
+static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
 #endif
 
 #define hpet_cpuhp_online	NULL
@@ -820,7 +814,7 @@ static struct clocksource clocksource_hp
 	.resume		= hpet_resume_counter,
 };
 
-static int hpet_clocksource_register(void)
+static int __init hpet_clocksource_register(void)
 {
 	u64 start, now;
 	u64 t1;



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 09/29] x86/hpet: Move static and global variables to one place
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (7 preceding siblings ...)
  2019-06-23 13:23 ` [patch 08/29] x86/hpet: Sanitize stub functions Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:39   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 10/29] x86/hpet: Shuffle code around for readability sake Thomas Gleixner
                   ` (20 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Having static and global variables sprinkled all over the code is just
annoying to read. Move them all to the top of the file.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   50 +++++++++++++++++++++----------------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -23,6 +23,15 @@
 #undef  pr_fmt
 #define pr_fmt(fmt) "hpet: " fmt
 
+struct hpet_dev {
+	struct clock_event_device	evt;
+	unsigned int			num;
+	int				cpu;
+	unsigned int			irq;
+	unsigned int			flags;
+	char				name[10];
+};
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -43,18 +52,22 @@ bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
 static unsigned int			hpet_num_timers;
+static struct hpet_dev			*hpet_devs;
+static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
+static struct irq_domain		*hpet_domain;
 #endif
+
 static void __iomem			*hpet_virt_address;
 static u32				*hpet_boot_cfg;
 
-struct hpet_dev {
-	struct clock_event_device	evt;
-	unsigned int			num;
-	int				cpu;
-	unsigned int			irq;
-	unsigned int			flags;
-	char				name[10];
-};
+static bool				hpet_legacy_int_enabled;
+static unsigned long			hpet_freq;
+
+bool					boot_hpet_disable;
+bool					hpet_force_user;
+static bool				hpet_verbose;
+
+static struct clock_event_device	hpet_clockevent;
 
 static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
 {
@@ -85,10 +98,6 @@ static inline void hpet_clear_mapping(vo
 /*
  * HPET command line enable / disable
  */
-bool boot_hpet_disable;
-bool hpet_force_user;
-static bool hpet_verbose;
-
 static int __init hpet_setup(char *str)
 {
 	while (str) {
@@ -120,11 +129,6 @@ static inline int is_hpet_capable(void)
 	return !boot_hpet_disable && hpet_address;
 }
 
-/*
- * HPET timer interrupt enable / disable
- */
-static bool hpet_legacy_int_enabled;
-
 /**
  * is_hpet_enabled - check whether the hpet timer interrupt is enabled
  */
@@ -217,13 +221,7 @@ static void __init hpet_reserve_platform
 static void hpet_reserve_platform_timers(unsigned int id) { }
 #endif
 
-/*
- * Common hpet info
- */
-static unsigned long hpet_freq;
-
-static struct clock_event_device hpet_clockevent;
-
+/* Common hpet functions */
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
@@ -430,10 +428,6 @@ static struct clock_event_device hpet_cl
  */
 #ifdef CONFIG_PCI_MSI
 
-static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
-static struct hpet_dev	*hpet_devs;
-static struct irq_domain *hpet_domain;
-
 void hpet_msi_unmask(struct irq_data *data)
 {
 	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 10/29] x86/hpet: Shuffle code around for readability sake
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (8 preceding siblings ...)
  2019-06-23 13:23 ` [patch 09/29] x86/hpet: Move static and global variables to one place Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:40   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 11/29] x86/hpet: Separate counter check out of clocksource register code Thomas Gleixner
                   ` (19 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

It doesn't make sense to have init functions in the middle of other
code. Aside of that, further changes in that area create horrible diffs if
the code stays where it is.

No functional change

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   81 ++++++++++++++++++++++++-------------------------
 1 file changed, 41 insertions(+), 40 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -559,6 +559,47 @@ static void init_one_hpet_msi_clockevent
 					0x7FFFFFFF);
 }
 
+static struct hpet_dev *hpet_get_unused_timer(void)
+{
+	int i;
+
+	if (!hpet_devs)
+		return NULL;
+
+	for (i = 0; i < hpet_num_timers; i++) {
+		struct hpet_dev *hdev = &hpet_devs[i];
+
+		if (!(hdev->flags & HPET_DEV_VALID))
+			continue;
+		if (test_and_set_bit(HPET_DEV_USED_BIT,
+			(unsigned long *)&hdev->flags))
+			continue;
+		return hdev;
+	}
+	return NULL;
+}
+
+static int hpet_cpuhp_online(unsigned int cpu)
+{
+	struct hpet_dev *hdev = hpet_get_unused_timer();
+
+	if (hdev)
+		init_one_hpet_msi_clockevent(hdev, cpu);
+	return 0;
+}
+
+static int hpet_cpuhp_dead(unsigned int cpu)
+{
+	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
+
+	if (!hdev)
+		return 0;
+	free_irq(hdev->irq, hdev);
+	hdev->flags &= ~HPET_DEV_USED;
+	per_cpu(cpu_hpet_dev, cpu) = NULL;
+	return 0;
+}
+
 #ifdef CONFIG_HPET
 /* Reserve at least one timer for userspace (/dev/hpet) */
 #define RESERVE_TIMERS 1
@@ -644,46 +685,6 @@ static void __init hpet_reserve_msi_time
 }
 #endif
 
-static struct hpet_dev *hpet_get_unused_timer(void)
-{
-	int i;
-
-	if (!hpet_devs)
-		return NULL;
-
-	for (i = 0; i < hpet_num_timers; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
-
-		if (!(hdev->flags & HPET_DEV_VALID))
-			continue;
-		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hdev->flags))
-			continue;
-		return hdev;
-	}
-	return NULL;
-}
-
-static int hpet_cpuhp_online(unsigned int cpu)
-{
-	struct hpet_dev *hdev = hpet_get_unused_timer();
-
-	if (hdev)
-		init_one_hpet_msi_clockevent(hdev, cpu);
-	return 0;
-}
-
-static int hpet_cpuhp_dead(unsigned int cpu)
-{
-	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
-
-	if (!hdev)
-		return 0;
-	free_irq(hdev->irq, hdev);
-	hdev->flags &= ~HPET_DEV_USED;
-	per_cpu(cpu_hpet_dev, cpu) = NULL;
-	return 0;
-}
 #else
 
 static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 11/29] x86/hpet: Separate counter check out of clocksource register code
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (9 preceding siblings ...)
  2019-06-23 13:23 ` [patch 10/29] x86/hpet: Shuffle code around for readability sake Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:41   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 12/29] x86/hpet: Simplify counter validation Thomas Gleixner
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

The init code checks whether the HPET counter works late in the init
function when the clocksource is registered. That should happen right with
the other sanity checks.

Split it into a separate validation function and move it to the other
sanity checks.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   65 +++++++++++++++++++++++--------------------------
 1 file changed, 31 insertions(+), 34 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -809,38 +809,6 @@ static struct clocksource clocksource_hp
 	.resume		= hpet_resume_counter,
 };
 
-static int __init hpet_clocksource_register(void)
-{
-	u64 start, now;
-	u64 t1;
-
-	/* Start the counter */
-	hpet_restart_counter();
-
-	/* Verify whether hpet counter works */
-	t1 = hpet_readl(HPET_COUNTER);
-	start = rdtsc();
-
-	/*
-	 * We don't know the TSC frequency yet, but waiting for
-	 * 200000 TSC cycles is safe:
-	 * 4 GHz == 50us
-	 * 1 GHz == 200us
-	 */
-	do {
-		rep_nop();
-		now = rdtsc();
-	} while ((now - start) < 200000UL);
-
-	if (t1 == hpet_readl(HPET_COUNTER)) {
-		pr_warn("Counter not counting. HPET disabled\n");
-		return -ENODEV;
-	}
-
-	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
-	return 0;
-}
-
 /*
  * AMD SB700 based systems with spread spectrum enabled use a SMM based
  * HPET emulation to provide proper frequency setting.
@@ -869,6 +837,32 @@ static bool __init hpet_cfg_working(void
 	return false;
 }
 
+static bool __init hpet_counting(void)
+{
+	u64 start, now, t1;
+
+	hpet_restart_counter();
+
+	t1 = hpet_readl(HPET_COUNTER);
+	start = rdtsc();
+
+	/*
+	 * We don't know the TSC frequency yet, but waiting for
+	 * 200000 TSC cycles is safe:
+	 * 4 GHz == 50us
+	 * 1 GHz == 200us
+	 */
+	do {
+		rep_nop();
+		now = rdtsc();
+	} while ((now - start) < 200000UL);
+
+	if (t1 == hpet_readl(HPET_COUNTER)) {
+		pr_warn("Counter not counting. HPET disabled\n");
+		return false;
+	}
+	return true;
+}
 
 /**
  * hpet_enable - Try to setup the HPET timer. Returns 1 on success.
@@ -890,6 +884,10 @@ int __init hpet_enable(void)
 	if (!hpet_cfg_working())
 		goto out_nohpet;
 
+	/* Validate that the counter is counting */
+	if (!hpet_counting())
+		goto out_nohpet;
+
 	/*
 	 * Read the period and check for a sane value:
 	 */
@@ -948,8 +946,7 @@ int __init hpet_enable(void)
 	}
 	hpet_print_config();
 
-	if (hpet_clocksource_register())
-		goto out_nohpet;
+	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
 		hpet_legacy_clockevent_register();



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 12/29] x86/hpet: Simplify counter validation
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (10 preceding siblings ...)
  2019-06-23 13:23 ` [patch 11/29] x86/hpet: Separate counter check out of clocksource register code Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:41   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 13/29] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV Thomas Gleixner
                   ` (17 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

There is no point to loop for 200k TSC cycles to check afterwards whether
the HPET counter is working. Read the counter inside of the loop and break
out when the counter value changed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -853,15 +853,13 @@ static bool __init hpet_counting(void)
 	 * 1 GHz == 200us
 	 */
 	do {
-		rep_nop();
+		if (t1 != hpet_readl(HPET_COUNTER))
+			return true;
 		now = rdtsc();
 	} while ((now - start) < 200000UL);
 
-	if (t1 == hpet_readl(HPET_COUNTER)) {
-		pr_warn("Counter not counting. HPET disabled\n");
-		return false;
-	}
-	return true;
+	pr_warn("Counter not counting. HPET disabled\n");
+	return false;
 }
 
 /**



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 13/29] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (11 preceding siblings ...)
  2019-06-23 13:23 ` [patch 12/29] x86/hpet: Simplify counter validation Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:42   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 14/29] x86/hpet: Remove not required includes Thomas Gleixner
                   ` (16 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

It's a function not a macro and the upcoming changes use channel for the
individual hpet timer units to allow a step by step refactoring approach.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -69,9 +69,10 @@ static bool				hpet_verbose;
 
 static struct clock_event_device	hpet_clockevent;
 
-static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
+static inline
+struct hpet_dev *clockevent_to_channel(struct clock_event_device *evt)
 {
-	return container_of(evtdev, struct hpet_dev, evt);
+	return container_of(evt, struct hpet_dev, evt);
 }
 
 inline unsigned int hpet_readl(unsigned int a)
@@ -458,28 +459,22 @@ void hpet_msi_write(struct hpet_dev *hde
 
 static int hpet_msi_shutdown(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_shutdown(evt, hdev->num);
+	return hpet_shutdown(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_set_oneshot(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_set_oneshot(evt, hdev->num);
+	return hpet_set_oneshot(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_set_periodic(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_set_periodic(evt, hdev->num);
+	return hpet_set_periodic(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+	struct hpet_dev *hdev = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hdev->irq);
 	struct msi_msg msg;
 
@@ -491,16 +486,14 @@ static int hpet_msi_resume(struct clock_
 }
 
 static int hpet_msi_next_event(unsigned long delta,
-				struct clock_event_device *evt)
+			       struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_next_event(delta, hdev->num);
+	return hpet_next_event(delta, clockevent_to_channel(evt)->num);
 }
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *dev = (struct hpet_dev *)data;
+	struct hpet_dev *dev = data;
 	struct clock_event_device *hevt = &dev->evt;
 
 	if (!hevt->event_handler) {



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 14/29] x86/hpet: Remove not required includes
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (12 preceding siblings ...)
  2019-06-23 13:23 ` [patch 13/29] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:43   ` [tip:x86/timers] " tip-bot for Ingo Molnar
  2019-06-23 13:23 ` [patch 15/29] x86/hpet: Make naming consistent Thomas Gleixner
                   ` (15 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar,
	Ingo Molnar

From: Ingo Molnar <mingo@kernel.org>

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -1,22 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
-#include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/export.h>
 #include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/i8253.h>
-#include <linux/slab.h>
 #include <linux/hpet.h>
-#include <linux/init.h>
 #include <linux/cpu.h>
-#include <linux/pm.h>
-#include <linux/io.h>
+#include <linux/irq.h>
 
-#include <asm/cpufeature.h>
-#include <asm/irqdomain.h>
-#include <asm/fixmap.h>
 #include <asm/hpet.h>
 #include <asm/time.h>
 



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 15/29] x86/hpet: Make naming consistent
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (13 preceding siblings ...)
  2019-06-23 13:23 ` [patch 14/29] x86/hpet: Remove not required includes Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:44   ` [tip:x86/timers] " tip-bot for Ingo Molnar
  2019-06-23 13:23 ` [patch 16/29] x86/hpet: Clean up comments Thomas Gleixner
                   ` (14 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar,
	Ingo Molnar

From: Ingo Molnar <mingo@kernel.org>

Use 'evt' for clockevents pointers and capitalize HPET in comments.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -121,7 +121,7 @@ static inline int is_hpet_capable(void)
 }
 
 /**
- * is_hpet_enabled - check whether the hpet timer interrupt is enabled
+ * is_hpet_enabled - Check whether the legacy HPET timer interrupt is enabled
  */
 int is_hpet_enabled(void)
 {
@@ -164,7 +164,7 @@ do {								\
 } while (0)
 
 /*
- * When the hpet driver (/dev/hpet) is enabled, we need to reserve
+ * When the HPET driver (/dev/hpet) is enabled, we need to reserve
  * timer 0 and timer 1 in case of RTC emulation.
  */
 #ifdef CONFIG_HPET
@@ -212,7 +212,7 @@ static void __init hpet_reserve_platform
 static void hpet_reserve_platform_timers(unsigned int id) { }
 #endif
 
-/* Common hpet functions */
+/* Common HPET functions */
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
@@ -266,7 +266,7 @@ static void hpet_legacy_clockevent_regis
 	hpet_enable_legacy_int();
 
 	/*
-	 * Start hpet with the boot cpu mask and make it
+	 * Start HPET with the boot cpu mask and make it
 	 * global after the IO_APIC has been initialized.
 	 */
 	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
@@ -399,7 +399,7 @@ static int hpet_legacy_next_event(unsign
 }
 
 /*
- * The hpet clock event device
+ * The HPET clock event device
  */
 static struct clock_event_device hpet_clockevent = {
 	.name			= "hpet",
@@ -484,14 +484,14 @@ static int hpet_msi_next_event(unsigned
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
 	struct hpet_dev *dev = data;
-	struct clock_event_device *hevt = &dev->evt;
+	struct clock_event_device *evt = &dev->evt;
 
-	if (!hevt->event_handler) {
+	if (!evt->event_handler) {
 		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
 		return IRQ_HANDLED;
 	}
 
-	hevt->event_handler(hevt);
+	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
@@ -703,7 +703,7 @@ static inline void hpet_reserve_msi_time
  * with its associated locking overhead. And we also need 64-bit atomic
  * read.
  *
- * The lock and the hpet value are stored together and can be read in a
+ * The lock and the HPET value are stored together and can be read in a
  * single atomic 64-bit read. It is explicitly assumed that arch_spinlock_t
  * is 32 bits in size.
  */
@@ -1053,7 +1053,7 @@ static unsigned long hpet_pie_limit;
 static rtc_irq_handler irq_handler;
 
 /*
- * Check that the hpet counter c1 is ahead of the c2
+ * Check that the HPET counter c1 is ahead of the c2
  */
 static inline int hpet_cnt_ahead(u32 c1, u32 c2)
 {



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 16/29] x86/hpet: Clean up comments
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (14 preceding siblings ...)
  2019-06-23 13:23 ` [patch 15/29] x86/hpet: Make naming consistent Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:44   ` [tip:x86/timers] " tip-bot for Ingo Molnar
  2019-06-23 13:23 ` [patch 17/29] x86/hpet: Coding style cleanup Thomas Gleixner
                   ` (13 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar,
	Ingo Molnar

From: Ingo Molnar <mingo@kernel.org>

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -266,8 +266,8 @@ static void hpet_legacy_clockevent_regis
 	hpet_enable_legacy_int();
 
 	/*
-	 * Start HPET with the boot cpu mask and make it
-	 * global after the IO_APIC has been initialized.
+	 * Start HPET with the boot CPU's cpumask and make it global after
+	 * the IO_APIC has been initialized.
 	 */
 	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
 	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
@@ -688,10 +688,10 @@ static inline void hpet_reserve_msi_time
 /*
  * Reading the HPET counter is a very slow operation. If a large number of
  * CPUs are trying to access the HPET counter simultaneously, it can cause
- * massive delay and slow down system performance dramatically. This may
+ * massive delays and slow down system performance dramatically. This may
  * happen when HPET is the default clock source instead of TSC. For a
  * really large system with hundreds of CPUs, the slowdown may be so
- * severe that it may actually crash the system because of a NMI watchdog
+ * severe, that it can actually crash the system because of a NMI watchdog
  * soft lockup, for example.
  *
  * If multiple CPUs are trying to access the HPET counter at the same time,
@@ -700,8 +700,7 @@ static inline void hpet_reserve_msi_time
  *
  * This special feature is only enabled on x86-64 systems. It is unlikely
  * that 32-bit x86 systems will have enough CPUs to require this feature
- * with its associated locking overhead. And we also need 64-bit atomic
- * read.
+ * with its associated locking overhead. We also need 64-bit atomic read.
  *
  * The lock and the HPET value are stored together and can be read in a
  * single atomic 64-bit read. It is explicitly assumed that arch_spinlock_t
@@ -1020,19 +1019,25 @@ void hpet_disable(void)
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+/*
+ * HPET in LegacyReplacement mode eats up the RTC interrupt line. When HPET
  * is enabled, we support RTC interrupt functionality in software.
+ *
  * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
+ *
+ *  1) Update Interrupt - generate an interrupt, every second, when the
+ *     RTC clock is updated
+ *  2) Alarm Interrupt - generate an interrupt at a specific time of day
+ *  3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *     2Hz-8192Hz (2Hz-64Hz for non-root user) (all frequencies in powers of 2)
+ *
+ * (1) and (2) above are implemented using polling at a frequency of 64 Hz:
+ * DEFAULT_RTC_INT_FREQ.
+ *
+ * The exact frequency is a tradeoff between accuracy and interrupt overhead.
+ *
+ * For (3), we use interrupts at 64 Hz, or the user specified periodic frequency,
+ * if it's higher.
  */
 #include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
@@ -1053,7 +1058,7 @@ static unsigned long hpet_pie_limit;
 static rtc_irq_handler irq_handler;
 
 /*
- * Check that the HPET counter c1 is ahead of the c2
+ * Check that the HPET counter c1 is ahead of c2
  */
 static inline int hpet_cnt_ahead(u32 c1, u32 c2)
 {



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 17/29] x86/hpet: Coding style cleanup
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (15 preceding siblings ...)
  2019-06-23 13:23 ` [patch 16/29] x86/hpet: Clean up comments Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:45   ` [tip:x86/timers] " tip-bot for Ingo Molnar
  2019-06-23 13:23 ` [patch 18/29] x86/hpet: Introduce struct hpet_base and struct hpet_channel Thomas Gleixner
                   ` (12 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar,
	Ingo Molnar

From: Ingo Molnar <mingo@kernel.org>

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -131,26 +131,33 @@ EXPORT_SYMBOL_GPL(is_hpet_enabled);
 
 static void _hpet_print_config(const char *function, int line)
 {
-	u32 i, timers, l, h;
+	u32 i, id, period, cfg, status, channels, l, h;
+
 	pr_info("%s(%d):\n", function, line);
-	l = hpet_readl(HPET_ID);
-	h = hpet_readl(HPET_PERIOD);
-	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
-	pr_info("ID: 0x%x, PERIOD: 0x%x\n", l, h);
-	l = hpet_readl(HPET_CFG);
-	h = hpet_readl(HPET_STATUS);
-	pr_info("CFG: 0x%x, STATUS: 0x%x\n", l, h);
+
+	id = hpet_readl(HPET_ID);
+	period = hpet_readl(HPET_PERIOD);
+	pr_info("ID: 0x%x, PERIOD: 0x%x\n", id, period);
+
+	cfg = hpet_readl(HPET_CFG);
+	status = hpet_readl(HPET_STATUS);
+	pr_info("CFG: 0x%x, STATUS: 0x%x\n", cfg, status);
+
 	l = hpet_readl(HPET_COUNTER);
 	h = hpet_readl(HPET_COUNTER+4);
 	pr_info("COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
 
-	for (i = 0; i < timers; i++) {
+	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+
+	for (i = 0; i < channels; i++) {
 		l = hpet_readl(HPET_Tn_CFG(i));
 		h = hpet_readl(HPET_Tn_CFG(i)+4);
 		pr_info("T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h);
+
 		l = hpet_readl(HPET_Tn_CMP(i));
 		h = hpet_readl(HPET_Tn_CMP(i)+4);
 		pr_info("T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h);
+
 		l = hpet_readl(HPET_Tn_ROUTE(i));
 		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
 		pr_info("T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h);
@@ -216,6 +223,7 @@ static void hpet_reserve_platform_timers
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
+
 	cfg &= ~HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 }
@@ -229,6 +237,7 @@ static void hpet_reset_counter(void)
 static void hpet_start_counter(void)
 {
 	unsigned int cfg = hpet_readl(HPET_CFG);
+
 	cfg |= HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 }
@@ -393,7 +402,7 @@ static int hpet_legacy_resume(struct clo
 }
 
 static int hpet_legacy_next_event(unsigned long delta,
-			struct clock_event_device *evt)
+				  struct clock_event_device *evt)
 {
 	return hpet_next_event(delta, 0);
 }
@@ -1142,6 +1151,7 @@ EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
 static void hpet_disable_rtc_channel(void)
 {
 	u32 cfg = hpet_readl(HPET_T1_CFG);
+
 	cfg &= ~HPET_TN_ENABLE;
 	hpet_writel(cfg, HPET_T1_CFG);
 }
@@ -1183,8 +1193,7 @@ int hpet_set_rtc_irq_bit(unsigned long b
 }
 EXPORT_SYMBOL_GPL(hpet_set_rtc_irq_bit);
 
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min,
-			unsigned char sec)
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
 {
 	if (!is_hpet_enabled())
 		return 0;
@@ -1204,15 +1213,16 @@ int hpet_set_periodic_freq(unsigned long
 	if (!is_hpet_enabled())
 		return 0;
 
-	if (freq <= DEFAULT_RTC_INT_FREQ)
+	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
-	else {
+	} else {
 		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
 		do_div(clc, freq);
 		clc >>= hpet_clockevent.shift;
 		hpet_pie_delta = clc;
 		hpet_pie_limit = 0;
 	}
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(hpet_set_periodic_freq);
@@ -1272,8 +1282,7 @@ irqreturn_t hpet_rtc_interrupt(int irq,
 		hpet_prev_update_sec = curr_time.tm_sec;
 	}
 
-	if (hpet_rtc_flags & RTC_PIE &&
-	    ++hpet_pie_count >= hpet_pie_limit) {
+	if (hpet_rtc_flags & RTC_PIE && ++hpet_pie_count >= hpet_pie_limit) {
 		rtc_int_flag |= RTC_PF;
 		hpet_pie_count = 0;
 	}
@@ -1282,7 +1291,7 @@ irqreturn_t hpet_rtc_interrupt(int irq,
 	    (curr_time.tm_sec == hpet_alarm_time.tm_sec) &&
 	    (curr_time.tm_min == hpet_alarm_time.tm_min) &&
 	    (curr_time.tm_hour == hpet_alarm_time.tm_hour))
-			rtc_int_flag |= RTC_AF;
+		rtc_int_flag |= RTC_AF;
 
 	if (rtc_int_flag) {
 		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 18/29] x86/hpet: Introduce struct hpet_base and struct hpet_channel
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (16 preceding siblings ...)
  2019-06-23 13:23 ` [patch 17/29] x86/hpet: Coding style cleanup Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:46   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:23 ` [patch 19/29] x86/hpet: Use cached channel data Thomas Gleixner
                   ` (11 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Introduce new data structures to replace the ad hoc collection of separate
variables and pointers.

Replace the boot configuration store and restore as a first step.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   84 ++++++++++++++++++++++++++++---------------------
 1 file changed, 49 insertions(+), 35 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -22,6 +22,17 @@ struct hpet_dev {
 	char				name[10];
 };
 
+struct hpet_channel {
+	unsigned int			num;
+	unsigned int			boot_cfg;
+};
+
+struct hpet_base {
+	unsigned int			nr_channels;
+	unsigned int			boot_cfg;
+	struct hpet_channel		*channels;
+};
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -48,7 +59,7 @@ static struct irq_domain		*hpet_domain;
 #endif
 
 static void __iomem			*hpet_virt_address;
-static u32				*hpet_boot_cfg;
+static struct hpet_base			hpet_base;
 
 static bool				hpet_legacy_int_enabled;
 static unsigned long			hpet_freq;
@@ -860,6 +871,7 @@ int __init hpet_enable(void)
 {
 	u32 hpet_period, cfg, id;
 	unsigned int i, channels;
+	struct hpet_channel *hc;
 	u64 freq;
 
 	if (!is_hpet_capable())
@@ -899,34 +911,39 @@ int __init hpet_enable(void)
 	/* This is the HPET channel number which is zero based */
 	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
 
-#ifdef CONFIG_HPET_EMULATE_RTC
 	/*
 	 * The legacy routing mode needs at least two channels, tick timer
 	 * and the rtc emulation channel.
 	 */
-	if (channels < 2)
+	if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC) && channels < 2)
 		goto out_nohpet;
-#endif
 
+	hc = kcalloc(channels, sizeof(*hc), GFP_KERNEL);
+	if (!hc) {
+		pr_warn("Disabling HPET.\n");
+		goto out_nohpet;
+	}
+	hpet_base.channels = hc;
+	hpet_base.nr_channels = channels;
+
+	/* Read, store and sanitize the global configuration */
 	cfg = hpet_readl(HPET_CFG);
-	/* Allocate entries for the global and the channel configurations */
-	hpet_boot_cfg = kmalloc_array(channels + 1, sizeof(*hpet_boot_cfg),
-				      GFP_KERNEL);
-	if (hpet_boot_cfg)
-		*hpet_boot_cfg = cfg;
-	else
-		pr_warn("HPET initial state will not be saved\n");
+	hpet_base.boot_cfg = cfg;
 	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
 	hpet_writel(cfg, HPET_CFG);
 	if (cfg)
 		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
-	for (i = 0; i < channels; ++i) {
+	/* Read, store and sanitize the per channel configuration */
+	for (i = 0; i < channels; i++, hc++) {
+		hc->num = i;
+
 		cfg = hpet_readl(HPET_Tn_CFG(i));
-		if (hpet_boot_cfg)
-			hpet_boot_cfg[i + 1] = cfg;
+		hc->boot_cfg = cfg;
+
 		cfg &= ~(HPET_TN_ENABLE | HPET_TN_LEVEL | HPET_TN_FSB);
 		hpet_writel(cfg, HPET_Tn_CFG(i));
+
 		cfg &= ~(HPET_TN_PERIODIC | HPET_TN_PERIODIC_CAP
 			 | HPET_TN_64BIT_CAP | HPET_TN_32BIT | HPET_TN_ROUTE
 			 | HPET_TN_FSB | HPET_TN_FSB_CAP);
@@ -944,6 +961,9 @@ int __init hpet_enable(void)
 	return 0;
 
 out_nohpet:
+	kfree(hpet_base.channels);
+	hpet_base.channels = NULL;
+	hpet_base.nr_channels = 0;
 	hpet_clear_mapping();
 	hpet_address = 0;
 	return 0;
@@ -1000,30 +1020,24 @@ fs_initcall(hpet_late_init);
 
 void hpet_disable(void)
 {
-	if (is_hpet_capable() && hpet_virt_address) {
-		unsigned int cfg = hpet_readl(HPET_CFG), id, last;
-
-		if (hpet_boot_cfg)
-			cfg = *hpet_boot_cfg;
-		else if (hpet_legacy_int_enabled) {
-			cfg &= ~HPET_CFG_LEGACY;
-			hpet_legacy_int_enabled = false;
-		}
-		cfg &= ~HPET_CFG_ENABLE;
-		hpet_writel(cfg, HPET_CFG);
-
-		if (!hpet_boot_cfg)
-			return;
+	unsigned int i;
+	u32 cfg;
 
-		id = hpet_readl(HPET_ID);
-		last = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
+	if (!is_hpet_capable() || !hpet_virt_address)
+		return;
 
-		for (id = 0; id <= last; ++id)
-			hpet_writel(hpet_boot_cfg[id + 1], HPET_Tn_CFG(id));
+	/* Restore boot configuration with the enable bit cleared */
+	cfg = hpet_base.boot_cfg;
+	cfg &= ~HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
 
-		if (*hpet_boot_cfg & HPET_CFG_ENABLE)
-			hpet_writel(*hpet_boot_cfg, HPET_CFG);
-	}
+	/* Restore the channel boot configuration */
+	for (i = 0; i < hpet_base.nr_channels; i++)
+		hpet_writel(hpet_base.channels[i].boot_cfg, HPET_Tn_CFG(i));
+
+	/* If the HPET was enabled at boot time, reenable it */
+	if (hpet_base.boot_cfg & HPET_CFG_ENABLE)
+		hpet_writel(hpet_base.boot_cfg, HPET_CFG);
 }
 
 #ifdef CONFIG_HPET_EMULATE_RTC



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 19/29] x86/hpet: Use cached channel data
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (17 preceding siblings ...)
  2019-06-23 13:23 ` [patch 18/29] x86/hpet: Introduce struct hpet_base and struct hpet_channel Thomas Gleixner
@ 2019-06-23 13:23 ` Thomas Gleixner
  2019-06-27 23:46   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 20/29] x86/hpet: Add mode information to struct hpet_channel Thomas Gleixner
                   ` (10 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:23 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Instead of rereading the HPET registers over and over use the information
which was cached in hpet_enable().

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -24,6 +24,7 @@ struct hpet_dev {
 
 struct hpet_channel {
 	unsigned int			num;
+	unsigned int			irq;
 	unsigned int			boot_cfg;
 };
 
@@ -52,7 +53,6 @@ u8					hpet_blockid; /* OS timer block n
 bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
-static unsigned int			hpet_num_timers;
 static struct hpet_dev			*hpet_devs;
 static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
 static struct irq_domain		*hpet_domain;
@@ -189,19 +189,15 @@ do {								\
 
 static void hpet_reserve_msi_timers(struct hpet_data *hd);
 
-static void __init hpet_reserve_platform_timers(unsigned int id)
+static void __init hpet_reserve_platform_timers(void)
 {
-	struct hpet __iomem *hpet = hpet_virt_address;
-	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
-	unsigned int nrtimers, i;
 	struct hpet_data hd;
-
-	nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+	unsigned int i;
 
 	memset(&hd, 0, sizeof(hd));
 	hd.hd_phys_address	= hpet_address;
-	hd.hd_address		= hpet;
-	hd.hd_nirqs		= nrtimers;
+	hd.hd_address		= hpet_virt_address;
+	hd.hd_nirqs		= hpet_base.nr_channels;
 	hpet_reserve_timer(&hd, 0);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
@@ -216,10 +212,8 @@ static void __init hpet_reserve_platform
 	hd.hd_irq[0] = HPET_LEGACY_8254;
 	hd.hd_irq[1] = HPET_LEGACY_RTC;
 
-	for (i = 2; i < nrtimers; timer++, i++) {
-		hd.hd_irq[i] = (readl(&timer->hpet_config) &
-			Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT;
-	}
+	for (i = 2; i < hpet_base.nr_channels; i++)
+		hd.hd_irq[i] = hpet_base.channels[i].irq;
 
 	hpet_reserve_msi_timers(&hd);
 
@@ -227,7 +221,7 @@ static void __init hpet_reserve_platform
 
 }
 #else
-static void hpet_reserve_platform_timers(unsigned int id) { }
+static inline void hpet_reserve_platform_timers(void) { }
 #endif
 
 /* Common HPET functions */
@@ -569,7 +563,7 @@ static struct hpet_dev *hpet_get_unused_
 	if (!hpet_devs)
 		return NULL;
 
-	for (i = 0; i < hpet_num_timers; i++) {
+	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_dev *hdev = &hpet_devs[i];
 
 		if (!(hdev->flags & HPET_DEV_VALID))
@@ -612,7 +606,6 @@ static int hpet_cpuhp_dead(unsigned int
 
 static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 {
-	unsigned int id;
 	unsigned int num_timers;
 	unsigned int num_timers_used = 0;
 	int i, irq;
@@ -622,10 +615,8 @@ static void __init hpet_msi_capability_l
 
 	if (boot_cpu_has(X86_FEATURE_ARAT))
 		return;
-	id = hpet_readl(HPET_ID);
 
-	num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
-	num_timers++; /* Value read out starts from 0 */
+	num_timers = hpet_base.nr_channels;
 	hpet_print_config();
 
 	hpet_domain = hpet_create_irq_domain(hpet_blockid);
@@ -636,11 +627,9 @@ static void __init hpet_msi_capability_l
 	if (!hpet_devs)
 		return;
 
-	hpet_num_timers = num_timers;
-
 	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
 		struct hpet_dev *hdev = &hpet_devs[num_timers_used];
-		unsigned int cfg = hpet_readl(HPET_Tn_CFG(i));
+		unsigned int cfg = hpet_base.channels[i].boot_cfg;
 
 		/* Only consider HPET timer with MSI support */
 		if (!(cfg & HPET_TN_FSB_CAP))
@@ -676,7 +665,7 @@ static void __init hpet_reserve_msi_time
 	if (!hpet_devs)
 		return;
 
-	for (i = 0; i < hpet_num_timers; i++) {
+	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_dev *hdev = &hpet_devs[i];
 
 		if (!(hdev->flags & HPET_DEV_VALID))
@@ -869,7 +858,7 @@ static bool __init hpet_counting(void)
  */
 int __init hpet_enable(void)
 {
-	u32 hpet_period, cfg, id;
+	u32 hpet_period, cfg, id, irq;
 	unsigned int i, channels;
 	struct hpet_channel *hc;
 	u64 freq;
@@ -940,6 +929,8 @@ int __init hpet_enable(void)
 
 		cfg = hpet_readl(HPET_Tn_CFG(i));
 		hc->boot_cfg = cfg;
+		irq = (cfg & Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT;
+		hc->irq = irq;
 
 		cfg &= ~(HPET_TN_ENABLE | HPET_TN_LEVEL | HPET_TN_FSB);
 		hpet_writel(cfg, HPET_Tn_CFG(i));
@@ -993,7 +984,7 @@ static __init int hpet_late_init(void)
 	else
 		hpet_msi_capability_lookup(0);
 
-	hpet_reserve_platform_timers(hpet_readl(HPET_ID));
+	hpet_reserve_platform_timers();
 	hpet_print_config();
 
 	if (hpet_msi_disable)



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 20/29] x86/hpet: Add mode information to struct hpet_channel
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (18 preceding siblings ...)
  2019-06-23 13:23 ` [patch 19/29] x86/hpet: Use cached channel data Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:47   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 21/29] x86/hpet: Add function to select a /dev/hpet channel Thomas Gleixner
                   ` (9 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

The usage of the individual HPET channels is not tracked in a central
place. The information is scattered in different data structures. Also the
HPET reservation in the HPET character device is split out into several
places which makes the code hard to follow.

Assigning a mode to the channel allows to consolidate the reservation code
and paves the way for further simplifications.

As a first step set the mode of the legacy channels when the HPET is in
legacy mode.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   11 +++++++++++
 1 file changed, 11 insertions(+)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -22,9 +22,17 @@ struct hpet_dev {
 	char				name[10];
 };
 
+enum hpet_mode {
+	HPET_MODE_UNUSED,
+	HPET_MODE_LEGACY,
+	HPET_MODE_CLOCKEVT,
+	HPET_MODE_DEVICE,
+};
+
 struct hpet_channel {
 	unsigned int			num;
 	unsigned int			irq;
+	enum hpet_mode			mode;
 	unsigned int			boot_cfg;
 };
 
@@ -947,6 +955,9 @@ int __init hpet_enable(void)
 
 	if (id & HPET_ID_LEGSUP) {
 		hpet_legacy_clockevent_register();
+		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
+		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
+			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
 		return 1;
 	}
 	return 0;



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 21/29] x86/hpet: Add function to select a /dev/hpet channel
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (19 preceding siblings ...)
  2019-06-23 13:24 ` [patch 20/29] x86/hpet: Add mode information to struct hpet_channel Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:48   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 22/29] x86/hpet: Rename variables to prepare for switching to channels Thomas Gleixner
                   ` (8 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

If CONFIG_HPET=y is enabled the x86 specific HPET code should reserve at
least one channel for the /dev/hpet character device, so that not all
channels are absorbed for per CPU clockevent devices.

Create a function to assign HPET_MODE_DEVICE so the rework of the
clockevents allocation code can utilize the mode information instead of
reducing the number of evaluated channels by #ifdef hackery.

The function is not yet used, but provided as a separate patch for ease of
review. It will be used when the rework of the clockevent selection takes
place.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -228,8 +228,25 @@ static void __init hpet_reserve_platform
 	hpet_alloc(&hd);
 
 }
+
+static void __init hpet_select_device_channel(void)
+{
+	int i;
+
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
+
+		/* Associate the first unused channel to /dev/hpet */
+		if (hc->mode == HPET_MODE_UNUSED) {
+			hc->mode = HPET_MODE_DEVICE;
+			return;
+		}
+	}
+}
+
 #else
 static inline void hpet_reserve_platform_timers(void) { }
+static inline void hpet_select_device_channel(void) {}
 #endif
 
 /* Common HPET functions */



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 22/29] x86/hpet: Rename variables to prepare for switching to channels
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (20 preceding siblings ...)
  2019-06-23 13:24 ` [patch 21/29] x86/hpet: Add function to select a /dev/hpet channel Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:49   ` [tip:x86/timers] " tip-bot for Ingo Molnar
  2019-06-23 13:24 ` [patch 23/29] x86/hpet: Move clockevents into channels Thomas Gleixner
                   ` (7 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar,
	Ingo Molnar

From: Ingo Molnar <mingo@kernel.org>

struct hpet_dev is gone with the next change as the clockevent storage
moves into struct hpet_channel. So the variable name hdev will not make
sense anymore. Ditto for timer vs. channel and similar details.

Doing the rename in the change makes the patch harder to review. Doing it
afterward is problematic vs. tracking down issues.  Doing it upfront is the
easiest solution as it does not change functionality.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |  124 ++++++++++++++++++++++++-------------------------
 1 file changed, 62 insertions(+), 62 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -315,7 +315,7 @@ static void hpet_legacy_clockevent_regis
 	pr_debug("Clockevent registered\n");
 }
 
-static int hpet_set_periodic(struct clock_event_device *evt, int timer)
+static int hpet_set_periodic(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg, cmp, now;
 	uint64_t delta;
@@ -325,11 +325,11 @@ static int hpet_set_periodic(struct cloc
 	delta >>= evt->shift;
 	now = hpet_readl(HPET_COUNTER);
 	cmp = now + (unsigned int)delta;
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
 	       HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
-	hpet_writel(cmp, HPET_Tn_CMP(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
+	hpet_writel(cmp, HPET_Tn_CMP(channel));
 	udelay(1);
 	/*
 	 * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
@@ -338,32 +338,32 @@ static int hpet_set_periodic(struct cloc
 	 * (See AMD-8111 HyperTransport I/O Hub Data Sheet,
 	 * Publication # 24674)
 	 */
-	hpet_writel((unsigned int)delta, HPET_Tn_CMP(timer));
+	hpet_writel((unsigned int)delta, HPET_Tn_CMP(channel));
 	hpet_start_counter();
 	hpet_print_config();
 
 	return 0;
 }
 
-static int hpet_set_oneshot(struct clock_event_device *evt, int timer)
+static int hpet_set_oneshot(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg;
 
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg &= ~HPET_TN_PERIODIC;
 	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
 
 	return 0;
 }
 
-static int hpet_shutdown(struct clock_event_device *evt, int timer)
+static int hpet_shutdown(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg;
 
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg &= ~HPET_TN_ENABLE;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
 
 	return 0;
 }
@@ -460,30 +460,30 @@ static struct clock_event_device hpet_cl
 
 void hpet_msi_unmask(struct irq_data *data)
 {
-	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);
+	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
 	/* unmask it */
-	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
+	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
-	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
+	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
 void hpet_msi_mask(struct irq_data *data)
 {
-	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);
+	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
 	/* mask it */
-	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
+	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
-	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
+	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
-void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_dev *hc, struct msi_msg *msg)
 {
-	hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
-	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
+	hpet_writel(msg->data, HPET_Tn_ROUTE(hc->num));
+	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
 }
 
 static int hpet_msi_shutdown(struct clock_event_device *evt)
@@ -503,13 +503,13 @@ static int hpet_msi_set_periodic(struct
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = clockevent_to_channel(evt);
-	struct irq_data *data = irq_get_irq_data(hdev->irq);
+	struct hpet_dev *hc = clockevent_to_channel(evt);
+	struct irq_data *data = irq_get_irq_data(hc->irq);
 	struct msi_msg msg;
 
 	/* Restore the MSI msg and unmask the interrupt */
 	irq_chip_compose_msi_msg(data, &msg);
-	hpet_msi_write(hdev, &msg);
+	hpet_msi_write(hc, &msg);
 	hpet_msi_unmask(data);
 	return 0;
 }
@@ -522,11 +522,11 @@ static int hpet_msi_next_event(unsigned
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *dev = data;
-	struct clock_event_device *evt = &dev->evt;
+	struct hpet_dev *hc = data;
+	struct clock_event_device *evt = &hc->evt;
 
 	if (!evt->event_handler) {
-		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
+		pr_info("Spurious interrupt HPET channel %d\n", hc->num);
 		return IRQ_HANDLED;
 	}
 
@@ -551,22 +551,22 @@ static int hpet_setup_irq(struct hpet_de
 	return 0;
 }
 
-static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
+static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
 {
-	struct clock_event_device *evt = &hdev->evt;
+	struct clock_event_device *evt = &hc->evt;
 
-	if (!(hdev->flags & HPET_DEV_VALID))
+	if (!(hc->flags & HPET_DEV_VALID))
 		return;
 
-	hdev->cpu = cpu;
-	per_cpu(cpu_hpet_dev, cpu) = hdev;
-	evt->name = hdev->name;
-	hpet_setup_irq(hdev);
-	evt->irq = hdev->irq;
+	hc->cpu = cpu;
+	per_cpu(cpu_hpet_dev, cpu) = hc;
+	evt->name = hc->name;
+	hpet_setup_irq(hc);
+	evt->irq = hc->irq;
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hdev->flags & HPET_DEV_PERI_CAP) {
+	if (hc->flags & HPET_DEV_PERI_CAP) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
 		evt->set_state_periodic = hpet_msi_set_periodic;
 	}
@@ -575,7 +575,7 @@ static void init_one_hpet_msi_clockevent
 	evt->set_state_oneshot = hpet_msi_set_oneshot;
 	evt->tick_resume = hpet_msi_resume;
 	evt->set_next_event = hpet_msi_next_event;
-	evt->cpumask = cpumask_of(hdev->cpu);
+	evt->cpumask = cpumask_of(hc->cpu);
 
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
 					0x7FFFFFFF);
@@ -589,35 +589,35 @@ static struct hpet_dev *hpet_get_unused_
 		return NULL;
 
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
+		struct hpet_dev *hc = &hpet_devs[i];
 
-		if (!(hdev->flags & HPET_DEV_VALID))
+		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
 		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hdev->flags))
+			(unsigned long *)&hc->flags))
 			continue;
-		return hdev;
+		return hc;
 	}
 	return NULL;
 }
 
 static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hdev = hpet_get_unused_timer();
+	struct hpet_dev *hc = hpet_get_unused_timer();
 
-	if (hdev)
-		init_one_hpet_msi_clockevent(hdev, cpu);
+	if (hc)
+		init_one_hpet_msi_clockevent(hc, cpu);
 	return 0;
 }
 
 static int hpet_cpuhp_dead(unsigned int cpu)
 {
-	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
+	struct hpet_dev *hc = per_cpu(cpu_hpet_dev, cpu);
 
-	if (!hdev)
+	if (!hc)
 		return 0;
-	free_irq(hdev->irq, hdev);
-	hdev->flags &= ~HPET_DEV_USED;
+	free_irq(hc->irq, hc);
+	hc->flags &= ~HPET_DEV_USED;
 	per_cpu(cpu_hpet_dev, cpu) = NULL;
 	return 0;
 }
@@ -653,26 +653,26 @@ static void __init hpet_msi_capability_l
 		return;
 
 	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
-		struct hpet_dev *hdev = &hpet_devs[num_timers_used];
+		struct hpet_dev *hc = &hpet_devs[num_timers_used];
 		unsigned int cfg = hpet_base.channels[i].boot_cfg;
 
 		/* Only consider HPET timer with MSI support */
 		if (!(cfg & HPET_TN_FSB_CAP))
 			continue;
 
-		hdev->flags = 0;
+		hc->flags = 0;
 		if (cfg & HPET_TN_PERIODIC_CAP)
-			hdev->flags |= HPET_DEV_PERI_CAP;
-		sprintf(hdev->name, "hpet%d", i);
-		hdev->num = i;
+			hc->flags |= HPET_DEV_PERI_CAP;
+		sprintf(hc->name, "hpet%d", i);
+		hc->num = i;
 
-		irq = hpet_assign_irq(hpet_domain, hdev, hdev->num);
+		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
 		if (irq <= 0)
 			continue;
 
-		hdev->irq = irq;
-		hdev->flags |= HPET_DEV_FSB_CAP;
-		hdev->flags |= HPET_DEV_VALID;
+		hc->irq = irq;
+		hc->flags |= HPET_DEV_FSB_CAP;
+		hc->flags |= HPET_DEV_VALID;
 		num_timers_used++;
 		if (num_timers_used == num_possible_cpus())
 			break;
@@ -691,13 +691,13 @@ static void __init hpet_reserve_msi_time
 		return;
 
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
+		struct hpet_dev *hc = &hpet_devs[i];
 
-		if (!(hdev->flags & HPET_DEV_VALID))
+		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
 
-		hd->hd_irq[hdev->num] = hdev->irq;
-		hpet_reserve_timer(hd, hdev->num);
+		hd->hd_irq[hc->num] = hc->irq;
+		hpet_reserve_timer(hd, hc->num);
 	}
 }
 #endif
@@ -1138,8 +1138,8 @@ void hpet_unregister_irq_handler(rtc_irq
 EXPORT_SYMBOL_GPL(hpet_unregister_irq_handler);
 
 /*
- * Timer 1 for RTC emulation. We use one shot mode, as periodic mode
- * is not supported by all HPET implementations for timer 1.
+ * Channel 1 for RTC emulation. We use one shot mode, as periodic mode
+ * is not supported by all HPET implementations for channel 1.
  *
  * hpet_rtc_timer_init() is called when the rtc is initialized.
  */



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 23/29] x86/hpet: Move clockevents into channels
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (21 preceding siblings ...)
  2019-06-23 13:24 ` [patch 22/29] x86/hpet: Rename variables to prepare for switching to channels Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:49   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 24/29] x86/hpet: Use cached info instead of extra flags Thomas Gleixner
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Instead of allocating yet another data structure, move the clock event data
into the channel structure. This allows further consolidation of the
reservation code and the reuse of the cached boot config to replace the
extra flags in the clockevent data.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/hpet.h |    6 -
 arch/x86/kernel/apic/msi.c  |    4 -
 arch/x86/kernel/hpet.c      |  139 ++++++++++++++++++--------------------------
 3 files changed, 64 insertions(+), 85 deletions(-)

--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -75,15 +75,15 @@ extern unsigned int hpet_readl(unsigned
 extern void force_hpet_resume(void);
 
 struct irq_data;
-struct hpet_dev;
+struct hpet_channel;
 struct irq_domain;
 
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
-extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
+extern void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg);
 extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
-			   struct hpet_dev *dev, int dev_num);
+			   struct hpet_channel *hc, int dev_num);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -373,14 +373,14 @@ struct irq_domain *hpet_create_irq_domai
 	return d;
 }
 
-int hpet_assign_irq(struct irq_domain *domain, struct hpet_dev *dev,
+int hpet_assign_irq(struct irq_domain *domain, struct hpet_channel *hc,
 		    int dev_num)
 {
 	struct irq_alloc_info info;
 
 	init_irq_alloc_info(&info, NULL);
 	info.type = X86_IRQ_ALLOC_TYPE_HPET;
-	info.hpet_data = dev;
+	info.hpet_data = hc;
 	info.hpet_id = hpet_dev_id(domain);
 	info.hpet_index = dev_num;
 
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -13,15 +13,6 @@
 #undef  pr_fmt
 #define pr_fmt(fmt) "hpet: " fmt
 
-struct hpet_dev {
-	struct clock_event_device	evt;
-	unsigned int			num;
-	int				cpu;
-	unsigned int			irq;
-	unsigned int			flags;
-	char				name[10];
-};
-
 enum hpet_mode {
 	HPET_MODE_UNUSED,
 	HPET_MODE_LEGACY,
@@ -30,14 +21,19 @@ enum hpet_mode {
 };
 
 struct hpet_channel {
+	struct clock_event_device	evt;
 	unsigned int			num;
+	unsigned int			cpu;
 	unsigned int			irq;
 	enum hpet_mode			mode;
+	unsigned int			flags;
 	unsigned int			boot_cfg;
+	char				name[10];
 };
 
 struct hpet_base {
 	unsigned int			nr_channels;
+	unsigned int			nr_clockevents;
 	unsigned int			boot_cfg;
 	struct hpet_channel		*channels;
 };
@@ -61,8 +57,7 @@ u8					hpet_blockid; /* OS timer block n
 bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
-static struct hpet_dev			*hpet_devs;
-static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
+static DEFINE_PER_CPU(struct hpet_channel *, cpu_hpet_channel);
 static struct irq_domain		*hpet_domain;
 #endif
 
@@ -79,9 +74,9 @@ static bool				hpet_verbose;
 static struct clock_event_device	hpet_clockevent;
 
 static inline
-struct hpet_dev *clockevent_to_channel(struct clock_event_device *evt)
+struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
 {
-	return container_of(evt, struct hpet_dev, evt);
+	return container_of(evt, struct hpet_channel, evt);
 }
 
 inline unsigned int hpet_readl(unsigned int a)
@@ -460,10 +455,9 @@ static struct clock_event_device hpet_cl
 
 void hpet_msi_unmask(struct irq_data *data)
 {
-	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
+	struct hpet_channel *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
-	/* unmask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
 	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
@@ -471,16 +465,15 @@ void hpet_msi_unmask(struct irq_data *da
 
 void hpet_msi_mask(struct irq_data *data)
 {
-	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
+	struct hpet_channel *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
-	/* mask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
 	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
-void hpet_msi_write(struct hpet_dev *hc, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg)
 {
 	hpet_writel(msg->data, HPET_Tn_ROUTE(hc->num));
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
@@ -503,7 +496,7 @@ static int hpet_msi_set_periodic(struct
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hc = clockevent_to_channel(evt);
+	struct hpet_channel *hc = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hc->irq);
 	struct msi_msg msg;
 
@@ -522,7 +515,7 @@ static int hpet_msi_next_event(unsigned
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *hc = data;
+	struct hpet_channel *hc = data;
 	struct clock_event_device *evt = &hc->evt;
 
 	if (!evt->event_handler) {
@@ -534,24 +527,23 @@ static irqreturn_t hpet_interrupt_handle
 	return IRQ_HANDLED;
 }
 
-static int hpet_setup_irq(struct hpet_dev *dev)
+static int hpet_setup_irq(struct hpet_channel *hc)
 {
-
-	if (request_irq(dev->irq, hpet_interrupt_handler,
+	if (request_irq(hc->irq, hpet_interrupt_handler,
 			IRQF_TIMER | IRQF_NOBALANCING,
-			dev->name, dev))
+			hc->name, hc))
 		return -1;
 
-	disable_irq(dev->irq);
-	irq_set_affinity(dev->irq, cpumask_of(dev->cpu));
-	enable_irq(dev->irq);
+	disable_irq(hc->irq);
+	irq_set_affinity(hc->irq, cpumask_of(hc->cpu));
+	enable_irq(hc->irq);
 
-	pr_debug("%s irq %d for MSI\n", dev->name, dev->irq);
+	pr_debug("%s irq %u for MSI\n", hc->name, hc->irq);
 
 	return 0;
 }
 
-static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
+static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 {
 	struct clock_event_device *evt = &hc->evt;
 
@@ -559,7 +551,7 @@ static void init_one_hpet_msi_clockevent
 		return;
 
 	hc->cpu = cpu;
-	per_cpu(cpu_hpet_dev, cpu) = hc;
+	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
 	hpet_setup_irq(hc);
 	evt->irq = hc->irq;
@@ -581,15 +573,12 @@ static void init_one_hpet_msi_clockevent
 					0x7FFFFFFF);
 }
 
-static struct hpet_dev *hpet_get_unused_timer(void)
+static struct hpet_channel *hpet_get_unused_clockevent(void)
 {
 	int i;
 
-	if (!hpet_devs)
-		return NULL;
-
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hc = &hpet_devs[i];
+		struct hpet_channel *hc = hpet_base.channels + i;
 
 		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
@@ -603,7 +592,7 @@ static struct hpet_dev *hpet_get_unused_
 
 static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hc = hpet_get_unused_timer();
+	struct hpet_channel *hc = hpet_get_unused_clockevent();
 
 	if (hc)
 		init_one_hpet_msi_clockevent(hc, cpu);
@@ -612,59 +601,47 @@ static int hpet_cpuhp_online(unsigned in
 
 static int hpet_cpuhp_dead(unsigned int cpu)
 {
-	struct hpet_dev *hc = per_cpu(cpu_hpet_dev, cpu);
+	struct hpet_channel *hc = per_cpu(cpu_hpet_channel, cpu);
 
 	if (!hc)
 		return 0;
 	free_irq(hc->irq, hc);
 	hc->flags &= ~HPET_DEV_USED;
-	per_cpu(cpu_hpet_dev, cpu) = NULL;
+	per_cpu(cpu_hpet_channel, cpu) = NULL;
 	return 0;
 }
 
-#ifdef CONFIG_HPET
-/* Reserve at least one timer for userspace (/dev/hpet) */
-#define RESERVE_TIMERS 1
-#else
-#define RESERVE_TIMERS 0
-#endif
-
-static void __init hpet_msi_capability_lookup(unsigned int start_timer)
+static void __init hpet_select_clockevents(void)
 {
-	unsigned int num_timers;
-	unsigned int num_timers_used = 0;
-	int i, irq;
+	unsigned int i;
 
-	if (hpet_msi_disable)
-		return;
+	hpet_base.nr_clockevents = 0;
 
-	if (boot_cpu_has(X86_FEATURE_ARAT))
+	/* No point if MSI is disabled or CPU has an Always Runing APIC Timer */
+	if (hpet_msi_disable || boot_cpu_has(X86_FEATURE_ARAT))
 		return;
 
-	num_timers = hpet_base.nr_channels;
 	hpet_print_config();
 
 	hpet_domain = hpet_create_irq_domain(hpet_blockid);
 	if (!hpet_domain)
 		return;
 
-	hpet_devs = kcalloc(num_timers, sizeof(struct hpet_dev), GFP_KERNEL);
-	if (!hpet_devs)
-		return;
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
+		int irq;
 
-	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
-		struct hpet_dev *hc = &hpet_devs[num_timers_used];
-		unsigned int cfg = hpet_base.channels[i].boot_cfg;
+		if (hc->mode != HPET_MODE_UNUSED)
+			continue;
 
-		/* Only consider HPET timer with MSI support */
-		if (!(cfg & HPET_TN_FSB_CAP))
+		/* Only consider HPET channel with MSI support */
+		if (!(hc->boot_cfg & HPET_TN_FSB_CAP))
 			continue;
 
 		hc->flags = 0;
-		if (cfg & HPET_TN_PERIODIC_CAP)
+		if (hc->boot_cfg & HPET_TN_PERIODIC_CAP)
 			hc->flags |= HPET_DEV_PERI_CAP;
 		sprintf(hc->name, "hpet%d", i);
-		hc->num = i;
 
 		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
 		if (irq <= 0)
@@ -673,13 +650,14 @@ static void __init hpet_msi_capability_l
 		hc->irq = irq;
 		hc->flags |= HPET_DEV_FSB_CAP;
 		hc->flags |= HPET_DEV_VALID;
-		num_timers_used++;
-		if (num_timers_used == num_possible_cpus())
+		hc->mode = HPET_MODE_CLOCKEVT;
+
+		if (++hpet_base.nr_clockevents == num_possible_cpus())
 			break;
 	}
 
 	pr_info("%d channels of %d reserved for per-cpu timers\n",
-		num_timers, num_timers_used);
+		hpet_base.nr_channels, hpet_base.nr_clockevents);
 }
 
 #ifdef CONFIG_HPET
@@ -687,11 +665,8 @@ static void __init hpet_reserve_msi_time
 {
 	int i;
 
-	if (!hpet_devs)
-		return;
-
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hc = &hpet_devs[i];
+		struct hpet_channel *hc = hpet_base.channels + i;
 
 		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
@@ -704,7 +679,7 @@ static void __init hpet_reserve_msi_time
 
 #else
 
-static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }
+static inline void hpet_select_clockevents(void) { }
 
 #ifdef CONFIG_HPET
 static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
@@ -991,6 +966,16 @@ int __init hpet_enable(void)
 /*
  * The late initialization runs after the PCI quirks have been invoked
  * which might have detected a system on which the HPET can be enforced.
+ *
+ * Also, the MSI machinery is not working yet when the HPET is initialized
+ * early.
+ *
+ * If the HPET is enabled, then:
+ *
+ *  1) Reserve one channel for /dev/hpet if CONFIG_HPET=y
+ *  2) Reserve up to num_possible_cpus() channels as per CPU clockevents
+ *  3) Setup /dev/hpet if CONFIG_HPET=y
+ *  4) Register hotplug callbacks when clockevents are available
  */
 static __init int hpet_late_init(void)
 {
@@ -1007,18 +992,12 @@ static __init int hpet_late_init(void)
 	if (!hpet_virt_address)
 		return -ENODEV;
 
-	if (hpet_readl(HPET_ID) & HPET_ID_LEGSUP)
-		hpet_msi_capability_lookup(2);
-	else
-		hpet_msi_capability_lookup(0);
-
+	hpet_select_device_channel();
+	hpet_select_clockevents();
 	hpet_reserve_platform_timers();
 	hpet_print_config();
 
-	if (hpet_msi_disable)
-		return 0;
-
-	if (boot_cpu_has(X86_FEATURE_ARAT))
+	if (!hpet_base.nr_clockevents)
 		return 0;
 
 	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "x86/hpet:online",



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 24/29] x86/hpet: Use cached info instead of extra flags
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (22 preceding siblings ...)
  2019-06-23 13:24 ` [patch 23/29] x86/hpet: Move clockevents into channels Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-26 21:20   ` Ingo Molnar
  2019-06-27 23:50   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 25/29] x86/hpet: Wrap legacy clockevent in hpet_channel Thomas Gleixner
                   ` (5 subsequent siblings)
  29 siblings, 2 replies; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Now that HPET clockevent support is integrated into the channel data, reuse
the cached boot configuration instead of copying the same information into
a flags field.

This also allows to consolidate the reservation code into one place, which
can now solely depend on the mode information.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   76 ++++++++++++++-----------------------------------
 1 file changed, 23 insertions(+), 53 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -25,8 +25,8 @@ struct hpet_channel {
 	unsigned int			num;
 	unsigned int			cpu;
 	unsigned int			irq;
+	unsigned int			inuse;
 	enum hpet_mode			mode;
-	unsigned int			flags;
 	unsigned int			boot_cfg;
 	char				name[10];
 };
@@ -40,12 +40,6 @@ struct hpet_base {
 
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
-#define HPET_DEV_USED_BIT		2
-#define HPET_DEV_USED			(1 << HPET_DEV_USED_BIT)
-#define HPET_DEV_VALID			0x8
-#define HPET_DEV_FSB_CAP		0x1000
-#define HPET_DEV_PERI_CAP		0x2000
-
 #define HPET_MIN_CYCLES			128
 #define HPET_MIN_PROG_DELTA		(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
 
@@ -62,6 +56,7 @@ static struct irq_domain		*hpet_domain;
 #endif
 
 static void __iomem			*hpet_virt_address;
+
 static struct hpet_base			hpet_base;
 
 static bool				hpet_legacy_int_enabled;
@@ -190,8 +185,6 @@ do {								\
  */
 #ifdef CONFIG_HPET
 
-static void hpet_reserve_msi_timers(struct hpet_data *hd);
-
 static void __init hpet_reserve_platform_timers(void)
 {
 	struct hpet_data hd;
@@ -201,11 +194,6 @@ static void __init hpet_reserve_platform
 	hd.hd_phys_address	= hpet_address;
 	hd.hd_address		= hpet_virt_address;
 	hd.hd_nirqs		= hpet_base.nr_channels;
-	hpet_reserve_timer(&hd, 0);
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-	hpet_reserve_timer(&hd, 1);
-#endif
 
 	/*
 	 * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254
@@ -215,13 +203,25 @@ static void __init hpet_reserve_platform
 	hd.hd_irq[0] = HPET_LEGACY_8254;
 	hd.hd_irq[1] = HPET_LEGACY_RTC;
 
-	for (i = 2; i < hpet_base.nr_channels; i++)
-		hd.hd_irq[i] = hpet_base.channels[i].irq;
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
 
-	hpet_reserve_msi_timers(&hd);
+		if (i >= 2)
+			hd.hd_irq[i] = hc->irq;
 
-	hpet_alloc(&hd);
+		switch (hc->mode) {
+		case HPET_MODE_UNUSED:
+		case HPET_MODE_DEVICE:
+			hc->mode = HPET_MODE_DEVICE;
+			break;
+		case HPET_MODE_CLOCKEVT:
+		case HPET_MODE_LEGACY:
+			hpet_reserve_timer(&hd, hc->num);
+			break;
+		}
+	}
 
+	hpet_alloc(&hd);
 }
 
 static void __init hpet_select_device_channel(void)
@@ -543,13 +543,11 @@ static int hpet_setup_irq(struct hpet_ch
 	return 0;
 }
 
+/* Invoked from the hotplug callback on @cpu */
 static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 {
 	struct clock_event_device *evt = &hc->evt;
 
-	if (!(hc->flags & HPET_DEV_VALID))
-		return;
-
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
@@ -558,7 +556,7 @@ static void init_one_hpet_msi_clockevent
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hc->flags & HPET_DEV_PERI_CAP) {
+	if (hc->boot_cfg & HPET_TN_PERIODIC) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
 		evt->set_state_periodic = hpet_msi_set_periodic;
 	}
@@ -580,11 +578,9 @@ static struct hpet_channel *hpet_get_unu
 	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_channel *hc = hpet_base.channels + i;
 
-		if (!(hc->flags & HPET_DEV_VALID))
-			continue;
-		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hc->flags))
+		if (hc->mode != HPET_MODE_CLOCKEVT || hc->inuse)
 			continue;
+		hc->inuse = 1;
 		return hc;
 	}
 	return NULL;
@@ -606,7 +602,7 @@ static int hpet_cpuhp_dead(unsigned int
 	if (!hc)
 		return 0;
 	free_irq(hc->irq, hc);
-	hc->flags &= ~HPET_DEV_USED;
+	hc->inuse = 0;
 	per_cpu(cpu_hpet_channel, cpu) = NULL;
 	return 0;
 }
@@ -638,9 +634,6 @@ static void __init hpet_select_clockeven
 		if (!(hc->boot_cfg & HPET_TN_FSB_CAP))
 			continue;
 
-		hc->flags = 0;
-		if (hc->boot_cfg & HPET_TN_PERIODIC_CAP)
-			hc->flags |= HPET_DEV_PERI_CAP;
 		sprintf(hc->name, "hpet%d", i);
 
 		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
@@ -648,8 +641,6 @@ static void __init hpet_select_clockeven
 			continue;
 
 		hc->irq = irq;
-		hc->flags |= HPET_DEV_FSB_CAP;
-		hc->flags |= HPET_DEV_VALID;
 		hc->mode = HPET_MODE_CLOCKEVT;
 
 		if (++hpet_base.nr_clockevents == num_possible_cpus())
@@ -660,31 +651,10 @@ static void __init hpet_select_clockeven
 		hpet_base.nr_channels, hpet_base.nr_clockevents);
 }
 
-#ifdef CONFIG_HPET
-static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
-{
-	int i;
-
-	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_channel *hc = hpet_base.channels + i;
-
-		if (!(hc->flags & HPET_DEV_VALID))
-			continue;
-
-		hd->hd_irq[hc->num] = hc->irq;
-		hpet_reserve_timer(hd, hc->num);
-	}
-}
-#endif
-
 #else
 
 static inline void hpet_select_clockevents(void) { }
 
-#ifdef CONFIG_HPET
-static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
-#endif
-
 #define hpet_cpuhp_online	NULL
 #define hpet_cpuhp_dead		NULL
 



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 25/29] x86/hpet: Wrap legacy clockevent in hpet_channel
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (23 preceding siblings ...)
  2019-06-23 13:24 ` [patch 24/29] x86/hpet: Use cached info instead of extra flags Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:51   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 26/29] x86/hpet: Consolidate clockevent functions Thomas Gleixner
                   ` (4 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

For HPET channel 0 there exist two clockevent structures right now:
  - the static hpet_clockevent
  - the clockevent in channel 0 storage

The goal is to use the clockevent in the channel storage, remove the static
variable and share code with the MSI implementation.

As a first step wrap the legacy clockevent into a hpet_channel struct and
convert the users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   49 +++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 22 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,7 +66,7 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
-static struct clock_event_device	hpet_clockevent;
+static struct hpet_channel		hpet_channel0;
 
 static inline
 struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
@@ -294,7 +294,7 @@ static void hpet_enable_legacy_int(void)
 	hpet_legacy_int_enabled = true;
 }
 
-static void hpet_legacy_clockevent_register(void)
+static void hpet_legacy_clockevent_register(struct hpet_channel *hc)
 {
 	/* Start HPET legacy interrupts */
 	hpet_enable_legacy_int();
@@ -303,10 +303,10 @@ static void hpet_legacy_clockevent_regis
 	 * Start HPET with the boot CPU's cpumask and make it global after
 	 * the IO_APIC has been initialized.
 	 */
-	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
-	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
+	hc->evt.cpumask = cpumask_of(boot_cpu_data.cpu_index);
+	clockevents_config_and_register(&hc->evt, hpet_freq,
 					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
-	global_clock_event = &hpet_clockevent;
+	global_clock_event = &hc->evt;
 	pr_debug("Clockevent registered\n");
 }
 
@@ -433,19 +433,21 @@ static int hpet_legacy_next_event(unsign
 }
 
 /*
- * The HPET clock event device
+ * The HPET clock event device wrapped in a channel for conversion
  */
-static struct clock_event_device hpet_clockevent = {
-	.name			= "hpet",
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.set_state_periodic	= hpet_legacy_set_periodic,
-	.set_state_oneshot	= hpet_legacy_set_oneshot,
-	.set_state_shutdown	= hpet_legacy_shutdown,
-	.tick_resume		= hpet_legacy_resume,
-	.set_next_event		= hpet_legacy_next_event,
-	.irq			= 0,
-	.rating			= 50,
+static struct hpet_channel hpet_channel0 = {
+	.evt = {
+		.name			= "hpet",
+		.features		= CLOCK_EVT_FEAT_PERIODIC |
+					  CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_periodic	= hpet_legacy_set_periodic,
+		.set_state_oneshot	= hpet_legacy_set_oneshot,
+		.set_state_shutdown	= hpet_legacy_shutdown,
+		.tick_resume		= hpet_legacy_resume,
+		.set_next_event		= hpet_legacy_next_event,
+		.irq			= 0,
+		.rating			= 50,
+	}
 };
 
 /*
@@ -916,7 +918,7 @@ int __init hpet_enable(void)
 	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
-		hpet_legacy_clockevent_register();
+		hpet_legacy_clockevent_register(&hpet_channel0);
 		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
 		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
 			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
@@ -1101,10 +1103,11 @@ int hpet_rtc_timer_init(void)
 		return 0;
 
 	if (!hpet_default_delta) {
+		struct clock_event_device *evt = &hpet_channel0.evt;
 		uint64_t clc;
 
-		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
-		clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT;
+		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
+		clc >>= evt->shift + DEFAULT_RTC_SHIFT;
 		hpet_default_delta = clc;
 	}
 
@@ -1198,9 +1201,11 @@ int hpet_set_periodic_freq(unsigned long
 	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
 	} else {
-		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+		struct clock_event_device *evt = &hpet_channel0.evt;
+
+		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
 		do_div(clc, freq);
-		clc >>= hpet_clockevent.shift;
+		clc >>= evt->shift;
 		hpet_pie_delta = clc;
 		hpet_pie_limit = 0;
 	}



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 26/29] x86/hpet: Consolidate clockevent functions
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (24 preceding siblings ...)
  2019-06-23 13:24 ` [patch 25/29] x86/hpet: Wrap legacy clockevent in hpet_channel Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-26 21:17   ` Ingo Molnar
  2019-06-27 23:51   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 27/29] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent() Thomas Gleixner
                   ` (3 subsequent siblings)
  29 siblings, 2 replies; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Now that the legacy clockevent is wrapped in a hpet_channel struct most
clockevent functions can be shared between the legacy and the MSI based
clockevents.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   92 +++++++++++++------------------------------------
 1 file changed, 25 insertions(+), 67 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -310,8 +310,9 @@ static void hpet_legacy_clockevent_regis
 	pr_debug("Clockevent registered\n");
 }
 
-static int hpet_set_periodic(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_set_periodic(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg, cmp, now;
 	uint64_t delta;
 
@@ -340,8 +341,9 @@ static int hpet_set_periodic(struct cloc
 	return 0;
 }
 
-static int hpet_set_oneshot(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_set_oneshot(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg;
 
 	cfg = hpet_readl(HPET_Tn_CFG(channel));
@@ -352,8 +354,9 @@ static int hpet_set_oneshot(struct clock
 	return 0;
 }
 
-static int hpet_shutdown(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_shutdown(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg;
 
 	cfg = hpet_readl(HPET_Tn_CFG(channel));
@@ -363,15 +366,17 @@ static int hpet_shutdown(struct clock_ev
 	return 0;
 }
 
-static int hpet_resume(struct clock_event_device *evt)
+static int hpet_clkevt_legacy_resume(struct clock_event_device *evt)
 {
 	hpet_enable_legacy_int();
 	hpet_print_config();
 	return 0;
 }
 
-static int hpet_next_event(unsigned long delta, int channel)
+static int
+hpet_clkevt_set_next_event(unsigned long delta, struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	u32 cnt;
 	s32 res;
 
@@ -406,32 +411,6 @@ static int hpet_next_event(unsigned long
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
-static int hpet_legacy_shutdown(struct clock_event_device *evt)
-{
-	return hpet_shutdown(evt, 0);
-}
-
-static int hpet_legacy_set_oneshot(struct clock_event_device *evt)
-{
-	return hpet_set_oneshot(evt, 0);
-}
-
-static int hpet_legacy_set_periodic(struct clock_event_device *evt)
-{
-	return hpet_set_periodic(evt, 0);
-}
-
-static int hpet_legacy_resume(struct clock_event_device *evt)
-{
-	return hpet_resume(evt);
-}
-
-static int hpet_legacy_next_event(unsigned long delta,
-				  struct clock_event_device *evt)
-{
-	return hpet_next_event(delta, 0);
-}
-
 /*
  * The HPET clock event device wrapped in a channel for conversion
  */
@@ -440,11 +419,11 @@ static struct hpet_channel hpet_channel0
 		.name			= "hpet",
 		.features		= CLOCK_EVT_FEAT_PERIODIC |
 					  CLOCK_EVT_FEAT_ONESHOT,
-		.set_state_periodic	= hpet_legacy_set_periodic,
-		.set_state_oneshot	= hpet_legacy_set_oneshot,
-		.set_state_shutdown	= hpet_legacy_shutdown,
-		.tick_resume		= hpet_legacy_resume,
-		.set_next_event		= hpet_legacy_next_event,
+		.set_state_periodic	= hpet_clkevt_set_periodic,
+		.set_state_oneshot	= hpet_clkevt_set_oneshot,
+		.set_state_shutdown	= hpet_clkevt_shutdown,
+		.tick_resume		= hpet_clkevt_legacy_resume,
+		.set_next_event		= hpet_clkevt_set_next_event,
 		.irq			= 0,
 		.rating			= 50,
 	}
@@ -481,22 +460,7 @@ void hpet_msi_write(struct hpet_channel
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
 }
 
-static int hpet_msi_shutdown(struct clock_event_device *evt)
-{
-	return hpet_shutdown(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_set_oneshot(struct clock_event_device *evt)
-{
-	return hpet_set_oneshot(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_set_periodic(struct clock_event_device *evt)
-{
-	return hpet_set_periodic(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_resume(struct clock_event_device *evt)
+static int hpet_clkevt_msi_resume(struct clock_event_device *evt)
 {
 	struct hpet_channel *hc = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hc->irq);
@@ -509,13 +473,7 @@ static int hpet_msi_resume(struct clock_
 	return 0;
 }
 
-static int hpet_msi_next_event(unsigned long delta,
-			       struct clock_event_device *evt)
-{
-	return hpet_next_event(delta, clockevent_to_channel(evt)->num);
-}
-
-static irqreturn_t hpet_interrupt_handler(int irq, void *data)
+static irqreturn_t hpet_msi_interrupt_handler(int irq, void *data)
 {
 	struct hpet_channel *hc = data;
 	struct clock_event_device *evt = &hc->evt;
@@ -529,9 +487,9 @@ static irqreturn_t hpet_interrupt_handle
 	return IRQ_HANDLED;
 }
 
-static int hpet_setup_irq(struct hpet_channel *hc)
+static int hpet_setup_msi_irq(struct hpet_channel *hc)
 {
-	if (request_irq(hc->irq, hpet_interrupt_handler,
+	if (request_irq(hc->irq, hpet_msi_interrupt_handler,
 			IRQF_TIMER | IRQF_NOBALANCING,
 			hc->name, hc))
 		return -1;
@@ -553,20 +511,20 @@ static void init_one_hpet_msi_clockevent
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
-	hpet_setup_irq(hc);
+	hpet_setup_msi_irq(hc);
 	evt->irq = hc->irq;
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
 	if (hc->boot_cfg & HPET_TN_PERIODIC) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
-		evt->set_state_periodic = hpet_msi_set_periodic;
+		evt->set_state_periodic = hpet_clkevt_set_periodic;
 	}
 
-	evt->set_state_shutdown = hpet_msi_shutdown;
-	evt->set_state_oneshot = hpet_msi_set_oneshot;
-	evt->tick_resume = hpet_msi_resume;
-	evt->set_next_event = hpet_msi_next_event;
+	evt->set_state_shutdown = hpet_clkevt_shutdown;
+	evt->set_state_oneshot = hpet_clkevt_set_oneshot;
+	evt->set_next_event = hpet_clkevt_set_next_event;
+	evt->tick_resume = hpet_clkevt_msi_resume;
 	evt->cpumask = cpumask_of(hc->cpu);
 
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 27/29] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent()
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (25 preceding siblings ...)
  2019-06-23 13:24 ` [patch 26/29] x86/hpet: Consolidate clockevent functions Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:52   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 28/29] x86/hpet: Use common init for legacy clockevent Thomas Gleixner
                   ` (2 subsequent siblings)
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

To finally remove the static channel0/clockevent storage and to utilize the
channel 0 storage in hpet_base, it's required to run time initialize the
clockevent. The MSI clockevents already have a run time init function.

Carve out the parts which can be shared between the legacy and the MSI
implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -411,6 +411,25 @@ hpet_clkevt_set_next_event(unsigned long
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
+static void hpet_init_clockevent(struct hpet_channel *hc, unsigned int rating)
+{
+	struct clock_event_device *evt = &hc->evt;
+
+	evt->rating		= rating;
+	evt->irq		= hc->irq;
+	evt->name		= hc->name;
+	evt->cpumask		= cpumask_of(hc->cpu);
+	evt->set_state_oneshot	= hpet_clkevt_set_oneshot;
+	evt->set_next_event	= hpet_clkevt_set_next_event;
+	evt->set_state_shutdown	= hpet_clkevt_shutdown;
+
+	evt->features = CLOCK_EVT_FEAT_ONESHOT;
+	if (hc->boot_cfg & HPET_TN_PERIODIC) {
+		evt->features		|= CLOCK_EVT_FEAT_PERIODIC;
+		evt->set_state_periodic	= hpet_clkevt_set_periodic;
+	}
+}
+
 /*
  * The HPET clock event device wrapped in a channel for conversion
  */
@@ -510,23 +529,10 @@ static void init_one_hpet_msi_clockevent
 
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
-	evt->name = hc->name;
 	hpet_setup_msi_irq(hc);
-	evt->irq = hc->irq;
 
-	evt->rating = 110;
-	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hc->boot_cfg & HPET_TN_PERIODIC) {
-		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
-		evt->set_state_periodic = hpet_clkevt_set_periodic;
-	}
-
-	evt->set_state_shutdown = hpet_clkevt_shutdown;
-	evt->set_state_oneshot = hpet_clkevt_set_oneshot;
-	evt->set_next_event = hpet_clkevt_set_next_event;
+	hpet_init_clockevent(hc, 110);
 	evt->tick_resume = hpet_clkevt_msi_resume;
-	evt->cpumask = cpumask_of(hc->cpu);
-
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
 					0x7FFFFFFF);
 }



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 28/29] x86/hpet: Use common init for legacy clockevent
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (26 preceding siblings ...)
  2019-06-23 13:24 ` [patch 27/29] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent() Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-26 21:13   ` Ingo Molnar
  2019-06-27 23:53   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-23 13:24 ` [patch 29/29] x86/hpet: Use channel for legacy clockevent storage Thomas Gleixner
  2019-06-26 21:22 ` [patch 00/29] x86/hpet: Cleanup the channel management Ingo Molnar
  29 siblings, 2 replies; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

Replace the static initialization of the legacy clockevent with runtime
initialization utilizing the common init function as the last preparatory
step to switch the legacy clockevent over to the channel 0 storage in
hpet_base.

This comes with a twist. The static clockevent initializer has selected
support for periodic and oneshot mode unconditionally whether the HPET
config advertised periodic mode or not. Even the pre clockevents code did
this. But....

Using the conditional in hpet_init_clockevent() makes at least Qemu and one
hardware machine fail to boot.  There are two issues which cause the boot
failure:

 #1 After the timer delivery test in IOAPIC and the IOAPIC setup the next
    interrupt is not delivered despite the HPET channel being programmed
    correctly. Reprogramming the HPET after switching to IOAPIC makes it
    work again. After fixing this, the next issue surfaces:

 #2 Due to the unconditional periodic mode 'availability' the Local APIC
    timer calibration can hijack the global clockevents event handler
    without causing damage. Using oneshot at this stage makes if hang
    because the HPET does not get reprogrammed due to the handler
    hijacking. Duh, stupid me!

Both issues require major surgery and especially the kick HPET again after
enabling IOAPIC results in really nasty hackery.  This 'assume periodic
works' magic has survived since HPET support got added, so it's
questionable whether this should be fixed. Both Qemu and the failing
hardware machine support periodic mode despite the fact that both don't
advertise it in the configuration register and both need that extra kick
after switching to IOAPIC. Seems to be a feature...

Keep the 'assume periodic works' magic around and add a big fat comment.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   87 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 54 insertions(+), 33 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,6 +66,9 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
+/*
+ * The HPET clock event device wrapped in a channel for conversion
+ */
 static struct hpet_channel		hpet_channel0;
 
 static inline
@@ -294,22 +297,6 @@ static void hpet_enable_legacy_int(void)
 	hpet_legacy_int_enabled = true;
 }
 
-static void hpet_legacy_clockevent_register(struct hpet_channel *hc)
-{
-	/* Start HPET legacy interrupts */
-	hpet_enable_legacy_int();
-
-	/*
-	 * Start HPET with the boot CPU's cpumask and make it global after
-	 * the IO_APIC has been initialized.
-	 */
-	hc->evt.cpumask = cpumask_of(boot_cpu_data.cpu_index);
-	clockevents_config_and_register(&hc->evt, hpet_freq,
-					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
-	global_clock_event = &hc->evt;
-	pr_debug("Clockevent registered\n");
-}
-
 static int hpet_clkevt_set_periodic(struct clock_event_device *evt)
 {
 	unsigned int channel = clockevent_to_channel(evt)->num;
@@ -430,23 +417,57 @@ static void hpet_init_clockevent(struct
 	}
 }
 
-/*
- * The HPET clock event device wrapped in a channel for conversion
- */
-static struct hpet_channel hpet_channel0 = {
-	.evt = {
-		.name			= "hpet",
-		.features		= CLOCK_EVT_FEAT_PERIODIC |
-					  CLOCK_EVT_FEAT_ONESHOT,
-		.set_state_periodic	= hpet_clkevt_set_periodic,
-		.set_state_oneshot	= hpet_clkevt_set_oneshot,
-		.set_state_shutdown	= hpet_clkevt_shutdown,
-		.tick_resume		= hpet_clkevt_legacy_resume,
-		.set_next_event		= hpet_clkevt_set_next_event,
-		.irq			= 0,
-		.rating			= 50,
-	}
-};
+static void __init hpet_legacy_clockevent_register(struct hpet_channel *hc)
+{
+	/*
+	 * Start HPET with the boot CPU's cpumask and make it global after
+	 * the IO_APIC has been initialized.
+	 */
+	hc->cpu = boot_cpu_data.cpu_index;
+	strncpy(hc->name, "hpet", sizeof(hc->name));
+	hpet_init_clockevent(hc, 50);
+
+	hc->evt.tick_resume	= hpet_clkevt_legacy_resume;
+
+	/*
+	 * Legacy horrors and sins from the past. HPET used periodic mode
+	 * unconditionally for ever on the legacy channel 0. Removing the
+	 * below hack and using the conditional in hpet_init_clockevent()
+	 * makes at least Qemu and one hardware machine fail to boot.
+	 * There are two issues which cause the boot failure:
+	 *
+	 * #1 After the timer delivery test in IOAPIC and the IOAPIC setup
+	 *    the next interrupt is not delivered despite the HPET channel
+	 *    being programmed correctly. Reprogramming the HPET after
+	 *    switching to IOAPIC makes it work again. After fixing this,
+	 *    the next issue surfaces:
+	 *
+	 * #2 Due to the unconditional periodic mode availability the Local
+	 *    APIC timer calibration can hijack the global clockevents
+	 *    event handler without causing damage. Using oneshot at this
+	 *    stage makes if hang because the HPET does not get
+	 *    reprogrammed due to the handler hijacking. Duh, stupid me!
+	 *
+	 * Both issues require major surgery and especially the kick HPET
+	 * again after enabling IOAPIC results in really nasty hackery.
+	 * This 'assume periodic works' magic has survived since HPET
+	 * support got added, so it's questionable whether this should be
+	 * fixed. Both Qemu and the failing hardware machine support
+	 * periodic mode despite the fact that both don't advertise it in
+	 * the configuration register and both need that extra kick after
+	 * switching to IOAPIC. Seems to be a feature...
+	 */
+	hc->evt.features		|= CLOCK_EVT_FEAT_PERIODIC;
+	hc->evt.set_state_periodic	= hpet_clkevt_set_periodic;
+
+	/* Start HPET legacy interrupts */
+	hpet_enable_legacy_int();
+
+	clockevents_config_and_register(&hc->evt, hpet_freq,
+					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
+	global_clock_event = &hc->evt;
+	pr_debug("Clockevent registered\n");
+}
 
 /*
  * HPET MSI Support



^ permalink raw reply	[flat|nested] 66+ messages in thread

* [patch 29/29] x86/hpet: Use channel for legacy clockevent storage
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (27 preceding siblings ...)
  2019-06-23 13:24 ` [patch 28/29] x86/hpet: Use common init for legacy clockevent Thomas Gleixner
@ 2019-06-23 13:24 ` Thomas Gleixner
  2019-06-27 23:53   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  2019-06-26 21:22 ` [patch 00/29] x86/hpet: Cleanup the channel management Ingo Molnar
  29 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-23 13:24 UTC (permalink / raw)
  To: LKML
  Cc: x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

All preparations are done. Use the channel storage for the legacy
clockevent and remove the static variable.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/kernel/hpet.c |   11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,11 +66,6 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
-/*
- * The HPET clock event device wrapped in a channel for conversion
- */
-static struct hpet_channel		hpet_channel0;
-
 static inline
 struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
 {
@@ -903,7 +898,7 @@ int __init hpet_enable(void)
 	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
-		hpet_legacy_clockevent_register(&hpet_channel0);
+		hpet_legacy_clockevent_register(&hpet_base.channels[0]);
 		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
 		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
 			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
@@ -1088,7 +1083,7 @@ int hpet_rtc_timer_init(void)
 		return 0;
 
 	if (!hpet_default_delta) {
-		struct clock_event_device *evt = &hpet_channel0.evt;
+		struct clock_event_device *evt = &hpet_base.channels[0].evt;
 		uint64_t clc;
 
 		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
@@ -1186,7 +1181,7 @@ int hpet_set_periodic_freq(unsigned long
 	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
 	} else {
-		struct clock_event_device *evt = &hpet_channel0.evt;
+		struct clock_event_device *evt = &hpet_base.channels[0].evt;
 
 		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
 		do_div(clc, freq);



^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 28/29] x86/hpet: Use common init for legacy clockevent
  2019-06-23 13:24 ` [patch 28/29] x86/hpet: Use common init for legacy clockevent Thomas Gleixner
@ 2019-06-26 21:13   ` Ingo Molnar
  2019-06-27 23:53   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 66+ messages in thread
From: Ingo Molnar @ 2019-06-26 21:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar


* Thomas Gleixner <tglx@linutronix.de> wrote:

> +static void __init hpet_legacy_clockevent_register(struct hpet_channel *hc)
> +{
> +	/*
> +	 * Start HPET with the boot CPU's cpumask and make it global after
> +	 * the IO_APIC has been initialized.
> +	 */
> +	hc->cpu = boot_cpu_data.cpu_index;
> +	strncpy(hc->name, "hpet", sizeof(hc->name));
> +	hpet_init_clockevent(hc, 50);
> +
> +	hc->evt.tick_resume	= hpet_clkevt_legacy_resume;
> +
> +	/*
> +	 * Legacy horrors and sins from the past. HPET used periodic mode
> +	 * unconditionally for ever on the legacy channel 0. Removing the

s/for ever
 /forever

With that typo fixed:

Reviewed-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 26/29] x86/hpet: Consolidate clockevent functions
  2019-06-23 13:24 ` [patch 26/29] x86/hpet: Consolidate clockevent functions Thomas Gleixner
@ 2019-06-26 21:17   ` Ingo Molnar
  2019-06-27 22:44     ` Thomas Gleixner
  2019-06-27 23:51   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  1 sibling, 1 reply; 66+ messages in thread
From: Ingo Molnar @ 2019-06-26 21:17 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar


* Thomas Gleixner <tglx@linutronix.de> wrote:

> @@ -440,11 +419,11 @@ static struct hpet_channel hpet_channel0
>  		.name			= "hpet",
>  		.features		= CLOCK_EVT_FEAT_PERIODIC |
>  					  CLOCK_EVT_FEAT_ONESHOT,
> -		.set_state_periodic	= hpet_legacy_set_periodic,
> -		.set_state_oneshot	= hpet_legacy_set_oneshot,
> -		.set_state_shutdown	= hpet_legacy_shutdown,
> -		.tick_resume		= hpet_legacy_resume,
> -		.set_next_event		= hpet_legacy_next_event,
> +		.set_state_periodic	= hpet_clkevt_set_periodic,
> +		.set_state_oneshot	= hpet_clkevt_set_oneshot,
> +		.set_state_shutdown	= hpet_clkevt_shutdown,
> +		.tick_resume		= hpet_clkevt_legacy_resume,
> +		.set_next_event		= hpet_clkevt_set_next_event,
>  		.irq			= 0,
>  		.rating			= 50,

> -	evt->set_state_shutdown = hpet_msi_shutdown;
> -	evt->set_state_oneshot = hpet_msi_set_oneshot;
> -	evt->tick_resume = hpet_msi_resume;
> -	evt->set_next_event = hpet_msi_next_event;
> +	evt->set_state_shutdown = hpet_clkevt_shutdown;
> +	evt->set_state_oneshot = hpet_clkevt_set_oneshot;
> +	evt->set_next_event = hpet_clkevt_set_next_event;
> +	evt->tick_resume = hpet_clkevt_msi_resume;
>  	evt->cpumask = cpumask_of(hc->cpu);

My compulsive-obsessive half really wants this to look like:

> +	evt->set_state_shutdown	= hpet_clkevt_shutdown;
> +	evt->set_state_oneshot	= hpet_clkevt_set_oneshot;
> +	evt->set_next_event	= hpet_clkevt_set_next_event;
> +	evt->tick_resume	= hpet_clkevt_msi_resume;
>  	evt->cpumask		= cpumask_of(hc->cpu);

:-)

Also, maybe harmonize the callback names with the local function names, 
like hpet_clkevt_set_next_event() already does and 
hpet_clkevt_set_oneshot() almost does:

 s/hpet_clkevt_shutdown
  /hpet_clkevt_set_state_shutdown

 s/hpet_clkevt_set_oneshot
  /hpet_clkevt_set_state_oneshot

 s/hpet_clkevt_msi_resume
  /hpet_clkevt_tick_resume

... unless the name variations have some hidden purpose and meaning?

With that fixed:

Reviewed-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 24/29] x86/hpet: Use cached info instead of extra flags
  2019-06-23 13:24 ` [patch 24/29] x86/hpet: Use cached info instead of extra flags Thomas Gleixner
@ 2019-06-26 21:20   ` Ingo Molnar
  2019-06-27 23:50   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 66+ messages in thread
From: Ingo Molnar @ 2019-06-26 21:20 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar


* Thomas Gleixner <tglx@linutronix.de> wrote:

> Now that HPET clockevent support is integrated into the channel data, reuse
> the cached boot configuration instead of copying the same information into
> a flags field.
> 
> This also allows to consolidate the reservation code into one place, which
> can now solely depend on the mode information.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  arch/x86/kernel/hpet.c |   76 ++++++++++++++-----------------------------------
>  1 file changed, 23 insertions(+), 53 deletions(-)
> 
> --- a/arch/x86/kernel/hpet.c
> +++ b/arch/x86/kernel/hpet.c
> @@ -25,8 +25,8 @@ struct hpet_channel {
>  	unsigned int			num;
>  	unsigned int			cpu;
>  	unsigned int			irq;
> +	unsigned int			inuse;
>  	enum hpet_mode			mode;
> -	unsigned int			flags;
>  	unsigned int			boot_cfg;
>  	char				name[10];

Let's fight entropy name by name and s/inuse/in_use ?

Because in_use is closer to harmony:

 dagon:~/tip> git grep -w in_use | wc -l
 518
 dagon:~/tip> git grep -w inuse | wc -l
 318

and also easier to read.

Reviewed-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 00/29] x86/hpet: Cleanup the channel management
  2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
                   ` (28 preceding siblings ...)
  2019-06-23 13:24 ` [patch 29/29] x86/hpet: Use channel for legacy clockevent storage Thomas Gleixner
@ 2019-06-26 21:22 ` Ingo Molnar
  29 siblings, 0 replies; 66+ messages in thread
From: Ingo Molnar @ 2019-06-26 21:22 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar


* Thomas Gleixner <tglx@linutronix.de> wrote:

> When reviewing the HPET NMI watchdog series, I stared into the HPET code
> and the proposed changes. The latter try to add yet another layer of duct
> tape and ifdeffery to the existing maze. No, thanks.
> 
> The following series cleans up the channel management and consolidates all
> state storage into a single place instead of 3 different ad hoc allocated
> places which carry redundant information and make the code hard to follow.
> 
> The reservation of a HPET channel for a NMI watchdog becomes a few lines of
> code after that series and just fits naturaly into that scheme without glue
> and more extra storage and ifdeffery.
> 
> For your conveniance the series is also available from git:
> 
>     git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.x86/hpet
> 
> Thanks,
> 
> 	tglx
> 
> 8<---------------------
>  include/asm/hpet.h |    7 
>  kernel/apic/msi.c  |    4 
>  kernel/hpet.c      |  937 +++++++++++++++++++++++------------------------------
>  3 files changed, 428 insertions(+), 520 deletions(-)

Modulo the minor nits I just posted, all the other patches (not written 
by me) are looking good:

  Reviewed-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 26/29] x86/hpet: Consolidate clockevent functions
  2019-06-26 21:17   ` Ingo Molnar
@ 2019-06-27 22:44     ` Thomas Gleixner
  2019-06-27 22:53       ` Thomas Gleixner
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-27 22:44 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

On Wed, 26 Jun 2019, Ingo Molnar wrote:
> * Thomas Gleixner <tglx@linutronix.de> wrote:
> > -	evt->set_state_shutdown = hpet_msi_shutdown;
> > -	evt->set_state_oneshot = hpet_msi_set_oneshot;
> > -	evt->tick_resume = hpet_msi_resume;
> > -	evt->set_next_event = hpet_msi_next_event;
> > +	evt->set_state_shutdown = hpet_clkevt_shutdown;
> > +	evt->set_state_oneshot = hpet_clkevt_set_oneshot;
> > +	evt->set_next_event = hpet_clkevt_set_next_event;
> > +	evt->tick_resume = hpet_clkevt_msi_resume;
> >  	evt->cpumask = cpumask_of(hc->cpu);
> 
> My compulsive-obsessive half really wants this to look like:
> 
> > +	evt->set_state_shutdown	= hpet_clkevt_shutdown;
> > +	evt->set_state_oneshot	= hpet_clkevt_set_oneshot;
> > +	evt->set_next_event	= hpet_clkevt_set_next_event;
> > +	evt->tick_resume	= hpet_clkevt_msi_resume;
> >  	evt->cpumask		= cpumask_of(hc->cpu);

Just to remove all of that in the next patch again, which then has the
proper aligned thing to make you happy :)

> Also, maybe harmonize the callback names with the local function names, 
> like hpet_clkevt_set_next_event() already does and 
> hpet_clkevt_set_oneshot() almost does:
> 
>  s/hpet_clkevt_shutdown
>   /hpet_clkevt_set_state_shutdown
> 
>  s/hpet_clkevt_set_oneshot
>   /hpet_clkevt_set_state_oneshot
> 
>  s/hpet_clkevt_msi_resume
>   /hpet_clkevt_tick_resume
> 
> ... unless the name variations have some hidden purpose and meaning?

Historical but we want to preserve some of the old stuff for sentimental
reasons.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [patch 26/29] x86/hpet: Consolidate clockevent functions
  2019-06-27 22:44     ` Thomas Gleixner
@ 2019-06-27 22:53       ` Thomas Gleixner
  2019-06-28  8:32         ` Ingo Molnar
  0 siblings, 1 reply; 66+ messages in thread
From: Thomas Gleixner @ 2019-06-27 22:53 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar

On Fri, 28 Jun 2019, Thomas Gleixner wrote:
> On Wed, 26 Jun 2019, Ingo Molnar wrote:
> > 
> >  s/hpet_clkevt_msi_resume
> >   /hpet_clkevt_tick_resume
> > 
> > ... unless the name variations have some hidden purpose and meaning?
> 
> Historical but we want to preserve some of the old stuff for sentimental
> reasons.

The msi_resume naming actually has a real reason as there is also the
legacy_resume one.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Simplify CPU online code
  2019-06-23 13:23 ` [patch 01/29] x86/hpet: Simplify CPU online code Thomas Gleixner
@ 2019-06-27 23:34   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ricardo.neri-calderon, hpa, tglx, mingo, ravi.v.shankar,
	linux-kernel, peterz, eranian, andi.kleen, Suravee.Suthikulpanit,
	ashok.raj

Commit-ID:  36b9017f0250a5299bb715b3b8c41b5e2b05b320
Gitweb:     https://git.kernel.org/tip/36b9017f0250a5299bb715b3b8c41b5e2b05b320
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:41 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:15 +0200

x86/hpet: Simplify CPU online code

The indirection via work scheduled on the upcoming CPU was necessary with the
old hotplug code because the online callback was invoked on the control CPU
not on the upcoming CPU. The rework of the CPU hotplug core guarantees that
the online callbacks are invoked on the upcoming CPU.

Remove the now pointless work redirection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.047254075@linutronix.de

---
 arch/x86/kernel/hpet.c | 31 ++-----------------------------
 1 file changed, 2 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index a0573f2e7763..a6aa22677768 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -547,12 +547,10 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 	return 0;
 }
 
-/* This should be called in specific @cpu */
 static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 {
 	struct clock_event_device *evt = &hdev->evt;
 
-	WARN_ON(cpu != smp_processor_id());
 	if (!(hdev->flags & HPET_DEV_VALID))
 		return;
 
@@ -684,36 +682,12 @@ static struct hpet_dev *hpet_get_unused_timer(void)
 	return NULL;
 }
 
-struct hpet_work_struct {
-	struct delayed_work work;
-	struct completion complete;
-};
-
-static void hpet_work(struct work_struct *w)
+static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hdev;
-	int cpu = smp_processor_id();
-	struct hpet_work_struct *hpet_work;
+	struct hpet_dev *hdev = hpet_get_unused_timer();
 
-	hpet_work = container_of(w, struct hpet_work_struct, work.work);
-
-	hdev = hpet_get_unused_timer();
 	if (hdev)
 		init_one_hpet_msi_clockevent(hdev, cpu);
-
-	complete(&hpet_work->complete);
-}
-
-static int hpet_cpuhp_online(unsigned int cpu)
-{
-	struct hpet_work_struct work;
-
-	INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work);
-	init_completion(&work.complete);
-	/* FIXME: add schedule_work_on() */
-	schedule_delayed_work_on(cpu, &work.work, 0);
-	wait_for_completion(&work.complete);
-	destroy_delayed_work_on_stack(&work.work);
 	return 0;
 }
 
@@ -1045,7 +1019,6 @@ static __init int hpet_late_init(void)
 	if (boot_cpu_has(X86_FEATURE_ARAT))
 		return 0;
 
-	/* This notifier should be called after workqueue is ready */
 	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "x86/hpet:online",
 				hpet_cpuhp_online, NULL);
 	if (ret)

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Replace printk(KERN...) with pr_...()
  2019-06-23 13:23 ` [patch 02/29] x86/hpet: Replace printk(KERN...) with pr_...() Thomas Gleixner
@ 2019-06-27 23:34   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:34 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, eranian, linux-kernel, peterz, mingo,
	ricardo.neri-calderon, ashok.raj, Suravee.Suthikulpanit,
	ravi.v.shankar, hpa, andi.kleen

Commit-ID:  46e5b64fdeb49e6f95b875fa4702cedf6c37188d
Gitweb:     https://git.kernel.org/tip/46e5b64fdeb49e6f95b875fa4702cedf6c37188d
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:42 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:15 +0200

x86/hpet: Replace printk(KERN...) with pr_...()

And sanitize the format strings while at it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.140411339@linutronix.de

---
 arch/x86/kernel/hpet.c | 45 +++++++++++++++++++--------------------------
 1 file changed, 19 insertions(+), 26 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index a6aa22677768..cf3dbf43e548 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -20,6 +20,9 @@
 #include <asm/hpet.h>
 #include <asm/time.h>
 
+#undef  pr_fmt
+#define pr_fmt(fmt) "hpet: " fmt
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -137,31 +140,28 @@ EXPORT_SYMBOL_GPL(is_hpet_enabled);
 static void _hpet_print_config(const char *function, int line)
 {
 	u32 i, timers, l, h;
-	printk(KERN_INFO "hpet: %s(%d):\n", function, line);
+	pr_info("%s(%d):\n", function, line);
 	l = hpet_readl(HPET_ID);
 	h = hpet_readl(HPET_PERIOD);
 	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
-	printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
+	pr_info("ID: 0x%x, PERIOD: 0x%x\n", l, h);
 	l = hpet_readl(HPET_CFG);
 	h = hpet_readl(HPET_STATUS);
-	printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
+	pr_info("CFG: 0x%x, STATUS: 0x%x\n", l, h);
 	l = hpet_readl(HPET_COUNTER);
 	h = hpet_readl(HPET_COUNTER+4);
-	printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
+	pr_info("COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
 
 	for (i = 0; i < timers; i++) {
 		l = hpet_readl(HPET_Tn_CFG(i));
 		h = hpet_readl(HPET_Tn_CFG(i)+4);
-		printk(KERN_INFO "hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h);
 		l = hpet_readl(HPET_Tn_CMP(i));
 		h = hpet_readl(HPET_Tn_CMP(i)+4);
-		printk(KERN_INFO "hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h);
 		l = hpet_readl(HPET_Tn_ROUTE(i));
 		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
-		printk(KERN_INFO "hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n",
-		       i, l, h);
+		pr_info("T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h);
 	}
 }
 
@@ -287,7 +287,7 @@ static void hpet_legacy_clockevent_register(void)
 	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
 					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
 	global_clock_event = &hpet_clockevent;
-	printk(KERN_DEBUG "hpet clockevent registered\n");
+	pr_debug("Clockevent registered\n");
 }
 
 static int hpet_set_periodic(struct clock_event_device *evt, int timer)
@@ -520,8 +520,7 @@ static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 	struct clock_event_device *hevt = &dev->evt;
 
 	if (!hevt->event_handler) {
-		printk(KERN_INFO "Spurious HPET timer interrupt on HPET timer %d\n",
-				dev->num);
+		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
 		return IRQ_HANDLED;
 	}
 
@@ -541,8 +540,7 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 	irq_set_affinity(dev->irq, cpumask_of(dev->cpu));
 	enable_irq(dev->irq);
 
-	printk(KERN_DEBUG "hpet: %s irq %d for MSI\n",
-			 dev->name, dev->irq);
+	pr_debug("%s irq %d for MSI\n", dev->name, dev->irq);
 
 	return 0;
 }
@@ -638,7 +636,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
 			break;
 	}
 
-	printk(KERN_INFO "HPET: %d timers in total, %d timers will be used for per-cpu timer\n",
+	pr_info("%d channels of %d reserved for per-cpu timers\n",
 		num_timers, num_timers_used);
 }
 
@@ -856,8 +854,7 @@ static int hpet_clocksource_register(void)
 	} while ((now - start) < 200000UL);
 
 	if (t1 == hpet_readl(HPET_COUNTER)) {
-		printk(KERN_WARNING
-		       "HPET counter not counting. HPET disabled\n");
+		pr_warn("Counter not counting. HPET disabled\n");
 		return -ENODEV;
 	}
 
@@ -903,9 +900,7 @@ int __init hpet_enable(void)
 	 */
 	for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) {
 		if (i == 1000) {
-			printk(KERN_WARNING
-			       "HPET config register value = 0xFFFFFFFF. "
-			       "Disabling HPET\n");
+			pr_warn("Config register invalid. Disabling HPET\n");
 			goto out_nohpet;
 		}
 	}
@@ -949,7 +944,7 @@ int __init hpet_enable(void)
 	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
 	hpet_writel(cfg, HPET_CFG);
 	if (cfg)
-		pr_warn("Unrecognized bits %#x set in global cfg\n", cfg);
+		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
 	for (i = 0; i <= last; ++i) {
 		cfg = hpet_readl(HPET_Tn_CFG(i));
@@ -961,8 +956,7 @@ int __init hpet_enable(void)
 			 | HPET_TN_64BIT_CAP | HPET_TN_32BIT | HPET_TN_ROUTE
 			 | HPET_TN_FSB | HPET_TN_FSB_CAP);
 		if (cfg)
-			pr_warn("Unrecognized bits %#x set in cfg#%u\n",
-				cfg, i);
+			pr_warn("Channel #%u config: Unknown bits %#x\n", i, cfg);
 	}
 	hpet_print_config();
 
@@ -1290,8 +1284,7 @@ static void hpet_rtc_timer_reinit(void)
 		if (hpet_rtc_flags & RTC_PIE)
 			hpet_pie_count += lost_ints;
 		if (printk_ratelimit())
-			printk(KERN_WARNING "hpet1: lost %d rtc interrupts\n",
-				lost_ints);
+			pr_warn("Lost %d RTC interrupts\n", lost_ints);
 	}
 }
 

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Restructure init code
  2019-06-23 13:23 ` [patch 03/29] x86/hpet: Restructure init code Thomas Gleixner
@ 2019-06-27 23:35   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi.kleen, Suravee.Suthikulpanit, ravi.v.shankar, mingo,
	ashok.raj, ricardo.neri-calderon, tglx, hpa, linux-kernel,
	peterz, eranian

Commit-ID:  9b0b28de837a3a59b409613d15e90d5569938945
Gitweb:     https://git.kernel.org/tip/9b0b28de837a3a59b409613d15e90d5569938945
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:43 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:15 +0200

x86/hpet: Restructure init code

As a preparatory change for further consolidation, restructure the HPET
init code so it becomes more readable. Fix up misleading and stale comments
and rename variables so they actually make sense.

No intended functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.247842972@linutronix.de

---
 arch/x86/kernel/hpet.c | 81 +++++++++++++++++++++++++++-----------------------
 1 file changed, 43 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index cf3dbf43e548..daa97e14296b 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -45,6 +45,7 @@ bool					hpet_msi_disable;
 static unsigned int			hpet_num_timers;
 #endif
 static void __iomem			*hpet_virt_address;
+static u32				*hpet_boot_cfg;
 
 struct hpet_dev {
 	struct clock_event_device	evt;
@@ -862,7 +863,34 @@ static int hpet_clocksource_register(void)
 	return 0;
 }
 
-static u32 *hpet_boot_cfg;
+/*
+ * AMD SB700 based systems with spread spectrum enabled use a SMM based
+ * HPET emulation to provide proper frequency setting.
+ *
+ * On such systems the SMM code is initialized with the first HPET register
+ * access and takes some time to complete. During this time the config
+ * register reads 0xffffffff. We check for max 1000 loops whether the
+ * config register reads a non-0xffffffff value to make sure that the
+ * HPET is up and running before we proceed any further.
+ *
+ * A counting loop is safe, as the HPET access takes thousands of CPU cycles.
+ *
+ * On non-SB700 based machines this check is only done once and has no
+ * side effects.
+ */
+static bool __init hpet_cfg_working(void)
+{
+	int i;
+
+	for (i = 0; i < 1000; i++) {
+		if (hpet_readl(HPET_CFG) != 0xFFFFFFFF)
+			return true;
+	}
+
+	pr_warn("Config register invalid. Disabling HPET\n");
+	return false;
+}
+
 
 /**
  * hpet_enable - Try to setup the HPET timer. Returns 1 on success.
@@ -870,8 +898,8 @@ static u32 *hpet_boot_cfg;
 int __init hpet_enable(void)
 {
 	u32 hpet_period, cfg, id;
+	unsigned int i, channels;
 	u64 freq;
-	unsigned int i, last;
 
 	if (!is_hpet_capable())
 		return 0;
@@ -880,38 +908,18 @@ int __init hpet_enable(void)
 	if (!hpet_virt_address)
 		return 0;
 
+	/* Validate that the config register is working */
+	if (!hpet_cfg_working())
+		goto out_nohpet;
+
 	/*
 	 * Read the period and check for a sane value:
 	 */
 	hpet_period = hpet_readl(HPET_PERIOD);
-
-	/*
-	 * AMD SB700 based systems with spread spectrum enabled use a
-	 * SMM based HPET emulation to provide proper frequency
-	 * setting. The SMM code is initialized with the first HPET
-	 * register access and takes some time to complete. During
-	 * this time the config register reads 0xffffffff. We check
-	 * for max. 1000 loops whether the config register reads a non
-	 * 0xffffffff value to make sure that HPET is up and running
-	 * before we go further. A counting loop is safe, as the HPET
-	 * access takes thousands of CPU cycles. On non SB700 based
-	 * machines this check is only done once and has no side
-	 * effects.
-	 */
-	for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) {
-		if (i == 1000) {
-			pr_warn("Config register invalid. Disabling HPET\n");
-			goto out_nohpet;
-		}
-	}
-
 	if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
 		goto out_nohpet;
 
-	/*
-	 * The period is a femto seconds value. Convert it to a
-	 * frequency.
-	 */
+	/* The period is a femtoseconds value. Convert it to a frequency. */
 	freq = FSEC_PER_SEC;
 	do_div(freq, hpet_period);
 	hpet_freq = freq;
@@ -923,19 +931,21 @@ int __init hpet_enable(void)
 	id = hpet_readl(HPET_ID);
 	hpet_print_config();
 
-	last = (id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
+	/* This is the HPET channel number which is zero based */
+	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 	/*
 	 * The legacy routing mode needs at least two channels, tick timer
 	 * and the rtc emulation channel.
 	 */
-	if (!last)
+	if (channels < 2)
 		goto out_nohpet;
 #endif
 
 	cfg = hpet_readl(HPET_CFG);
-	hpet_boot_cfg = kmalloc_array(last + 2, sizeof(*hpet_boot_cfg),
+	/* Allocate entries for the global and the channel configurations */
+	hpet_boot_cfg = kmalloc_array(channels + 1, sizeof(*hpet_boot_cfg),
 				      GFP_KERNEL);
 	if (hpet_boot_cfg)
 		*hpet_boot_cfg = cfg;
@@ -946,7 +956,7 @@ int __init hpet_enable(void)
 	if (cfg)
 		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
-	for (i = 0; i <= last; ++i) {
+	for (i = 0; i < channels; ++i) {
 		cfg = hpet_readl(HPET_Tn_CFG(i));
 		if (hpet_boot_cfg)
 			hpet_boot_cfg[i + 1] = cfg;
@@ -976,18 +986,13 @@ out_nohpet:
 }
 
 /*
- * Needs to be late, as the reserve_timer code calls kalloc !
- *
- * Not a problem on i386 as hpet_enable is called from late_time_init,
- * but on x86_64 it is necessary !
+ * The late initialization runs after the PCI quirks have been invoked
+ * which might have detected a system on which the HPET can be enforced.
  */
 static __init int hpet_late_init(void)
 {
 	int ret;
 
-	if (boot_hpet_disable)
-		return -ENODEV;
-
 	if (!hpet_address) {
 		if (!force_hpet_address)
 			return -ENODEV;

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Remove pointless x86-64 specific #include
  2019-06-23 13:23 ` [patch 04/29] x86/hpet: Remove pointless x86-64 specific #include Thomas Gleixner
@ 2019-06-27 23:36   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Suravee.Suthikulpanit, andi.kleen, linux-kernel, peterz,
	ricardo.neri-calderon, ravi.v.shankar, tglx, hpa, ashok.raj,
	eranian, mingo

Commit-ID:  7c4b0e0898ebff4d4821d5dd7a564903a1e88821
Gitweb:     https://git.kernel.org/tip/7c4b0e0898ebff4d4821d5dd7a564903a1e88821
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:44 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:16 +0200

x86/hpet: Remove pointless x86-64 specific #include

Nothing requires asm/pgtable.h here anymore.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.339011567@linutronix.de

---
 arch/x86/kernel/hpet.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index daa97e14296b..76d63ed62ce8 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -71,10 +71,6 @@ static inline void hpet_writel(unsigned int d, unsigned int a)
 	writel(d, hpet_virt_address + a);
 }
 
-#ifdef CONFIG_X86_64
-#include <asm/pgtable.h>
-#endif
-
 static inline void hpet_set_mapping(void)
 {
 	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Remove unused parameter from hpet_next_event()
  2019-06-23 13:23 ` [patch 05/29] x86/hpet: Remove unused parameter from hpet_next_event() Thomas Gleixner
@ 2019-06-27 23:36   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, ravi.v.shankar, eranian, ashok.raj, tglx,
	ricardo.neri-calderon, mingo, Suravee.Suthikulpanit, andi.kleen,
	peterz, linux-kernel

Commit-ID:  853acaf064acf3aad6189b36de814bd381d35133
Gitweb:     https://git.kernel.org/tip/853acaf064acf3aad6189b36de814bd381d35133
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:45 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:16 +0200

x86/hpet: Remove unused parameter from hpet_next_event()

The clockevent device pointer is not used in this function.

While at it, rename the misnamed 'timer' parameter to 'channel', which makes it
clear what this parameter means.

No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.447880978@linutronix.de

---
 arch/x86/kernel/hpet.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 76d63ed62ce8..b2ec52a7773d 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -347,15 +347,14 @@ static int hpet_resume(struct clock_event_device *evt)
 	return 0;
 }
 
-static int hpet_next_event(unsigned long delta,
-			   struct clock_event_device *evt, int timer)
+static int hpet_next_event(unsigned long delta, int channel)
 {
 	u32 cnt;
 	s32 res;
 
 	cnt = hpet_readl(HPET_COUNTER);
 	cnt += (u32) delta;
-	hpet_writel(cnt, HPET_Tn_CMP(timer));
+	hpet_writel(cnt, HPET_Tn_CMP(channel));
 
 	/*
 	 * HPETs are a complete disaster. The compare register is
@@ -407,7 +406,7 @@ static int hpet_legacy_resume(struct clock_event_device *evt)
 static int hpet_legacy_next_event(unsigned long delta,
 			struct clock_event_device *evt)
 {
-	return hpet_next_event(delta, evt, 0);
+	return hpet_next_event(delta, 0);
 }
 
 /*
@@ -508,7 +507,8 @@ static int hpet_msi_next_event(unsigned long delta,
 				struct clock_event_device *evt)
 {
 	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-	return hpet_next_event(delta, evt, hdev->num);
+
+	return hpet_next_event(delta, hdev->num);
 }
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Remove the unused hpet_msi_read() function
  2019-06-23 13:23 ` [patch 06/29] x86/hpet: Remove the unused hpet_msi_read() function Thomas Gleixner
@ 2019-06-27 23:37   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, ravi.v.shankar, ricardo.neri-calderon,
	Suravee.Suthikulpanit, ashok.raj, andi.kleen, linux-kernel, tglx,
	hpa, mingo, peterz

Commit-ID:  eb8ec32c45a87efbc6683b771597084c4d904a17
Gitweb:     https://git.kernel.org/tip/eb8ec32c45a87efbc6683b771597084c4d904a17
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:46 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:16 +0200

x86/hpet: Remove the unused hpet_msi_read() function

No users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.553729327@linutronix.de

---
 arch/x86/include/asm/hpet.h | 1 -
 arch/x86/kernel/hpet.c      | 7 -------
 2 files changed, 8 deletions(-)

diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index 67385d56d4f4..e3209f5de65d 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -81,7 +81,6 @@ struct irq_domain;
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
 extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
-extern void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg);
 extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
 			   struct hpet_dev *dev, int dev_num);
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index b2ec52a7773d..69cd0829f432 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -462,13 +462,6 @@ void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
 }
 
-void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg)
-{
-	msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
-	msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
-	msg->address_hi = 0;
-}
-
 static int hpet_msi_shutdown(struct clock_event_device *evt)
 {
 	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Mark init functions __init
  2019-06-23 13:23 ` [patch 07/29] x86/hpet: Mark init functions __init Thomas Gleixner
@ 2019-06-27 23:38   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ravi.v.shankar, mingo, eranian, andi.kleen, tglx,
	ricardo.neri-calderon, linux-kernel, hpa, Suravee.Suthikulpanit,
	peterz, ashok.raj

Commit-ID:  433526cc0502ff13d9b2fd63ba546a202dac0463
Gitweb:     https://git.kernel.org/tip/433526cc0502ff13d9b2fd63ba546a202dac0463
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:47 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:17 +0200

x86/hpet: Mark init functions __init

They are only called from init code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.645357869@linutronix.de

---
 arch/x86/kernel/hpet.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 69cd0829f432..638aaff39819 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -176,7 +176,7 @@ do {								\
 
 static void hpet_reserve_msi_timers(struct hpet_data *hd);
 
-static void hpet_reserve_platform_timers(unsigned int id)
+static void __init hpet_reserve_platform_timers(unsigned int id)
 {
 	struct hpet __iomem *hpet = hpet_virt_address;
 	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
@@ -572,7 +572,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 #define RESERVE_TIMERS 0
 #endif
 
-static void hpet_msi_capability_lookup(unsigned int start_timer)
+static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 {
 	unsigned int id;
 	unsigned int num_timers;
@@ -631,7 +631,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
 }
 
 #ifdef CONFIG_HPET
-static void hpet_reserve_msi_timers(struct hpet_data *hd)
+static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 {
 	int i;
 

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Sanitize stub functions
  2019-06-23 13:23 ` [patch 08/29] x86/hpet: Sanitize stub functions Thomas Gleixner
@ 2019-06-27 23:39   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, peterz, tglx, linux-kernel, hpa, mingo, ashok.raj,
	andi.kleen, ricardo.neri-calderon, Suravee.Suthikulpanit,
	ravi.v.shankar

Commit-ID:  4ce78e2094fc2736f8ecd04ec85e5566acaed516
Gitweb:     https://git.kernel.org/tip/4ce78e2094fc2736f8ecd04ec85e5566acaed516
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:48 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:17 +0200

x86/hpet: Sanitize stub functions

Mark them inline and remove the pointless 'return;' statement.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.754768274@linutronix.de

---
 arch/x86/kernel/hpet.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 638aaff39819..cb120e412dc6 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -692,16 +692,10 @@ static int hpet_cpuhp_dead(unsigned int cpu)
 }
 #else
 
-static void hpet_msi_capability_lookup(unsigned int start_timer)
-{
-	return;
-}
+static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }
 
 #ifdef CONFIG_HPET
-static void hpet_reserve_msi_timers(struct hpet_data *hd)
-{
-	return;
-}
+static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
 #endif
 
 #define hpet_cpuhp_online	NULL
@@ -820,7 +814,7 @@ static struct clocksource clocksource_hpet = {
 	.resume		= hpet_resume_counter,
 };
 
-static int hpet_clocksource_register(void)
+static int __init hpet_clocksource_register(void)
 {
 	u64 start, now;
 	u64 t1;

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Move static and global variables to one place
  2019-06-23 13:23 ` [patch 09/29] x86/hpet: Move static and global variables to one place Thomas Gleixner
@ 2019-06-27 23:39   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, Suravee.Suthikulpanit, ricardo.neri-calderon,
	ashok.raj, andi.kleen, peterz, ravi.v.shankar, tglx, mingo, hpa,
	eranian

Commit-ID:  8c273f2c81f0756f65b24771196c0eff7ac90e7b
Gitweb:     https://git.kernel.org/tip/8c273f2c81f0756f65b24771196c0eff7ac90e7b
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:49 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:17 +0200

x86/hpet: Move static and global variables to one place

Having static and global variables sprinkled all over the code is just
annoying to read. Move them all to the top of the file.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.860549134@linutronix.de

---
 arch/x86/kernel/hpet.c | 50 ++++++++++++++++++++++----------------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index cb120e412dc6..d6bd0ed6885b 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -23,6 +23,15 @@
 #undef  pr_fmt
 #define pr_fmt(fmt) "hpet: " fmt
 
+struct hpet_dev {
+	struct clock_event_device	evt;
+	unsigned int			num;
+	int				cpu;
+	unsigned int			irq;
+	unsigned int			flags;
+	char				name[10];
+};
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -43,18 +52,22 @@ bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
 static unsigned int			hpet_num_timers;
+static struct hpet_dev			*hpet_devs;
+static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
+static struct irq_domain		*hpet_domain;
 #endif
+
 static void __iomem			*hpet_virt_address;
 static u32				*hpet_boot_cfg;
 
-struct hpet_dev {
-	struct clock_event_device	evt;
-	unsigned int			num;
-	int				cpu;
-	unsigned int			irq;
-	unsigned int			flags;
-	char				name[10];
-};
+static bool				hpet_legacy_int_enabled;
+static unsigned long			hpet_freq;
+
+bool					boot_hpet_disable;
+bool					hpet_force_user;
+static bool				hpet_verbose;
+
+static struct clock_event_device	hpet_clockevent;
 
 static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
 {
@@ -85,10 +98,6 @@ static inline void hpet_clear_mapping(void)
 /*
  * HPET command line enable / disable
  */
-bool boot_hpet_disable;
-bool hpet_force_user;
-static bool hpet_verbose;
-
 static int __init hpet_setup(char *str)
 {
 	while (str) {
@@ -120,11 +129,6 @@ static inline int is_hpet_capable(void)
 	return !boot_hpet_disable && hpet_address;
 }
 
-/*
- * HPET timer interrupt enable / disable
- */
-static bool hpet_legacy_int_enabled;
-
 /**
  * is_hpet_enabled - check whether the hpet timer interrupt is enabled
  */
@@ -217,13 +221,7 @@ static void __init hpet_reserve_platform_timers(unsigned int id)
 static void hpet_reserve_platform_timers(unsigned int id) { }
 #endif
 
-/*
- * Common hpet info
- */
-static unsigned long hpet_freq;
-
-static struct clock_event_device hpet_clockevent;
-
+/* Common hpet functions */
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
@@ -430,10 +428,6 @@ static struct clock_event_device hpet_clockevent = {
  */
 #ifdef CONFIG_PCI_MSI
 
-static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
-static struct hpet_dev	*hpet_devs;
-static struct irq_domain *hpet_domain;
-
 void hpet_msi_unmask(struct irq_data *data)
 {
 	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Shuffle code around for readability sake
  2019-06-23 13:23 ` [patch 10/29] x86/hpet: Shuffle code around for readability sake Thomas Gleixner
@ 2019-06-27 23:40   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, ravi.v.shankar, mingo, linux-kernel, andi.kleen, peterz,
	ricardo.neri-calderon, tglx, Suravee.Suthikulpanit, ashok.raj,
	hpa

Commit-ID:  6bdec41a0cbcbda35c9044915fc8f45503a595a0
Gitweb:     https://git.kernel.org/tip/6bdec41a0cbcbda35c9044915fc8f45503a595a0
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:50 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:18 +0200

x86/hpet: Shuffle code around for readability sake

It doesn't make sense to have init functions in the middle of other
code. Aside of that, further changes in that area create horrible diffs if
the code stays where it is.

No functional change

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132434.951733064@linutronix.de

---
 arch/x86/kernel/hpet.c | 81 +++++++++++++++++++++++++-------------------------
 1 file changed, 41 insertions(+), 40 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index d6bd0ed6885b..71533f53fa1d 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -559,6 +559,47 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 					0x7FFFFFFF);
 }
 
+static struct hpet_dev *hpet_get_unused_timer(void)
+{
+	int i;
+
+	if (!hpet_devs)
+		return NULL;
+
+	for (i = 0; i < hpet_num_timers; i++) {
+		struct hpet_dev *hdev = &hpet_devs[i];
+
+		if (!(hdev->flags & HPET_DEV_VALID))
+			continue;
+		if (test_and_set_bit(HPET_DEV_USED_BIT,
+			(unsigned long *)&hdev->flags))
+			continue;
+		return hdev;
+	}
+	return NULL;
+}
+
+static int hpet_cpuhp_online(unsigned int cpu)
+{
+	struct hpet_dev *hdev = hpet_get_unused_timer();
+
+	if (hdev)
+		init_one_hpet_msi_clockevent(hdev, cpu);
+	return 0;
+}
+
+static int hpet_cpuhp_dead(unsigned int cpu)
+{
+	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
+
+	if (!hdev)
+		return 0;
+	free_irq(hdev->irq, hdev);
+	hdev->flags &= ~HPET_DEV_USED;
+	per_cpu(cpu_hpet_dev, cpu) = NULL;
+	return 0;
+}
+
 #ifdef CONFIG_HPET
 /* Reserve at least one timer for userspace (/dev/hpet) */
 #define RESERVE_TIMERS 1
@@ -644,46 +685,6 @@ static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 }
 #endif
 
-static struct hpet_dev *hpet_get_unused_timer(void)
-{
-	int i;
-
-	if (!hpet_devs)
-		return NULL;
-
-	for (i = 0; i < hpet_num_timers; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
-
-		if (!(hdev->flags & HPET_DEV_VALID))
-			continue;
-		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hdev->flags))
-			continue;
-		return hdev;
-	}
-	return NULL;
-}
-
-static int hpet_cpuhp_online(unsigned int cpu)
-{
-	struct hpet_dev *hdev = hpet_get_unused_timer();
-
-	if (hdev)
-		init_one_hpet_msi_clockevent(hdev, cpu);
-	return 0;
-}
-
-static int hpet_cpuhp_dead(unsigned int cpu)
-{
-	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
-
-	if (!hdev)
-		return 0;
-	free_irq(hdev->irq, hdev);
-	hdev->flags &= ~HPET_DEV_USED;
-	per_cpu(cpu_hpet_dev, cpu) = NULL;
-	return 0;
-}
 #else
 
 static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Separate counter check out of clocksource register code
  2019-06-23 13:23 ` [patch 11/29] x86/hpet: Separate counter check out of clocksource register code Thomas Gleixner
@ 2019-06-27 23:41   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ricardo.neri-calderon, tglx, linux-kernel, Suravee.Suthikulpanit,
	hpa, andi.kleen, peterz, eranian, ravi.v.shankar, mingo,
	ashok.raj

Commit-ID:  3222daf970f30133cc4c639cbecdc29c4ae91b2b
Gitweb:     https://git.kernel.org/tip/3222daf970f30133cc4c639cbecdc29c4ae91b2b
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:51 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:18 +0200

x86/hpet: Separate counter check out of clocksource register code

The init code checks whether the HPET counter works late in the init
function when the clocksource is registered. That should happen right with
the other sanity checks.

Split it into a separate validation function and move it to the other
sanity checks.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.058540608@linutronix.de

---
 arch/x86/kernel/hpet.c | 65 ++++++++++++++++++++++++--------------------------
 1 file changed, 31 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 71533f53fa1d..8c57dbf15e3b 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -809,38 +809,6 @@ static struct clocksource clocksource_hpet = {
 	.resume		= hpet_resume_counter,
 };
 
-static int __init hpet_clocksource_register(void)
-{
-	u64 start, now;
-	u64 t1;
-
-	/* Start the counter */
-	hpet_restart_counter();
-
-	/* Verify whether hpet counter works */
-	t1 = hpet_readl(HPET_COUNTER);
-	start = rdtsc();
-
-	/*
-	 * We don't know the TSC frequency yet, but waiting for
-	 * 200000 TSC cycles is safe:
-	 * 4 GHz == 50us
-	 * 1 GHz == 200us
-	 */
-	do {
-		rep_nop();
-		now = rdtsc();
-	} while ((now - start) < 200000UL);
-
-	if (t1 == hpet_readl(HPET_COUNTER)) {
-		pr_warn("Counter not counting. HPET disabled\n");
-		return -ENODEV;
-	}
-
-	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
-	return 0;
-}
-
 /*
  * AMD SB700 based systems with spread spectrum enabled use a SMM based
  * HPET emulation to provide proper frequency setting.
@@ -869,6 +837,32 @@ static bool __init hpet_cfg_working(void)
 	return false;
 }
 
+static bool __init hpet_counting(void)
+{
+	u64 start, now, t1;
+
+	hpet_restart_counter();
+
+	t1 = hpet_readl(HPET_COUNTER);
+	start = rdtsc();
+
+	/*
+	 * We don't know the TSC frequency yet, but waiting for
+	 * 200000 TSC cycles is safe:
+	 * 4 GHz == 50us
+	 * 1 GHz == 200us
+	 */
+	do {
+		rep_nop();
+		now = rdtsc();
+	} while ((now - start) < 200000UL);
+
+	if (t1 == hpet_readl(HPET_COUNTER)) {
+		pr_warn("Counter not counting. HPET disabled\n");
+		return false;
+	}
+	return true;
+}
 
 /**
  * hpet_enable - Try to setup the HPET timer. Returns 1 on success.
@@ -890,6 +884,10 @@ int __init hpet_enable(void)
 	if (!hpet_cfg_working())
 		goto out_nohpet;
 
+	/* Validate that the counter is counting */
+	if (!hpet_counting())
+		goto out_nohpet;
+
 	/*
 	 * Read the period and check for a sane value:
 	 */
@@ -948,8 +946,7 @@ int __init hpet_enable(void)
 	}
 	hpet_print_config();
 
-	if (hpet_clocksource_register())
-		goto out_nohpet;
+	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
 		hpet_legacy_clockevent_register();

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Simplify counter validation
  2019-06-23 13:23 ` [patch 12/29] x86/hpet: Simplify counter validation Thomas Gleixner
@ 2019-06-27 23:41   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, eranian, linux-kernel, ravi.v.shankar, andi.kleen,
	Suravee.Suthikulpanit, peterz, hpa, mingo, ricardo.neri-calderon,
	ashok.raj

Commit-ID:  44b5be5733e119300115b98409cbcf9a45b8d3f1
Gitweb:     https://git.kernel.org/tip/44b5be5733e119300115b98409cbcf9a45b8d3f1
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:52 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:19 +0200

x86/hpet: Simplify counter validation

There is no point to loop for 200k TSC cycles to check afterwards whether
the HPET counter is working. Read the counter inside of the loop and break
out when the counter value changed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.149535103@linutronix.de

---
 arch/x86/kernel/hpet.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 8c57dbf15e3b..74756c0a3a10 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -853,15 +853,13 @@ static bool __init hpet_counting(void)
 	 * 1 GHz == 200us
 	 */
 	do {
-		rep_nop();
+		if (t1 != hpet_readl(HPET_COUNTER))
+			return true;
 		now = rdtsc();
 	} while ((now - start) < 200000UL);
 
-	if (t1 == hpet_readl(HPET_COUNTER)) {
-		pr_warn("Counter not counting. HPET disabled\n");
-		return false;
-	}
-	return true;
+	pr_warn("Counter not counting. HPET disabled\n");
+	return false;
 }
 
 /**

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV
  2019-06-23 13:23 ` [patch 13/29] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV Thomas Gleixner
@ 2019-06-27 23:42   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, mingo, peterz, eranian, ravi.v.shankar,
	ricardo.neri-calderon, Suravee.Suthikulpanit, andi.kleen, hpa,
	ashok.raj, tglx

Commit-ID:  3535aa12f7f26fc755514b13aee8fac15741267e
Gitweb:     https://git.kernel.org/tip/3535aa12f7f26fc755514b13aee8fac15741267e
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:53 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:19 +0200

x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV

It's a function not a macro and the upcoming changes use channel for the
individual hpet timer units to allow a step by step refactoring approach.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.241032433@linutronix.de

---
 arch/x86/kernel/hpet.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 74756c0a3a10..4cf93294bacc 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -69,9 +69,10 @@ static bool				hpet_verbose;
 
 static struct clock_event_device	hpet_clockevent;
 
-static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
+static inline
+struct hpet_dev *clockevent_to_channel(struct clock_event_device *evt)
 {
-	return container_of(evtdev, struct hpet_dev, evt);
+	return container_of(evt, struct hpet_dev, evt);
 }
 
 inline unsigned int hpet_readl(unsigned int a)
@@ -458,28 +459,22 @@ void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
 
 static int hpet_msi_shutdown(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_shutdown(evt, hdev->num);
+	return hpet_shutdown(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_set_oneshot(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_set_oneshot(evt, hdev->num);
+	return hpet_set_oneshot(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_set_periodic(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_set_periodic(evt, hdev->num);
+	return hpet_set_periodic(evt, clockevent_to_channel(evt)->num);
 }
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+	struct hpet_dev *hdev = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hdev->irq);
 	struct msi_msg msg;
 
@@ -491,16 +486,14 @@ static int hpet_msi_resume(struct clock_event_device *evt)
 }
 
 static int hpet_msi_next_event(unsigned long delta,
-				struct clock_event_device *evt)
+			       struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
-
-	return hpet_next_event(delta, hdev->num);
+	return hpet_next_event(delta, clockevent_to_channel(evt)->num);
 }
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *dev = (struct hpet_dev *)data;
+	struct hpet_dev *dev = data;
 	struct clock_event_device *hevt = &dev->evt;
 
 	if (!hevt->event_handler) {

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Remove not required includes
  2019-06-23 13:23 ` [patch 14/29] x86/hpet: Remove not required includes Thomas Gleixner
@ 2019-06-27 23:43   ` tip-bot for Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Ingo Molnar @ 2019-06-27 23:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ashok.raj, linux-kernel, hpa, tglx, Suravee.Suthikulpanit,
	eranian, andi.kleen, mingo, peterz, ricardo.neri-calderon,
	ravi.v.shankar

Commit-ID:  9bc9e1d4c139497553599a73839ea846dce63f72
Gitweb:     https://git.kernel.org/tip/9bc9e1d4c139497553599a73839ea846dce63f72
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Sun, 23 Jun 2019 15:23:54 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:20 +0200

x86/hpet: Remove not required includes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.348089155@linutronix.de

---
 arch/x86/kernel/hpet.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 4cf93294bacc..96daae404b29 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -1,22 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
-#include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/export.h>
 #include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/i8253.h>
-#include <linux/slab.h>
 #include <linux/hpet.h>
-#include <linux/init.h>
 #include <linux/cpu.h>
-#include <linux/pm.h>
-#include <linux/io.h>
+#include <linux/irq.h>
 
-#include <asm/cpufeature.h>
-#include <asm/irqdomain.h>
-#include <asm/fixmap.h>
 #include <asm/hpet.h>
 #include <asm/time.h>
 

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Make naming consistent
  2019-06-23 13:23 ` [patch 15/29] x86/hpet: Make naming consistent Thomas Gleixner
@ 2019-06-27 23:44   ` tip-bot for Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Ingo Molnar @ 2019-06-27 23:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, Suravee.Suthikulpanit, linux-kernel,
	ricardo.neri-calderon, mingo, andi.kleen, hpa, ashok.raj, tglx,
	peterz, ravi.v.shankar

Commit-ID:  3fe50c34dc1fa8ae2c24ec202b9decbbef72921d
Gitweb:     https://git.kernel.org/tip/3fe50c34dc1fa8ae2c24ec202b9decbbef72921d
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Sun, 23 Jun 2019 15:23:55 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:20 +0200

x86/hpet: Make naming consistent

Use 'evt' for clockevents pointers and capitalize HPET in comments.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.454138339@linutronix.de

---
 arch/x86/kernel/hpet.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 96daae404b29..823e8d32182a 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -121,7 +121,7 @@ static inline int is_hpet_capable(void)
 }
 
 /**
- * is_hpet_enabled - check whether the hpet timer interrupt is enabled
+ * is_hpet_enabled - Check whether the legacy HPET timer interrupt is enabled
  */
 int is_hpet_enabled(void)
 {
@@ -164,7 +164,7 @@ do {								\
 } while (0)
 
 /*
- * When the hpet driver (/dev/hpet) is enabled, we need to reserve
+ * When the HPET driver (/dev/hpet) is enabled, we need to reserve
  * timer 0 and timer 1 in case of RTC emulation.
  */
 #ifdef CONFIG_HPET
@@ -212,7 +212,7 @@ static void __init hpet_reserve_platform_timers(unsigned int id)
 static void hpet_reserve_platform_timers(unsigned int id) { }
 #endif
 
-/* Common hpet functions */
+/* Common HPET functions */
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
@@ -266,7 +266,7 @@ static void hpet_legacy_clockevent_register(void)
 	hpet_enable_legacy_int();
 
 	/*
-	 * Start hpet with the boot cpu mask and make it
+	 * Start HPET with the boot cpu mask and make it
 	 * global after the IO_APIC has been initialized.
 	 */
 	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
@@ -399,7 +399,7 @@ static int hpet_legacy_next_event(unsigned long delta,
 }
 
 /*
- * The hpet clock event device
+ * The HPET clock event device
  */
 static struct clock_event_device hpet_clockevent = {
 	.name			= "hpet",
@@ -484,14 +484,14 @@ static int hpet_msi_next_event(unsigned long delta,
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
 	struct hpet_dev *dev = data;
-	struct clock_event_device *hevt = &dev->evt;
+	struct clock_event_device *evt = &dev->evt;
 
-	if (!hevt->event_handler) {
+	if (!evt->event_handler) {
 		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
 		return IRQ_HANDLED;
 	}
 
-	hevt->event_handler(hevt);
+	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
@@ -703,7 +703,7 @@ static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
  * with its associated locking overhead. And we also need 64-bit atomic
  * read.
  *
- * The lock and the hpet value are stored together and can be read in a
+ * The lock and the HPET value are stored together and can be read in a
  * single atomic 64-bit read. It is explicitly assumed that arch_spinlock_t
  * is 32 bits in size.
  */
@@ -1053,7 +1053,7 @@ static unsigned long hpet_pie_limit;
 static rtc_irq_handler irq_handler;
 
 /*
- * Check that the hpet counter c1 is ahead of the c2
+ * Check that the HPET counter c1 is ahead of the c2
  */
 static inline int hpet_cnt_ahead(u32 c1, u32 c2)
 {

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Clean up comments
  2019-06-23 13:23 ` [patch 16/29] x86/hpet: Clean up comments Thomas Gleixner
@ 2019-06-27 23:44   ` tip-bot for Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Ingo Molnar @ 2019-06-27 23:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, andi.kleen, Suravee.Suthikulpanit, linux-kernel, ashok.raj,
	tglx, ravi.v.shankar, eranian, mingo, ricardo.neri-calderon,
	peterz

Commit-ID:  dfe36b573ed320ce311b2cb9251d2543be9e52ac
Gitweb:     https://git.kernel.org/tip/dfe36b573ed320ce311b2cb9251d2543be9e52ac
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Sun, 23 Jun 2019 15:23:56 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:20 +0200

x86/hpet: Clean up comments

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.545653922@linutronix.de

---
 arch/x86/kernel/hpet.c | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 823e8d32182a..1a389a2ff42a 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -266,8 +266,8 @@ static void hpet_legacy_clockevent_register(void)
 	hpet_enable_legacy_int();
 
 	/*
-	 * Start HPET with the boot cpu mask and make it
-	 * global after the IO_APIC has been initialized.
+	 * Start HPET with the boot CPU's cpumask and make it global after
+	 * the IO_APIC has been initialized.
 	 */
 	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
 	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
@@ -688,10 +688,10 @@ static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
 /*
  * Reading the HPET counter is a very slow operation. If a large number of
  * CPUs are trying to access the HPET counter simultaneously, it can cause
- * massive delay and slow down system performance dramatically. This may
+ * massive delays and slow down system performance dramatically. This may
  * happen when HPET is the default clock source instead of TSC. For a
  * really large system with hundreds of CPUs, the slowdown may be so
- * severe that it may actually crash the system because of a NMI watchdog
+ * severe, that it can actually crash the system because of a NMI watchdog
  * soft lockup, for example.
  *
  * If multiple CPUs are trying to access the HPET counter at the same time,
@@ -700,8 +700,7 @@ static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
  *
  * This special feature is only enabled on x86-64 systems. It is unlikely
  * that 32-bit x86 systems will have enough CPUs to require this feature
- * with its associated locking overhead. And we also need 64-bit atomic
- * read.
+ * with its associated locking overhead. We also need 64-bit atomic read.
  *
  * The lock and the HPET value are stored together and can be read in a
  * single atomic 64-bit read. It is explicitly assumed that arch_spinlock_t
@@ -1020,19 +1019,25 @@ void hpet_disable(void)
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
+/*
+ * HPET in LegacyReplacement mode eats up the RTC interrupt line. When HPET
  * is enabled, we support RTC interrupt functionality in software.
+ *
  * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
+ *
+ *  1) Update Interrupt - generate an interrupt, every second, when the
+ *     RTC clock is updated
+ *  2) Alarm Interrupt - generate an interrupt at a specific time of day
+ *  3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *     2Hz-8192Hz (2Hz-64Hz for non-root user) (all frequencies in powers of 2)
+ *
+ * (1) and (2) above are implemented using polling at a frequency of 64 Hz:
+ * DEFAULT_RTC_INT_FREQ.
+ *
+ * The exact frequency is a tradeoff between accuracy and interrupt overhead.
+ *
+ * For (3), we use interrupts at 64 Hz, or the user specified periodic frequency,
+ * if it's higher.
  */
 #include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
@@ -1053,7 +1058,7 @@ static unsigned long hpet_pie_limit;
 static rtc_irq_handler irq_handler;
 
 /*
- * Check that the HPET counter c1 is ahead of the c2
+ * Check that the HPET counter c1 is ahead of c2
  */
 static inline int hpet_cnt_ahead(u32 c1, u32 c2)
 {

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Coding style cleanup
  2019-06-23 13:23 ` [patch 17/29] x86/hpet: Coding style cleanup Thomas Gleixner
@ 2019-06-27 23:45   ` tip-bot for Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Ingo Molnar @ 2019-06-27 23:45 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ravi.v.shankar, Suravee.Suthikulpanit, tglx,
	ricardo.neri-calderon, andi.kleen, eranian, linux-kernel,
	ashok.raj, mingo, hpa, peterz

Commit-ID:  0b5c597de6aa30000480d6add2f37ef7de3f9312
Gitweb:     https://git.kernel.org/tip/0b5c597de6aa30000480d6add2f37ef7de3f9312
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Sun, 23 Jun 2019 15:23:57 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:21 +0200

x86/hpet: Coding style cleanup

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.637420368@linutronix.de

---
 arch/x86/kernel/hpet.c | 43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 1a389a2ff42a..ed2d556f2c96 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -131,26 +131,33 @@ EXPORT_SYMBOL_GPL(is_hpet_enabled);
 
 static void _hpet_print_config(const char *function, int line)
 {
-	u32 i, timers, l, h;
+	u32 i, id, period, cfg, status, channels, l, h;
+
 	pr_info("%s(%d):\n", function, line);
-	l = hpet_readl(HPET_ID);
-	h = hpet_readl(HPET_PERIOD);
-	timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
-	pr_info("ID: 0x%x, PERIOD: 0x%x\n", l, h);
-	l = hpet_readl(HPET_CFG);
-	h = hpet_readl(HPET_STATUS);
-	pr_info("CFG: 0x%x, STATUS: 0x%x\n", l, h);
+
+	id = hpet_readl(HPET_ID);
+	period = hpet_readl(HPET_PERIOD);
+	pr_info("ID: 0x%x, PERIOD: 0x%x\n", id, period);
+
+	cfg = hpet_readl(HPET_CFG);
+	status = hpet_readl(HPET_STATUS);
+	pr_info("CFG: 0x%x, STATUS: 0x%x\n", cfg, status);
+
 	l = hpet_readl(HPET_COUNTER);
 	h = hpet_readl(HPET_COUNTER+4);
 	pr_info("COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
 
-	for (i = 0; i < timers; i++) {
+	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+
+	for (i = 0; i < channels; i++) {
 		l = hpet_readl(HPET_Tn_CFG(i));
 		h = hpet_readl(HPET_Tn_CFG(i)+4);
 		pr_info("T%d: CFG_l: 0x%x, CFG_h: 0x%x\n", i, l, h);
+
 		l = hpet_readl(HPET_Tn_CMP(i));
 		h = hpet_readl(HPET_Tn_CMP(i)+4);
 		pr_info("T%d: CMP_l: 0x%x, CMP_h: 0x%x\n", i, l, h);
+
 		l = hpet_readl(HPET_Tn_ROUTE(i));
 		h = hpet_readl(HPET_Tn_ROUTE(i)+4);
 		pr_info("T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x\n", i, l, h);
@@ -216,6 +223,7 @@ static void hpet_reserve_platform_timers(unsigned int id) { }
 static void hpet_stop_counter(void)
 {
 	u32 cfg = hpet_readl(HPET_CFG);
+
 	cfg &= ~HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 }
@@ -229,6 +237,7 @@ static void hpet_reset_counter(void)
 static void hpet_start_counter(void)
 {
 	unsigned int cfg = hpet_readl(HPET_CFG);
+
 	cfg |= HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 }
@@ -393,7 +402,7 @@ static int hpet_legacy_resume(struct clock_event_device *evt)
 }
 
 static int hpet_legacy_next_event(unsigned long delta,
-			struct clock_event_device *evt)
+				  struct clock_event_device *evt)
 {
 	return hpet_next_event(delta, 0);
 }
@@ -1142,6 +1151,7 @@ EXPORT_SYMBOL_GPL(hpet_rtc_timer_init);
 static void hpet_disable_rtc_channel(void)
 {
 	u32 cfg = hpet_readl(HPET_T1_CFG);
+
 	cfg &= ~HPET_TN_ENABLE;
 	hpet_writel(cfg, HPET_T1_CFG);
 }
@@ -1183,8 +1193,7 @@ int hpet_set_rtc_irq_bit(unsigned long bit_mask)
 }
 EXPORT_SYMBOL_GPL(hpet_set_rtc_irq_bit);
 
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min,
-			unsigned char sec)
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
 {
 	if (!is_hpet_enabled())
 		return 0;
@@ -1204,15 +1213,16 @@ int hpet_set_periodic_freq(unsigned long freq)
 	if (!is_hpet_enabled())
 		return 0;
 
-	if (freq <= DEFAULT_RTC_INT_FREQ)
+	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
-	else {
+	} else {
 		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
 		do_div(clc, freq);
 		clc >>= hpet_clockevent.shift;
 		hpet_pie_delta = clc;
 		hpet_pie_limit = 0;
 	}
+
 	return 1;
 }
 EXPORT_SYMBOL_GPL(hpet_set_periodic_freq);
@@ -1272,8 +1282,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
 		hpet_prev_update_sec = curr_time.tm_sec;
 	}
 
-	if (hpet_rtc_flags & RTC_PIE &&
-	    ++hpet_pie_count >= hpet_pie_limit) {
+	if (hpet_rtc_flags & RTC_PIE && ++hpet_pie_count >= hpet_pie_limit) {
 		rtc_int_flag |= RTC_PF;
 		hpet_pie_count = 0;
 	}
@@ -1282,7 +1291,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
 	    (curr_time.tm_sec == hpet_alarm_time.tm_sec) &&
 	    (curr_time.tm_min == hpet_alarm_time.tm_min) &&
 	    (curr_time.tm_hour == hpet_alarm_time.tm_hour))
-			rtc_int_flag |= RTC_AF;
+		rtc_int_flag |= RTC_AF;
 
 	if (rtc_int_flag) {
 		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Introduce struct hpet_base and struct hpet_channel
  2019-06-23 13:23 ` [patch 18/29] x86/hpet: Introduce struct hpet_base and struct hpet_channel Thomas Gleixner
@ 2019-06-27 23:46   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:46 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, mingo, ricardo.neri-calderon, andi.kleen, ashok.raj,
	peterz, hpa, ravi.v.shankar, tglx, Suravee.Suthikulpanit,
	linux-kernel

Commit-ID:  e37f0881e9d9ec8b12f242cc2b78d93259aa7f0f
Gitweb:     https://git.kernel.org/tip/e37f0881e9d9ec8b12f242cc2b78d93259aa7f0f
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:58 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:21 +0200

x86/hpet: Introduce struct hpet_base and struct hpet_channel

Introduce new data structures to replace the ad hoc collection of separate
variables and pointers.

Replace the boot configuration store and restore as a first step.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.728456320@linutronix.de

---
 arch/x86/kernel/hpet.c | 82 +++++++++++++++++++++++++++++---------------------
 1 file changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index ed2d556f2c96..59a81d7fd05b 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -22,6 +22,17 @@ struct hpet_dev {
 	char				name[10];
 };
 
+struct hpet_channel {
+	unsigned int			num;
+	unsigned int			boot_cfg;
+};
+
+struct hpet_base {
+	unsigned int			nr_channels;
+	unsigned int			boot_cfg;
+	struct hpet_channel		*channels;
+};
+
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
 #define HPET_DEV_USED_BIT		2
@@ -48,7 +59,7 @@ static struct irq_domain		*hpet_domain;
 #endif
 
 static void __iomem			*hpet_virt_address;
-static u32				*hpet_boot_cfg;
+static struct hpet_base			hpet_base;
 
 static bool				hpet_legacy_int_enabled;
 static unsigned long			hpet_freq;
@@ -860,6 +871,7 @@ int __init hpet_enable(void)
 {
 	u32 hpet_period, cfg, id;
 	unsigned int i, channels;
+	struct hpet_channel *hc;
 	u64 freq;
 
 	if (!is_hpet_capable())
@@ -899,34 +911,39 @@ int __init hpet_enable(void)
 	/* This is the HPET channel number which is zero based */
 	channels = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
 
-#ifdef CONFIG_HPET_EMULATE_RTC
 	/*
 	 * The legacy routing mode needs at least two channels, tick timer
 	 * and the rtc emulation channel.
 	 */
-	if (channels < 2)
+	if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC) && channels < 2)
 		goto out_nohpet;
-#endif
 
+	hc = kcalloc(channels, sizeof(*hc), GFP_KERNEL);
+	if (!hc) {
+		pr_warn("Disabling HPET.\n");
+		goto out_nohpet;
+	}
+	hpet_base.channels = hc;
+	hpet_base.nr_channels = channels;
+
+	/* Read, store and sanitize the global configuration */
 	cfg = hpet_readl(HPET_CFG);
-	/* Allocate entries for the global and the channel configurations */
-	hpet_boot_cfg = kmalloc_array(channels + 1, sizeof(*hpet_boot_cfg),
-				      GFP_KERNEL);
-	if (hpet_boot_cfg)
-		*hpet_boot_cfg = cfg;
-	else
-		pr_warn("HPET initial state will not be saved\n");
+	hpet_base.boot_cfg = cfg;
 	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
 	hpet_writel(cfg, HPET_CFG);
 	if (cfg)
 		pr_warn("Global config: Unknown bits %#x\n", cfg);
 
-	for (i = 0; i < channels; ++i) {
+	/* Read, store and sanitize the per channel configuration */
+	for (i = 0; i < channels; i++, hc++) {
+		hc->num = i;
+
 		cfg = hpet_readl(HPET_Tn_CFG(i));
-		if (hpet_boot_cfg)
-			hpet_boot_cfg[i + 1] = cfg;
+		hc->boot_cfg = cfg;
+
 		cfg &= ~(HPET_TN_ENABLE | HPET_TN_LEVEL | HPET_TN_FSB);
 		hpet_writel(cfg, HPET_Tn_CFG(i));
+
 		cfg &= ~(HPET_TN_PERIODIC | HPET_TN_PERIODIC_CAP
 			 | HPET_TN_64BIT_CAP | HPET_TN_32BIT | HPET_TN_ROUTE
 			 | HPET_TN_FSB | HPET_TN_FSB_CAP);
@@ -944,6 +961,9 @@ int __init hpet_enable(void)
 	return 0;
 
 out_nohpet:
+	kfree(hpet_base.channels);
+	hpet_base.channels = NULL;
+	hpet_base.nr_channels = 0;
 	hpet_clear_mapping();
 	hpet_address = 0;
 	return 0;
@@ -1000,30 +1020,24 @@ fs_initcall(hpet_late_init);
 
 void hpet_disable(void)
 {
-	if (is_hpet_capable() && hpet_virt_address) {
-		unsigned int cfg = hpet_readl(HPET_CFG), id, last;
-
-		if (hpet_boot_cfg)
-			cfg = *hpet_boot_cfg;
-		else if (hpet_legacy_int_enabled) {
-			cfg &= ~HPET_CFG_LEGACY;
-			hpet_legacy_int_enabled = false;
-		}
-		cfg &= ~HPET_CFG_ENABLE;
-		hpet_writel(cfg, HPET_CFG);
+	unsigned int i;
+	u32 cfg;
 
-		if (!hpet_boot_cfg)
-			return;
+	if (!is_hpet_capable() || !hpet_virt_address)
+		return;
 
-		id = hpet_readl(HPET_ID);
-		last = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
+	/* Restore boot configuration with the enable bit cleared */
+	cfg = hpet_base.boot_cfg;
+	cfg &= ~HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
 
-		for (id = 0; id <= last; ++id)
-			hpet_writel(hpet_boot_cfg[id + 1], HPET_Tn_CFG(id));
+	/* Restore the channel boot configuration */
+	for (i = 0; i < hpet_base.nr_channels; i++)
+		hpet_writel(hpet_base.channels[i].boot_cfg, HPET_Tn_CFG(i));
 
-		if (*hpet_boot_cfg & HPET_CFG_ENABLE)
-			hpet_writel(*hpet_boot_cfg, HPET_CFG);
-	}
+	/* If the HPET was enabled at boot time, reenable it */
+	if (hpet_base.boot_cfg & HPET_CFG_ENABLE)
+		hpet_writel(hpet_base.boot_cfg, HPET_CFG);
 }
 
 #ifdef CONFIG_HPET_EMULATE_RTC

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Use cached channel data
  2019-06-23 13:23 ` [patch 19/29] x86/hpet: Use cached channel data Thomas Gleixner
@ 2019-06-27 23:46   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:46 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, andi.kleen, linux-kernel, ashok.raj,
	ricardo.neri-calderon, mingo, ravi.v.shankar,
	Suravee.Suthikulpanit, peterz, eranian

Commit-ID:  2460d5878ad69c178f9ff1cc3eee9f09b017e15f
Gitweb:     https://git.kernel.org/tip/2460d5878ad69c178f9ff1cc3eee9f09b017e15f
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:23:59 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:22 +0200

x86/hpet: Use cached channel data

Instead of rereading the HPET registers over and over use the information
which was cached in hpet_enable().

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.821728550@linutronix.de

---
 arch/x86/kernel/hpet.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 59a81d7fd05b..8711f1fdef8f 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -24,6 +24,7 @@ struct hpet_dev {
 
 struct hpet_channel {
 	unsigned int			num;
+	unsigned int			irq;
 	unsigned int			boot_cfg;
 };
 
@@ -52,7 +53,6 @@ u8					hpet_blockid; /* OS timer block num */
 bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
-static unsigned int			hpet_num_timers;
 static struct hpet_dev			*hpet_devs;
 static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
 static struct irq_domain		*hpet_domain;
@@ -189,19 +189,15 @@ do {								\
 
 static void hpet_reserve_msi_timers(struct hpet_data *hd);
 
-static void __init hpet_reserve_platform_timers(unsigned int id)
+static void __init hpet_reserve_platform_timers(void)
 {
-	struct hpet __iomem *hpet = hpet_virt_address;
-	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
-	unsigned int nrtimers, i;
 	struct hpet_data hd;
-
-	nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
+	unsigned int i;
 
 	memset(&hd, 0, sizeof(hd));
 	hd.hd_phys_address	= hpet_address;
-	hd.hd_address		= hpet;
-	hd.hd_nirqs		= nrtimers;
+	hd.hd_address		= hpet_virt_address;
+	hd.hd_nirqs		= hpet_base.nr_channels;
 	hpet_reserve_timer(&hd, 0);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
@@ -216,10 +212,8 @@ static void __init hpet_reserve_platform_timers(unsigned int id)
 	hd.hd_irq[0] = HPET_LEGACY_8254;
 	hd.hd_irq[1] = HPET_LEGACY_RTC;
 
-	for (i = 2; i < nrtimers; timer++, i++) {
-		hd.hd_irq[i] = (readl(&timer->hpet_config) &
-			Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT;
-	}
+	for (i = 2; i < hpet_base.nr_channels; i++)
+		hd.hd_irq[i] = hpet_base.channels[i].irq;
 
 	hpet_reserve_msi_timers(&hd);
 
@@ -227,7 +221,7 @@ static void __init hpet_reserve_platform_timers(unsigned int id)
 
 }
 #else
-static void hpet_reserve_platform_timers(unsigned int id) { }
+static inline void hpet_reserve_platform_timers(void) { }
 #endif
 
 /* Common HPET functions */
@@ -569,7 +563,7 @@ static struct hpet_dev *hpet_get_unused_timer(void)
 	if (!hpet_devs)
 		return NULL;
 
-	for (i = 0; i < hpet_num_timers; i++) {
+	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_dev *hdev = &hpet_devs[i];
 
 		if (!(hdev->flags & HPET_DEV_VALID))
@@ -612,7 +606,6 @@ static int hpet_cpuhp_dead(unsigned int cpu)
 
 static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 {
-	unsigned int id;
 	unsigned int num_timers;
 	unsigned int num_timers_used = 0;
 	int i, irq;
@@ -622,10 +615,8 @@ static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 
 	if (boot_cpu_has(X86_FEATURE_ARAT))
 		return;
-	id = hpet_readl(HPET_ID);
 
-	num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
-	num_timers++; /* Value read out starts from 0 */
+	num_timers = hpet_base.nr_channels;
 	hpet_print_config();
 
 	hpet_domain = hpet_create_irq_domain(hpet_blockid);
@@ -636,11 +627,9 @@ static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 	if (!hpet_devs)
 		return;
 
-	hpet_num_timers = num_timers;
-
 	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
 		struct hpet_dev *hdev = &hpet_devs[num_timers_used];
-		unsigned int cfg = hpet_readl(HPET_Tn_CFG(i));
+		unsigned int cfg = hpet_base.channels[i].boot_cfg;
 
 		/* Only consider HPET timer with MSI support */
 		if (!(cfg & HPET_TN_FSB_CAP))
@@ -676,7 +665,7 @@ static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 	if (!hpet_devs)
 		return;
 
-	for (i = 0; i < hpet_num_timers; i++) {
+	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_dev *hdev = &hpet_devs[i];
 
 		if (!(hdev->flags & HPET_DEV_VALID))
@@ -869,7 +858,7 @@ static bool __init hpet_counting(void)
  */
 int __init hpet_enable(void)
 {
-	u32 hpet_period, cfg, id;
+	u32 hpet_period, cfg, id, irq;
 	unsigned int i, channels;
 	struct hpet_channel *hc;
 	u64 freq;
@@ -940,6 +929,8 @@ int __init hpet_enable(void)
 
 		cfg = hpet_readl(HPET_Tn_CFG(i));
 		hc->boot_cfg = cfg;
+		irq = (cfg & Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT;
+		hc->irq = irq;
 
 		cfg &= ~(HPET_TN_ENABLE | HPET_TN_LEVEL | HPET_TN_FSB);
 		hpet_writel(cfg, HPET_Tn_CFG(i));
@@ -993,7 +984,7 @@ static __init int hpet_late_init(void)
 	else
 		hpet_msi_capability_lookup(0);
 
-	hpet_reserve_platform_timers(hpet_readl(HPET_ID));
+	hpet_reserve_platform_timers();
 	hpet_print_config();
 
 	if (hpet_msi_disable)

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Add mode information to struct hpet_channel
  2019-06-23 13:24 ` [patch 20/29] x86/hpet: Add mode information to struct hpet_channel Thomas Gleixner
@ 2019-06-27 23:47   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:47 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ricardo.neri-calderon, linux-kernel, peterz, ashok.raj, hpa,
	mingo, ravi.v.shankar, eranian, andi.kleen, tglx,
	Suravee.Suthikulpanit

Commit-ID:  9e16e4933e48819a259b8967e72e5765349953b1
Gitweb:     https://git.kernel.org/tip/9e16e4933e48819a259b8967e72e5765349953b1
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:00 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:23 +0200

x86/hpet: Add mode information to struct hpet_channel

The usage of the individual HPET channels is not tracked in a central
place. The information is scattered in different data structures. Also the
HPET reservation in the HPET character device is split out into several
places which makes the code hard to follow.

Assigning a mode to the channel allows to consolidate the reservation code
and paves the way for further simplifications.

As a first step set the mode of the legacy channels when the HPET is in
legacy mode.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132435.911652981@linutronix.de

---
 arch/x86/kernel/hpet.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 8711f1fdef8f..3a8ec363d569 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -22,9 +22,17 @@ struct hpet_dev {
 	char				name[10];
 };
 
+enum hpet_mode {
+	HPET_MODE_UNUSED,
+	HPET_MODE_LEGACY,
+	HPET_MODE_CLOCKEVT,
+	HPET_MODE_DEVICE,
+};
+
 struct hpet_channel {
 	unsigned int			num;
 	unsigned int			irq;
+	enum hpet_mode			mode;
 	unsigned int			boot_cfg;
 };
 
@@ -947,6 +955,9 @@ int __init hpet_enable(void)
 
 	if (id & HPET_ID_LEGSUP) {
 		hpet_legacy_clockevent_register();
+		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
+		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
+			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
 		return 1;
 	}
 	return 0;

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Add function to select a /dev/hpet channel
  2019-06-23 13:24 ` [patch 21/29] x86/hpet: Add function to select a /dev/hpet channel Thomas Gleixner
@ 2019-06-27 23:48   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:48 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, eranian, Suravee.Suthikulpanit, tglx, ashok.raj,
	mingo, ravi.v.shankar, peterz, hpa, andi.kleen,
	ricardo.neri-calderon

Commit-ID:  af5a1dadf3fcf673906af1a1129b2b7528494ee5
Gitweb:     https://git.kernel.org/tip/af5a1dadf3fcf673906af1a1129b2b7528494ee5
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:01 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:23 +0200

x86/hpet: Add function to select a /dev/hpet channel

If CONFIG_HPET=y is enabled the x86 specific HPET code should reserve at
least one channel for the /dev/hpet character device, so that not all
channels are absorbed for per CPU clockevent devices.

Create a function to assign HPET_MODE_DEVICE so the rework of the
clockevents allocation code can utilize the mode information instead of
reducing the number of evaluated channels by #ifdef hackery.

The function is not yet used, but provided as a separate patch for ease of
review. It will be used when the rework of the clockevent selection takes
place.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.002758910@linutronix.de

---
 arch/x86/kernel/hpet.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 3a8ec363d569..640ff75cc523 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -228,8 +228,25 @@ static void __init hpet_reserve_platform_timers(void)
 	hpet_alloc(&hd);
 
 }
+
+static void __init hpet_select_device_channel(void)
+{
+	int i;
+
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
+
+		/* Associate the first unused channel to /dev/hpet */
+		if (hc->mode == HPET_MODE_UNUSED) {
+			hc->mode = HPET_MODE_DEVICE;
+			return;
+		}
+	}
+}
+
 #else
 static inline void hpet_reserve_platform_timers(void) { }
+static inline void hpet_select_device_channel(void) {}
 #endif
 
 /* Common HPET functions */

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Rename variables to prepare for switching to channels
  2019-06-23 13:24 ` [patch 22/29] x86/hpet: Rename variables to prepare for switching to channels Thomas Gleixner
@ 2019-06-27 23:49   ` tip-bot for Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Ingo Molnar @ 2019-06-27 23:49 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, ravi.v.shankar, linux-kernel, andi.kleen, eranian, mingo,
	Suravee.Suthikulpanit, ricardo.neri-calderon, peterz, tglx,
	ashok.raj

Commit-ID:  d415c7543140f77fe1d2d9d3942cbf51a9737993
Gitweb:     https://git.kernel.org/tip/d415c7543140f77fe1d2d9d3942cbf51a9737993
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Sun, 23 Jun 2019 15:24:02 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:24 +0200

x86/hpet: Rename variables to prepare for switching to channels

struct hpet_dev is gone with the next change as the clockevent storage
moves into struct hpet_channel. So the variable name hdev will not make
sense anymore. Ditto for timer vs. channel and similar details.

Doing the rename in the change makes the patch harder to review. Doing it
afterward is problematic vs. tracking down issues.  Doing it upfront is the
easiest solution as it does not change functionality.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.093113681@linutronix.de

---
 arch/x86/kernel/hpet.c | 124 ++++++++++++++++++++++++-------------------------
 1 file changed, 62 insertions(+), 62 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 640ff75cc523..32f21b429881 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -315,7 +315,7 @@ static void hpet_legacy_clockevent_register(void)
 	pr_debug("Clockevent registered\n");
 }
 
-static int hpet_set_periodic(struct clock_event_device *evt, int timer)
+static int hpet_set_periodic(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg, cmp, now;
 	uint64_t delta;
@@ -325,11 +325,11 @@ static int hpet_set_periodic(struct clock_event_device *evt, int timer)
 	delta >>= evt->shift;
 	now = hpet_readl(HPET_COUNTER);
 	cmp = now + (unsigned int)delta;
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
 	       HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
-	hpet_writel(cmp, HPET_Tn_CMP(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
+	hpet_writel(cmp, HPET_Tn_CMP(channel));
 	udelay(1);
 	/*
 	 * HPET on AMD 81xx needs a second write (with HPET_TN_SETVAL
@@ -338,32 +338,32 @@ static int hpet_set_periodic(struct clock_event_device *evt, int timer)
 	 * (See AMD-8111 HyperTransport I/O Hub Data Sheet,
 	 * Publication # 24674)
 	 */
-	hpet_writel((unsigned int)delta, HPET_Tn_CMP(timer));
+	hpet_writel((unsigned int)delta, HPET_Tn_CMP(channel));
 	hpet_start_counter();
 	hpet_print_config();
 
 	return 0;
 }
 
-static int hpet_set_oneshot(struct clock_event_device *evt, int timer)
+static int hpet_set_oneshot(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg;
 
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg &= ~HPET_TN_PERIODIC;
 	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
 
 	return 0;
 }
 
-static int hpet_shutdown(struct clock_event_device *evt, int timer)
+static int hpet_shutdown(struct clock_event_device *evt, int channel)
 {
 	unsigned int cfg;
 
-	cfg = hpet_readl(HPET_Tn_CFG(timer));
+	cfg = hpet_readl(HPET_Tn_CFG(channel));
 	cfg &= ~HPET_TN_ENABLE;
-	hpet_writel(cfg, HPET_Tn_CFG(timer));
+	hpet_writel(cfg, HPET_Tn_CFG(channel));
 
 	return 0;
 }
@@ -460,30 +460,30 @@ static struct clock_event_device hpet_clockevent = {
 
 void hpet_msi_unmask(struct irq_data *data)
 {
-	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);
+	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
 	/* unmask it */
-	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
+	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
-	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
+	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
 void hpet_msi_mask(struct irq_data *data)
 {
-	struct hpet_dev *hdev = irq_data_get_irq_handler_data(data);
+	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
 	/* mask it */
-	cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
+	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
-	hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
+	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
-void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_dev *hc, struct msi_msg *msg)
 {
-	hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
-	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
+	hpet_writel(msg->data, HPET_Tn_ROUTE(hc->num));
+	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
 }
 
 static int hpet_msi_shutdown(struct clock_event_device *evt)
@@ -503,13 +503,13 @@ static int hpet_msi_set_periodic(struct clock_event_device *evt)
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hdev = clockevent_to_channel(evt);
-	struct irq_data *data = irq_get_irq_data(hdev->irq);
+	struct hpet_dev *hc = clockevent_to_channel(evt);
+	struct irq_data *data = irq_get_irq_data(hc->irq);
 	struct msi_msg msg;
 
 	/* Restore the MSI msg and unmask the interrupt */
 	irq_chip_compose_msi_msg(data, &msg);
-	hpet_msi_write(hdev, &msg);
+	hpet_msi_write(hc, &msg);
 	hpet_msi_unmask(data);
 	return 0;
 }
@@ -522,11 +522,11 @@ static int hpet_msi_next_event(unsigned long delta,
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *dev = data;
-	struct clock_event_device *evt = &dev->evt;
+	struct hpet_dev *hc = data;
+	struct clock_event_device *evt = &hc->evt;
 
 	if (!evt->event_handler) {
-		pr_info("Spurious interrupt HPET timer %d\n", dev->num);
+		pr_info("Spurious interrupt HPET channel %d\n", hc->num);
 		return IRQ_HANDLED;
 	}
 
@@ -551,22 +551,22 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 	return 0;
 }
 
-static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
+static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
 {
-	struct clock_event_device *evt = &hdev->evt;
+	struct clock_event_device *evt = &hc->evt;
 
-	if (!(hdev->flags & HPET_DEV_VALID))
+	if (!(hc->flags & HPET_DEV_VALID))
 		return;
 
-	hdev->cpu = cpu;
-	per_cpu(cpu_hpet_dev, cpu) = hdev;
-	evt->name = hdev->name;
-	hpet_setup_irq(hdev);
-	evt->irq = hdev->irq;
+	hc->cpu = cpu;
+	per_cpu(cpu_hpet_dev, cpu) = hc;
+	evt->name = hc->name;
+	hpet_setup_irq(hc);
+	evt->irq = hc->irq;
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hdev->flags & HPET_DEV_PERI_CAP) {
+	if (hc->flags & HPET_DEV_PERI_CAP) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
 		evt->set_state_periodic = hpet_msi_set_periodic;
 	}
@@ -575,7 +575,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 	evt->set_state_oneshot = hpet_msi_set_oneshot;
 	evt->tick_resume = hpet_msi_resume;
 	evt->set_next_event = hpet_msi_next_event;
-	evt->cpumask = cpumask_of(hdev->cpu);
+	evt->cpumask = cpumask_of(hc->cpu);
 
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
 					0x7FFFFFFF);
@@ -589,35 +589,35 @@ static struct hpet_dev *hpet_get_unused_timer(void)
 		return NULL;
 
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
+		struct hpet_dev *hc = &hpet_devs[i];
 
-		if (!(hdev->flags & HPET_DEV_VALID))
+		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
 		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hdev->flags))
+			(unsigned long *)&hc->flags))
 			continue;
-		return hdev;
+		return hc;
 	}
 	return NULL;
 }
 
 static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hdev = hpet_get_unused_timer();
+	struct hpet_dev *hc = hpet_get_unused_timer();
 
-	if (hdev)
-		init_one_hpet_msi_clockevent(hdev, cpu);
+	if (hc)
+		init_one_hpet_msi_clockevent(hc, cpu);
 	return 0;
 }
 
 static int hpet_cpuhp_dead(unsigned int cpu)
 {
-	struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
+	struct hpet_dev *hc = per_cpu(cpu_hpet_dev, cpu);
 
-	if (!hdev)
+	if (!hc)
 		return 0;
-	free_irq(hdev->irq, hdev);
-	hdev->flags &= ~HPET_DEV_USED;
+	free_irq(hc->irq, hc);
+	hc->flags &= ~HPET_DEV_USED;
 	per_cpu(cpu_hpet_dev, cpu) = NULL;
 	return 0;
 }
@@ -653,26 +653,26 @@ static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 		return;
 
 	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
-		struct hpet_dev *hdev = &hpet_devs[num_timers_used];
+		struct hpet_dev *hc = &hpet_devs[num_timers_used];
 		unsigned int cfg = hpet_base.channels[i].boot_cfg;
 
 		/* Only consider HPET timer with MSI support */
 		if (!(cfg & HPET_TN_FSB_CAP))
 			continue;
 
-		hdev->flags = 0;
+		hc->flags = 0;
 		if (cfg & HPET_TN_PERIODIC_CAP)
-			hdev->flags |= HPET_DEV_PERI_CAP;
-		sprintf(hdev->name, "hpet%d", i);
-		hdev->num = i;
+			hc->flags |= HPET_DEV_PERI_CAP;
+		sprintf(hc->name, "hpet%d", i);
+		hc->num = i;
 
-		irq = hpet_assign_irq(hpet_domain, hdev, hdev->num);
+		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
 		if (irq <= 0)
 			continue;
 
-		hdev->irq = irq;
-		hdev->flags |= HPET_DEV_FSB_CAP;
-		hdev->flags |= HPET_DEV_VALID;
+		hc->irq = irq;
+		hc->flags |= HPET_DEV_FSB_CAP;
+		hc->flags |= HPET_DEV_VALID;
 		num_timers_used++;
 		if (num_timers_used == num_possible_cpus())
 			break;
@@ -691,13 +691,13 @@ static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 		return;
 
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hdev = &hpet_devs[i];
+		struct hpet_dev *hc = &hpet_devs[i];
 
-		if (!(hdev->flags & HPET_DEV_VALID))
+		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
 
-		hd->hd_irq[hdev->num] = hdev->irq;
-		hpet_reserve_timer(hd, hdev->num);
+		hd->hd_irq[hc->num] = hc->irq;
+		hpet_reserve_timer(hd, hc->num);
 	}
 }
 #endif
@@ -1138,8 +1138,8 @@ void hpet_unregister_irq_handler(rtc_irq_handler handler)
 EXPORT_SYMBOL_GPL(hpet_unregister_irq_handler);
 
 /*
- * Timer 1 for RTC emulation. We use one shot mode, as periodic mode
- * is not supported by all HPET implementations for timer 1.
+ * Channel 1 for RTC emulation. We use one shot mode, as periodic mode
+ * is not supported by all HPET implementations for channel 1.
  *
  * hpet_rtc_timer_init() is called when the rtc is initialized.
  */

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Move clockevents into channels
  2019-06-23 13:24 ` [patch 23/29] x86/hpet: Move clockevents into channels Thomas Gleixner
@ 2019-06-27 23:49   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:49 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, peterz, linux-kernel, ashok.raj, eranian,
	ricardo.neri-calderon, tglx, mingo, andi.kleen,
	Suravee.Suthikulpanit, ravi.v.shankar

Commit-ID:  4d5e68330df4e79633bcde2bebcbfed1ba0421d5
Gitweb:     https://git.kernel.org/tip/4d5e68330df4e79633bcde2bebcbfed1ba0421d5
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:03 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:24 +0200

x86/hpet: Move clockevents into channels

Instead of allocating yet another data structure, move the clock event data
into the channel structure. This allows further consolidation of the
reservation code and the reuse of the cached boot config to replace the
extra flags in the clockevent data.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.185851116@linutronix.de

---
 arch/x86/include/asm/hpet.h |   6 +-
 arch/x86/kernel/apic/msi.c  |   4 +-
 arch/x86/kernel/hpet.c      | 139 +++++++++++++++++++-------------------------
 3 files changed, 64 insertions(+), 85 deletions(-)

diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index e3209f5de65d..6352dee37cda 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -75,15 +75,15 @@ extern unsigned int hpet_readl(unsigned int a);
 extern void force_hpet_resume(void);
 
 struct irq_data;
-struct hpet_dev;
+struct hpet_channel;
 struct irq_domain;
 
 extern void hpet_msi_unmask(struct irq_data *data);
 extern void hpet_msi_mask(struct irq_data *data);
-extern void hpet_msi_write(struct hpet_dev *hdev, struct msi_msg *msg);
+extern void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg);
 extern struct irq_domain *hpet_create_irq_domain(int hpet_id);
 extern int hpet_assign_irq(struct irq_domain *domain,
-			   struct hpet_dev *dev, int dev_num);
+			   struct hpet_channel *hc, int dev_num);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
index dad0dd759de2..7f7533462474 100644
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -370,14 +370,14 @@ struct irq_domain *hpet_create_irq_domain(int hpet_id)
 	return d;
 }
 
-int hpet_assign_irq(struct irq_domain *domain, struct hpet_dev *dev,
+int hpet_assign_irq(struct irq_domain *domain, struct hpet_channel *hc,
 		    int dev_num)
 {
 	struct irq_alloc_info info;
 
 	init_irq_alloc_info(&info, NULL);
 	info.type = X86_IRQ_ALLOC_TYPE_HPET;
-	info.hpet_data = dev;
+	info.hpet_data = hc;
 	info.hpet_id = hpet_dev_id(domain);
 	info.hpet_index = dev_num;
 
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 32f21b429881..7f76f07138a6 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -13,15 +13,6 @@
 #undef  pr_fmt
 #define pr_fmt(fmt) "hpet: " fmt
 
-struct hpet_dev {
-	struct clock_event_device	evt;
-	unsigned int			num;
-	int				cpu;
-	unsigned int			irq;
-	unsigned int			flags;
-	char				name[10];
-};
-
 enum hpet_mode {
 	HPET_MODE_UNUSED,
 	HPET_MODE_LEGACY,
@@ -30,14 +21,19 @@ enum hpet_mode {
 };
 
 struct hpet_channel {
+	struct clock_event_device	evt;
 	unsigned int			num;
+	unsigned int			cpu;
 	unsigned int			irq;
 	enum hpet_mode			mode;
+	unsigned int			flags;
 	unsigned int			boot_cfg;
+	char				name[10];
 };
 
 struct hpet_base {
 	unsigned int			nr_channels;
+	unsigned int			nr_clockevents;
 	unsigned int			boot_cfg;
 	struct hpet_channel		*channels;
 };
@@ -61,8 +57,7 @@ u8					hpet_blockid; /* OS timer block num */
 bool					hpet_msi_disable;
 
 #ifdef CONFIG_PCI_MSI
-static struct hpet_dev			*hpet_devs;
-static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
+static DEFINE_PER_CPU(struct hpet_channel *, cpu_hpet_channel);
 static struct irq_domain		*hpet_domain;
 #endif
 
@@ -79,9 +74,9 @@ static bool				hpet_verbose;
 static struct clock_event_device	hpet_clockevent;
 
 static inline
-struct hpet_dev *clockevent_to_channel(struct clock_event_device *evt)
+struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
 {
-	return container_of(evt, struct hpet_dev, evt);
+	return container_of(evt, struct hpet_channel, evt);
 }
 
 inline unsigned int hpet_readl(unsigned int a)
@@ -460,10 +455,9 @@ static struct clock_event_device hpet_clockevent = {
 
 void hpet_msi_unmask(struct irq_data *data)
 {
-	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
+	struct hpet_channel *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
-	/* unmask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
 	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
@@ -471,16 +465,15 @@ void hpet_msi_unmask(struct irq_data *data)
 
 void hpet_msi_mask(struct irq_data *data)
 {
-	struct hpet_dev *hc = irq_data_get_irq_handler_data(data);
+	struct hpet_channel *hc = irq_data_get_irq_handler_data(data);
 	unsigned int cfg;
 
-	/* mask it */
 	cfg = hpet_readl(HPET_Tn_CFG(hc->num));
 	cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
 	hpet_writel(cfg, HPET_Tn_CFG(hc->num));
 }
 
-void hpet_msi_write(struct hpet_dev *hc, struct msi_msg *msg)
+void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg)
 {
 	hpet_writel(msg->data, HPET_Tn_ROUTE(hc->num));
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
@@ -503,7 +496,7 @@ static int hpet_msi_set_periodic(struct clock_event_device *evt)
 
 static int hpet_msi_resume(struct clock_event_device *evt)
 {
-	struct hpet_dev *hc = clockevent_to_channel(evt);
+	struct hpet_channel *hc = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hc->irq);
 	struct msi_msg msg;
 
@@ -522,7 +515,7 @@ static int hpet_msi_next_event(unsigned long delta,
 
 static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 {
-	struct hpet_dev *hc = data;
+	struct hpet_channel *hc = data;
 	struct clock_event_device *evt = &hc->evt;
 
 	if (!evt->event_handler) {
@@ -534,24 +527,23 @@ static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int hpet_setup_irq(struct hpet_dev *dev)
+static int hpet_setup_irq(struct hpet_channel *hc)
 {
-
-	if (request_irq(dev->irq, hpet_interrupt_handler,
+	if (request_irq(hc->irq, hpet_interrupt_handler,
 			IRQF_TIMER | IRQF_NOBALANCING,
-			dev->name, dev))
+			hc->name, hc))
 		return -1;
 
-	disable_irq(dev->irq);
-	irq_set_affinity(dev->irq, cpumask_of(dev->cpu));
-	enable_irq(dev->irq);
+	disable_irq(hc->irq);
+	irq_set_affinity(hc->irq, cpumask_of(hc->cpu));
+	enable_irq(hc->irq);
 
-	pr_debug("%s irq %d for MSI\n", dev->name, dev->irq);
+	pr_debug("%s irq %u for MSI\n", hc->name, hc->irq);
 
 	return 0;
 }
 
-static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
+static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 {
 	struct clock_event_device *evt = &hc->evt;
 
@@ -559,7 +551,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
 		return;
 
 	hc->cpu = cpu;
-	per_cpu(cpu_hpet_dev, cpu) = hc;
+	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
 	hpet_setup_irq(hc);
 	evt->irq = hc->irq;
@@ -581,15 +573,12 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hc, int cpu)
 					0x7FFFFFFF);
 }
 
-static struct hpet_dev *hpet_get_unused_timer(void)
+static struct hpet_channel *hpet_get_unused_clockevent(void)
 {
 	int i;
 
-	if (!hpet_devs)
-		return NULL;
-
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hc = &hpet_devs[i];
+		struct hpet_channel *hc = hpet_base.channels + i;
 
 		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
@@ -603,7 +592,7 @@ static struct hpet_dev *hpet_get_unused_timer(void)
 
 static int hpet_cpuhp_online(unsigned int cpu)
 {
-	struct hpet_dev *hc = hpet_get_unused_timer();
+	struct hpet_channel *hc = hpet_get_unused_clockevent();
 
 	if (hc)
 		init_one_hpet_msi_clockevent(hc, cpu);
@@ -612,59 +601,47 @@ static int hpet_cpuhp_online(unsigned int cpu)
 
 static int hpet_cpuhp_dead(unsigned int cpu)
 {
-	struct hpet_dev *hc = per_cpu(cpu_hpet_dev, cpu);
+	struct hpet_channel *hc = per_cpu(cpu_hpet_channel, cpu);
 
 	if (!hc)
 		return 0;
 	free_irq(hc->irq, hc);
 	hc->flags &= ~HPET_DEV_USED;
-	per_cpu(cpu_hpet_dev, cpu) = NULL;
+	per_cpu(cpu_hpet_channel, cpu) = NULL;
 	return 0;
 }
 
-#ifdef CONFIG_HPET
-/* Reserve at least one timer for userspace (/dev/hpet) */
-#define RESERVE_TIMERS 1
-#else
-#define RESERVE_TIMERS 0
-#endif
-
-static void __init hpet_msi_capability_lookup(unsigned int start_timer)
+static void __init hpet_select_clockevents(void)
 {
-	unsigned int num_timers;
-	unsigned int num_timers_used = 0;
-	int i, irq;
+	unsigned int i;
 
-	if (hpet_msi_disable)
-		return;
+	hpet_base.nr_clockevents = 0;
 
-	if (boot_cpu_has(X86_FEATURE_ARAT))
+	/* No point if MSI is disabled or CPU has an Always Runing APIC Timer */
+	if (hpet_msi_disable || boot_cpu_has(X86_FEATURE_ARAT))
 		return;
 
-	num_timers = hpet_base.nr_channels;
 	hpet_print_config();
 
 	hpet_domain = hpet_create_irq_domain(hpet_blockid);
 	if (!hpet_domain)
 		return;
 
-	hpet_devs = kcalloc(num_timers, sizeof(struct hpet_dev), GFP_KERNEL);
-	if (!hpet_devs)
-		return;
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
+		int irq;
 
-	for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
-		struct hpet_dev *hc = &hpet_devs[num_timers_used];
-		unsigned int cfg = hpet_base.channels[i].boot_cfg;
+		if (hc->mode != HPET_MODE_UNUSED)
+			continue;
 
-		/* Only consider HPET timer with MSI support */
-		if (!(cfg & HPET_TN_FSB_CAP))
+		/* Only consider HPET channel with MSI support */
+		if (!(hc->boot_cfg & HPET_TN_FSB_CAP))
 			continue;
 
 		hc->flags = 0;
-		if (cfg & HPET_TN_PERIODIC_CAP)
+		if (hc->boot_cfg & HPET_TN_PERIODIC_CAP)
 			hc->flags |= HPET_DEV_PERI_CAP;
 		sprintf(hc->name, "hpet%d", i);
-		hc->num = i;
 
 		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
 		if (irq <= 0)
@@ -673,13 +650,14 @@ static void __init hpet_msi_capability_lookup(unsigned int start_timer)
 		hc->irq = irq;
 		hc->flags |= HPET_DEV_FSB_CAP;
 		hc->flags |= HPET_DEV_VALID;
-		num_timers_used++;
-		if (num_timers_used == num_possible_cpus())
+		hc->mode = HPET_MODE_CLOCKEVT;
+
+		if (++hpet_base.nr_clockevents == num_possible_cpus())
 			break;
 	}
 
 	pr_info("%d channels of %d reserved for per-cpu timers\n",
-		num_timers, num_timers_used);
+		hpet_base.nr_channels, hpet_base.nr_clockevents);
 }
 
 #ifdef CONFIG_HPET
@@ -687,11 +665,8 @@ static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 {
 	int i;
 
-	if (!hpet_devs)
-		return;
-
 	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_dev *hc = &hpet_devs[i];
+		struct hpet_channel *hc = hpet_base.channels + i;
 
 		if (!(hc->flags & HPET_DEV_VALID))
 			continue;
@@ -704,7 +679,7 @@ static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
 
 #else
 
-static inline void hpet_msi_capability_lookup(unsigned int start_timer) { }
+static inline void hpet_select_clockevents(void) { }
 
 #ifdef CONFIG_HPET
 static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
@@ -991,6 +966,16 @@ out_nohpet:
 /*
  * The late initialization runs after the PCI quirks have been invoked
  * which might have detected a system on which the HPET can be enforced.
+ *
+ * Also, the MSI machinery is not working yet when the HPET is initialized
+ * early.
+ *
+ * If the HPET is enabled, then:
+ *
+ *  1) Reserve one channel for /dev/hpet if CONFIG_HPET=y
+ *  2) Reserve up to num_possible_cpus() channels as per CPU clockevents
+ *  3) Setup /dev/hpet if CONFIG_HPET=y
+ *  4) Register hotplug callbacks when clockevents are available
  */
 static __init int hpet_late_init(void)
 {
@@ -1007,18 +992,12 @@ static __init int hpet_late_init(void)
 	if (!hpet_virt_address)
 		return -ENODEV;
 
-	if (hpet_readl(HPET_ID) & HPET_ID_LEGSUP)
-		hpet_msi_capability_lookup(2);
-	else
-		hpet_msi_capability_lookup(0);
-
+	hpet_select_device_channel();
+	hpet_select_clockevents();
 	hpet_reserve_platform_timers();
 	hpet_print_config();
 
-	if (hpet_msi_disable)
-		return 0;
-
-	if (boot_cpu_has(X86_FEATURE_ARAT))
+	if (!hpet_base.nr_clockevents)
 		return 0;
 
 	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "x86/hpet:online",

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Use cached info instead of extra flags
  2019-06-23 13:24 ` [patch 24/29] x86/hpet: Use cached info instead of extra flags Thomas Gleixner
  2019-06-26 21:20   ` Ingo Molnar
@ 2019-06-27 23:50   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:50 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi.kleen, ricardo.neri-calderon, eranian, linux-kernel, mingo,
	ravi.v.shankar, tglx, Suravee.Suthikulpanit, peterz, ashok.raj,
	hpa

Commit-ID:  45e0a415634600e608188480bc355b20344f9e3f
Gitweb:     https://git.kernel.org/tip/45e0a415634600e608188480bc355b20344f9e3f
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:04 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:25 +0200

x86/hpet: Use cached info instead of extra flags

Now that HPET clockevent support is integrated into the channel data, reuse
the cached boot configuration instead of copying the same information into
a flags field.

This also allows to consolidate the reservation code into one place, which
can now solely depend on the mode information.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.277510163@linutronix.de

---
 arch/x86/kernel/hpet.c | 76 +++++++++++++++-----------------------------------
 1 file changed, 23 insertions(+), 53 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 7f76f07138a6..985a2246d20c 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -25,8 +25,8 @@ struct hpet_channel {
 	unsigned int			num;
 	unsigned int			cpu;
 	unsigned int			irq;
+	unsigned int			in_use;
 	enum hpet_mode			mode;
-	unsigned int			flags;
 	unsigned int			boot_cfg;
 	char				name[10];
 };
@@ -40,12 +40,6 @@ struct hpet_base {
 
 #define HPET_MASK			CLOCKSOURCE_MASK(32)
 
-#define HPET_DEV_USED_BIT		2
-#define HPET_DEV_USED			(1 << HPET_DEV_USED_BIT)
-#define HPET_DEV_VALID			0x8
-#define HPET_DEV_FSB_CAP		0x1000
-#define HPET_DEV_PERI_CAP		0x2000
-
 #define HPET_MIN_CYCLES			128
 #define HPET_MIN_PROG_DELTA		(HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
 
@@ -62,6 +56,7 @@ static struct irq_domain		*hpet_domain;
 #endif
 
 static void __iomem			*hpet_virt_address;
+
 static struct hpet_base			hpet_base;
 
 static bool				hpet_legacy_int_enabled;
@@ -190,8 +185,6 @@ do {								\
  */
 #ifdef CONFIG_HPET
 
-static void hpet_reserve_msi_timers(struct hpet_data *hd);
-
 static void __init hpet_reserve_platform_timers(void)
 {
 	struct hpet_data hd;
@@ -201,11 +194,6 @@ static void __init hpet_reserve_platform_timers(void)
 	hd.hd_phys_address	= hpet_address;
 	hd.hd_address		= hpet_virt_address;
 	hd.hd_nirqs		= hpet_base.nr_channels;
-	hpet_reserve_timer(&hd, 0);
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-	hpet_reserve_timer(&hd, 1);
-#endif
 
 	/*
 	 * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254
@@ -215,13 +203,25 @@ static void __init hpet_reserve_platform_timers(void)
 	hd.hd_irq[0] = HPET_LEGACY_8254;
 	hd.hd_irq[1] = HPET_LEGACY_RTC;
 
-	for (i = 2; i < hpet_base.nr_channels; i++)
-		hd.hd_irq[i] = hpet_base.channels[i].irq;
+	for (i = 0; i < hpet_base.nr_channels; i++) {
+		struct hpet_channel *hc = hpet_base.channels + i;
 
-	hpet_reserve_msi_timers(&hd);
+		if (i >= 2)
+			hd.hd_irq[i] = hc->irq;
 
-	hpet_alloc(&hd);
+		switch (hc->mode) {
+		case HPET_MODE_UNUSED:
+		case HPET_MODE_DEVICE:
+			hc->mode = HPET_MODE_DEVICE;
+			break;
+		case HPET_MODE_CLOCKEVT:
+		case HPET_MODE_LEGACY:
+			hpet_reserve_timer(&hd, hc->num);
+			break;
+		}
+	}
 
+	hpet_alloc(&hd);
 }
 
 static void __init hpet_select_device_channel(void)
@@ -543,13 +543,11 @@ static int hpet_setup_irq(struct hpet_channel *hc)
 	return 0;
 }
 
+/* Invoked from the hotplug callback on @cpu */
 static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 {
 	struct clock_event_device *evt = &hc->evt;
 
-	if (!(hc->flags & HPET_DEV_VALID))
-		return;
-
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
@@ -558,7 +556,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hc->flags & HPET_DEV_PERI_CAP) {
+	if (hc->boot_cfg & HPET_TN_PERIODIC) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
 		evt->set_state_periodic = hpet_msi_set_periodic;
 	}
@@ -580,11 +578,9 @@ static struct hpet_channel *hpet_get_unused_clockevent(void)
 	for (i = 0; i < hpet_base.nr_channels; i++) {
 		struct hpet_channel *hc = hpet_base.channels + i;
 
-		if (!(hc->flags & HPET_DEV_VALID))
-			continue;
-		if (test_and_set_bit(HPET_DEV_USED_BIT,
-			(unsigned long *)&hc->flags))
+		if (hc->mode != HPET_MODE_CLOCKEVT || hc->in_use)
 			continue;
+		hc->in_use = 1;
 		return hc;
 	}
 	return NULL;
@@ -606,7 +602,7 @@ static int hpet_cpuhp_dead(unsigned int cpu)
 	if (!hc)
 		return 0;
 	free_irq(hc->irq, hc);
-	hc->flags &= ~HPET_DEV_USED;
+	hc->in_use = 0;
 	per_cpu(cpu_hpet_channel, cpu) = NULL;
 	return 0;
 }
@@ -638,9 +634,6 @@ static void __init hpet_select_clockevents(void)
 		if (!(hc->boot_cfg & HPET_TN_FSB_CAP))
 			continue;
 
-		hc->flags = 0;
-		if (hc->boot_cfg & HPET_TN_PERIODIC_CAP)
-			hc->flags |= HPET_DEV_PERI_CAP;
 		sprintf(hc->name, "hpet%d", i);
 
 		irq = hpet_assign_irq(hpet_domain, hc, hc->num);
@@ -648,8 +641,6 @@ static void __init hpet_select_clockevents(void)
 			continue;
 
 		hc->irq = irq;
-		hc->flags |= HPET_DEV_FSB_CAP;
-		hc->flags |= HPET_DEV_VALID;
 		hc->mode = HPET_MODE_CLOCKEVT;
 
 		if (++hpet_base.nr_clockevents == num_possible_cpus())
@@ -660,31 +651,10 @@ static void __init hpet_select_clockevents(void)
 		hpet_base.nr_channels, hpet_base.nr_clockevents);
 }
 
-#ifdef CONFIG_HPET
-static void __init hpet_reserve_msi_timers(struct hpet_data *hd)
-{
-	int i;
-
-	for (i = 0; i < hpet_base.nr_channels; i++) {
-		struct hpet_channel *hc = hpet_base.channels + i;
-
-		if (!(hc->flags & HPET_DEV_VALID))
-			continue;
-
-		hd->hd_irq[hc->num] = hc->irq;
-		hpet_reserve_timer(hd, hc->num);
-	}
-}
-#endif
-
 #else
 
 static inline void hpet_select_clockevents(void) { }
 
-#ifdef CONFIG_HPET
-static inline void hpet_reserve_msi_timers(struct hpet_data *hd) { }
-#endif
-
 #define hpet_cpuhp_online	NULL
 #define hpet_cpuhp_dead		NULL
 

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Wrap legacy clockevent in hpet_channel
  2019-06-23 13:24 ` [patch 25/29] x86/hpet: Wrap legacy clockevent in hpet_channel Thomas Gleixner
@ 2019-06-27 23:51   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:51 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, mingo, ashok.raj, linux-kernel, Suravee.Suthikulpanit,
	peterz, ricardo.neri-calderon, andi.kleen, ravi.v.shankar, tglx,
	hpa

Commit-ID:  18e84a2dff00c3c817161a105332cd3fc7592648
Gitweb:     https://git.kernel.org/tip/18e84a2dff00c3c817161a105332cd3fc7592648
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:05 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:25 +0200

x86/hpet: Wrap legacy clockevent in hpet_channel

For HPET channel 0 there exist two clockevent structures right now:
  - the static hpet_clockevent
  - the clockevent in channel 0 storage

The goal is to use the clockevent in the channel storage, remove the static
variable and share code with the MSI implementation.

As a first step wrap the legacy clockevent into a hpet_channel struct and
convert the users.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.368141247@linutronix.de

---
 arch/x86/kernel/hpet.c | 49 +++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 985a2246d20c..19e3ac81c3b9 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,7 +66,7 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
-static struct clock_event_device	hpet_clockevent;
+static struct hpet_channel		hpet_channel0;
 
 static inline
 struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
@@ -294,7 +294,7 @@ static void hpet_enable_legacy_int(void)
 	hpet_legacy_int_enabled = true;
 }
 
-static void hpet_legacy_clockevent_register(void)
+static void hpet_legacy_clockevent_register(struct hpet_channel *hc)
 {
 	/* Start HPET legacy interrupts */
 	hpet_enable_legacy_int();
@@ -303,10 +303,10 @@ static void hpet_legacy_clockevent_register(void)
 	 * Start HPET with the boot CPU's cpumask and make it global after
 	 * the IO_APIC has been initialized.
 	 */
-	hpet_clockevent.cpumask = cpumask_of(boot_cpu_data.cpu_index);
-	clockevents_config_and_register(&hpet_clockevent, hpet_freq,
+	hc->evt.cpumask = cpumask_of(boot_cpu_data.cpu_index);
+	clockevents_config_and_register(&hc->evt, hpet_freq,
 					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
-	global_clock_event = &hpet_clockevent;
+	global_clock_event = &hc->evt;
 	pr_debug("Clockevent registered\n");
 }
 
@@ -433,19 +433,21 @@ static int hpet_legacy_next_event(unsigned long delta,
 }
 
 /*
- * The HPET clock event device
+ * The HPET clock event device wrapped in a channel for conversion
  */
-static struct clock_event_device hpet_clockevent = {
-	.name			= "hpet",
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.set_state_periodic	= hpet_legacy_set_periodic,
-	.set_state_oneshot	= hpet_legacy_set_oneshot,
-	.set_state_shutdown	= hpet_legacy_shutdown,
-	.tick_resume		= hpet_legacy_resume,
-	.set_next_event		= hpet_legacy_next_event,
-	.irq			= 0,
-	.rating			= 50,
+static struct hpet_channel hpet_channel0 = {
+	.evt = {
+		.name			= "hpet",
+		.features		= CLOCK_EVT_FEAT_PERIODIC |
+					  CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_periodic	= hpet_legacy_set_periodic,
+		.set_state_oneshot	= hpet_legacy_set_oneshot,
+		.set_state_shutdown	= hpet_legacy_shutdown,
+		.tick_resume		= hpet_legacy_resume,
+		.set_next_event		= hpet_legacy_next_event,
+		.irq			= 0,
+		.rating			= 50,
+	}
 };
 
 /*
@@ -916,7 +918,7 @@ int __init hpet_enable(void)
 	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
-		hpet_legacy_clockevent_register();
+		hpet_legacy_clockevent_register(&hpet_channel0);
 		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
 		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
 			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
@@ -1101,10 +1103,11 @@ int hpet_rtc_timer_init(void)
 		return 0;
 
 	if (!hpet_default_delta) {
+		struct clock_event_device *evt = &hpet_channel0.evt;
 		uint64_t clc;
 
-		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
-		clc >>= hpet_clockevent.shift + DEFAULT_RTC_SHIFT;
+		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
+		clc >>= evt->shift + DEFAULT_RTC_SHIFT;
 		hpet_default_delta = clc;
 	}
 
@@ -1198,9 +1201,11 @@ int hpet_set_periodic_freq(unsigned long freq)
 	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
 	} else {
-		clc = (uint64_t) hpet_clockevent.mult * NSEC_PER_SEC;
+		struct clock_event_device *evt = &hpet_channel0.evt;
+
+		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
 		do_div(clc, freq);
-		clc >>= hpet_clockevent.shift;
+		clc >>= evt->shift;
 		hpet_pie_delta = clc;
 		hpet_pie_limit = 0;
 	}

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Consolidate clockevent functions
  2019-06-23 13:24 ` [patch 26/29] x86/hpet: Consolidate clockevent functions Thomas Gleixner
  2019-06-26 21:17   ` Ingo Molnar
@ 2019-06-27 23:51   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:51 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, eranian, peterz, linux-kernel, ravi.v.shankar,
	ricardo.neri-calderon, Suravee.Suthikulpanit, mingo, andi.kleen,
	tglx, ashok.raj

Commit-ID:  310b5b3eb6ba5d3a92d783b9fa1c5a3ffb5932e9
Gitweb:     https://git.kernel.org/tip/310b5b3eb6ba5d3a92d783b9fa1c5a3ffb5932e9
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:06 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:26 +0200

x86/hpet: Consolidate clockevent functions

Now that the legacy clockevent is wrapped in a hpet_channel struct most
clockevent functions can be shared between the legacy and the MSI based
clockevents.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.461437795@linutronix.de

---
 arch/x86/kernel/hpet.c | 92 ++++++++++++++------------------------------------
 1 file changed, 25 insertions(+), 67 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 19e3ac81c3b9..47eb4d36864e 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -310,8 +310,9 @@ static void hpet_legacy_clockevent_register(struct hpet_channel *hc)
 	pr_debug("Clockevent registered\n");
 }
 
-static int hpet_set_periodic(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_set_state_periodic(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg, cmp, now;
 	uint64_t delta;
 
@@ -340,8 +341,9 @@ static int hpet_set_periodic(struct clock_event_device *evt, int channel)
 	return 0;
 }
 
-static int hpet_set_oneshot(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_set_state_oneshot(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg;
 
 	cfg = hpet_readl(HPET_Tn_CFG(channel));
@@ -352,8 +354,9 @@ static int hpet_set_oneshot(struct clock_event_device *evt, int channel)
 	return 0;
 }
 
-static int hpet_shutdown(struct clock_event_device *evt, int channel)
+static int hpet_clkevt_set_state_shutdown(struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	unsigned int cfg;
 
 	cfg = hpet_readl(HPET_Tn_CFG(channel));
@@ -363,15 +366,17 @@ static int hpet_shutdown(struct clock_event_device *evt, int channel)
 	return 0;
 }
 
-static int hpet_resume(struct clock_event_device *evt)
+static int hpet_clkevt_legacy_resume(struct clock_event_device *evt)
 {
 	hpet_enable_legacy_int();
 	hpet_print_config();
 	return 0;
 }
 
-static int hpet_next_event(unsigned long delta, int channel)
+static int
+hpet_clkevt_set_next_event(unsigned long delta, struct clock_event_device *evt)
 {
+	unsigned int channel = clockevent_to_channel(evt)->num;
 	u32 cnt;
 	s32 res;
 
@@ -406,32 +411,6 @@ static int hpet_next_event(unsigned long delta, int channel)
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
-static int hpet_legacy_shutdown(struct clock_event_device *evt)
-{
-	return hpet_shutdown(evt, 0);
-}
-
-static int hpet_legacy_set_oneshot(struct clock_event_device *evt)
-{
-	return hpet_set_oneshot(evt, 0);
-}
-
-static int hpet_legacy_set_periodic(struct clock_event_device *evt)
-{
-	return hpet_set_periodic(evt, 0);
-}
-
-static int hpet_legacy_resume(struct clock_event_device *evt)
-{
-	return hpet_resume(evt);
-}
-
-static int hpet_legacy_next_event(unsigned long delta,
-				  struct clock_event_device *evt)
-{
-	return hpet_next_event(delta, 0);
-}
-
 /*
  * The HPET clock event device wrapped in a channel for conversion
  */
@@ -440,11 +419,11 @@ static struct hpet_channel hpet_channel0 = {
 		.name			= "hpet",
 		.features		= CLOCK_EVT_FEAT_PERIODIC |
 					  CLOCK_EVT_FEAT_ONESHOT,
-		.set_state_periodic	= hpet_legacy_set_periodic,
-		.set_state_oneshot	= hpet_legacy_set_oneshot,
-		.set_state_shutdown	= hpet_legacy_shutdown,
-		.tick_resume		= hpet_legacy_resume,
-		.set_next_event		= hpet_legacy_next_event,
+		.set_state_periodic	= hpet_clkevt_set_state_periodic,
+		.set_state_oneshot	= hpet_clkevt_set_state_oneshot,
+		.set_state_shutdown	= hpet_clkevt_set_state_shutdown,
+		.tick_resume		= hpet_clkevt_legacy_resume,
+		.set_next_event		= hpet_clkevt_set_next_event,
 		.irq			= 0,
 		.rating			= 50,
 	}
@@ -481,22 +460,7 @@ void hpet_msi_write(struct hpet_channel *hc, struct msi_msg *msg)
 	hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hc->num) + 4);
 }
 
-static int hpet_msi_shutdown(struct clock_event_device *evt)
-{
-	return hpet_shutdown(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_set_oneshot(struct clock_event_device *evt)
-{
-	return hpet_set_oneshot(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_set_periodic(struct clock_event_device *evt)
-{
-	return hpet_set_periodic(evt, clockevent_to_channel(evt)->num);
-}
-
-static int hpet_msi_resume(struct clock_event_device *evt)
+static int hpet_clkevt_msi_resume(struct clock_event_device *evt)
 {
 	struct hpet_channel *hc = clockevent_to_channel(evt);
 	struct irq_data *data = irq_get_irq_data(hc->irq);
@@ -509,13 +473,7 @@ static int hpet_msi_resume(struct clock_event_device *evt)
 	return 0;
 }
 
-static int hpet_msi_next_event(unsigned long delta,
-			       struct clock_event_device *evt)
-{
-	return hpet_next_event(delta, clockevent_to_channel(evt)->num);
-}
-
-static irqreturn_t hpet_interrupt_handler(int irq, void *data)
+static irqreturn_t hpet_msi_interrupt_handler(int irq, void *data)
 {
 	struct hpet_channel *hc = data;
 	struct clock_event_device *evt = &hc->evt;
@@ -529,9 +487,9 @@ static irqreturn_t hpet_interrupt_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int hpet_setup_irq(struct hpet_channel *hc)
+static int hpet_setup_msi_irq(struct hpet_channel *hc)
 {
-	if (request_irq(hc->irq, hpet_interrupt_handler,
+	if (request_irq(hc->irq, hpet_msi_interrupt_handler,
 			IRQF_TIMER | IRQF_NOBALANCING,
 			hc->name, hc))
 		return -1;
@@ -553,20 +511,20 @@ static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
 	evt->name = hc->name;
-	hpet_setup_irq(hc);
+	hpet_setup_msi_irq(hc);
 	evt->irq = hc->irq;
 
 	evt->rating = 110;
 	evt->features = CLOCK_EVT_FEAT_ONESHOT;
 	if (hc->boot_cfg & HPET_TN_PERIODIC) {
 		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
-		evt->set_state_periodic = hpet_msi_set_periodic;
+		evt->set_state_periodic = hpet_clkevt_set_state_periodic;
 	}
 
-	evt->set_state_shutdown = hpet_msi_shutdown;
-	evt->set_state_oneshot = hpet_msi_set_oneshot;
-	evt->tick_resume = hpet_msi_resume;
-	evt->set_next_event = hpet_msi_next_event;
+	evt->set_state_shutdown	= hpet_clkevt_set_state_shutdown;
+	evt->set_state_oneshot = hpet_clkevt_set_state_oneshot;
+	evt->set_next_event = hpet_clkevt_set_next_event;
+	evt->tick_resume = hpet_clkevt_msi_resume;
 	evt->cpumask = cpumask_of(hc->cpu);
 
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent()
  2019-06-23 13:24 ` [patch 27/29] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent() Thomas Gleixner
@ 2019-06-27 23:52   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:52 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: andi.kleen, mingo, hpa, Suravee.Suthikulpanit, linux-kernel,
	ricardo.neri-calderon, tglx, peterz, ashok.raj, ravi.v.shankar,
	eranian

Commit-ID:  ea99110dd024d2f31bde19dda049f3fbf3816a70
Gitweb:     https://git.kernel.org/tip/ea99110dd024d2f31bde19dda049f3fbf3816a70
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:07 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:26 +0200

x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent()

To finally remove the static channel0/clockevent storage and to utilize the
channel 0 storage in hpet_base, it's required to run time initialize the
clockevent. The MSI clockevents already have a run time init function.

Carve out the parts which can be shared between the legacy and the MSI
implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.552451082@linutronix.de

---
 arch/x86/kernel/hpet.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 47eb4d36864e..80497fe5354c 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -411,6 +411,25 @@ hpet_clkevt_set_next_event(unsigned long delta, struct clock_event_device *evt)
 	return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
+static void hpet_init_clockevent(struct hpet_channel *hc, unsigned int rating)
+{
+	struct clock_event_device *evt = &hc->evt;
+
+	evt->rating		= rating;
+	evt->irq		= hc->irq;
+	evt->name		= hc->name;
+	evt->cpumask		= cpumask_of(hc->cpu);
+	evt->set_state_oneshot	= hpet_clkevt_set_state_oneshot;
+	evt->set_next_event	= hpet_clkevt_set_next_event;
+	evt->set_state_shutdown	= hpet_clkevt_set_state_shutdown;
+
+	evt->features = CLOCK_EVT_FEAT_ONESHOT;
+	if (hc->boot_cfg & HPET_TN_PERIODIC) {
+		evt->features		|= CLOCK_EVT_FEAT_PERIODIC;
+		evt->set_state_periodic	= hpet_clkevt_set_state_periodic;
+	}
+}
+
 /*
  * The HPET clock event device wrapped in a channel for conversion
  */
@@ -510,22 +529,10 @@ static void init_one_hpet_msi_clockevent(struct hpet_channel *hc, int cpu)
 
 	hc->cpu = cpu;
 	per_cpu(cpu_hpet_channel, cpu) = hc;
-	evt->name = hc->name;
 	hpet_setup_msi_irq(hc);
-	evt->irq = hc->irq;
 
-	evt->rating = 110;
-	evt->features = CLOCK_EVT_FEAT_ONESHOT;
-	if (hc->boot_cfg & HPET_TN_PERIODIC) {
-		evt->features |= CLOCK_EVT_FEAT_PERIODIC;
-		evt->set_state_periodic = hpet_clkevt_set_state_periodic;
-	}
-
-	evt->set_state_shutdown	= hpet_clkevt_set_state_shutdown;
-	evt->set_state_oneshot = hpet_clkevt_set_state_oneshot;
-	evt->set_next_event = hpet_clkevt_set_next_event;
+	hpet_init_clockevent(hc, 110);
 	evt->tick_resume = hpet_clkevt_msi_resume;
-	evt->cpumask = cpumask_of(hc->cpu);
 
 	clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
 					0x7FFFFFFF);

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Use common init for legacy clockevent
  2019-06-23 13:24 ` [patch 28/29] x86/hpet: Use common init for legacy clockevent Thomas Gleixner
  2019-06-26 21:13   ` Ingo Molnar
@ 2019-06-27 23:53   ` tip-bot for Thomas Gleixner
  1 sibling, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:53 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ashok.raj, eranian, linux-kernel, peterz, ravi.v.shankar,
	andi.kleen, hpa, ricardo.neri-calderon, Suravee.Suthikulpanit,
	tglx, mingo

Commit-ID:  49adaa60fa75a04457d30f38321378cdc3547212
Gitweb:     https://git.kernel.org/tip/49adaa60fa75a04457d30f38321378cdc3547212
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:08 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:27 +0200

x86/hpet: Use common init for legacy clockevent

Replace the static initialization of the legacy clockevent with runtime
initialization utilizing the common init function as the last preparatory
step to switch the legacy clockevent over to the channel 0 storage in
hpet_base.

This comes with a twist. The static clockevent initializer has selected
support for periodic and oneshot mode unconditionally whether the HPET
config advertised periodic mode or not. Even the pre clockevents code did
this. But....

Using the conditional in hpet_init_clockevent() makes at least Qemu and one
hardware machine fail to boot.  There are two issues which cause the boot
failure:

 #1 After the timer delivery test in IOAPIC and the IOAPIC setup the next
    interrupt is not delivered despite the HPET channel being programmed
    correctly. Reprogramming the HPET after switching to IOAPIC makes it
    work again. After fixing this, the next issue surfaces:

 #2 Due to the unconditional periodic mode 'availability' the Local APIC
    timer calibration can hijack the global clockevents event handler
    without causing damage. Using oneshot at this stage makes if hang
    because the HPET does not get reprogrammed due to the handler
    hijacking. Duh, stupid me!

Both issues require major surgery and especially the kick HPET again after
enabling IOAPIC results in really nasty hackery.  This 'assume periodic
works' magic has survived since HPET support got added, so it's
questionable whether this should be fixed. Both Qemu and the failing
hardware machine support periodic mode despite the fact that both don't
advertise it in the configuration register and both need that extra kick
after switching to IOAPIC. Seems to be a feature...

Keep the 'assume periodic works' magic around and add a big fat comment.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.646565913@linutronix.de

---
 arch/x86/kernel/hpet.c | 87 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 54 insertions(+), 33 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 80497fe5354c..35633e577d21 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,6 +66,9 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
+/*
+ * The HPET clock event device wrapped in a channel for conversion
+ */
 static struct hpet_channel		hpet_channel0;
 
 static inline
@@ -294,22 +297,6 @@ static void hpet_enable_legacy_int(void)
 	hpet_legacy_int_enabled = true;
 }
 
-static void hpet_legacy_clockevent_register(struct hpet_channel *hc)
-{
-	/* Start HPET legacy interrupts */
-	hpet_enable_legacy_int();
-
-	/*
-	 * Start HPET with the boot CPU's cpumask and make it global after
-	 * the IO_APIC has been initialized.
-	 */
-	hc->evt.cpumask = cpumask_of(boot_cpu_data.cpu_index);
-	clockevents_config_and_register(&hc->evt, hpet_freq,
-					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
-	global_clock_event = &hc->evt;
-	pr_debug("Clockevent registered\n");
-}
-
 static int hpet_clkevt_set_state_periodic(struct clock_event_device *evt)
 {
 	unsigned int channel = clockevent_to_channel(evt)->num;
@@ -430,23 +417,57 @@ static void hpet_init_clockevent(struct hpet_channel *hc, unsigned int rating)
 	}
 }
 
-/*
- * The HPET clock event device wrapped in a channel for conversion
- */
-static struct hpet_channel hpet_channel0 = {
-	.evt = {
-		.name			= "hpet",
-		.features		= CLOCK_EVT_FEAT_PERIODIC |
-					  CLOCK_EVT_FEAT_ONESHOT,
-		.set_state_periodic	= hpet_clkevt_set_state_periodic,
-		.set_state_oneshot	= hpet_clkevt_set_state_oneshot,
-		.set_state_shutdown	= hpet_clkevt_set_state_shutdown,
-		.tick_resume		= hpet_clkevt_legacy_resume,
-		.set_next_event		= hpet_clkevt_set_next_event,
-		.irq			= 0,
-		.rating			= 50,
-	}
-};
+static void __init hpet_legacy_clockevent_register(struct hpet_channel *hc)
+{
+	/*
+	 * Start HPET with the boot CPU's cpumask and make it global after
+	 * the IO_APIC has been initialized.
+	 */
+	hc->cpu = boot_cpu_data.cpu_index;
+	strncpy(hc->name, "hpet", sizeof(hc->name));
+	hpet_init_clockevent(hc, 50);
+
+	hc->evt.tick_resume	= hpet_clkevt_legacy_resume;
+
+	/*
+	 * Legacy horrors and sins from the past. HPET used periodic mode
+	 * unconditionally forever on the legacy channel 0. Removing the
+	 * below hack and using the conditional in hpet_init_clockevent()
+	 * makes at least Qemu and one hardware machine fail to boot.
+	 * There are two issues which cause the boot failure:
+	 *
+	 * #1 After the timer delivery test in IOAPIC and the IOAPIC setup
+	 *    the next interrupt is not delivered despite the HPET channel
+	 *    being programmed correctly. Reprogramming the HPET after
+	 *    switching to IOAPIC makes it work again. After fixing this,
+	 *    the next issue surfaces:
+	 *
+	 * #2 Due to the unconditional periodic mode availability the Local
+	 *    APIC timer calibration can hijack the global clockevents
+	 *    event handler without causing damage. Using oneshot at this
+	 *    stage makes if hang because the HPET does not get
+	 *    reprogrammed due to the handler hijacking. Duh, stupid me!
+	 *
+	 * Both issues require major surgery and especially the kick HPET
+	 * again after enabling IOAPIC results in really nasty hackery.
+	 * This 'assume periodic works' magic has survived since HPET
+	 * support got added, so it's questionable whether this should be
+	 * fixed. Both Qemu and the failing hardware machine support
+	 * periodic mode despite the fact that both don't advertise it in
+	 * the configuration register and both need that extra kick after
+	 * switching to IOAPIC. Seems to be a feature...
+	 */
+	hc->evt.features		|= CLOCK_EVT_FEAT_PERIODIC;
+	hc->evt.set_state_periodic	= hpet_clkevt_set_state_periodic;
+
+	/* Start HPET legacy interrupts */
+	hpet_enable_legacy_int();
+
+	clockevents_config_and_register(&hc->evt, hpet_freq,
+					HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
+	global_clock_event = &hc->evt;
+	pr_debug("Clockevent registered\n");
+}
 
 /*
  * HPET MSI Support

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [tip:x86/timers] x86/hpet: Use channel for legacy clockevent storage
  2019-06-23 13:24 ` [patch 29/29] x86/hpet: Use channel for legacy clockevent storage Thomas Gleixner
@ 2019-06-27 23:53   ` tip-bot for Thomas Gleixner
  0 siblings, 0 replies; 66+ messages in thread
From: tip-bot for Thomas Gleixner @ 2019-06-27 23:53 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, andi.kleen, Suravee.Suthikulpanit, ricardo.neri-calderon,
	peterz, eranian, ashok.raj, ravi.v.shankar, mingo, linux-kernel,
	tglx

Commit-ID:  e44252f4fe79dd9ca93bcf4e8f74389a5b8452f5
Gitweb:     https://git.kernel.org/tip/e44252f4fe79dd9ca93bcf4e8f74389a5b8452f5
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Sun, 23 Jun 2019 15:24:09 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2019 00:57:27 +0200

x86/hpet: Use channel for legacy clockevent storage

All preparations are done. Use the channel storage for the legacy
clockevent and remove the static variable.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Cc: Andi Kleen <andi.kleen@intel.com>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Link: https://lkml.kernel.org/r/20190623132436.737689919@linutronix.de

---
 arch/x86/kernel/hpet.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 35633e577d21..c43e96a938d0 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -66,11 +66,6 @@ bool					boot_hpet_disable;
 bool					hpet_force_user;
 static bool				hpet_verbose;
 
-/*
- * The HPET clock event device wrapped in a channel for conversion
- */
-static struct hpet_channel		hpet_channel0;
-
 static inline
 struct hpet_channel *clockevent_to_channel(struct clock_event_device *evt)
 {
@@ -904,7 +899,7 @@ int __init hpet_enable(void)
 	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 
 	if (id & HPET_ID_LEGSUP) {
-		hpet_legacy_clockevent_register(&hpet_channel0);
+		hpet_legacy_clockevent_register(&hpet_base.channels[0]);
 		hpet_base.channels[0].mode = HPET_MODE_LEGACY;
 		if (IS_ENABLED(CONFIG_HPET_EMULATE_RTC))
 			hpet_base.channels[1].mode = HPET_MODE_LEGACY;
@@ -1089,7 +1084,7 @@ int hpet_rtc_timer_init(void)
 		return 0;
 
 	if (!hpet_default_delta) {
-		struct clock_event_device *evt = &hpet_channel0.evt;
+		struct clock_event_device *evt = &hpet_base.channels[0].evt;
 		uint64_t clc;
 
 		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
@@ -1187,7 +1182,7 @@ int hpet_set_periodic_freq(unsigned long freq)
 	if (freq <= DEFAULT_RTC_INT_FREQ) {
 		hpet_pie_limit = DEFAULT_RTC_INT_FREQ / freq;
 	} else {
-		struct clock_event_device *evt = &hpet_channel0.evt;
+		struct clock_event_device *evt = &hpet_base.channels[0].evt;
 
 		clc = (uint64_t) evt->mult * NSEC_PER_SEC;
 		do_div(clc, freq);

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [patch 26/29] x86/hpet: Consolidate clockevent functions
  2019-06-27 22:53       ` Thomas Gleixner
@ 2019-06-28  8:32         ` Ingo Molnar
  0 siblings, 0 replies; 66+ messages in thread
From: Ingo Molnar @ 2019-06-28  8:32 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, x86, Peter Zijlstra, Ricardo Neri, Ashok Raj, Andi Kleen,
	Suravee Suthikulpanit, Stephane Eranian, Ravi Shankar


* Thomas Gleixner <tglx@linutronix.de> wrote:

> On Fri, 28 Jun 2019, Thomas Gleixner wrote:
> > On Wed, 26 Jun 2019, Ingo Molnar wrote:
> > > 
> > >  s/hpet_clkevt_msi_resume
> > >   /hpet_clkevt_tick_resume
> > > 
> > > ... unless the name variations have some hidden purpose and meaning?
> > 
> > Historical but we want to preserve some of the old stuff for sentimental
> > reasons.
> 
> The msi_resume naming actually has a real reason as there is also the
> legacy_resume one.

Makes sense!

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2019-06-28  8:32 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-23 13:23 [patch 00/29] x86/hpet: Cleanup the channel management Thomas Gleixner
2019-06-23 13:23 ` [patch 01/29] x86/hpet: Simplify CPU online code Thomas Gleixner
2019-06-27 23:34   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 02/29] x86/hpet: Replace printk(KERN...) with pr_...() Thomas Gleixner
2019-06-27 23:34   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 03/29] x86/hpet: Restructure init code Thomas Gleixner
2019-06-27 23:35   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 04/29] x86/hpet: Remove pointless x86-64 specific #include Thomas Gleixner
2019-06-27 23:36   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 05/29] x86/hpet: Remove unused parameter from hpet_next_event() Thomas Gleixner
2019-06-27 23:36   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 06/29] x86/hpet: Remove the unused hpet_msi_read() function Thomas Gleixner
2019-06-27 23:37   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 07/29] x86/hpet: Mark init functions __init Thomas Gleixner
2019-06-27 23:38   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 08/29] x86/hpet: Sanitize stub functions Thomas Gleixner
2019-06-27 23:39   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 09/29] x86/hpet: Move static and global variables to one place Thomas Gleixner
2019-06-27 23:39   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 10/29] x86/hpet: Shuffle code around for readability sake Thomas Gleixner
2019-06-27 23:40   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 11/29] x86/hpet: Separate counter check out of clocksource register code Thomas Gleixner
2019-06-27 23:41   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 12/29] x86/hpet: Simplify counter validation Thomas Gleixner
2019-06-27 23:41   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 13/29] x86/hpet: Decapitalize and rename EVT_TO_HPET_DEV Thomas Gleixner
2019-06-27 23:42   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 14/29] x86/hpet: Remove not required includes Thomas Gleixner
2019-06-27 23:43   ` [tip:x86/timers] " tip-bot for Ingo Molnar
2019-06-23 13:23 ` [patch 15/29] x86/hpet: Make naming consistent Thomas Gleixner
2019-06-27 23:44   ` [tip:x86/timers] " tip-bot for Ingo Molnar
2019-06-23 13:23 ` [patch 16/29] x86/hpet: Clean up comments Thomas Gleixner
2019-06-27 23:44   ` [tip:x86/timers] " tip-bot for Ingo Molnar
2019-06-23 13:23 ` [patch 17/29] x86/hpet: Coding style cleanup Thomas Gleixner
2019-06-27 23:45   ` [tip:x86/timers] " tip-bot for Ingo Molnar
2019-06-23 13:23 ` [patch 18/29] x86/hpet: Introduce struct hpet_base and struct hpet_channel Thomas Gleixner
2019-06-27 23:46   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:23 ` [patch 19/29] x86/hpet: Use cached channel data Thomas Gleixner
2019-06-27 23:46   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 20/29] x86/hpet: Add mode information to struct hpet_channel Thomas Gleixner
2019-06-27 23:47   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 21/29] x86/hpet: Add function to select a /dev/hpet channel Thomas Gleixner
2019-06-27 23:48   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 22/29] x86/hpet: Rename variables to prepare for switching to channels Thomas Gleixner
2019-06-27 23:49   ` [tip:x86/timers] " tip-bot for Ingo Molnar
2019-06-23 13:24 ` [patch 23/29] x86/hpet: Move clockevents into channels Thomas Gleixner
2019-06-27 23:49   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 24/29] x86/hpet: Use cached info instead of extra flags Thomas Gleixner
2019-06-26 21:20   ` Ingo Molnar
2019-06-27 23:50   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 25/29] x86/hpet: Wrap legacy clockevent in hpet_channel Thomas Gleixner
2019-06-27 23:51   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 26/29] x86/hpet: Consolidate clockevent functions Thomas Gleixner
2019-06-26 21:17   ` Ingo Molnar
2019-06-27 22:44     ` Thomas Gleixner
2019-06-27 22:53       ` Thomas Gleixner
2019-06-28  8:32         ` Ingo Molnar
2019-06-27 23:51   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 27/29] x86/hpet: Carve out shareable parts of init_one_hpet_msi_clockevent() Thomas Gleixner
2019-06-27 23:52   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 28/29] x86/hpet: Use common init for legacy clockevent Thomas Gleixner
2019-06-26 21:13   ` Ingo Molnar
2019-06-27 23:53   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-23 13:24 ` [patch 29/29] x86/hpet: Use channel for legacy clockevent storage Thomas Gleixner
2019-06-27 23:53   ` [tip:x86/timers] " tip-bot for Thomas Gleixner
2019-06-26 21:22 ` [patch 00/29] x86/hpet: Cleanup the channel management Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).