xref: /linux/fs/smb/smbdirect/main.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
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