diff mbox

[for-next,2/4] IB/sa: Add support for sa get ClassPortInfo

Message ID 1461070287-13469-3-git-send-email-erezsh@mellanox.com (mailing list archive)
State Superseded
Headers show

Commit Message

Erez Shitrit April 19, 2016, 12:51 p.m. UTC
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@mellanox.com>
Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/sa_query.c | 174 +++++++++++++++++++++++++++++++++++++
 include/rdma/ib_sa.h               |  12 +++
 2 files changed, 186 insertions(+)

Comments

Hal Rosenstock April 20, 2016, 12:09 p.m. UTC | #1
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@mellanox.com>
> Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
> ---
>  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@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Or Gerlitz April 20, 2016, 1:12 p.m. UTC | #2
On Tue, Apr 19, 2016 at 3:51 PM, Erez Shitrit <erezsh@mellanox.com> wrote:
>
> New sa query function to return the ClassPortInfo struct from the sa.

sa --> SA in all your change-logs, please

and in the subject it's the SA agent not the SA your are patching
here, reflect that
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Erez Shitrit April 20, 2016, 1:19 p.m. UTC | #3
On Wed, Apr 20, 2016 at 4:12 PM, Or Gerlitz <gerlitz.or@gmail.com> wrote:
> On Tue, Apr 19, 2016 at 3:51 PM, Erez Shitrit <erezsh@mellanox.com> wrote:
>>
>> New sa query function to return the ClassPortInfo struct from the sa.
>
> sa --> SA in all your change-logs, please
>
> and in the subject it's the SA agent not the SA your are patching
> here, reflect that

Ack

> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Erez Shitrit April 20, 2016, 2:24 p.m. UTC | #4
On Wed, Apr 20, 2016 at 3:09 PM, Hal Rosenstock <hal@dev.mellanox.co.il> wrote:
> 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@mellanox.com>
>> Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
>> ---
>>  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 ?

Agree. will fix that. thanks.

>
>> +     .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@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Erez Shitrit April 21, 2016, 12:12 p.m. UTC | #5
On Wed, Apr 20, 2016 at 3:09 PM, Hal Rosenstock <hal@dev.mellanox.co.il> wrote:
> 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@mellanox.com>
>> Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
>> ---
>>  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

Tried to follow the sm implementation.
Anyway, will fix that.
Thanks.

>
>> +     { 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@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

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) \
+	.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 },
+	{ 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 */