1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2025, Stefan Metzmacher 4 */ 5 6 #include "internal.h" 7 #include <linux/module.h> 8 9 struct smbdirect_module_state smbdirect_globals = { 10 .mutex = __MUTEX_INITIALIZER(smbdirect_globals.mutex), 11 }; 12 13 static __init int smbdirect_module_init(void) 14 { 15 int ret = -ENOMEM; 16 17 pr_notice("subsystem loading...\n"); 18 mutex_lock(&smbdirect_globals.mutex); 19 20 smbdirect_globals.workqueues.accept = alloc_workqueue("smbdirect-accept", 21 WQ_SYSFS | 22 WQ_PERCPU | 23 WQ_POWER_EFFICIENT, 24 0); 25 if (smbdirect_globals.workqueues.accept == NULL) 26 goto alloc_accept_wq_failed; 27 28 smbdirect_globals.workqueues.connect = alloc_workqueue("smbdirect-connect", 29 WQ_SYSFS | 30 WQ_PERCPU | 31 WQ_POWER_EFFICIENT, 32 0); 33 if (smbdirect_globals.workqueues.connect == NULL) 34 goto alloc_connect_wq_failed; 35 36 smbdirect_globals.workqueues.idle = alloc_workqueue("smbdirect-idle", 37 WQ_SYSFS | 38 WQ_PERCPU | 39 WQ_POWER_EFFICIENT, 40 0); 41 if (smbdirect_globals.workqueues.idle == NULL) 42 goto alloc_idle_wq_failed; 43 44 smbdirect_globals.workqueues.refill = alloc_workqueue("smbdirect-refill", 45 WQ_HIGHPRI | 46 WQ_SYSFS | 47 WQ_PERCPU | 48 WQ_POWER_EFFICIENT, 49 0); 50 if (smbdirect_globals.workqueues.refill == NULL) 51 goto alloc_refill_wq_failed; 52 53 smbdirect_globals.workqueues.immediate = alloc_workqueue("smbdirect-immediate", 54 WQ_HIGHPRI | 55 WQ_SYSFS | 56 WQ_PERCPU | 57 WQ_POWER_EFFICIENT, 58 0); 59 if (smbdirect_globals.workqueues.immediate == NULL) 60 goto alloc_immediate_wq_failed; 61 62 smbdirect_globals.workqueues.cleanup = alloc_workqueue("smbdirect-cleanup", 63 WQ_MEM_RECLAIM | 64 WQ_HIGHPRI | 65 WQ_SYSFS | 66 WQ_PERCPU | 67 WQ_POWER_EFFICIENT, 68 0); 69 if (smbdirect_globals.workqueues.cleanup == NULL) 70 goto alloc_cleanup_wq_failed; 71 72 ret = smbdirect_devices_init(); 73 if (ret) 74 goto devices_init_failed; 75 76 mutex_unlock(&smbdirect_globals.mutex); 77 pr_notice("subsystem loaded\n"); 78 return 0; 79 80 devices_init_failed: 81 destroy_workqueue(smbdirect_globals.workqueues.cleanup); 82 alloc_cleanup_wq_failed: 83 destroy_workqueue(smbdirect_globals.workqueues.immediate); 84 alloc_immediate_wq_failed: 85 destroy_workqueue(smbdirect_globals.workqueues.refill); 86 alloc_refill_wq_failed: 87 destroy_workqueue(smbdirect_globals.workqueues.idle); 88 alloc_idle_wq_failed: 89 destroy_workqueue(smbdirect_globals.workqueues.connect); 90 alloc_connect_wq_failed: 91 destroy_workqueue(smbdirect_globals.workqueues.accept); 92 alloc_accept_wq_failed: 93 mutex_unlock(&smbdirect_globals.mutex); 94 pr_crit("failed to loaded: %d (%1pe)\n", 95 ret, SMBDIRECT_DEBUG_ERR_PTR(ret)); 96 return ret; 97 } 98 99 static __exit void smbdirect_module_exit(void) 100 { 101 pr_notice("subsystem unloading...\n"); 102 mutex_lock(&smbdirect_globals.mutex); 103 104 smbdirect_devices_exit(); 105 106 destroy_workqueue(smbdirect_globals.workqueues.accept); 107 destroy_workqueue(smbdirect_globals.workqueues.connect); 108 destroy_workqueue(smbdirect_globals.workqueues.idle); 109 destroy_workqueue(smbdirect_globals.workqueues.refill); 110 destroy_workqueue(smbdirect_globals.workqueues.immediate); 111 destroy_workqueue(smbdirect_globals.workqueues.cleanup); 112 113 mutex_unlock(&smbdirect_globals.mutex); 114 pr_notice("subsystem unloaded\n"); 115 } 116 117 module_init(smbdirect_module_init); 118 module_exit(smbdirect_module_exit); 119 120 MODULE_DESCRIPTION("smbdirect subsystem"); 121 MODULE_LICENSE("GPL"); 122