diff options
author | Erez Shitrit <erezsh@mellanox.co.il> | 2012-06-19 04:21:38 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-07-08 21:05:06 -0400 |
commit | aeab97ed1503bedbe14d1e1c5ab7b90253a67664 (patch) | |
tree | 49e7e2d930982c66ba5b627ac63c6a70f8e85840 | |
parent | b1d8eb5a213640f1be98a90e73a241d15b70045c (diff) |
IB/sa: Add GuidInfoRecord query support
This query is needed for SRIOV alias GUID support.
The query is implemented per the IB Spec definition
in section 15.2.5.18 (GuidInfoRecord).
Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | drivers/infiniband/core/sa_query.c | 133 | ||||
-rw-r--r-- | include/rdma/ib_sa.h | 33 |
2 files changed, 166 insertions, 0 deletions
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index fbbfa24cf572..a8905abc56e4 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -94,6 +94,12 @@ struct ib_sa_path_query { | |||
94 | struct ib_sa_query sa_query; | 94 | struct ib_sa_query sa_query; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | struct ib_sa_guidinfo_query { | ||
98 | void (*callback)(int, struct ib_sa_guidinfo_rec *, void *); | ||
99 | void *context; | ||
100 | struct ib_sa_query sa_query; | ||
101 | }; | ||
102 | |||
97 | struct ib_sa_mcmember_query { | 103 | struct ib_sa_mcmember_query { |
98 | void (*callback)(int, struct ib_sa_mcmember_rec *, void *); | 104 | void (*callback)(int, struct ib_sa_mcmember_rec *, void *); |
99 | void *context; | 105 | void *context; |
@@ -347,6 +353,34 @@ static const struct ib_field service_rec_table[] = { | |||
347 | .size_bits = 2*64 }, | 353 | .size_bits = 2*64 }, |
348 | }; | 354 | }; |
349 | 355 | ||
356 | #define GUIDINFO_REC_FIELD(field) \ | ||
357 | .struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \ | ||
358 | .struct_size_bytes = sizeof((struct ib_sa_guidinfo_rec *) 0)->field, \ | ||
359 | .field_name = "sa_guidinfo_rec:" #field | ||
360 | |||
361 | static const struct ib_field guidinfo_rec_table[] = { | ||
362 | { GUIDINFO_REC_FIELD(lid), | ||
363 | .offset_words = 0, | ||
364 | .offset_bits = 0, | ||
365 | .size_bits = 16 }, | ||
366 | { GUIDINFO_REC_FIELD(block_num), | ||
367 | .offset_words = 0, | ||
368 | .offset_bits = 16, | ||
369 | .size_bits = 8 }, | ||
370 | { GUIDINFO_REC_FIELD(res1), | ||
371 | .offset_words = 0, | ||
372 | .offset_bits = 24, | ||
373 | .size_bits = 8 }, | ||
374 | { GUIDINFO_REC_FIELD(res2), | ||
375 | .offset_words = 1, | ||
376 | .offset_bits = 0, | ||
377 | .size_bits = 32 }, | ||
378 | { GUIDINFO_REC_FIELD(guid_info_list), | ||
379 | .offset_words = 2, | ||
380 | .offset_bits = 0, | ||
381 | .size_bits = 512 }, | ||
382 | }; | ||
383 | |||
350 | static void free_sm_ah(struct kref *kref) | 384 | static void free_sm_ah(struct kref *kref) |
351 | { | 385 | { |
352 | struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref); | 386 | struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref); |
@@ -945,6 +979,105 @@ err1: | |||
945 | return ret; | 979 | return ret; |
946 | } | 980 | } |
947 | 981 | ||
982 | /* Support GuidInfoRecord */ | ||
983 | static void ib_sa_guidinfo_rec_callback(struct ib_sa_query *sa_query, | ||
984 | int status, | ||
985 | struct ib_sa_mad *mad) | ||
986 | { | ||
987 | struct ib_sa_guidinfo_query *query = | ||
988 | container_of(sa_query, struct ib_sa_guidinfo_query, sa_query); | ||
989 | |||
990 | if (mad) { | ||
991 | struct ib_sa_guidinfo_rec rec; | ||
992 | |||
993 | ib_unpack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), | ||
994 | mad->data, &rec); | ||
995 | query->callback(status, &rec, query->context); | ||
996 | } else | ||
997 | query->callback(status, NULL, query->context); | ||
998 | } | ||
999 | |||
1000 | static void ib_sa_guidinfo_rec_release(struct ib_sa_query *sa_query) | ||
1001 | { | ||
1002 | kfree(container_of(sa_query, struct ib_sa_guidinfo_query, sa_query)); | ||
1003 | } | ||
1004 | |||
1005 | int ib_sa_guid_info_rec_query(struct ib_sa_client *client, | ||
1006 | struct ib_device *device, u8 port_num, | ||
1007 | struct ib_sa_guidinfo_rec *rec, | ||
1008 | ib_sa_comp_mask comp_mask, u8 method, | ||
1009 | int timeout_ms, gfp_t gfp_mask, | ||
1010 | void (*callback)(int status, | ||
1011 | struct ib_sa_guidinfo_rec *resp, | ||
1012 | void *context), | ||
1013 | void *context, | ||
1014 | struct ib_sa_query **sa_query) | ||
1015 | { | ||
1016 | struct ib_sa_guidinfo_query *query; | ||
1017 | struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); | ||
1018 | struct ib_sa_port *port; | ||
1019 | struct ib_mad_agent *agent; | ||
1020 | struct ib_sa_mad *mad; | ||
1021 | int ret; | ||
1022 | |||
1023 | if (!sa_dev) | ||
1024 | return -ENODEV; | ||
1025 | |||
1026 | if (method != IB_MGMT_METHOD_GET && | ||
1027 | method != IB_MGMT_METHOD_SET && | ||
1028 | method != IB_SA_METHOD_DELETE) { | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | port = &sa_dev->port[port_num - sa_dev->start_port]; | ||
1033 | agent = port->agent; | ||
1034 | |||
1035 | query = kmalloc(sizeof *query, gfp_mask); | ||
1036 | if (!query) | ||
1037 | return -ENOMEM; | ||
1038 | |||
1039 | query->sa_query.port = port; | ||
1040 | ret = alloc_mad(&query->sa_query, gfp_mask); | ||
1041 | if (ret) | ||
1042 | goto err1; | ||
1043 | |||
1044 | ib_sa_client_get(client); | ||
1045 | query->sa_query.client = client; | ||
1046 | query->callback = callback; | ||
1047 | query->context = context; | ||
1048 | |||
1049 | mad = query->sa_query.mad_buf->mad; | ||
1050 | init_mad(mad, agent); | ||
1051 | |||
1052 | query->sa_query.callback = callback ? ib_sa_guidinfo_rec_callback : NULL; | ||
1053 | query->sa_query.release = ib_sa_guidinfo_rec_release; | ||
1054 | |||
1055 | mad->mad_hdr.method = method; | ||
1056 | mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_GUID_INFO_REC); | ||
1057 | mad->sa_hdr.comp_mask = comp_mask; | ||
1058 | |||
1059 | ib_pack(guidinfo_rec_table, ARRAY_SIZE(guidinfo_rec_table), rec, | ||
1060 | mad->data); | ||
1061 | |||
1062 | *sa_query = &query->sa_query; | ||
1063 | |||
1064 | ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); | ||
1065 | if (ret < 0) | ||
1066 | goto err2; | ||
1067 | |||
1068 | return ret; | ||
1069 | |||
1070 | err2: | ||
1071 | *sa_query = NULL; | ||
1072 | ib_sa_client_put(query->sa_query.client); | ||
1073 | free_mad(&query->sa_query); | ||
1074 | |||
1075 | err1: | ||
1076 | kfree(query); | ||
1077 | return ret; | ||
1078 | } | ||
1079 | EXPORT_SYMBOL(ib_sa_guid_info_rec_query); | ||
1080 | |||
948 | static void send_handler(struct ib_mad_agent *agent, | 1081 | static void send_handler(struct ib_mad_agent *agent, |
949 | struct ib_mad_send_wc *mad_send_wc) | 1082 | struct ib_mad_send_wc *mad_send_wc) |
950 | { | 1083 | { |
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h index d44a56388a3e..8275e539bace 100644 --- a/include/rdma/ib_sa.h +++ b/include/rdma/ib_sa.h | |||
@@ -251,6 +251,28 @@ struct ib_sa_service_rec { | |||
251 | u64 data64[2]; | 251 | u64 data64[2]; |
252 | }; | 252 | }; |
253 | 253 | ||
254 | #define IB_SA_GUIDINFO_REC_LID IB_SA_COMP_MASK(0) | ||
255 | #define IB_SA_GUIDINFO_REC_BLOCK_NUM IB_SA_COMP_MASK(1) | ||
256 | #define IB_SA_GUIDINFO_REC_RES1 IB_SA_COMP_MASK(2) | ||
257 | #define IB_SA_GUIDINFO_REC_RES2 IB_SA_COMP_MASK(3) | ||
258 | #define IB_SA_GUIDINFO_REC_GID0 IB_SA_COMP_MASK(4) | ||
259 | #define IB_SA_GUIDINFO_REC_GID1 IB_SA_COMP_MASK(5) | ||
260 | #define IB_SA_GUIDINFO_REC_GID2 IB_SA_COMP_MASK(6) | ||
261 | #define IB_SA_GUIDINFO_REC_GID3 IB_SA_COMP_MASK(7) | ||
262 | #define IB_SA_GUIDINFO_REC_GID4 IB_SA_COMP_MASK(8) | ||
263 | #define IB_SA_GUIDINFO_REC_GID5 IB_SA_COMP_MASK(9) | ||
264 | #define IB_SA_GUIDINFO_REC_GID6 IB_SA_COMP_MASK(10) | ||
265 | #define IB_SA_GUIDINFO_REC_GID7 IB_SA_COMP_MASK(11) | ||
266 | |||
267 | struct ib_sa_guidinfo_rec { | ||
268 | __be16 lid; | ||
269 | u8 block_num; | ||
270 | /* reserved */ | ||
271 | u8 res1; | ||
272 | __be32 res2; | ||
273 | u8 guid_info_list[64]; | ||
274 | }; | ||
275 | |||
254 | struct ib_sa_client { | 276 | struct ib_sa_client { |
255 | atomic_t users; | 277 | atomic_t users; |
256 | struct completion comp; | 278 | struct completion comp; |
@@ -385,4 +407,15 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num, | |||
385 | */ | 407 | */ |
386 | void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec); | 408 | void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec); |
387 | 409 | ||
410 | /* Support GuidInfoRecord */ | ||
411 | int ib_sa_guid_info_rec_query(struct ib_sa_client *client, | ||
412 | struct ib_device *device, u8 port_num, | ||
413 | struct ib_sa_guidinfo_rec *rec, | ||
414 | ib_sa_comp_mask comp_mask, u8 method, | ||
415 | int timeout_ms, gfp_t gfp_mask, | ||
416 | void (*callback)(int status, | ||
417 | struct ib_sa_guidinfo_rec *resp, | ||
418 | void *context), | ||
419 | void *context, | ||
420 | struct ib_sa_query **sa_query); | ||
388 | #endif /* IB_SA_H */ | 421 | #endif /* IB_SA_H */ |