diff mbox series

[RFC,03/26] thermal: intel: hfi: Add HFI notifier helpers to notify HFI update

Message ID 20240203091214.411862-4-zhao1.liu@linux.intel.com
State New
Headers show
Series Intel Thread Director Virtualization | expand

Commit Message

Zhao Liu Feb. 3, 2024, 9:11 a.m. UTC
From: Zhuocheng Ding <zhuocheng.ding@intel.com>

KVM builds virtual HFI tables for virtual machines, which also needs to
sync Host's HFI table update in time.

Add notifier_chain in HFI instance to notify other modules about HFI
table updates, and provide 2 helpers to register/unregister notifier
hook in HFI driver.

Tested-by: Yanting Jiang <yanting.jiang@intel.com>
Signed-off-by: Zhuocheng Ding <zhuocheng.ding@intel.com>
Co-developed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
 arch/x86/include/asm/hfi.h        |  8 ++++
 drivers/thermal/intel/intel_hfi.c | 63 ++++++++++++++++++++++++++++---
 2 files changed, 65 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/arch/x86/include/asm/hfi.h b/arch/x86/include/asm/hfi.h
index e0fe5b30fb53..19e3e5a7fb77 100644
--- a/arch/x86/include/asm/hfi.h
+++ b/arch/x86/include/asm/hfi.h
@@ -90,6 +90,10 @@  int intel_hfi_build_virt_table(struct hfi_table *table, struct hfi_features *fea
 			       unsigned int nr_classes, unsigned int hfi_index,
 			       unsigned int cpu);
 static inline bool intel_hfi_enabled(void) { return intel_hfi_max_instances() > 0; }
+int intel_hfi_notifier_register(struct notifier_block *notifier,
+				unsigned int cpu);
+int intel_hfi_notifier_unregister(struct notifier_block *notifier,
+				  unsigned int cpu);
 #else
 static inline int intel_hfi_max_instances(void) { return 0; }
 static inline int intel_hfi_build_virt_features(struct hfi_features *features,
@@ -100,6 +104,10 @@  static inline int intel_hfi_build_virt_table(struct hfi_table *table,
 					     unsigned int nr_classes, unsigned int hfi_index,
 					     unsigned int cpu) { return 0; }
 static inline bool intel_hfi_enabled(void) { return false; }
+static inline int intel_hfi_notifier_register(struct notifier_block *notifier,
+					      unsigned int cpu) { return -ENODEV; }
+static inline int intel_hfi_notifier_unregister(struct notifier_block *notifier,
+						unsigned int cpu) { return -ENODEV; }
 #endif
 
 #endif /* _ASM_X86_HFI_H */
diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c
index 139ce2d4b26b..330b264ca23d 100644
--- a/drivers/thermal/intel/intel_hfi.c
+++ b/drivers/thermal/intel/intel_hfi.c
@@ -72,18 +72,20 @@  struct hfi_cpu_data {
  * @cpus:		CPUs represented in this HFI table instance
  * @hw_table:		Pointer to the HFI table of this instance
  * @update_work:	Delayed work to process HFI updates
+ * @notifier_chain:	Notification chain dedicated to this instance
  * @table_lock:		Lock to protect acceses to the table of this instance
  * @event_lock:		Lock to process HFI interrupts
  *
  * A set of parameters to parse and navigate a specific HFI table.
  */
 struct hfi_instance {
-	struct hfi_table	local_table;
-	cpumask_var_t		cpus;
-	void			*hw_table;
-	struct delayed_work	update_work;
-	raw_spinlock_t		table_lock;
-	raw_spinlock_t		event_lock;
+	struct hfi_table		local_table;
+	cpumask_var_t			cpus;
+	void				*hw_table;
+	struct delayed_work		update_work;
+	struct raw_notifier_head	notifier_chain;
+	raw_spinlock_t			table_lock;
+	raw_spinlock_t			event_lock;
 };
 
 /**
@@ -189,6 +191,7 @@  static void hfi_update_work_fn(struct work_struct *work)
 				    update_work);
 
 	update_capabilities(hfi_instance);
+	raw_notifier_call_chain(&hfi_instance->notifier_chain, 0, NULL);
 }
 
 void intel_hfi_process_event(__u64 pkg_therm_status_msr_val)
@@ -448,6 +451,7 @@  void intel_hfi_online(unsigned int cpu)
 	init_hfi_instance(hfi_instance);
 
 	INIT_DELAYED_WORK(&hfi_instance->update_work, hfi_update_work_fn);
+	RAW_INIT_NOTIFIER_HEAD(&hfi_instance->notifier_chain);
 	raw_spin_lock_init(&hfi_instance->table_lock);
 	raw_spin_lock_init(&hfi_instance->event_lock);
 
@@ -791,3 +795,50 @@  int intel_hfi_build_virt_table(struct hfi_table *table,
 	return table_changed;
 }
 EXPORT_SYMBOL_GPL(intel_hfi_build_virt_table);
+
+/**
+ * intel_hfi_notifier_register() - Register @notifier hook at @hfi_instance.
+ *
+ * @notifier:		HFI notifier hook to be registered
+ * @cpu:		CPU whose HFI instance the notifier is register at
+ *
+ * When the HFI instance of @cpu receives HFI interrupt and updates its local
+ * HFI table, the registered HFI notifier will be called.
+ *
+ * Return: 0 if successful, otherwise error.
+ */
+int intel_hfi_notifier_register(struct notifier_block *notifier,
+				unsigned int cpu)
+{
+	struct hfi_instance *hfi_instance;
+
+	if (!notifier || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	hfi_instance = per_cpu(hfi_cpu_info, cpu).hfi_instance;
+	return raw_notifier_chain_register(&hfi_instance->notifier_chain,
+					   notifier);
+}
+EXPORT_SYMBOL_GPL(intel_hfi_notifier_register);
+
+/**
+ * intel_hfi_notifier_unregister() - Unregister @notifier hook at @hfi_instance
+ *
+ * @notifier:		HFI notifier hook to be unregistered
+ * @cpu:		CPU whose HFI instance the notifier is unregister from
+ *
+ * Return: 0 if successful, otherwise error.
+ */
+int intel_hfi_notifier_unregister(struct notifier_block *notifier,
+				  unsigned int cpu)
+{
+	struct hfi_instance *hfi_instance;
+
+	if (!notifier || cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	hfi_instance = per_cpu(hfi_cpu_info, cpu).hfi_instance;
+	return raw_notifier_chain_unregister(&hfi_instance->notifier_chain,
+					     notifier);
+}
+EXPORT_SYMBOL_GPL(intel_hfi_notifier_unregister);