]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/rdma/rdma_device.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / rdma / rdma_device.c
1 /*
2  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
3  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  * $Id: device.c 1349 2004-12-16 21:09:43Z roland $
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/condvar.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
44 #include <sys/kernel.h>
45 #include <sys/libkern.h>
46 #include <sys/socket.h>
47 #include <sys/module.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 #include <sys/rwlock.h>
51 #include <sys/queue.h>
52 #include <sys/taskqueue.h>
53 #include <sys/priv.h>
54 #include <sys/syslog.h>
55
56 #include <contrib/rdma/core_priv.h>
57
58 struct ib_client_data {
59         TAILQ_ENTRY(ib_client_data) list;
60         struct ib_client *client;
61         void *            data;
62 };
63
64 static TAILQ_HEAD(, ib_device) device_list;
65 static TAILQ_HEAD(client_list_s, ib_client) client_list;
66
67 /*
68  * device_mutex protects access to both device_list and client_list.
69  * There's no real point to using multiple locks or something fancier
70  * like an rwsem: we always access both lists, and we're always
71  * modifying one list or the other list.  In any case this is not a
72  * hot path so there's no point in trying to optimize.
73  */
74 static struct mtx device_mutex;
75
76 static int ib_device_check_mandatory(struct ib_device *device)
77 {
78 #define IB_MANDATORY_FUNC(x) { offsetof(struct ib_device, x), #x }
79 #define MANDATORY_TABLE_DEPTH 19
80         static const struct {
81                 size_t offset;
82                 char  *name;
83         } mandatory_table[] = {
84                 IB_MANDATORY_FUNC(query_device),
85                 IB_MANDATORY_FUNC(query_port),
86                 IB_MANDATORY_FUNC(query_pkey),
87                 IB_MANDATORY_FUNC(query_gid),
88                 IB_MANDATORY_FUNC(alloc_pd),
89                 IB_MANDATORY_FUNC(dealloc_pd),
90                 IB_MANDATORY_FUNC(create_ah),
91                 IB_MANDATORY_FUNC(destroy_ah),
92                 IB_MANDATORY_FUNC(create_qp),
93                 IB_MANDATORY_FUNC(modify_qp),
94                 IB_MANDATORY_FUNC(destroy_qp),
95                 IB_MANDATORY_FUNC(post_send),
96                 IB_MANDATORY_FUNC(post_recv),
97                 IB_MANDATORY_FUNC(create_cq),
98                 IB_MANDATORY_FUNC(destroy_cq),
99                 IB_MANDATORY_FUNC(poll_cq),
100                 IB_MANDATORY_FUNC(req_notify_cq),
101                 IB_MANDATORY_FUNC(get_dma_mr),
102                 IB_MANDATORY_FUNC(dereg_mr)
103         };
104         int i;
105
106         for (i = 0; i < MANDATORY_TABLE_DEPTH; ++i) {
107                 if (!*(void **) ((void *) ((unsigned long)device + mandatory_table[i].offset))) {
108                         log(LOG_WARNING, "Device %s is missing mandatory function %s\n",
109                                device->name, mandatory_table[i].name);
110                         return (EINVAL);
111                 }
112         }
113
114         return 0;
115 }
116
117 static struct ib_device *__ib_device_get_by_name(const char *name)
118 {
119         struct ib_device *device;
120
121         TAILQ_FOREACH(device, &device_list, core_list)
122                 if (!strncmp(name, device->name, IB_DEVICE_NAME_MAX))
123                         return device;
124
125         return NULL;
126 }
127
128
129 static int alloc_name(char *name)
130 {
131         long *inuse;
132         char buf[IB_DEVICE_NAME_MAX];
133         struct ib_device *device;
134         int i;
135
136         inuse = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
137         if (!inuse)
138                 return (ENOMEM);
139
140         TAILQ_FOREACH(device, &device_list, core_list) {
141                 if (!sscanf(device->name, name, &i))
142                         continue;
143                 if (i < 0 || i >= PAGE_SIZE * 8)
144                         continue;
145                 snprintf(buf, sizeof buf, name, i);
146                 if (!strncmp(buf, device->name, IB_DEVICE_NAME_MAX))
147                         setbit(inuse, i);
148         }
149
150         i = find_first_zero_bit(inuse, PAGE_SIZE * 8);
151         free(inuse, M_DEVBUF);
152         snprintf(buf, sizeof buf, name, i);
153
154         if (__ib_device_get_by_name(buf))
155                 return (ENFILE);
156
157         strlcpy(name, buf, IB_DEVICE_NAME_MAX);
158         return 0;
159 }
160
161 static int start_port(struct ib_device *device)
162 {
163         return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1;
164 }
165
166
167 static int end_port(struct ib_device *device)
168 {
169         return (device->node_type == RDMA_NODE_IB_SWITCH) ?
170                 0 : device->phys_port_cnt;
171 }
172
173 /**
174  * ib_alloc_device - allocate an IB device struct
175  * @size:size of structure to allocate
176  *
177  * Low-level drivers should use ib_alloc_device() to allocate &struct
178  * ib_device.  @size is the size of the structure to be allocated,
179  * including any private data used by the low-level driver.
180  * ib_dealloc_device() must be used to free structures allocated with
181  * ib_alloc_device().
182  */
183 struct ib_device *ib_alloc_device(size_t size)
184 {
185         void *dev;
186
187         if (size < sizeof (struct ib_device))
188                 panic("size=%zd < sizeof (struct ib_device)=%zd)",
189                     size, sizeof (struct ib_device));
190         
191         dev = malloc(size, M_DEVBUF, M_NOWAIT);
192         if (dev)
193                 bzero(dev, size);
194         return dev;
195 }
196
197 /**
198  * ib_dealloc_device - free an IB device struct
199  * @device:structure to free
200  *
201  * Free a structure allocated with ib_alloc_device().
202  */
203 void ib_dealloc_device(struct ib_device *device)
204 {
205         if (device->reg_state == IB_DEV_UNINITIALIZED) {
206                 free(device, M_DEVBUF);
207                 return;
208         }
209
210         if (device->reg_state != IB_DEV_UNREGISTERED)
211                 panic("device->reg_state=%d != IB_DEV_UNREGISTERED)",
212                     device->reg_state);
213 #ifdef notyet
214         ib_device_unregister_sysfs(device);
215 #endif
216 }
217
218 static int add_client_context(struct ib_device *device, struct ib_client *client)
219 {
220         struct ib_client_data *context;
221
222         context = malloc(sizeof *context, M_DEVBUF, M_NOWAIT);
223         if (!context) {
224                 log(LOG_WARNING, "Couldn't allocate client context for %s/%s\n",
225                        device->name, client->name);
226                 return (ENOMEM);
227         }
228
229         context->client = client;
230         context->data   = NULL;
231
232         mtx_lock(&device->client_data_lock);
233         TAILQ_INSERT_TAIL(&device->client_data_list, context, list);
234         mtx_unlock(&device->client_data_lock);
235
236         return 0;
237 }
238
239 static int read_port_table_lengths(struct ib_device *device)
240 {
241         struct ib_port_attr *tprops = NULL;
242         int num_ports, ret = ENOMEM;
243         u8 port_index;
244
245         tprops = malloc(sizeof *tprops, M_DEVBUF, M_NOWAIT);
246         if (!tprops)
247                 goto out;
248
249         num_ports = end_port(device) - start_port(device) + 1;
250
251         device->pkey_tbl_len = malloc(sizeof *device->pkey_tbl_len * num_ports,
252                                        M_DEVBUF, M_NOWAIT);
253         device->gid_tbl_len = malloc(sizeof *device->gid_tbl_len * num_ports,
254                                       M_DEVBUF, M_NOWAIT);
255         if (!device->pkey_tbl_len || !device->gid_tbl_len)
256                 goto err;
257
258         for (port_index = 0; port_index < num_ports; ++port_index) {
259                 ret = ib_query_port(device, port_index + start_port(device),
260                                         tprops);
261                 if (ret)
262                         goto err;
263                 device->pkey_tbl_len[port_index] = tprops->pkey_tbl_len;
264                 device->gid_tbl_len[port_index]  = tprops->gid_tbl_len;
265         }
266
267         ret = 0;
268         goto out;
269
270 err:
271         free(device->gid_tbl_len, M_DEVBUF);
272         free(device->pkey_tbl_len, M_DEVBUF);
273 out:
274         free(tprops, M_DEVBUF);
275         return ret;
276 }
277
278 /**
279  * ib_register_device - Register an IB device with IB core
280  * @device:Device to register
281  *
282  * Low-level drivers use ib_register_device() to register their
283  * devices with the IB core.  All registered clients will receive a
284  * callback for each device that is added. @device must be allocated
285  * with ib_alloc_device().
286  */
287 int ib_register_device(struct ib_device *device)
288 {
289         int ret;
290
291         mtx_lock(&device_mutex);
292
293         if (strchr(device->name, '%')) {
294                 ret = alloc_name(device->name);
295                 if (ret)
296                         goto out;
297         }
298
299         if (ib_device_check_mandatory(device)) {
300                 ret = EINVAL;
301                 goto out;
302         }
303
304         TAILQ_INIT(&device->event_handler_list);
305         TAILQ_INIT(&device->client_data_list);
306         mtx_init(&device->event_handler_lock, "ib event handler", NULL, 
307                  MTX_DUPOK|MTX_DEF);
308         mtx_init(&device->client_data_lock, "ib client data", NULL, 
309                  MTX_DUPOK|MTX_DEF);
310
311         ret = read_port_table_lengths(device);
312         if (ret) {
313                 log(LOG_WARNING, "Couldn't create table lengths cache for device %s\n",
314                        device->name);
315                 goto out;
316         }
317
318 #ifdef notyet
319         ret = ib_device_register_sysfs(device);
320         if (ret) {
321                 log(LOG_WARNING, "Couldn't register device %s with driver model\n",
322                        device->name);
323                 free(device->gid_tbl_len, M_DEVBUF);
324                 free(device->pkey_tbl_len, M_DEVBUF);
325                 goto out;
326         }
327 #endif
328
329         TAILQ_INSERT_TAIL(&device_list, device, core_list);
330
331         device->reg_state = IB_DEV_REGISTERED;
332
333         {
334                 struct ib_client *client;
335
336                 TAILQ_FOREACH(client, &client_list, list)
337                         if (client->add && !add_client_context(device, client))
338                                 client->add(device);
339         }
340
341  out:
342         mtx_unlock(&device_mutex);
343         return ret;
344 }
345
346 /**
347  * ib_unregister_device - Unregister an IB device
348  * @device:Device to unregister
349  *
350  * Unregister an IB device.  All clients will receive a remove callback.
351  */
352 void ib_unregister_device(struct ib_device *device)
353 {
354         struct ib_client *client;
355         struct ib_client_data *context, *tmp;
356
357         mtx_lock(&device_mutex);
358
359         TAILQ_FOREACH_REVERSE(client, &client_list, client_list_s, list)
360                 if (client->remove)
361                         client->remove(device);
362
363         TAILQ_REMOVE(&device_list, device, core_list);
364
365         free(device->gid_tbl_len, M_DEVBUF);
366         free(device->pkey_tbl_len, M_DEVBUF);
367
368         mtx_unlock(&device_mutex);
369
370         mtx_lock(&device->client_data_lock);
371         TAILQ_FOREACH_SAFE(context, &device->client_data_list, list, tmp)
372                 free(context, M_DEVBUF);
373         mtx_unlock(&device->client_data_lock);
374
375         device->reg_state = IB_DEV_UNREGISTERED;
376 }
377
378 /**
379  * ib_register_client - Register an IB client
380  * @client:Client to register
381  *
382  * Upper level users of the IB drivers can use ib_register_client() to
383  * register callbacks for IB device addition and removal.  When an IB
384  * device is added, each registered client's add method will be called
385  * (in the order the clients were registered), and when a device is
386  * removed, each client's remove method will be called (in the reverse
387  * order that clients were registered).  In addition, when
388  * ib_register_client() is called, the client will receive an add
389  * callback for all devices already registered.
390  */
391 int ib_register_client(struct ib_client *client)
392 {
393         struct ib_device *device;
394
395         mtx_lock(&device_mutex);
396
397         TAILQ_INSERT_TAIL(&client_list, client, list);
398         TAILQ_FOREACH(device, &device_list, core_list)
399                 if (client->add && !add_client_context(device, client))
400                         client->add(device);
401
402         mtx_unlock(&device_mutex);
403
404         return 0;
405 }
406
407 /**
408  * ib_unregister_client - Unregister an IB client
409  * @client:Client to unregister
410  *
411  * Upper level users use ib_unregister_client() to remove their client
412  * registration.  When ib_unregister_client() is called, the client
413  * will receive a remove callback for each IB device still registered.
414  */
415 void ib_unregister_client(struct ib_client *client)
416 {
417         struct ib_client_data *context, *tmp;
418         struct ib_device *device;
419
420         mtx_lock(&device_mutex);
421
422         TAILQ_FOREACH(device, &device_list, core_list) {
423                 if (client->remove)
424                         client->remove(device);
425
426                 mtx_lock(&device->client_data_lock);
427                 TAILQ_FOREACH_SAFE(context, &device->client_data_list, list,tmp)
428                         if (context->client == client) {
429                                 TAILQ_REMOVE(&device->client_data_list, context,
430                                         list);
431                                 free(context, M_DEVBUF);
432                         }
433                 mtx_unlock(&device->client_data_lock);
434         }
435         TAILQ_REMOVE(&client_list, client, list);
436
437         mtx_unlock(&device_mutex);
438 }
439
440 /**
441  * ib_get_client_data - Get IB client context
442  * @device:Device to get context for
443  * @client:Client to get context for
444  *
445  * ib_get_client_data() returns client context set with
446  * ib_set_client_data().
447  */
448 void *ib_get_client_data(struct ib_device *device, struct ib_client *client)
449 {
450         struct ib_client_data *context;
451         void *ret = NULL;
452
453         mtx_lock(&device->client_data_lock);
454         TAILQ_FOREACH(context, &device->client_data_list, list)
455                 if (context->client == client) {
456                         ret = context->data;
457                         break;
458                 }
459         mtx_unlock(&device->client_data_lock);
460
461         return ret;
462 }
463
464 /**
465  * ib_set_client_data - Set IB client context
466  * @device:Device to set context for
467  * @client:Client to set context for
468  * @data:Context to set
469  *
470  * ib_set_client_data() sets client context that can be retrieved with
471  * ib_get_client_data().
472  */
473 void ib_set_client_data(struct ib_device *device, struct ib_client *client,
474                         void *data)
475 {
476         struct ib_client_data *context;
477
478         mtx_lock(&device->client_data_lock);
479         TAILQ_FOREACH(context, &device->client_data_list, list)
480                 if (context->client == client) {
481                         context->data = data;
482                         goto out;
483                 }
484
485         log(LOG_WARNING, "No client context found for %s/%s\n",
486                device->name, client->name);
487
488 out:
489         mtx_unlock(&device->client_data_lock);
490 }
491
492 /**
493  * ib_register_event_handler - Register an IB event handler
494  * @event_handler:Handler to register
495  *
496  * ib_register_event_handler() registers an event handler that will be
497  * called back when asynchronous IB events occur (as defined in
498  * chapter 11 of the InfiniBand Architecture Specification).  This
499  * callback may occur in interrupt context.
500  */
501 int ib_register_event_handler  (struct ib_event_handler *event_handler)
502 {
503         mtx_lock(&event_handler->device->event_handler_lock);
504         TAILQ_INSERT_TAIL(&event_handler->device->event_handler_list, 
505                 event_handler, list);
506         mtx_unlock(&event_handler->device->event_handler_lock);
507
508         return 0;
509 }
510
511 /**
512  * ib_unregister_event_handler - Unregister an event handler
513  * @event_handler:Handler to unregister
514  *
515  * Unregister an event handler registered with
516  * ib_register_event_handler().
517  */
518 int ib_unregister_event_handler(struct ib_event_handler *event_handler)
519 {
520         mtx_lock(&event_handler->device->event_handler_lock);
521         TAILQ_REMOVE(&event_handler->device->event_handler_list, event_handler,
522                 list);
523         mtx_unlock(&event_handler->device->event_handler_lock);
524
525         return 0;
526 }
527
528 /**
529  * ib_dispatch_event - Dispatch an asynchronous event
530  * @event:Event to dispatch
531  *
532  * Low-level drivers must call ib_dispatch_event() to dispatch the
533  * event to all registered event handlers when an asynchronous event
534  * occurs.
535  */
536 void ib_dispatch_event(struct ib_event *event)
537 {
538         struct ib_event_handler *handler;
539
540         mtx_lock(&event->device->event_handler_lock);
541
542         TAILQ_FOREACH(handler, &event->device->event_handler_list, list)
543                 handler->handler(handler, event);
544
545         mtx_unlock(&event->device->event_handler_lock);
546 }
547
548 /**
549  * ib_query_device - Query IB device attributes
550  * @device:Device to query
551  * @device_attr:Device attributes
552  *
553  * ib_query_device() returns the attributes of a device through the
554  * @device_attr pointer.
555  */
556 int ib_query_device(struct ib_device *device,
557                     struct ib_device_attr *device_attr)
558 {
559         return device->query_device(device, device_attr);
560 }
561
562 /**
563  * ib_query_port - Query IB port attributes
564  * @device:Device to query
565  * @port_num:Port number to query
566  * @port_attr:Port attributes
567  *
568  * ib_query_port() returns the attributes of a port through the
569  * @port_attr pointer.
570  */
571 int ib_query_port(struct ib_device *device,
572                   u8 port_num,
573                   struct ib_port_attr *port_attr)
574 {
575         if (port_num < start_port(device) || port_num > end_port(device))
576                 return (EINVAL);
577
578         return device->query_port(device, port_num, port_attr);
579 }
580
581 /**
582  * ib_query_gid - Get GID table entry
583  * @device:Device to query
584  * @port_num:Port number to query
585  * @index:GID table index to query
586  * @gid:Returned GID
587  *
588  * ib_query_gid() fetches the specified GID table entry.
589  */
590 int ib_query_gid(struct ib_device *device,
591                  u8 port_num, int index, union ib_gid *gid)
592 {
593         return device->query_gid(device, port_num, index, gid);
594 }
595
596 /**
597  * ib_query_pkey - Get P_Key table entry
598  * @device:Device to query
599  * @port_num:Port number to query
600  * @index:P_Key table index to query
601  * @pkey:Returned P_Key
602  *
603  * ib_query_pkey() fetches the specified P_Key table entry.
604  */
605 int ib_query_pkey(struct ib_device *device,
606                   u8 port_num, u16 index, u16 *pkey)
607 {
608         return device->query_pkey(device, port_num, index, pkey);
609 }
610
611 /**
612  * ib_modify_device - Change IB device attributes
613  * @device:Device to modify
614  * @device_modify_mask:Mask of attributes to change
615  * @device_modify:New attribute values
616  *
617  * ib_modify_device() changes a device's attributes as specified by
618  * the @device_modify_mask and @device_modify structure.
619  */
620 int ib_modify_device(struct ib_device *device,
621                      int device_modify_mask,
622                      struct ib_device_modify *device_modify)
623 {
624         return device->modify_device(device, device_modify_mask,
625                                      device_modify);
626 }
627
628 /**
629  * ib_modify_port - Modifies the attributes for the specified port.
630  * @device: The device to modify.
631  * @port_num: The number of the port to modify.
632  * @port_modify_mask: Mask used to specify which attributes of the port
633  *   to change.
634  * @port_modify: New attribute values for the port.
635  *
636  * ib_modify_port() changes a port's attributes as specified by the
637  * @port_modify_mask and @port_modify structure.
638  */
639 int ib_modify_port(struct ib_device *device,
640                    u8 port_num, int port_modify_mask,
641                    struct ib_port_modify *port_modify)
642 {
643         if (port_num < start_port(device) || port_num > end_port(device))
644                 return (EINVAL);
645
646         return device->modify_port(device, port_num, port_modify_mask,
647                                    port_modify);
648 }
649
650 /**
651  * ib_find_gid - Returns the port number and GID table index where
652  *   a specified GID value occurs.
653  * @device: The device to query.
654  * @gid: The GID value to search for.
655  * @port_num: The port number of the device where the GID value was found.
656  * @index: The index into the GID table where the GID was found.  This
657  *   parameter may be NULL.
658  */
659 int ib_find_gid(struct ib_device *device, union ib_gid *gid,
660                 u8 *port_num, u16 *index)
661 {
662         union ib_gid tmp_gid;
663         int ret, port, i;
664
665         for (port = start_port(device); port <= end_port(device); ++port) {
666                 for (i = 0; i < device->gid_tbl_len[port - start_port(device)]; ++i) {
667                         ret = ib_query_gid(device, port, i, &tmp_gid);
668                         if (ret)
669                                 return ret;
670                         if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
671                                 *port_num = port;
672                                 if (index)
673                                         *index = i;
674                                 return 0;
675                         }
676                 }
677         }
678
679         return (ENOENT);
680 }
681
682 /**
683  * ib_find_pkey - Returns the PKey table index where a specified
684  *   PKey value occurs.
685  * @device: The device to query.
686  * @port_num: The port number of the device to search for the PKey.
687  * @pkey: The PKey value to search for.
688  * @index: The index into the PKey table where the PKey was found.
689  */
690 int ib_find_pkey(struct ib_device *device,
691                  u8 port_num, u16 pkey, u16 *index)
692 {
693         int ret, i;
694         u16 tmp_pkey;
695
696         for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) {
697                 ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
698                 if (ret)
699                         return ret;
700
701                 if (pkey == tmp_pkey) {
702                         *index = i;
703                         return 0;
704                 }
705         }
706
707         return (ENOENT);
708 }
709
710 static int rdma_core_init(void)
711 {
712         int ret;
713 #ifdef notyet
714         ret = ib_sysfs_setup();
715         if (ret)
716                 log(LOG_WARNING, "Couldn't create InfiniBand device class\n");
717 #endif
718
719         mtx_init(&device_mutex, "rdma_device mutex", NULL, MTX_DEF);
720         TAILQ_INIT(&client_list);
721         TAILQ_INIT(&device_list);
722         ret = ib_cache_setup();
723         if (ret) {
724                 log(LOG_WARNING, "Couldn't set up InfiniBand P_Key/GID cache\n");
725 #ifdef notyet
726                 ib_sysfs_cleanup();
727 #endif
728         }
729
730         return ret;
731 }
732
733 static void rdma_core_cleanup(void)
734 {
735         ib_cache_cleanup();
736 #ifdef notyet
737         ib_sysfs_cleanup();
738         /* Make sure that any pending umem accounting work is done. */
739         flush_scheduled_work();
740 #endif
741 }
742
743 static int 
744 rdma_core_load(module_t mod, int cmd, void *arg)
745 {
746         int err = 0;
747
748         switch (cmd) {
749         case MOD_LOAD:
750                 printf("Loading rdma_core.\n");
751                 rdma_core_init();
752                 break;
753         case MOD_QUIESCE:
754                 break;
755         case MOD_UNLOAD:
756                 printf("Unloading rdma_core.\n");
757                 rdma_core_cleanup();
758                 break;
759         case MOD_SHUTDOWN:
760                 break;
761         default:
762                 err = EOPNOTSUPP;
763                 break;
764         }
765
766         return (err);
767 }
768
769 static moduledata_t mod_data = {
770         "rdma_core",
771         rdma_core_load,
772         0
773 };
774
775 MODULE_VERSION(rdma_core, 1);
776 DECLARE_MODULE(rdma_core, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);