1
+ // SPDX-License-Identifier: GPL-2.0
2
+
3
+ //! Infiniband mlx4 devices.
4
+ //!
5
+
1
6
use alloc:: boxed:: Box ;
2
- use cm:: CmWorkQueue ;
3
7
use core:: pin:: Pin ;
4
- use core:: { cell :: UnsafeCell , marker, ptr} ;
8
+ use core:: { marker, ptr} ;
5
9
use macros:: vtable;
6
- use mcg:: McgWorkQueue ;
7
- use qp:: QpWorkQueue ;
8
10
9
- use crate :: error:: { code:: * , Error , Result } ;
11
+ use crate :: bindings;
12
+ use crate :: error:: { code:: * , Result } ;
10
13
use crate :: str:: CStr ;
11
14
use crate :: workqueue:: { BoxedQueue , Queue } ;
12
- use crate :: { bindings, pr_info} ;
13
15
14
- mod cm;
15
- mod mcg;
16
- mod qp;
17
-
18
- /// Soft RDMA transport registration.
16
+ /// Infiband mlx4 device registration.
19
17
///
20
18
pub struct Registration < T : Mlx4Operation > {
21
19
registered : bool ,
20
+ #[ allow( dead_code) ]
22
21
name : & ' static CStr ,
23
-
24
22
wq : Mlx4WorkQueue ,
25
23
cm_wq : CmWorkQueue ,
26
24
qp_wq : QpWorkQueue ,
27
25
mcg_wq : McgWorkQueue ,
28
26
phantom : marker:: PhantomData < T > ,
29
- //rxe_link_ops: bindings::rdma_link_ops,
30
- //再包一层
31
- //_pin: PhantomPinned,
32
-
33
- // /// Context initialised on construction and made available to all file instances on
34
- // /// [`file::Operations::open`].
35
- //open_data: MaybeUninit<T::OpenData>,
36
27
}
37
28
38
29
impl < T : Mlx4Operation > Registration < T > {
30
+ /// Creates a new [`Registration`] but does not register it yet.
31
+ ///
32
+ /// It is allowed to move.
39
33
pub fn new ( name : & ' static CStr ) -> Self {
34
+ // INVARIANT: `registered` is `false`
40
35
Self {
41
36
registered : false ,
42
37
name,
@@ -45,18 +40,29 @@ impl<T: Mlx4Operation> Registration<T> {
45
40
qp_wq : QpWorkQueue :: new ( ) ,
46
41
mcg_wq : McgWorkQueue :: new ( ) ,
47
42
phantom : marker:: PhantomData ,
48
- //rxe_link_ops:bindings::rdma_link_ops::default(),
49
43
}
50
44
}
51
45
46
+ /// Registers a infiband mlx4 device.
47
+ ///
48
+ /// Returns a pinned heap-allocated representation of the registration.
52
49
pub fn new_pinned ( name : & ' static CStr ) -> Result < Pin < Box < Self > > > {
53
50
let mut r = Pin :: from ( Box :: try_new ( Self :: new ( name) ) ?) ;
54
51
r. as_mut ( ) . register ( ) ?;
55
52
Ok ( r)
56
53
}
57
54
55
+ // Registers a infiband mlx4 device with the rest of the kernel.
56
+ ///
57
+ /// It must be pinned because the memory block that represents the registration is
58
+ /// self-referential.
58
59
pub fn register ( self : Pin < & mut Self > ) -> Result {
60
+ // SAFETY: We must ensure that we never move out of `this`.
59
61
let this = unsafe { self . get_unchecked_mut ( ) } ;
62
+ if this. registered {
63
+ // Already registered.
64
+ return Err ( EINVAL ) ;
65
+ }
60
66
61
67
match this. wq . init ( ) {
62
68
Ok ( ( ) ) => { }
@@ -90,8 +96,7 @@ impl<T: Mlx4Operation> Registration<T> {
90
96
}
91
97
}
92
98
93
- // interface用vtable替换掉
94
-
99
+ // SAFETY: The adapter is compatible with the mlx4 register
95
100
unsafe {
96
101
bindings:: mlx4_register_interface ( Mlx4OperationTable :: < T > :: build ( ) ) ;
97
102
}
@@ -102,9 +107,9 @@ impl<T: Mlx4Operation> Registration<T> {
102
107
}
103
108
104
109
impl < T : Mlx4Operation > Drop for Registration < T > {
110
+ /// Removes the registration from the kernel if it has completed successfully before.
105
111
fn drop ( & mut self ) {
106
112
if self . registered {
107
- //unsafe{bindings::mlx4_unregister_interface();}
108
113
self . mcg_wq . clean ( ) ;
109
114
self . cm_wq . clean ( ) ;
110
115
self . qp_wq . clean ( ) ;
@@ -113,9 +118,15 @@ impl<T: Mlx4Operation> Drop for Registration<T> {
113
118
}
114
119
}
115
120
121
+ /// Build kernel's `struct mlx4_interface` type with mlx4 device operation.
116
122
pub struct Mlx4OperationTable < T > ( marker:: PhantomData < T > ) ;
117
123
118
124
impl < T : Mlx4Operation > Mlx4OperationTable < T > {
125
+ /// Builds an instance of [`struct mlx4_interface`].
126
+ ///
127
+ /// # Safety
128
+ ///
129
+ /// The caller must ensure that the adapter is compatible with the way the device is registered.
119
130
pub fn build ( ) -> * mut bindings:: mlx4_interface {
120
131
return & mut bindings:: mlx4_interface {
121
132
add : Some ( Self :: add_callback) ,
@@ -134,58 +145,39 @@ impl<T: Mlx4Operation> Mlx4OperationTable<T> {
134
145
} ;
135
146
}
136
147
137
- unsafe extern "C" fn add_callback ( dev : * mut bindings:: mlx4_dev ) -> * mut core:: ffi:: c_void {
148
+ unsafe extern "C" fn add_callback ( _dev : * mut bindings:: mlx4_dev ) -> * mut core:: ffi:: c_void {
149
+ let _ = T :: add ( ) ;
138
150
return ptr:: null_mut ( ) ;
139
151
}
140
152
141
153
unsafe extern "C" fn remove_callback (
142
- dev : * mut bindings:: mlx4_dev ,
143
- context : * mut core:: ffi:: c_void ,
154
+ _dev : * mut bindings:: mlx4_dev ,
155
+ _context : * mut core:: ffi:: c_void ,
144
156
) {
157
+ let _ = T :: remove ( ) ;
145
158
}
146
159
147
160
unsafe extern "C" fn event_callback (
148
- dev : * mut bindings:: mlx4_dev ,
149
- context : * mut core:: ffi:: c_void ,
150
- event : bindings:: mlx4_dev_event ,
151
- param : core:: ffi:: c_ulong ,
161
+ _dev : * mut bindings:: mlx4_dev ,
162
+ _context : * mut core:: ffi:: c_void ,
163
+ _event : bindings:: mlx4_dev_event ,
164
+ _param : core:: ffi:: c_ulong ,
152
165
) {
166
+ let _ = T :: event ( ) ;
153
167
}
154
-
155
- // unsafe extern "C" fn get_dev_callback(
156
- // dev: *mut mlx4_dev,
157
- // context: *mut core::ffi::c_void,
158
- // port: u8_,
159
- // ) -> *mut core::ffi::c_void {
160
- // }
161
-
162
- // unsafe extern "C" fn activate_callback(
163
- // dev: *mut mlx4_dev,
164
- // context: *mut core::ffi::c_void
165
- // ) {
166
- // }
167
-
168
- // MLX4FUNC:bindings::mlx4_interface=bindings::mlx4_interface {
169
- // add:Some(Self::add_callback),
170
- // remove:Some(Self::remove_callback),
171
- // event:Some(Self::event_callback),
172
- // get_dev:None,
173
- // activate:None,
174
- // list:bindings::list_head{next:ptr::null_mut(),prev:ptr::null_mut()},
175
- // // MLX4_PROT_IB_IPV6
176
- // protocol:0,
177
- // // MLX4_INTFF_BONDING
178
- // flags:1,
179
- // };
180
168
}
181
169
170
+ /// Corresponds to the kernel's `struct mlx4_interface`.
171
+ ///
172
+ /// You implement this trait whenever you would create a `struct mlx4_interface`.
182
173
#[ vtable]
183
174
pub trait Mlx4Operation {
184
- fn add ( ) ;
185
- fn remove ( ) ;
186
- fn event ( ) ;
187
- // fn get_dev();
188
- // fn activate();
175
+ /// Add a new mlx4 ib device.
176
+ fn add ( ) -> Result ;
177
+ /// Remove mlx4 ib device.
178
+ fn remove ( ) -> Result ;
179
+ /// Respond to specific mlx4 ib device event
180
+ fn event ( ) -> Result ;
189
181
}
190
182
191
183
pub ( crate ) struct Mlx4WorkQueue {
@@ -213,3 +205,84 @@ impl Mlx4WorkQueue {
213
205
}
214
206
}
215
207
}
208
+
209
+ pub ( crate ) struct CmWorkQueue {
210
+ cm_wq : Option < BoxedQueue > ,
211
+ }
212
+
213
+ impl CmWorkQueue {
214
+ pub ( crate ) fn new ( ) -> Self {
215
+ Self { cm_wq : None }
216
+ }
217
+
218
+ pub ( crate ) fn init ( & mut self ) -> Result {
219
+ let cm_wq_tmp = Queue :: try_new ( format_args ! ( "mlx4_ib_cm" ) , 0 , 0 ) ;
220
+ self . cm_wq = match cm_wq_tmp {
221
+ Ok ( cm_wq) => Some ( cm_wq) ,
222
+ Err ( e) => return Err ( e) ,
223
+ } ;
224
+
225
+ Ok ( ( ) )
226
+ }
227
+
228
+ pub ( crate ) fn clean ( & mut self ) {
229
+ if self . cm_wq . is_some ( ) {
230
+ drop ( self . cm_wq . take ( ) . unwrap ( ) ) ;
231
+ }
232
+ }
233
+ }
234
+
235
+ pub ( crate ) struct McgWorkQueue {
236
+ clean_wq : Option < BoxedQueue > ,
237
+ }
238
+
239
+ impl McgWorkQueue {
240
+ pub ( crate ) fn new ( ) -> Self {
241
+ Self { clean_wq : None }
242
+ }
243
+
244
+ pub ( crate ) fn init ( & mut self ) -> Result {
245
+ let clean_wq_tmp = Queue :: try_new ( format_args ! ( "mlx4_ib_mcg" ) , 655369 , 1 ) ;
246
+ self . clean_wq = match clean_wq_tmp {
247
+ Ok ( clean_wq) => Some ( clean_wq) ,
248
+ Err ( e) => return Err ( e) ,
249
+ } ;
250
+
251
+ Ok ( ( ) )
252
+ }
253
+
254
+ pub ( crate ) fn clean ( & mut self ) {
255
+ if self . clean_wq . is_some ( ) {
256
+ drop ( self . clean_wq . take ( ) . unwrap ( ) ) ;
257
+ }
258
+ }
259
+ }
260
+
261
+ pub ( crate ) struct QpWorkQueue {
262
+ mlx4_ib_qp_event_wq : Option < BoxedQueue > ,
263
+ }
264
+
265
+ impl QpWorkQueue {
266
+ pub ( crate ) fn new ( ) -> Self {
267
+ Self {
268
+ mlx4_ib_qp_event_wq : None ,
269
+ }
270
+ }
271
+
272
+ pub ( crate ) fn init ( & mut self ) -> Result {
273
+ let mlx4_ib_qp_event_wq_tmp =
274
+ Queue :: try_new ( format_args ! ( "mlx4_ib_qp_event_wq" ) , 655361 , 1 ) ;
275
+ self . mlx4_ib_qp_event_wq = match mlx4_ib_qp_event_wq_tmp {
276
+ Ok ( mlx4_ib_qp_event_wq) => Some ( mlx4_ib_qp_event_wq) ,
277
+ Err ( e) => return Err ( e) ,
278
+ } ;
279
+
280
+ Ok ( ( ) )
281
+ }
282
+
283
+ pub ( crate ) fn clean ( & mut self ) {
284
+ if self . mlx4_ib_qp_event_wq . is_some ( ) {
285
+ drop ( self . mlx4_ib_qp_event_wq . take ( ) . unwrap ( ) ) ;
286
+ }
287
+ }
288
+ }
0 commit comments