|
1 | 1 | /*
|
2 | 2 | * Copyright (c) 2004 Topspin Communications. All rights reserved.
|
| 3 | + * Copyright (c) 2005 Voltaire, Inc. All rights reserved. |
3 | 4 | *
|
4 | 5 | * This software is available to you under a choice of one of two
|
5 | 6 | * licenses. You may choose to be licensed under the terms of the GNU
|
|
29 | 30 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
30 | 31 | * SOFTWARE.
|
31 | 32 | *
|
32 |
| - * $Id: sa_query.c 1389 2004-12-27 22:56:47Z roland $ |
| 33 | + * $Id: sa_query.c 2811 2005-07-06 18:11:43Z halr $ |
33 | 34 | */
|
34 | 35 |
|
35 | 36 | #include <linux/module.h>
|
@@ -79,6 +80,12 @@ struct ib_sa_query {
|
79 | 80 | int id;
|
80 | 81 | };
|
81 | 82 |
|
| 83 | +struct ib_sa_service_query { |
| 84 | + void (*callback)(int, struct ib_sa_service_rec *, void *); |
| 85 | + void *context; |
| 86 | + struct ib_sa_query sa_query; |
| 87 | +}; |
| 88 | + |
82 | 89 | struct ib_sa_path_query {
|
83 | 90 | void (*callback)(int, struct ib_sa_path_rec *, void *);
|
84 | 91 | void *context;
|
@@ -320,6 +327,54 @@ static const struct ib_field mcmember_rec_table[] = {
|
320 | 327 | .size_bits = 23 },
|
321 | 328 | };
|
322 | 329 |
|
| 330 | +#define SERVICE_REC_FIELD(field) \ |
| 331 | + .struct_offset_bytes = offsetof(struct ib_sa_service_rec, field), \ |
| 332 | + .struct_size_bytes = sizeof ((struct ib_sa_service_rec *) 0)->field, \ |
| 333 | + .field_name = "sa_service_rec:" #field |
| 334 | + |
| 335 | +static const struct ib_field service_rec_table[] = { |
| 336 | + { SERVICE_REC_FIELD(id), |
| 337 | + .offset_words = 0, |
| 338 | + .offset_bits = 0, |
| 339 | + .size_bits = 64 }, |
| 340 | + { SERVICE_REC_FIELD(gid), |
| 341 | + .offset_words = 2, |
| 342 | + .offset_bits = 0, |
| 343 | + .size_bits = 128 }, |
| 344 | + { SERVICE_REC_FIELD(pkey), |
| 345 | + .offset_words = 6, |
| 346 | + .offset_bits = 0, |
| 347 | + .size_bits = 16 }, |
| 348 | + { SERVICE_REC_FIELD(lease), |
| 349 | + .offset_words = 7, |
| 350 | + .offset_bits = 0, |
| 351 | + .size_bits = 32 }, |
| 352 | + { SERVICE_REC_FIELD(key), |
| 353 | + .offset_words = 8, |
| 354 | + .offset_bits = 0, |
| 355 | + .size_bits = 128 }, |
| 356 | + { SERVICE_REC_FIELD(name), |
| 357 | + .offset_words = 12, |
| 358 | + .offset_bits = 0, |
| 359 | + .size_bits = 64*8 }, |
| 360 | + { SERVICE_REC_FIELD(data8), |
| 361 | + .offset_words = 28, |
| 362 | + .offset_bits = 0, |
| 363 | + .size_bits = 16*8 }, |
| 364 | + { SERVICE_REC_FIELD(data16), |
| 365 | + .offset_words = 32, |
| 366 | + .offset_bits = 0, |
| 367 | + .size_bits = 8*16 }, |
| 368 | + { SERVICE_REC_FIELD(data32), |
| 369 | + .offset_words = 36, |
| 370 | + .offset_bits = 0, |
| 371 | + .size_bits = 4*32 }, |
| 372 | + { SERVICE_REC_FIELD(data64), |
| 373 | + .offset_words = 40, |
| 374 | + .offset_bits = 0, |
| 375 | + .size_bits = 2*64 }, |
| 376 | +}; |
| 377 | + |
323 | 378 | static void free_sm_ah(struct kref *kref)
|
324 | 379 | {
|
325 | 380 | struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
|
@@ -443,7 +498,6 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms)
|
443 | 498 | .remote_qpn = 1,
|
444 | 499 | .remote_qkey = IB_QP1_QKEY,
|
445 | 500 | .timeout_ms = timeout_ms,
|
446 |
| - .retries = 0 |
447 | 501 | }
|
448 | 502 | }
|
449 | 503 | };
|
@@ -596,6 +650,114 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
|
596 | 650 | }
|
597 | 651 | EXPORT_SYMBOL(ib_sa_path_rec_get);
|
598 | 652 |
|
| 653 | +static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query, |
| 654 | + int status, |
| 655 | + struct ib_sa_mad *mad) |
| 656 | +{ |
| 657 | + struct ib_sa_service_query *query = |
| 658 | + container_of(sa_query, struct ib_sa_service_query, sa_query); |
| 659 | + |
| 660 | + if (mad) { |
| 661 | + struct ib_sa_service_rec rec; |
| 662 | + |
| 663 | + ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table), |
| 664 | + mad->data, &rec); |
| 665 | + query->callback(status, &rec, query->context); |
| 666 | + } else |
| 667 | + query->callback(status, NULL, query->context); |
| 668 | +} |
| 669 | + |
| 670 | +static void ib_sa_service_rec_release(struct ib_sa_query *sa_query) |
| 671 | +{ |
| 672 | + kfree(sa_query->mad); |
| 673 | + kfree(container_of(sa_query, struct ib_sa_service_query, sa_query)); |
| 674 | +} |
| 675 | + |
| 676 | +/** |
| 677 | + * ib_sa_service_rec_query - Start Service Record operation |
| 678 | + * @device:device to send request on |
| 679 | + * @port_num: port number to send request on |
| 680 | + * @method:SA method - should be get, set, or delete |
| 681 | + * @rec:Service Record to send in request |
| 682 | + * @comp_mask:component mask to send in request |
| 683 | + * @timeout_ms:time to wait for response |
| 684 | + * @gfp_mask:GFP mask to use for internal allocations |
| 685 | + * @callback:function called when request completes, times out or is |
| 686 | + * canceled |
| 687 | + * @context:opaque user context passed to callback |
| 688 | + * @sa_query:request context, used to cancel request |
| 689 | + * |
| 690 | + * Send a Service Record set/get/delete to the SA to register, |
| 691 | + * unregister or query a service record. |
| 692 | + * The callback function will be called when the request completes (or |
| 693 | + * fails); status is 0 for a successful response, -EINTR if the query |
| 694 | + * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error |
| 695 | + * occurred sending the query. The resp parameter of the callback is |
| 696 | + * only valid if status is 0. |
| 697 | + * |
| 698 | + * If the return value of ib_sa_service_rec_query() is negative, it is an |
| 699 | + * error code. Otherwise it is a request ID that can be used to cancel |
| 700 | + * the query. |
| 701 | + */ |
| 702 | +int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, |
| 703 | + struct ib_sa_service_rec *rec, |
| 704 | + ib_sa_comp_mask comp_mask, |
| 705 | + int timeout_ms, int gfp_mask, |
| 706 | + void (*callback)(int status, |
| 707 | + struct ib_sa_service_rec *resp, |
| 708 | + void *context), |
| 709 | + void *context, |
| 710 | + struct ib_sa_query **sa_query) |
| 711 | +{ |
| 712 | + struct ib_sa_service_query *query; |
| 713 | + struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); |
| 714 | + struct ib_sa_port *port = &sa_dev->port[port_num - sa_dev->start_port]; |
| 715 | + struct ib_mad_agent *agent = port->agent; |
| 716 | + int ret; |
| 717 | + |
| 718 | + if (method != IB_MGMT_METHOD_GET && |
| 719 | + method != IB_MGMT_METHOD_SET && |
| 720 | + method != IB_SA_METHOD_DELETE) |
| 721 | + return -EINVAL; |
| 722 | + |
| 723 | + query = kmalloc(sizeof *query, gfp_mask); |
| 724 | + if (!query) |
| 725 | + return -ENOMEM; |
| 726 | + query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask); |
| 727 | + if (!query->sa_query.mad) { |
| 728 | + kfree(query); |
| 729 | + return -ENOMEM; |
| 730 | + } |
| 731 | + |
| 732 | + query->callback = callback; |
| 733 | + query->context = context; |
| 734 | + |
| 735 | + init_mad(query->sa_query.mad, agent); |
| 736 | + |
| 737 | + query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL; |
| 738 | + query->sa_query.release = ib_sa_service_rec_release; |
| 739 | + query->sa_query.port = port; |
| 740 | + query->sa_query.mad->mad_hdr.method = method; |
| 741 | + query->sa_query.mad->mad_hdr.attr_id = |
| 742 | + cpu_to_be16(IB_SA_ATTR_SERVICE_REC); |
| 743 | + query->sa_query.mad->sa_hdr.comp_mask = comp_mask; |
| 744 | + |
| 745 | + ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table), |
| 746 | + rec, query->sa_query.mad->data); |
| 747 | + |
| 748 | + *sa_query = &query->sa_query; |
| 749 | + |
| 750 | + ret = send_mad(&query->sa_query, timeout_ms); |
| 751 | + if (ret < 0) { |
| 752 | + *sa_query = NULL; |
| 753 | + kfree(query->sa_query.mad); |
| 754 | + kfree(query); |
| 755 | + } |
| 756 | + |
| 757 | + return ret; |
| 758 | +} |
| 759 | +EXPORT_SYMBOL(ib_sa_service_rec_query); |
| 760 | + |
599 | 761 | static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
|
600 | 762 | int status,
|
601 | 763 | struct ib_sa_mad *mad)
|
|
0 commit comments