⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sa_query.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * It's not safe to dereference query any more, because the	 * send may already have completed and freed the query in	 * another context.	 */	return ret ? ret : id;}static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,				    int status,				    struct ib_sa_mad *mad){	struct ib_sa_path_query *query =		container_of(sa_query, struct ib_sa_path_query, sa_query);	if (mad) {		struct ib_sa_path_rec rec;		ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table),			  mad->data, &rec);		query->callback(status, &rec, query->context);	} else		query->callback(status, NULL, query->context);}static void ib_sa_path_rec_release(struct ib_sa_query *sa_query){	kfree(container_of(sa_query, struct ib_sa_path_query, sa_query));}/** * ib_sa_path_rec_get - Start a Path get query * @device:device to send query on * @port_num: port number to send query on * @rec:Path Record to send in query * @comp_mask:component mask to send in query * @timeout_ms:time to wait for response * @gfp_mask:GFP mask to use for internal allocations * @callback:function called when query completes, times out or is * canceled * @context:opaque user context passed to callback * @sa_query:query context, used to cancel query * * Send a Path Record Get query to the SA to look up a path.  The * callback function will be called when the query completes (or * fails); status is 0 for a successful response, -EINTR if the query * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error * occurred sending the query.  The resp parameter of the callback is * only valid if status is 0. * * If the return value of ib_sa_path_rec_get() is negative, it is an * error code.  Otherwise it is a query ID that can be used to cancel * the query. */int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,		       struct ib_sa_path_rec *rec,		       ib_sa_comp_mask comp_mask,		       int timeout_ms, gfp_t gfp_mask,		       void (*callback)(int status,					struct ib_sa_path_rec *resp,					void *context),		       void *context,		       struct ib_sa_query **sa_query){	struct ib_sa_path_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 = kmalloc(sizeof *query, gfp_mask);	if (!query)		return -ENOMEM;	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,						     0, IB_MGMT_SA_HDR,						     IB_MGMT_SA_DATA, gfp_mask);	if (!query->sa_query.mad_buf) {		ret = -ENOMEM;		goto err1;	}	query->callback = callback;	query->context  = context;	mad = query->sa_query.mad_buf->mad;	init_mad(mad, agent);	query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;	query->sa_query.release  = ib_sa_path_rec_release;	query->sa_query.port     = port;	mad->mad_hdr.method	 = IB_MGMT_METHOD_GET;	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_PATH_REC);	mad->sa_hdr.comp_mask	 = comp_mask;	ib_pack(path_rec_table, ARRAY_SIZE(path_rec_table), rec, mad->data);	*sa_query = &query->sa_query;	ret = send_mad(&query->sa_query, timeout_ms);	if (ret < 0)		goto err2;	return ret;err2:	*sa_query = NULL;	ib_free_send_mad(query->sa_query.mad_buf);err1:	kfree(query);	return ret;}EXPORT_SYMBOL(ib_sa_path_rec_get);static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,				    int status,				    struct ib_sa_mad *mad){	struct ib_sa_service_query *query =		container_of(sa_query, struct ib_sa_service_query, sa_query);	if (mad) {		struct ib_sa_service_rec rec;		ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),			  mad->data, &rec);		query->callback(status, &rec, query->context);	} else		query->callback(status, NULL, query->context);}static void ib_sa_service_rec_release(struct ib_sa_query *sa_query){	kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));}/** * ib_sa_service_rec_query - Start Service Record operation * @device:device to send request on * @port_num: port number to send request on * @method:SA method - should be get, set, or delete * @rec:Service Record to send in request * @comp_mask:component mask to send in request * @timeout_ms:time to wait for response * @gfp_mask:GFP mask to use for internal allocations * @callback:function called when request completes, times out or is * canceled * @context:opaque user context passed to callback * @sa_query:request context, used to cancel request * * Send a Service Record set/get/delete to the SA to register, * unregister or query a service record. * The callback function will be called when the request completes (or * fails); status is 0 for a successful response, -EINTR if the query * is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error * occurred sending the query.  The resp parameter of the callback is * only valid if status is 0. * * If the return value of ib_sa_service_rec_query() is negative, it is an * error code.  Otherwise it is a request ID that can be used to cancel * the query. */int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,			    struct ib_sa_service_rec *rec,			    ib_sa_comp_mask comp_mask,			    int timeout_ms, gfp_t gfp_mask,			    void (*callback)(int status,					     struct ib_sa_service_rec *resp,					     void *context),			    void *context,			    struct ib_sa_query **sa_query){	struct ib_sa_service_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;	if (method != IB_MGMT_METHOD_GET &&	    method != IB_MGMT_METHOD_SET &&	    method != IB_SA_METHOD_DELETE)		return -EINVAL;	query = kmalloc(sizeof *query, gfp_mask);	if (!query)		return -ENOMEM;	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,						     0, IB_MGMT_SA_HDR,						     IB_MGMT_SA_DATA, gfp_mask);	if (!query->sa_query.mad_buf) {		ret = -ENOMEM;		goto err1;	}	query->callback = callback;	query->context  = context;	mad = query->sa_query.mad_buf->mad;	init_mad(mad, agent);	query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;	query->sa_query.release  = ib_sa_service_rec_release;	query->sa_query.port     = port;	mad->mad_hdr.method	 = method;	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);	mad->sa_hdr.comp_mask	 = comp_mask;	ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),		rec, mad->data);	*sa_query = &query->sa_query;	ret = send_mad(&query->sa_query, timeout_ms);	if (ret < 0)		goto err2;	return ret;err2:	*sa_query = NULL;	ib_free_send_mad(query->sa_query.mad_buf);err1:	kfree(query);	return ret;}EXPORT_SYMBOL(ib_sa_service_rec_query);static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,					int status,					struct ib_sa_mad *mad){	struct ib_sa_mcmember_query *query =		container_of(sa_query, struct ib_sa_mcmember_query, sa_query);	if (mad) {		struct ib_sa_mcmember_rec rec;		ib_unpack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),			  mad->data, &rec);		query->callback(status, &rec, query->context);	} else		query->callback(status, NULL, query->context);}static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query){	kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query));}int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,			     u8 method,			     struct ib_sa_mcmember_rec *rec,			     ib_sa_comp_mask comp_mask,			     int timeout_ms, gfp_t gfp_mask,			     void (*callback)(int status,					      struct ib_sa_mcmember_rec *resp,					      void *context),			     void *context,			     struct ib_sa_query **sa_query){	struct ib_sa_mcmember_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 = kmalloc(sizeof *query, gfp_mask);	if (!query)		return -ENOMEM;	query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,						     0, IB_MGMT_SA_HDR,						     IB_MGMT_SA_DATA, gfp_mask);	if (!query->sa_query.mad_buf) {		ret = -ENOMEM;		goto err1;	}	query->callback = callback;	query->context  = context;	mad = query->sa_query.mad_buf->mad;	init_mad(mad, agent);	query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;	query->sa_query.release  = ib_sa_mcmember_rec_release;	query->sa_query.port     = port;	mad->mad_hdr.method	 = method;	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);	mad->sa_hdr.comp_mask	 = comp_mask;	ib_pack(mcmember_rec_table, ARRAY_SIZE(mcmember_rec_table),		rec, mad->data);	*sa_query = &query->sa_query;	ret = send_mad(&query->sa_query, timeout_ms);	if (ret < 0)		goto err2;	return ret;err2:	*sa_query = NULL;	ib_free_send_mad(query->sa_query.mad_buf);err1:	kfree(query);	return ret;}EXPORT_SYMBOL(ib_sa_mcmember_rec_query);static void send_handler(struct ib_mad_agent *agent,			 struct ib_mad_send_wc *mad_send_wc){	struct ib_sa_query *query = mad_send_wc->send_buf->context[0];	unsigned long flags;	if (query->callback)		switch (mad_send_wc->status) {		case IB_WC_SUCCESS:			/* No callback -- already got recv */			break;		case IB_WC_RESP_TIMEOUT_ERR:			query->callback(query, -ETIMEDOUT, NULL);			break;		case IB_WC_WR_FLUSH_ERR:			query->callback(query, -EINTR, NULL);			break;		default:			query->callback(query, -EIO, NULL);			break;		}	spin_lock_irqsave(&idr_lock, flags);	idr_remove(&query_idr, query->id);	spin_unlock_irqrestore(&idr_lock, flags);        ib_free_send_mad(mad_send_wc->send_buf);	kref_put(&query->sm_ah->ref, free_sm_ah);	query->release(query);}static void recv_handler(struct ib_mad_agent *mad_agent,			 struct ib_mad_recv_wc *mad_recv_wc){	struct ib_sa_query *query;	struct ib_mad_send_buf *mad_buf;	mad_buf = (void *) (unsigned long) mad_recv_wc->wc->wr_id;	query = mad_buf->context[0];	if (query->callback) {		if (mad_recv_wc->wc->status == IB_WC_SUCCESS)			query->callback(query,					mad_recv_wc->recv_buf.mad->mad_hdr.status ?					-EINVAL : 0,					(struct ib_sa_mad *) mad_recv_wc->recv_buf.mad);		else			query->callback(query, -EIO, NULL);	}	ib_free_recv_mad(mad_recv_wc);}static void ib_sa_add_one(struct ib_device *device){	struct ib_sa_device *sa_dev;	int s, e, i;	if (device->node_type == IB_NODE_SWITCH)		s = e = 0;	else {		s = 1;		e = device->phys_port_cnt;	}	sa_dev = kmalloc(sizeof *sa_dev +			 (e - s + 1) * sizeof (struct ib_sa_port),			 GFP_KERNEL);	if (!sa_dev)		return;	sa_dev->start_port = s;	sa_dev->end_port   = e;	for (i = 0; i <= e - s; ++i) {		sa_dev->port[i].sm_ah    = NULL;		sa_dev->port[i].port_num = i + s;		spin_lock_init(&sa_dev->port[i].ah_lock);		sa_dev->port[i].agent =			ib_register_mad_agent(device, i + s, IB_QPT_GSI,					      NULL, 0, send_handler,					      recv_handler, sa_dev);		if (IS_ERR(sa_dev->port[i].agent))			goto err;		INIT_WORK(&sa_dev->port[i].update_task,			  update_sm_ah, &sa_dev->port[i]);	}	ib_set_client_data(device, &sa_client, sa_dev);	/*	 * We register our event handler after everything is set up,	 * and then update our cached info after the event handler is	 * registered to avoid any problems if a port changes state	 * during our initialization.	 */	INIT_IB_EVENT_HANDLER(&sa_dev->event_handler, device, ib_sa_event);	if (ib_register_event_handler(&sa_dev->event_handler))		goto err;	for (i = 0; i <= e - s; ++i)		update_sm_ah(&sa_dev->port[i]);	return;err:	while (--i >= 0)		ib_unregister_mad_agent(sa_dev->port[i].agent);	kfree(sa_dev);	return;}static void ib_sa_remove_one(struct ib_device *device){	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);	int i;	if (!sa_dev)		return;	ib_unregister_event_handler(&sa_dev->event_handler);	for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {		ib_unregister_mad_agent(sa_dev->port[i].agent);		kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);	}	kfree(sa_dev);}static int __init ib_sa_init(void){	int ret;	spin_lock_init(&idr_lock);	spin_lock_init(&tid_lock);	get_random_bytes(&tid, sizeof tid);	ret = ib_register_client(&sa_client);	if (ret)		printk(KERN_ERR "Couldn't register ib_sa client\n");	return ret;}static void __exit ib_sa_cleanup(void){	ib_unregister_client(&sa_client);	idr_destroy(&query_idr);}module_init(ib_sa_init);module_exit(ib_sa_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -