s390/chsc: use notifier for AP configuration changes
authorHolger Dengler <dengler@linux.ibm.com>
Mon, 19 Feb 2024 16:32:54 +0000 (17:32 +0100)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Tue, 9 Apr 2024 15:29:55 +0000 (17:29 +0200)
The direct dependency of chsc and the AP bus prevents the
modularization of ap bus. Introduce a notifier interface for AP
changes, which decouples the producer of the change events (chsc) from
the consumer (ap_bus).

Remove the ap_cfg_chg() interface and replace it with the notifier
invocation. The ap bus module registers a notification handler, which
triggers the AP bus scan.

Cc: Vineeth Vijayan <vneethv@linux.ibm.com>
Cc: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/ap.h
arch/s390/include/asm/chsc.h
drivers/s390/cio/chsc.c
drivers/s390/crypto/ap_bus.c

index 2c5c907..395b02d 100644 (file)
@@ -549,15 +549,4 @@ static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
        return reg1.status;
 }
 
-/*
- * Interface to tell the AP bus code that a configuration
- * change has happened. The bus code should at least do
- * an ap bus resource rescan.
- */
-#if IS_ENABLED(CONFIG_ZCRYPT)
-void ap_bus_cfg_chg(void);
-#else
-static inline void ap_bus_cfg_chg(void){}
-#endif
-
 #endif /* _ASM_S390_AP_H_ */
index bb48ea3..bb78159 100644 (file)
@@ -11,6 +11,9 @@
 
 #include <uapi/asm/chsc.h>
 
+/* struct from linux/notifier.h */
+struct notifier_block;
+
 /**
  * Operation codes for CHSC PNSO:
  *    PNSO_OC_NET_BRIDGE_INFO - only addresses that are visible to a bridgeport
@@ -66,4 +69,16 @@ struct chsc_pnso_area {
        struct chsc_pnso_naid_l2 entries[];
 } __packed __aligned(PAGE_SIZE);
 
+/*
+ * notifier interface - registered notifiers gets called on
+ * the following events:
+ * - ap config changed (CHSC_NOTIFY_AP_CFG)
+ */
+enum chsc_notify_type {
+       CHSC_NOTIFY_AP_CFG = 3,
+};
+
+int chsc_notifier_register(struct notifier_block *nb);
+int chsc_notifier_unregister(struct notifier_block *nb);
+
 #endif /* _ASM_S390_CHSC_H */
index 44ea76f..89e51f1 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/crw.h>
 #include <asm/isc.h>
 #include <asm/ebcdic.h>
-#include <asm/ap.h>
 
 #include "css.h"
 #include "cio.h"
@@ -40,6 +39,20 @@ static DEFINE_SPINLOCK(chsc_page_lock);
 #define SEI_VF_FLA     0xc0 /* VF flag for Full Link Address */
 #define SEI_RS_CHPID   0x4  /* 4 in RS field indicates CHPID */
 
+static BLOCKING_NOTIFIER_HEAD(chsc_notifiers);
+
+int chsc_notifier_register(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&chsc_notifiers, nb);
+}
+EXPORT_SYMBOL(chsc_notifier_register);
+
+int chsc_notifier_unregister(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&chsc_notifiers, nb);
+}
+EXPORT_SYMBOL(chsc_notifier_unregister);
+
 /**
  * chsc_error_from_response() - convert a chsc response to an error
  * @response: chsc response code
@@ -581,7 +594,8 @@ static void chsc_process_sei_ap_cfg_chg(struct chsc_sei_nt0_area *sei_area)
        if (sei_area->rs != 5)
                return;
 
-       ap_bus_cfg_chg();
+       blocking_notifier_call_chain(&chsc_notifiers,
+                                    CHSC_NOTIFY_AP_CFG, NULL);
 }
 
 static void chsc_process_sei_fces_event(struct chsc_sei_nt0_area *sei_area)
index cdfaa32..9284ae6 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/ctype.h>
 #include <linux/module.h>
 #include <asm/uv.h>
+#include <asm/chsc.h>
 
 #include "ap_bus.h"
 #include "ap_debug.h"
@@ -1024,13 +1025,23 @@ EXPORT_SYMBOL(ap_bus_force_rescan);
 /*
  * A config change has happened, force an ap bus rescan.
  */
-void ap_bus_cfg_chg(void)
+static int ap_bus_cfg_chg(struct notifier_block *nb,
+                         unsigned long action, void *data)
 {
+       if (action != CHSC_NOTIFY_AP_CFG)
+               return NOTIFY_DONE;
+
        pr_debug("%s config change, forcing bus rescan\n", __func__);
 
        ap_bus_force_rescan();
+
+       return NOTIFY_OK;
 }
 
+static struct notifier_block ap_bus_nb = {
+       .notifier_call = ap_bus_cfg_chg,
+};
+
 /*
  * hex2bitmap() - parse hex mask string and set bitmap.
  * Valid strings are "0x012345678" with at least one valid hex number.
@@ -2291,16 +2302,22 @@ static inline int __init ap_async_init(void)
 
        queue_work(system_long_wq, &ap_scan_bus_work);
 
+       rc = chsc_notifier_register(&ap_bus_nb);
+       if (rc)
+               goto out;
+
        /* Start the low priority AP bus poll thread. */
        if (!ap_thread_flag)
                return 0;
 
        rc = ap_poll_thread_start();
        if (rc)
-               goto out;
+               goto out_notifier;
 
        return 0;
 
+out_notifier:
+       chsc_notifier_unregister(&ap_bus_nb);
 out:
        cancel_work(&ap_scan_bus_work);
        hrtimer_cancel(&ap_poll_timer);