Re: [PATCH rdma-core 5/7] IB/SA: Modify SA to implicity cache Class Port info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 3/15/2017 5:24 PM, Dasaratharaman Chandramouli wrote:
> SA will query and cache class port info as part of
> its initialization. SA will also invalidate and
> refresh the cache based on specific events. Callers such
> as IPoIB and CM can query the SA to get the classportinfo
> information. Apart from making the caller code much simpler,
> this change puts the onus on the SA to query and maintain
> classportinfo much like how it maitains the address handle to the SM.
> 
> Reviewed-by: Ira Weiny <ira.weiny@xxxxxxxxx>
> Reviewed-by: Don Hiatt <don.hiatt@xxxxxxxxx>
> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@xxxxxxxxx>
> ---
>  drivers/infiniband/core/cma.c                  |  76 ++---------
>  drivers/infiniband/core/sa_query.c             | 179 ++++++++++++++++++-------
>  drivers/infiniband/ulp/ipoib/ipoib.h           |   1 -
>  drivers/infiniband/ulp/ipoib/ipoib_main.c      |  71 ----------
>  drivers/infiniband/ulp/ipoib/ipoib_multicast.c |   9 +-
>  include/rdma/ib_sa.h                           |  12 +-
>  6 files changed, 142 insertions(+), 206 deletions(-)
> 
> diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
> index 5ed6ec9..421400a 100644
> --- a/drivers/infiniband/core/cma.c
> +++ b/drivers/infiniband/core/cma.c
> @@ -3943,63 +3943,10 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
>  	}
>  }
>  
> -static void cma_query_sa_classport_info_cb(int status,
> -					   struct ib_class_port_info *rec,
> -					   void *context)
> -{
> -	struct class_port_info_context *cb_ctx = context;
> -
> -	WARN_ON(!context);
> -
> -	if (status || !rec) {
> -		pr_debug("RDMA CM: %s port %u failed query ClassPortInfo status: %d\n",
> -			 cb_ctx->device->name, cb_ctx->port_num, status);
> -		goto out;
> -	}
> -
> -	memcpy(cb_ctx->class_port_info, rec, sizeof(struct ib_class_port_info));
> -
> -out:
> -	complete(&cb_ctx->done);
> -}
> -
> -static int cma_query_sa_classport_info(struct ib_device *device, u8 port_num,
> -				       struct ib_class_port_info *class_port_info)
> -{
> -	struct class_port_info_context *cb_ctx;
> -	int ret;
> -
> -	cb_ctx = kmalloc(sizeof(*cb_ctx), GFP_KERNEL);
> -	if (!cb_ctx)
> -		return -ENOMEM;
> -
> -	cb_ctx->device = device;
> -	cb_ctx->class_port_info = class_port_info;
> -	cb_ctx->port_num = port_num;
> -	init_completion(&cb_ctx->done);
> -
> -	ret = ib_sa_classport_info_rec_query(&sa_client, device, port_num,
> -					     CMA_QUERY_CLASSPORT_INFO_TIMEOUT,
> -					     GFP_KERNEL, cma_query_sa_classport_info_cb,
> -					     cb_ctx, &cb_ctx->sa_query);
> -	if (ret < 0) {
> -		pr_err("RDMA CM: %s port %u failed to send ClassPortInfo query, ret: %d\n",
> -		       device->name, port_num, ret);
> -		goto out;
> -	}
> -
> -	wait_for_completion(&cb_ctx->done);
> -
> -out:
> -	kfree(cb_ctx);
> -	return ret;
> -}
> -
>  static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
>  				 struct cma_multicast *mc)
>  {
>  	struct ib_sa_mcmember_rec rec;
> -	struct ib_class_port_info class_port_info;
>  	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
>  	ib_sa_comp_mask comp_mask;
>  	int ret;
> @@ -4020,21 +3967,14 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
>  	rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
>  	rec.join_state = mc->join_state;
>  
> -	if (rec.join_state == BIT(SENDONLY_FULLMEMBER_JOIN)) {
> -		ret = cma_query_sa_classport_info(id_priv->id.device,
> -						  id_priv->id.port_num,
> -						  &class_port_info);
> -
> -		if (ret)
> -			return ret;
> -
> -		if (!(ib_get_cpi_capmask2(&class_port_info) &
> -		      IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT)) {
> -			pr_warn("RDMA CM: %s port %u Unable to multicast join\n"
> -				"RDMA CM: SM doesn't support Send Only Full Member option\n",
> -				id_priv->id.device->name, id_priv->id.port_num);
> -			return -EOPNOTSUPP;
> -		}
> +	if ((rec.join_state == BIT(SENDONLY_FULLMEMBER_JOIN)) &&
> +	    (!ib_sa_sendonly_fullmem_support(&sa_client,
> +					     id_priv->id.device,
> +					     id_priv->id.port_num))) {
> +		pr_warn("RDMA CM: %s port %u Unable to multicast join\n"
> +			"RDMA CM: SM doesn't support Send Only Full Member option\n",
> +			id_priv->id.device->name, id_priv->id.port_num);
> +		return -EOPNOTSUPP;
>  	}
>  
>  	comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
> diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
> index 2181f8c..bc32989 100644
> --- a/drivers/infiniband/core/sa_query.c
> +++ b/drivers/infiniband/core/sa_query.c
> @@ -56,6 +56,8 @@
>  #define IB_SA_LOCAL_SVC_TIMEOUT_MIN		100
>  #define IB_SA_LOCAL_SVC_TIMEOUT_DEFAULT		2000
>  #define IB_SA_LOCAL_SVC_TIMEOUT_MAX		200000
> +#define IB_SA_CPI_MAX_RETRY_CNT			3
> +#define IB_SA_CPI_RETRY_WAIT			1000 /*msecs */
>  static int sa_local_svc_timeout_ms = IB_SA_LOCAL_SVC_TIMEOUT_DEFAULT;
>  
>  struct ib_sa_sm_ah {
> @@ -67,6 +69,7 @@ struct ib_sa_sm_ah {
>  
>  struct ib_sa_classport_cache {
>  	bool valid;
> +	int retry_cnt;
>  	struct ib_class_port_info data;
>  };
>  
> @@ -75,6 +78,7 @@ struct ib_sa_port {
>  	struct ib_sa_sm_ah  *sm_ah;
>  	struct work_struct   update_task;
>  	struct ib_sa_classport_cache classport_info;
> +	struct delayed_work ib_cpi_work;
>  	spinlock_t                   classport_lock; /* protects class port info set */
>  	spinlock_t           ah_lock;
>  	u8                   port_num;
> @@ -123,7 +127,7 @@ struct ib_sa_guidinfo_query {
>  };
>  
>  struct ib_sa_classport_info_query {
> -	void (*callback)(int, struct ib_class_port_info *, void *);
> +	void (*callback)(void *);
>  	void *context;
>  	struct ib_sa_query sa_query;
>  };
> @@ -1642,7 +1646,41 @@ int ib_sa_guid_info_rec_query(struct ib_sa_client *client,
>  }
>  EXPORT_SYMBOL(ib_sa_guid_info_rec_query);
>  
> -/* Support get SA ClassPortInfo */
> +bool ib_sa_sendonly_fullmem_support(struct ib_sa_client *client,
> +				    struct ib_device *device,
> +				    u8 port_num)
> +{
> +	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
> +	struct ib_sa_port *port;
> +	bool ret = false;
> +	unsigned long flags;
> +
> +	if (!sa_dev)
> +		return ret;
> +
> +	port  = &sa_dev->port[port_num - sa_dev->start_port];
> +
> +	spin_lock_irqsave(&port->classport_lock, flags);
> +	if (port->classport_info.valid)
> +		ret = ib_get_cpi_capmask2(&port->classport_info.data) &
> +			IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT;
> +	spin_unlock_irqrestore(&port->classport_lock, flags);
> +	return ret;
> +}
> +EXPORT_SYMBOL(ib_sa_sendonly_fullmem_support);
> +
> +struct ib_classport_info_context {
> +	struct completion	done;
> +	struct ib_sa_query	*sa_query;
> +};
> +
> +static void ib_classportinfo_cb(void *context)
> +{
> +	struct ib_classport_info_context *cb_ctx = context;
> +
> +	complete(&cb_ctx->done);
> +}
> +
>  static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
>  					      int status,
>  					      struct ib_sa_mad *mad)
> @@ -1666,54 +1704,30 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
>  			sa_query->port->classport_info.valid = true;
>  		}
>  		spin_unlock_irqrestore(&sa_query->port->classport_lock, flags);
> -
> -		query->callback(status, &rec, query->context);
> -	} else {
> -		query->callback(status, NULL, query->context);
>  	}
> +	query->callback(query->context);
>  }
>  
> -static void ib_sa_portclass_info_rec_release(struct ib_sa_query *sa_query)
> +static void ib_sa_classport_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)
> +static int ib_sa_classport_info_rec_query(struct ib_sa_port *port,
> +					  int timeout_ms,
> +					  void (*callback)(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_classport_info_query *query;
>  	struct ib_sa_mad *mad;
> -	struct ib_class_port_info cached_class_port_info;
> +	gfp_t gfp_mask = GFP_KERNEL;
>  	int ret;
> -	unsigned long flags;
> -
> -	if (!sa_dev)
> -		return -ENODEV;
>  
> -	port  = &sa_dev->port[port_num - sa_dev->start_port];
>  	agent = port->agent;
>  
> -	/* Use cached ClassPortInfo attribute if valid instead of sending mad */
> -	spin_lock_irqsave(&port->classport_lock, flags);
> -	if (port->classport_info.valid && callback) {
> -		memcpy(&cached_class_port_info, &port->classport_info.data,
> -		       sizeof(cached_class_port_info));
> -		spin_unlock_irqrestore(&port->classport_lock, flags);
> -		callback(0, &cached_class_port_info, context);
> -		return 0;
> -	}
> -	spin_unlock_irqrestore(&port->classport_lock, flags);
> -
>  	query = kzalloc(sizeof(*query), gfp_mask);
>  	if (!query)
>  		return -ENOMEM;
> @@ -1721,20 +1735,16 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
>  	query->sa_query.port = port;
>  	ret = alloc_mad(&query->sa_query, gfp_mask);
>  	if (ret)
> -		goto err1;
> +		goto err_free;
>  
> -	ib_sa_client_get(client);
> -	query->sa_query.client = client;
> -	query->callback        = callback;
> -	query->context         = context;
> +	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 */
> +	query->sa_query.callback = ib_sa_classport_info_rec_callback;
> +	query->sa_query.release  = ib_sa_classport_info_rec_release;
>  	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;
> @@ -1742,20 +1752,71 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
>  
>  	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
>  	if (ret < 0)
> -		goto err2;
> +		goto err_free_mad;
>  
>  	return ret;
>  
> -err2:
> +err_free_mad:
>  	*sa_query = NULL;
> -	ib_sa_client_put(query->sa_query.client);
>  	free_mad(&query->sa_query);
>  
> -err1:
> +err_free:
>  	kfree(query);
>  	return ret;
>  }
> -EXPORT_SYMBOL(ib_sa_classport_info_rec_query);
> +
> +static void update_ib_cpi(struct work_struct *work)
> +{
> +	struct ib_sa_port *port =
> +		container_of(work, struct ib_sa_port, ib_cpi_work.work);
> +	struct ib_classport_info_context *cb_context;
> +	unsigned long flags;
> +	int ret;
> +
> +	/* If the classport info is valid, nothing
> +	 * to do here.
> +	 */
> +	spin_lock_irqsave(&port->classport_lock, flags);
> +	if (port->classport_info.valid) {
> +		spin_unlock_irqrestore(&port->classport_lock, flags);
> +		return;
> +	}
> +	spin_unlock_irqrestore(&port->classport_lock, flags);
> +
> +	cb_context = kmalloc(sizeof(*cb_context), GFP_KERNEL);
> +	if (!cb_context)
> +		goto err_nomem;
> +
> +	init_completion(&cb_context->done);
> +
> +	ret = ib_sa_classport_info_rec_query(port, 3000,
> +					     ib_classportinfo_cb, cb_context,
> +					     &cb_context->sa_query);
> +	if (ret < 0)
> +		goto free_cb_err;
> +	wait_for_completion(&cb_context->done);
> +free_cb_err:
> +	kfree(cb_context);
> +	spin_lock_irqsave(&port->classport_lock, flags);
> +
> +	/* If the classport info is still not valid, the query should have
> +	 * failed for some reason. Retry issuing the query
> +	 */
> +	if (!port->classport_info.valid) {
> +		port->classport_info.retry_cnt++;
> +		if (port->classport_info.retry_cnt <=
> +		    IB_SA_CPI_MAX_RETRY_CNT) {
> +			unsigned long delay =
> +				msecs_to_jiffies(IB_SA_CPI_RETRY_WAIT);
> +
> +			queue_delayed_work(ib_wq, &port->ib_cpi_work, delay);
> +		}
> +	}
> +	spin_unlock_irqrestore(&port->classport_lock, flags);
> +
> +err_nomem:
> +	return;
> +}
>  
>  static void send_handler(struct ib_mad_agent *agent,
>  			 struct ib_mad_send_wc *mad_send_wc)
> @@ -1784,7 +1845,8 @@ static void send_handler(struct ib_mad_agent *agent,
>  	spin_unlock_irqrestore(&idr_lock, flags);
>  
>  	free_mad(query);
> -	ib_sa_client_put(query->client);
> +	if (query->client)
> +		ib_sa_client_put(query->client);
>  	query->release(query);
>  }
>  
> @@ -1894,6 +1956,19 @@ static void ib_sa_event(struct ib_event_handler *handler,
>  			spin_unlock_irqrestore(&port->classport_lock, flags);
>  		}
>  		queue_work(ib_wq, &sa_dev->port[port_num].update_task);
> +
> +		/*Query for class port info on a re-reregister event */
> +		if ((event->event == IB_EVENT_CLIENT_REREGISTER) ||
> +		    (event->event == IB_EVENT_PORT_ACTIVE)) {

Since SA CPI is invalidated on SM change and LID change events,
shouldn't these events also be included here to retrigger SA CPI query ?

-- Hal

> +			unsigned long delay =
> +				msecs_to_jiffies(IB_SA_CPI_RETRY_WAIT);
> +
> +			spin_lock_irqsave(&port->classport_lock, flags);
> +			port->classport_info.retry_cnt = 0;
> +			spin_unlock_irqrestore(&port->classport_lock, flags);
> +			queue_delayed_work(ib_wq,
> +					   &port->ib_cpi_work, delay);
> +		}
>  	}
>  }
>  
> @@ -1934,6 +2009,8 @@ static void ib_sa_add_one(struct ib_device *device)
>  			goto err;
>  
>  		INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah);
> +		INIT_DELAYED_WORK(&sa_dev->port[i].ib_cpi_work,
> +				  update_ib_cpi);
>  
>  		count++;
>  	}
> @@ -1980,11 +2057,11 @@ static void ib_sa_remove_one(struct ib_device *device, void *client_data)
>  		return;
>  
>  	ib_unregister_event_handler(&sa_dev->event_handler);
> -
>  	flush_workqueue(ib_wq);
>  
>  	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
>  		if (rdma_cap_ib_sa(device, i + 1)) {
> +			cancel_delayed_work_sync(&sa_dev->port[i].ib_cpi_work);
>  			ib_unregister_mad_agent(sa_dev->port[i].agent);
>  			if (sa_dev->port[i].sm_ah)
>  				kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
> diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
> index bed233b..060e543 100644
> --- a/drivers/infiniband/ulp/ipoib/ipoib.h
> +++ b/drivers/infiniband/ulp/ipoib/ipoib.h
> @@ -489,7 +489,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
>  struct ipoib_path *__path_find(struct net_device *dev, void *gid);
>  void ipoib_mark_paths_invalid(struct net_device *dev);
>  void ipoib_flush_paths(struct net_device *dev);
> -int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv);
>  struct ipoib_dev_priv *ipoib_intf_alloc(const char *format);
>  
>  int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
> index 259c59f..1c70ae9 100644
> --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
> +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
> @@ -650,77 +650,6 @@ void ipoib_mark_paths_invalid(struct net_device *dev)
>  	spin_unlock_irq(&priv->lock);
>  }
>  
> -struct classport_info_context {
> -	struct ipoib_dev_priv	*priv;
> -	struct completion	done;
> -	struct ib_sa_query	*sa_query;
> -};
> -
> -static void classport_info_query_cb(int status, struct ib_class_port_info *rec,
> -				    void *context)
> -{
> -	struct classport_info_context *cb_ctx = context;
> -	struct ipoib_dev_priv *priv;
> -
> -	WARN_ON(!context);
> -
> -	priv = cb_ctx->priv;
> -
> -	if (status || !rec) {
> -		pr_debug("device: %s failed query classport_info status: %d\n",
> -			 priv->dev->name, status);
> -		/* keeps the default, will try next mcast_restart */
> -		priv->sm_fullmember_sendonly_support = false;
> -		goto out;
> -	}
> -
> -	if (ib_get_cpi_capmask2(rec) &
> -	    IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT) {
> -		pr_debug("device: %s enabled fullmember-sendonly for sendonly MCG\n",
> -			 priv->dev->name);
> -		priv->sm_fullmember_sendonly_support = true;
> -	} else {
> -		pr_debug("device: %s disabled fullmember-sendonly for sendonly MCG\n",
> -			 priv->dev->name);
> -		priv->sm_fullmember_sendonly_support = false;
> -	}
> -
> -out:
> -	complete(&cb_ctx->done);
> -}
> -
> -int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv)
> -{
> -	struct classport_info_context *callback_context;
> -	int ret;
> -
> -	callback_context = kmalloc(sizeof(*callback_context), GFP_KERNEL);
> -	if (!callback_context)
> -		return -ENOMEM;
> -
> -	callback_context->priv = priv;
> -	init_completion(&callback_context->done);
> -
> -	ret = ib_sa_classport_info_rec_query(&ipoib_sa_client,
> -					     priv->ca, priv->port, 3000,
> -					     GFP_KERNEL,
> -					     classport_info_query_cb,
> -					     callback_context,
> -					     &callback_context->sa_query);
> -	if (ret < 0) {
> -		pr_info("%s failed to send ib_sa_classport_info query, ret: %d\n",
> -			priv->dev->name, ret);
> -		kfree(callback_context);
> -		return ret;
> -	}
> -
> -	/* waiting for the callback to finish before returnning */
> -	wait_for_completion(&callback_context->done);
> -	kfree(callback_context);
> -
> -	return ret;
> -}
> -
>  static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
>  {
>  	struct ipoib_pseudo_header *phdr;
> diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
> index 69e146c..3e3a84f 100644
> --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
> +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
> @@ -331,7 +331,6 @@ void ipoib_mcast_carrier_on_task(struct work_struct *work)
>  	struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
>  						   carrier_on_task);
>  	struct ib_port_attr attr;
> -	int ret;
>  
>  	if (ib_query_port(priv->ca, priv->port, &attr) ||
>  	    attr.state != IB_PORT_ACTIVE) {
> @@ -344,11 +343,9 @@ void ipoib_mcast_carrier_on_task(struct work_struct *work)
>  	 * because the broadcast group must always be joined first and is always
>  	 * re-joined if the SM changes substantially.
>  	 */
> -	ret = ipoib_check_sm_sendonly_fullmember_support(priv);
> -	if (ret < 0)
> -		pr_debug("%s failed query sm support for sendonly-fullmember (ret: %d)\n",
> -			 priv->dev->name, ret);
> -
> +	priv->sm_fullmember_sendonly_support =
> +		ib_sa_sendonly_fullmem_support(&ipoib_sa_client,
> +					       priv->ca, priv->port);
>  	/*
>  	 * Take rtnl_lock to avoid racing with ipoib_stop() and
>  	 * turning the carrier back on while a device is being
> diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
> index fd0e532..46838c8 100644
> --- a/include/rdma/ib_sa.h
> +++ b/include/rdma/ib_sa.h
> @@ -454,14 +454,8 @@ 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);
> +bool ib_sa_sendonly_fullmem_support(struct ib_sa_client *client,
> +				    struct ib_device *device,
> +				    u8 port_num);
>  
>  #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



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux