diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/infiniband/core/device.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/infiniband/core/device.c')
-rw-r--r-- | drivers/infiniband/core/device.c | 614 |
1 files changed, 614 insertions, 0 deletions
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c new file mode 100644 index 000000000000..9197e92d708a --- /dev/null +++ b/drivers/infiniband/core/device.c | |||
@@ -0,0 +1,614 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004 Topspin Communications. All rights reserved. | ||
3 | * | ||
4 | * This software is available to you under a choice of one of two | ||
5 | * licenses. You may choose to be licensed under the terms of the GNU | ||
6 | * General Public License (GPL) Version 2, available from the file | ||
7 | * COPYING in the main directory of this source tree, or the | ||
8 | * OpenIB.org BSD license below: | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or | ||
11 | * without modification, are permitted provided that the following | ||
12 | * conditions are met: | ||
13 | * | ||
14 | * - Redistributions of source code must retain the above | ||
15 | * copyright notice, this list of conditions and the following | ||
16 | * disclaimer. | ||
17 | * | ||
18 | * - Redistributions in binary form must reproduce the above | ||
19 | * copyright notice, this list of conditions and the following | ||
20 | * disclaimer in the documentation and/or other materials | ||
21 | * provided with the distribution. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
30 | * SOFTWARE. | ||
31 | * | ||
32 | * $Id: device.c 1349 2004-12-16 21:09:43Z roland $ | ||
33 | */ | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <linux/string.h> | ||
37 | #include <linux/errno.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/init.h> | ||
40 | |||
41 | #include <asm/semaphore.h> | ||
42 | |||
43 | #include "core_priv.h" | ||
44 | |||
45 | MODULE_AUTHOR("Roland Dreier"); | ||
46 | MODULE_DESCRIPTION("core kernel InfiniBand API"); | ||
47 | MODULE_LICENSE("Dual BSD/GPL"); | ||
48 | |||
49 | struct ib_client_data { | ||
50 | struct list_head list; | ||
51 | struct ib_client *client; | ||
52 | void * data; | ||
53 | }; | ||
54 | |||
55 | static LIST_HEAD(device_list); | ||
56 | static LIST_HEAD(client_list); | ||
57 | |||
58 | /* | ||
59 | * device_sem protects access to both device_list and client_list. | ||
60 | * There's no real point to using multiple locks or something fancier | ||
61 | * like an rwsem: we always access both lists, and we're always | ||
62 | * modifying one list or the other list. In any case this is not a | ||
63 | * hot path so there's no point in trying to optimize. | ||
64 | */ | ||
65 | static DECLARE_MUTEX(device_sem); | ||
66 | |||
67 | static int ib_device_check_mandatory(struct ib_device *device) | ||
68 | { | ||
69 | #define IB_MANDATORY_FUNC(x) { offsetof(struct ib_device, x), #x } | ||
70 | static const struct { | ||
71 | size_t offset; | ||
72 | char *name; | ||
73 | } mandatory_table[] = { | ||
74 | IB_MANDATORY_FUNC(query_device), | ||
75 | IB_MANDATORY_FUNC(query_port), | ||
76 | IB_MANDATORY_FUNC(query_pkey), | ||
77 | IB_MANDATORY_FUNC(query_gid), | ||
78 | IB_MANDATORY_FUNC(alloc_pd), | ||
79 | IB_MANDATORY_FUNC(dealloc_pd), | ||
80 | IB_MANDATORY_FUNC(create_ah), | ||
81 | IB_MANDATORY_FUNC(destroy_ah), | ||
82 | IB_MANDATORY_FUNC(create_qp), | ||
83 | IB_MANDATORY_FUNC(modify_qp), | ||
84 | IB_MANDATORY_FUNC(destroy_qp), | ||
85 | IB_MANDATORY_FUNC(post_send), | ||
86 | IB_MANDATORY_FUNC(post_recv), | ||
87 | IB_MANDATORY_FUNC(create_cq), | ||
88 | IB_MANDATORY_FUNC(destroy_cq), | ||
89 | IB_MANDATORY_FUNC(poll_cq), | ||
90 | IB_MANDATORY_FUNC(req_notify_cq), | ||
91 | IB_MANDATORY_FUNC(get_dma_mr), | ||
92 | IB_MANDATORY_FUNC(dereg_mr) | ||
93 | }; | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < sizeof mandatory_table / sizeof mandatory_table[0]; ++i) { | ||
97 | if (!*(void **) ((void *) device + mandatory_table[i].offset)) { | ||
98 | printk(KERN_WARNING "Device %s is missing mandatory function %s\n", | ||
99 | device->name, mandatory_table[i].name); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static struct ib_device *__ib_device_get_by_name(const char *name) | ||
108 | { | ||
109 | struct ib_device *device; | ||
110 | |||
111 | list_for_each_entry(device, &device_list, core_list) | ||
112 | if (!strncmp(name, device->name, IB_DEVICE_NAME_MAX)) | ||
113 | return device; | ||
114 | |||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | |||
119 | static int alloc_name(char *name) | ||
120 | { | ||
121 | long *inuse; | ||
122 | char buf[IB_DEVICE_NAME_MAX]; | ||
123 | struct ib_device *device; | ||
124 | int i; | ||
125 | |||
126 | inuse = (long *) get_zeroed_page(GFP_KERNEL); | ||
127 | if (!inuse) | ||
128 | return -ENOMEM; | ||
129 | |||
130 | list_for_each_entry(device, &device_list, core_list) { | ||
131 | if (!sscanf(device->name, name, &i)) | ||
132 | continue; | ||
133 | if (i < 0 || i >= PAGE_SIZE * 8) | ||
134 | continue; | ||
135 | snprintf(buf, sizeof buf, name, i); | ||
136 | if (!strncmp(buf, device->name, IB_DEVICE_NAME_MAX)) | ||
137 | set_bit(i, inuse); | ||
138 | } | ||
139 | |||
140 | i = find_first_zero_bit(inuse, PAGE_SIZE * 8); | ||
141 | free_page((unsigned long) inuse); | ||
142 | snprintf(buf, sizeof buf, name, i); | ||
143 | |||
144 | if (__ib_device_get_by_name(buf)) | ||
145 | return -ENFILE; | ||
146 | |||
147 | strlcpy(name, buf, IB_DEVICE_NAME_MAX); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * ib_alloc_device - allocate an IB device struct | ||
153 | * @size:size of structure to allocate | ||
154 | * | ||
155 | * Low-level drivers should use ib_alloc_device() to allocate &struct | ||
156 | * ib_device. @size is the size of the structure to be allocated, | ||
157 | * including any private data used by the low-level driver. | ||
158 | * ib_dealloc_device() must be used to free structures allocated with | ||
159 | * ib_alloc_device(). | ||
160 | */ | ||
161 | struct ib_device *ib_alloc_device(size_t size) | ||
162 | { | ||
163 | void *dev; | ||
164 | |||
165 | BUG_ON(size < sizeof (struct ib_device)); | ||
166 | |||
167 | dev = kmalloc(size, GFP_KERNEL); | ||
168 | if (!dev) | ||
169 | return NULL; | ||
170 | |||
171 | memset(dev, 0, size); | ||
172 | |||
173 | return dev; | ||
174 | } | ||
175 | EXPORT_SYMBOL(ib_alloc_device); | ||
176 | |||
177 | /** | ||
178 | * ib_dealloc_device - free an IB device struct | ||
179 | * @device:structure to free | ||
180 | * | ||
181 | * Free a structure allocated with ib_alloc_device(). | ||
182 | */ | ||
183 | void ib_dealloc_device(struct ib_device *device) | ||
184 | { | ||
185 | if (device->reg_state == IB_DEV_UNINITIALIZED) { | ||
186 | kfree(device); | ||
187 | return; | ||
188 | } | ||
189 | |||
190 | BUG_ON(device->reg_state != IB_DEV_UNREGISTERED); | ||
191 | |||
192 | ib_device_unregister_sysfs(device); | ||
193 | } | ||
194 | EXPORT_SYMBOL(ib_dealloc_device); | ||
195 | |||
196 | static int add_client_context(struct ib_device *device, struct ib_client *client) | ||
197 | { | ||
198 | struct ib_client_data *context; | ||
199 | unsigned long flags; | ||
200 | |||
201 | context = kmalloc(sizeof *context, GFP_KERNEL); | ||
202 | if (!context) { | ||
203 | printk(KERN_WARNING "Couldn't allocate client context for %s/%s\n", | ||
204 | device->name, client->name); | ||
205 | return -ENOMEM; | ||
206 | } | ||
207 | |||
208 | context->client = client; | ||
209 | context->data = NULL; | ||
210 | |||
211 | spin_lock_irqsave(&device->client_data_lock, flags); | ||
212 | list_add(&context->list, &device->client_data_list); | ||
213 | spin_unlock_irqrestore(&device->client_data_lock, flags); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * ib_register_device - Register an IB device with IB core | ||
220 | * @device:Device to register | ||
221 | * | ||
222 | * Low-level drivers use ib_register_device() to register their | ||
223 | * devices with the IB core. All registered clients will receive a | ||
224 | * callback for each device that is added. @device must be allocated | ||
225 | * with ib_alloc_device(). | ||
226 | */ | ||
227 | int ib_register_device(struct ib_device *device) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | down(&device_sem); | ||
232 | |||
233 | if (strchr(device->name, '%')) { | ||
234 | ret = alloc_name(device->name); | ||
235 | if (ret) | ||
236 | goto out; | ||
237 | } | ||
238 | |||
239 | if (ib_device_check_mandatory(device)) { | ||
240 | ret = -EINVAL; | ||
241 | goto out; | ||
242 | } | ||
243 | |||
244 | INIT_LIST_HEAD(&device->event_handler_list); | ||
245 | INIT_LIST_HEAD(&device->client_data_list); | ||
246 | spin_lock_init(&device->event_handler_lock); | ||
247 | spin_lock_init(&device->client_data_lock); | ||
248 | |||
249 | ret = ib_device_register_sysfs(device); | ||
250 | if (ret) { | ||
251 | printk(KERN_WARNING "Couldn't register device %s with driver model\n", | ||
252 | device->name); | ||
253 | goto out; | ||
254 | } | ||
255 | |||
256 | list_add_tail(&device->core_list, &device_list); | ||
257 | |||
258 | device->reg_state = IB_DEV_REGISTERED; | ||
259 | |||
260 | { | ||
261 | struct ib_client *client; | ||
262 | |||
263 | list_for_each_entry(client, &client_list, list) | ||
264 | if (client->add && !add_client_context(device, client)) | ||
265 | client->add(device); | ||
266 | } | ||
267 | |||
268 | out: | ||
269 | up(&device_sem); | ||
270 | return ret; | ||
271 | } | ||
272 | EXPORT_SYMBOL(ib_register_device); | ||
273 | |||
274 | /** | ||
275 | * ib_unregister_device - Unregister an IB device | ||
276 | * @device:Device to unregister | ||
277 | * | ||
278 | * Unregister an IB device. All clients will receive a remove callback. | ||
279 | */ | ||
280 | void ib_unregister_device(struct ib_device *device) | ||
281 | { | ||
282 | struct ib_client *client; | ||
283 | struct ib_client_data *context, *tmp; | ||
284 | unsigned long flags; | ||
285 | |||
286 | down(&device_sem); | ||
287 | |||
288 | list_for_each_entry_reverse(client, &client_list, list) | ||
289 | if (client->remove) | ||
290 | client->remove(device); | ||
291 | |||
292 | list_del(&device->core_list); | ||
293 | |||
294 | up(&device_sem); | ||
295 | |||
296 | spin_lock_irqsave(&device->client_data_lock, flags); | ||
297 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) | ||
298 | kfree(context); | ||
299 | spin_unlock_irqrestore(&device->client_data_lock, flags); | ||
300 | |||
301 | device->reg_state = IB_DEV_UNREGISTERED; | ||
302 | } | ||
303 | EXPORT_SYMBOL(ib_unregister_device); | ||
304 | |||
305 | /** | ||
306 | * ib_register_client - Register an IB client | ||
307 | * @client:Client to register | ||
308 | * | ||
309 | * Upper level users of the IB drivers can use ib_register_client() to | ||
310 | * register callbacks for IB device addition and removal. When an IB | ||
311 | * device is added, each registered client's add method will be called | ||
312 | * (in the order the clients were registered), and when a device is | ||
313 | * removed, each client's remove method will be called (in the reverse | ||
314 | * order that clients were registered). In addition, when | ||
315 | * ib_register_client() is called, the client will receive an add | ||
316 | * callback for all devices already registered. | ||
317 | */ | ||
318 | int ib_register_client(struct ib_client *client) | ||
319 | { | ||
320 | struct ib_device *device; | ||
321 | |||
322 | down(&device_sem); | ||
323 | |||
324 | list_add_tail(&client->list, &client_list); | ||
325 | list_for_each_entry(device, &device_list, core_list) | ||
326 | if (client->add && !add_client_context(device, client)) | ||
327 | client->add(device); | ||
328 | |||
329 | up(&device_sem); | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | EXPORT_SYMBOL(ib_register_client); | ||
334 | |||
335 | /** | ||
336 | * ib_unregister_client - Unregister an IB client | ||
337 | * @client:Client to unregister | ||
338 | * | ||
339 | * Upper level users use ib_unregister_client() to remove their client | ||
340 | * registration. When ib_unregister_client() is called, the client | ||
341 | * will receive a remove callback for each IB device still registered. | ||
342 | */ | ||
343 | void ib_unregister_client(struct ib_client *client) | ||
344 | { | ||
345 | struct ib_client_data *context, *tmp; | ||
346 | struct ib_device *device; | ||
347 | unsigned long flags; | ||
348 | |||
349 | down(&device_sem); | ||
350 | |||
351 | list_for_each_entry(device, &device_list, core_list) { | ||
352 | if (client->remove) | ||
353 | client->remove(device); | ||
354 | |||
355 | spin_lock_irqsave(&device->client_data_lock, flags); | ||
356 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) | ||
357 | if (context->client == client) { | ||
358 | list_del(&context->list); | ||
359 | kfree(context); | ||
360 | } | ||
361 | spin_unlock_irqrestore(&device->client_data_lock, flags); | ||
362 | } | ||
363 | list_del(&client->list); | ||
364 | |||
365 | up(&device_sem); | ||
366 | } | ||
367 | EXPORT_SYMBOL(ib_unregister_client); | ||
368 | |||
369 | /** | ||
370 | * ib_get_client_data - Get IB client context | ||
371 | * @device:Device to get context for | ||
372 | * @client:Client to get context for | ||
373 | * | ||
374 | * ib_get_client_data() returns client context set with | ||
375 | * ib_set_client_data(). | ||
376 | */ | ||
377 | void *ib_get_client_data(struct ib_device *device, struct ib_client *client) | ||
378 | { | ||
379 | struct ib_client_data *context; | ||
380 | void *ret = NULL; | ||
381 | unsigned long flags; | ||
382 | |||
383 | spin_lock_irqsave(&device->client_data_lock, flags); | ||
384 | list_for_each_entry(context, &device->client_data_list, list) | ||
385 | if (context->client == client) { | ||
386 | ret = context->data; | ||
387 | break; | ||
388 | } | ||
389 | spin_unlock_irqrestore(&device->client_data_lock, flags); | ||
390 | |||
391 | return ret; | ||
392 | } | ||
393 | EXPORT_SYMBOL(ib_get_client_data); | ||
394 | |||
395 | /** | ||
396 | * ib_set_client_data - Get IB client context | ||
397 | * @device:Device to set context for | ||
398 | * @client:Client to set context for | ||
399 | * @data:Context to set | ||
400 | * | ||
401 | * ib_set_client_data() sets client context that can be retrieved with | ||
402 | * ib_get_client_data(). | ||
403 | */ | ||
404 | void ib_set_client_data(struct ib_device *device, struct ib_client *client, | ||
405 | void *data) | ||
406 | { | ||
407 | struct ib_client_data *context; | ||
408 | unsigned long flags; | ||
409 | |||
410 | spin_lock_irqsave(&device->client_data_lock, flags); | ||
411 | list_for_each_entry(context, &device->client_data_list, list) | ||
412 | if (context->client == client) { | ||
413 | context->data = data; | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | printk(KERN_WARNING "No client context found for %s/%s\n", | ||
418 | device->name, client->name); | ||
419 | |||
420 | out: | ||
421 | spin_unlock_irqrestore(&device->client_data_lock, flags); | ||
422 | } | ||
423 | EXPORT_SYMBOL(ib_set_client_data); | ||
424 | |||
425 | /** | ||
426 | * ib_register_event_handler - Register an IB event handler | ||
427 | * @event_handler:Handler to register | ||
428 | * | ||
429 | * ib_register_event_handler() registers an event handler that will be | ||
430 | * called back when asynchronous IB events occur (as defined in | ||
431 | * chapter 11 of the InfiniBand Architecture Specification). This | ||
432 | * callback may occur in interrupt context. | ||
433 | */ | ||
434 | int ib_register_event_handler (struct ib_event_handler *event_handler) | ||
435 | { | ||
436 | unsigned long flags; | ||
437 | |||
438 | spin_lock_irqsave(&event_handler->device->event_handler_lock, flags); | ||
439 | list_add_tail(&event_handler->list, | ||
440 | &event_handler->device->event_handler_list); | ||
441 | spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | EXPORT_SYMBOL(ib_register_event_handler); | ||
446 | |||
447 | /** | ||
448 | * ib_unregister_event_handler - Unregister an event handler | ||
449 | * @event_handler:Handler to unregister | ||
450 | * | ||
451 | * Unregister an event handler registered with | ||
452 | * ib_register_event_handler(). | ||
453 | */ | ||
454 | int ib_unregister_event_handler(struct ib_event_handler *event_handler) | ||
455 | { | ||
456 | unsigned long flags; | ||
457 | |||
458 | spin_lock_irqsave(&event_handler->device->event_handler_lock, flags); | ||
459 | list_del(&event_handler->list); | ||
460 | spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags); | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | EXPORT_SYMBOL(ib_unregister_event_handler); | ||
465 | |||
466 | /** | ||
467 | * ib_dispatch_event - Dispatch an asynchronous event | ||
468 | * @event:Event to dispatch | ||
469 | * | ||
470 | * Low-level drivers must call ib_dispatch_event() to dispatch the | ||
471 | * event to all registered event handlers when an asynchronous event | ||
472 | * occurs. | ||
473 | */ | ||
474 | void ib_dispatch_event(struct ib_event *event) | ||
475 | { | ||
476 | unsigned long flags; | ||
477 | struct ib_event_handler *handler; | ||
478 | |||
479 | spin_lock_irqsave(&event->device->event_handler_lock, flags); | ||
480 | |||
481 | list_for_each_entry(handler, &event->device->event_handler_list, list) | ||
482 | handler->handler(handler, event); | ||
483 | |||
484 | spin_unlock_irqrestore(&event->device->event_handler_lock, flags); | ||
485 | } | ||
486 | EXPORT_SYMBOL(ib_dispatch_event); | ||
487 | |||
488 | /** | ||
489 | * ib_query_device - Query IB device attributes | ||
490 | * @device:Device to query | ||
491 | * @device_attr:Device attributes | ||
492 | * | ||
493 | * ib_query_device() returns the attributes of a device through the | ||
494 | * @device_attr pointer. | ||
495 | */ | ||
496 | int ib_query_device(struct ib_device *device, | ||
497 | struct ib_device_attr *device_attr) | ||
498 | { | ||
499 | return device->query_device(device, device_attr); | ||
500 | } | ||
501 | EXPORT_SYMBOL(ib_query_device); | ||
502 | |||
503 | /** | ||
504 | * ib_query_port - Query IB port attributes | ||
505 | * @device:Device to query | ||
506 | * @port_num:Port number to query | ||
507 | * @port_attr:Port attributes | ||
508 | * | ||
509 | * ib_query_port() returns the attributes of a port through the | ||
510 | * @port_attr pointer. | ||
511 | */ | ||
512 | int ib_query_port(struct ib_device *device, | ||
513 | u8 port_num, | ||
514 | struct ib_port_attr *port_attr) | ||
515 | { | ||
516 | return device->query_port(device, port_num, port_attr); | ||
517 | } | ||
518 | EXPORT_SYMBOL(ib_query_port); | ||
519 | |||
520 | /** | ||
521 | * ib_query_gid - Get GID table entry | ||
522 | * @device:Device to query | ||
523 | * @port_num:Port number to query | ||
524 | * @index:GID table index to query | ||
525 | * @gid:Returned GID | ||
526 | * | ||
527 | * ib_query_gid() fetches the specified GID table entry. | ||
528 | */ | ||
529 | int ib_query_gid(struct ib_device *device, | ||
530 | u8 port_num, int index, union ib_gid *gid) | ||
531 | { | ||
532 | return device->query_gid(device, port_num, index, gid); | ||
533 | } | ||
534 | EXPORT_SYMBOL(ib_query_gid); | ||
535 | |||
536 | /** | ||
537 | * ib_query_pkey - Get P_Key table entry | ||
538 | * @device:Device to query | ||
539 | * @port_num:Port number to query | ||
540 | * @index:P_Key table index to query | ||
541 | * @pkey:Returned P_Key | ||
542 | * | ||
543 | * ib_query_pkey() fetches the specified P_Key table entry. | ||
544 | */ | ||
545 | int ib_query_pkey(struct ib_device *device, | ||
546 | u8 port_num, u16 index, u16 *pkey) | ||
547 | { | ||
548 | return device->query_pkey(device, port_num, index, pkey); | ||
549 | } | ||
550 | EXPORT_SYMBOL(ib_query_pkey); | ||
551 | |||
552 | /** | ||
553 | * ib_modify_device - Change IB device attributes | ||
554 | * @device:Device to modify | ||
555 | * @device_modify_mask:Mask of attributes to change | ||
556 | * @device_modify:New attribute values | ||
557 | * | ||
558 | * ib_modify_device() changes a device's attributes as specified by | ||
559 | * the @device_modify_mask and @device_modify structure. | ||
560 | */ | ||
561 | int ib_modify_device(struct ib_device *device, | ||
562 | int device_modify_mask, | ||
563 | struct ib_device_modify *device_modify) | ||
564 | { | ||
565 | return device->modify_device(device, device_modify_mask, | ||
566 | device_modify); | ||
567 | } | ||
568 | EXPORT_SYMBOL(ib_modify_device); | ||
569 | |||
570 | /** | ||
571 | * ib_modify_port - Modifies the attributes for the specified port. | ||
572 | * @device: The device to modify. | ||
573 | * @port_num: The number of the port to modify. | ||
574 | * @port_modify_mask: Mask used to specify which attributes of the port | ||
575 | * to change. | ||
576 | * @port_modify: New attribute values for the port. | ||
577 | * | ||
578 | * ib_modify_port() changes a port's attributes as specified by the | ||
579 | * @port_modify_mask and @port_modify structure. | ||
580 | */ | ||
581 | int ib_modify_port(struct ib_device *device, | ||
582 | u8 port_num, int port_modify_mask, | ||
583 | struct ib_port_modify *port_modify) | ||
584 | { | ||
585 | return device->modify_port(device, port_num, port_modify_mask, | ||
586 | port_modify); | ||
587 | } | ||
588 | EXPORT_SYMBOL(ib_modify_port); | ||
589 | |||
590 | static int __init ib_core_init(void) | ||
591 | { | ||
592 | int ret; | ||
593 | |||
594 | ret = ib_sysfs_setup(); | ||
595 | if (ret) | ||
596 | printk(KERN_WARNING "Couldn't create InfiniBand device class\n"); | ||
597 | |||
598 | ret = ib_cache_setup(); | ||
599 | if (ret) { | ||
600 | printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); | ||
601 | ib_sysfs_cleanup(); | ||
602 | } | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | static void __exit ib_core_cleanup(void) | ||
608 | { | ||
609 | ib_cache_cleanup(); | ||
610 | ib_sysfs_cleanup(); | ||
611 | } | ||
612 | |||
613 | module_init(ib_core_init); | ||
614 | module_exit(ib_core_cleanup); | ||