aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErez Shitrit <erezsh@mellanox.co.il>2012-06-19 04:21:38 -0400
committerRoland Dreier <roland@purestorage.com>2012-07-08 21:05:06 -0400
commitaeab97ed1503bedbe14d1e1c5ab7b90253a67664 (patch)
tree49e7e2d930982c66ba5b627ac63c6a70f8e85840
parentb1d8eb5a213640f1be98a90e73a241d15b70045c (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.c133
-rw-r--r--include/rdma/ib_sa.h33
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
97struct 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
97struct ib_sa_mcmember_query { 103struct 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
361static 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
350static void free_sm_ah(struct kref *kref) 384static 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 */
983static 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
1000static 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
1005int 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
1070err2:
1071 *sa_query = NULL;
1072 ib_sa_client_put(query->sa_query.client);
1073 free_mad(&query->sa_query);
1074
1075err1:
1076 kfree(query);
1077 return ret;
1078}
1079EXPORT_SYMBOL(ib_sa_guid_info_rec_query);
1080
948static void send_handler(struct ib_mad_agent *agent, 1081static 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
267struct 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
254struct ib_sa_client { 276struct 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 */
386void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec); 408void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec);
387 409
410/* Support GuidInfoRecord */
411int 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 */