On 4/19/2016 8:51 AM, Erez Shitrit wrote: > New sa query function to return the ClassPortInfo struct from the sa. > If the SM supports FullMemberSendOnly mode for MCG's, it sets a > capability bit in the capability_mask2 field of the response. > > Signed-off-by: Erez Shitrit <erezsh@xxxxxxxxxxxx> > Reviewed-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> > --- > drivers/infiniband/core/sa_query.c | 174 +++++++++++++++++++++++++++++++++++++ > include/rdma/ib_sa.h | 12 +++ > 2 files changed, 186 insertions(+) > > diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c > index 8a09c0f..66535bf 100644 > --- a/drivers/infiniband/core/sa_query.c > +++ b/drivers/infiniband/core/sa_query.c > @@ -119,6 +119,12 @@ struct ib_sa_guidinfo_query { > struct ib_sa_query sa_query; > }; > > +struct ib_sa_classport_info_query { > + void (*callback)(int, struct ib_class_port_info *, void *); > + void *context; > + struct ib_sa_query sa_query; > +}; > + > struct ib_sa_mcmember_query { > void (*callback)(int, struct ib_sa_mcmember_rec *, void *); > void *context; > @@ -392,6 +398,83 @@ static const struct ib_field service_rec_table[] = { > .size_bits = 2*64 }, > }; > > +#define PORTCLASSINFO_REC_FIELD(field) \ Would CLASSPORTINFO_REC_FIELD be more consistent in terms of naming ? > + .struct_offset_bytes = offsetof(struct ib_class_port_info, field), \ > + .struct_size_bytes = sizeof((struct ib_class_port_info *)0)->field, \ > + .field_name = "ib_class_port_info:" #field > + > +static const struct ib_field classport_info_rec_table[] = { > + { PORTCLASSINFO_REC_FIELD(base_version), > + .offset_words = 0, > + .offset_bits = 0, > + .size_bits = 8 }, > + { PORTCLASSINFO_REC_FIELD(class_version), > + .offset_words = 0, > + .offset_bits = 8, > + .size_bits = 8 }, > + { PORTCLASSINFO_REC_FIELD(capability_mask), > + .offset_words = 0, > + .offset_bits = 16, > + .size_bits = 16 }, > + { PORTCLASSINFO_REC_FIELD(cap_mask2_resp_time), > + .offset_words = 1, > + .offset_bits = 0, > + .size_bits = 32 }, Why combine fields ? Syntax is rich enough to deal with bit fields. This is what was done for other SA attributes in this file. -- Hal > + { PORTCLASSINFO_REC_FIELD(redirect_gid), > + .offset_words = 2, > + .offset_bits = 0, > + .size_bits = 128 }, > + { PORTCLASSINFO_REC_FIELD(redirect_tcslfl), > + .offset_words = 6, > + .offset_bits = 0, > + .size_bits = 32 }, > + > + { PORTCLASSINFO_REC_FIELD(redirect_lid), > + .offset_words = 7, > + .offset_bits = 0, > + .size_bits = 16 }, > + { PORTCLASSINFO_REC_FIELD(redirect_pkey), > + .offset_words = 7, > + .offset_bits = 16, > + .size_bits = 16 }, > + > + { PORTCLASSINFO_REC_FIELD(redirect_qp), > + .offset_words = 8, > + .offset_bits = 0, > + .size_bits = 32 }, > + { PORTCLASSINFO_REC_FIELD(redirect_qkey), > + .offset_words = 9, > + .offset_bits = 0, > + .size_bits = 32 }, > + > + { PORTCLASSINFO_REC_FIELD(trap_gid), > + .offset_words = 10, > + .offset_bits = 0, > + .size_bits = 128 }, > + { PORTCLASSINFO_REC_FIELD(trap_tcslfl), > + .offset_words = 14, > + .offset_bits = 0, > + .size_bits = 32 }, > + > + { PORTCLASSINFO_REC_FIELD(trap_lid), > + .offset_words = 15, > + .offset_bits = 0, > + .size_bits = 16 }, > + { PORTCLASSINFO_REC_FIELD(trap_pkey), > + .offset_words = 15, > + .offset_bits = 16, > + .size_bits = 16 }, > + > + { PORTCLASSINFO_REC_FIELD(trap_hlqp), > + .offset_words = 16, > + .offset_bits = 0, > + .size_bits = 32 }, > + { PORTCLASSINFO_REC_FIELD(trap_qkey), > + .offset_words = 17, > + .offset_bits = 0, > + .size_bits = 32 }, > +}; > + > #define GUIDINFO_REC_FIELD(field) \ > .struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field), \ > .struct_size_bytes = sizeof((struct ib_sa_guidinfo_rec *) 0)->field, \ > @@ -1645,6 +1728,97 @@ err1: > } > EXPORT_SYMBOL(ib_sa_guid_info_rec_query); > > +/* Support get SA ClassPortInfo */ > +static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query, > + int status, > + struct ib_sa_mad *mad) > +{ > + struct ib_sa_classport_info_query *query = > + container_of(sa_query, struct ib_sa_classport_info_query, sa_query); > + > + if (mad) { > + struct ib_class_port_info rec; > + > + ib_unpack(classport_info_rec_table, > + ARRAY_SIZE(classport_info_rec_table), > + mad->data, &rec); > + query->callback(status, &rec, query->context); > + } else { > + query->callback(status, NULL, query->context); > + } > +} > + > +static void ib_sa_portclass_info_rec_release(struct ib_sa_query *sa_query) > +{ > + kfree(container_of(sa_query, struct ib_sa_classport_info_query, > + sa_query)); > +} > + > +int ib_sa_classport_info_rec_query(struct ib_sa_client *client, > + struct ib_device *device, u8 port_num, > + int timeout_ms, gfp_t gfp_mask, > + void (*callback)(int status, > + struct ib_class_port_info *resp, > + void *context), > + void *context, > + struct ib_sa_query **sa_query) > +{ > + struct ib_sa_classport_info_query *query; > + struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client); > + struct ib_sa_port *port; > + struct ib_mad_agent *agent; > + struct ib_sa_mad *mad; > + int ret; > + > + if (!sa_dev) > + return -ENODEV; > + > + port = &sa_dev->port[port_num - sa_dev->start_port]; > + agent = port->agent; > + > + query = kzalloc(sizeof(*query), gfp_mask); > + if (!query) > + return -ENOMEM; > + > + query->sa_query.port = port; > + ret = alloc_mad(&query->sa_query, gfp_mask); > + if (ret) > + goto err1; > + > + ib_sa_client_get(client); > + query->sa_query.client = client; > + query->callback = callback; > + query->context = context; > + > + mad = query->sa_query.mad_buf->mad; > + init_mad(mad, agent); > + > + query->sa_query.callback = callback ? ib_sa_classport_info_rec_callback : NULL; > + > + query->sa_query.release = ib_sa_portclass_info_rec_release; > + /* support GET only */ > + mad->mad_hdr.method = IB_MGMT_METHOD_GET; > + mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_CLASS_PORTINFO); > + mad->sa_hdr.comp_mask = 0; > + *sa_query = &query->sa_query; > + > + ret = send_mad(&query->sa_query, timeout_ms, gfp_mask); > + if (ret < 0) > + goto err2; > + > + return ret; > + > +err2: > + *sa_query = NULL; > + ib_sa_client_put(query->sa_query.client); > + free_mad(&query->sa_query); > + > +err1: > + kfree(query); > + return ret; > +} > +EXPORT_SYMBOL(ib_sa_classport_info_rec_query); > + > static void send_handler(struct ib_mad_agent *agent, > struct ib_mad_send_wc *mad_send_wc) > { > diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h > index cdc1c81..3840416 100644 > --- a/include/rdma/ib_sa.h > +++ b/include/rdma/ib_sa.h > @@ -94,6 +94,8 @@ enum ib_sa_selector { > IB_SA_BEST = 3 > }; > > +#define IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT BIT(12) > + > /* > * Structures for SA records are named "struct ib_sa_xxx_rec." No > * attempt is made to pack structures to match the physical layout of > @@ -439,4 +441,14 @@ int ib_sa_guid_info_rec_query(struct ib_sa_client *client, > void *context, > struct ib_sa_query **sa_query); > > +/* Support get SA ClassPortInfo */ > +int ib_sa_classport_info_rec_query(struct ib_sa_client *client, > + struct ib_device *device, u8 port_num, > + int timeout_ms, gfp_t gfp_mask, > + void (*callback)(int status, > + struct ib_class_port_info *resp, > + void *context), > + void *context, > + struct ib_sa_query **sa_query); > + > #endif /* IB_SA_H */ > -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html