summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolger Dengler <dengler@linux.ibm.com>2024-03-08 17:13:48 +0100
committerAlexander Gordeev <agordeev@linux.ibm.com>2024-04-09 17:29:55 +0200
commit170660ccf8806742052028093fb45872d2be4775 (patch)
treea98dd9bcae9f93b1a00d20aaac0edb9737cb079a
parent8dec9cb9f525b6c51e3467202b9c627591c472f8 (diff)
s390/ap: rework ap initialization
Rework the ap initialization and add missing cleanups to the error path. Errors during the registration of IRQ handler is now also detected. Suggested-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Holger Dengler <dengler@linux.ibm.com> Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-rw-r--r--drivers/s390/crypto/ap_bus.c102
1 files changed, 72 insertions, 30 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index d8f5882a8eaf..aabaf93004bc 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -2273,7 +2273,66 @@ static void ap_scan_bus_wq_callback(struct work_struct *unused)
}
}
-static int __init ap_debug_init(void)
+static inline int __init ap_async_init(void)
+{
+ int rc;
+
+ /* Setup the AP bus rescan timer. */
+ timer_setup(&ap_scan_bus_timer, ap_scan_bus_timer_callback, 0);
+
+ /*
+ * Setup the high resolution poll timer.
+ * If we are running under z/VM adjust polling to z/VM polling rate.
+ */
+ if (MACHINE_IS_VM)
+ poll_high_timeout = 1500000;
+ hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ ap_poll_timer.function = ap_poll_timeout;
+
+ queue_work(system_long_wq, &ap_scan_bus_work);
+
+ /* Start the low priority AP bus poll thread. */
+ if (!ap_thread_flag)
+ return 0;
+
+ rc = ap_poll_thread_start();
+ if (rc)
+ goto out;
+
+ return 0;
+
+out:
+ cancel_work(&ap_scan_bus_work);
+ hrtimer_cancel(&ap_poll_timer);
+ timer_delete(&ap_scan_bus_timer);
+ return rc;
+}
+
+static inline void ap_irq_exit(void)
+{
+ if (ap_irq_flag)
+ unregister_adapter_interrupt(&ap_airq);
+}
+
+static inline int __init ap_irq_init(void)
+{
+ int rc;
+
+ if (!ap_interrupts_available() || !ap_useirq)
+ return 0;
+
+ rc = register_adapter_interrupt(&ap_airq);
+ ap_irq_flag = (rc == 0);
+
+ return rc;
+}
+
+static inline void ap_debug_exit(void)
+{
+ debug_unregister(ap_dbf_info);
+}
+
+static inline int __init ap_debug_init(void)
{
ap_dbf_info = debug_register("ap", 2, 1,
AP_DBF_MAX_SPRINTF_ARGS * sizeof(long));
@@ -2342,15 +2401,14 @@ static int __init ap_module_init(void)
}
/* enable interrupts if available */
- if (ap_interrupts_available() && ap_useirq) {
- rc = register_adapter_interrupt(&ap_airq);
- ap_irq_flag = (rc == 0);
- }
+ rc = ap_irq_init();
+ if (rc)
+ goto out;
/* Create /sys/bus/ap. */
rc = bus_register(&ap_bus_type);
if (rc)
- goto out;
+ goto out_irq;
/* Create /sys/devices/ap. */
ap_root_device = root_device_register("ap");
@@ -2359,37 +2417,21 @@ static int __init ap_module_init(void)
goto out_bus;
ap_root_device->bus = &ap_bus_type;
- /* Setup the AP bus rescan timer. */
- timer_setup(&ap_scan_bus_timer, ap_scan_bus_timer_callback, 0);
-
- /*
- * Setup the high resolution poll timer.
- * If we are running under z/VM adjust polling to z/VM polling rate.
- */
- if (MACHINE_IS_VM)
- poll_high_timeout = 1500000;
- hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
- ap_poll_timer.function = ap_poll_timeout;
-
- /* Start the low priority AP bus poll thread. */
- if (ap_thread_flag) {
- rc = ap_poll_thread_start();
- if (rc)
- goto out_work;
- }
-
- queue_work(system_long_wq, &ap_scan_bus_work);
+ /* Setup asynchronous work (timers, workqueue, etc). */
+ rc = ap_async_init();
+ if (rc)
+ goto out_device;
return 0;
-out_work:
- hrtimer_cancel(&ap_poll_timer);
+out_device:
root_device_unregister(ap_root_device);
out_bus:
bus_unregister(&ap_bus_type);
+out_irq:
+ ap_irq_exit();
out:
- if (ap_irq_flag)
- unregister_adapter_interrupt(&ap_airq);
+ ap_debug_exit();
return rc;
}
device_initcall(ap_module_init);