mad.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,279 行 · 第 1/5 页

C
2,279
字号
		return IB_MGMT_DEVICE_HDR;	else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&		 (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))		return IB_MGMT_VENDOR_HDR;	else		return IB_MGMT_MAD_HDR;}EXPORT_SYMBOL(ib_get_mad_data_offset);int ib_is_mad_class_rmpp(u8 mgmt_class){	if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) ||	    (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) ||	    (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) ||	    (mgmt_class == IB_MGMT_CLASS_BIS) ||	    ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&	     (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)))		return 1;	return 0;}EXPORT_SYMBOL(ib_is_mad_class_rmpp);void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num){	struct ib_mad_send_wr_private *mad_send_wr;	struct list_head *list;	mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private,				   send_buf);	list = &mad_send_wr->cur_seg->list;	if (mad_send_wr->cur_seg->num < seg_num) {		list_for_each_entry(mad_send_wr->cur_seg, list, list)			if (mad_send_wr->cur_seg->num == seg_num)				break;	} else if (mad_send_wr->cur_seg->num > seg_num) {		list_for_each_entry_reverse(mad_send_wr->cur_seg, list, list)			if (mad_send_wr->cur_seg->num == seg_num)				break;	}	return mad_send_wr->cur_seg->data;}EXPORT_SYMBOL(ib_get_rmpp_segment);static inline void *ib_get_payload(struct ib_mad_send_wr_private *mad_send_wr){	if (mad_send_wr->send_buf.seg_count)		return ib_get_rmpp_segment(&mad_send_wr->send_buf,					   mad_send_wr->seg_num);	else		return mad_send_wr->send_buf.mad +		       mad_send_wr->send_buf.hdr_len;}void ib_free_send_mad(struct ib_mad_send_buf *send_buf){	struct ib_mad_agent_private *mad_agent_priv;	struct ib_mad_send_wr_private *mad_send_wr;	mad_agent_priv = container_of(send_buf->mad_agent,				      struct ib_mad_agent_private, agent);	mad_send_wr = container_of(send_buf, struct ib_mad_send_wr_private,				   send_buf);	free_send_rmpp_list(mad_send_wr);	kfree(send_buf->mad);	deref_mad_agent(mad_agent_priv);}EXPORT_SYMBOL(ib_free_send_mad);int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr){	struct ib_mad_qp_info *qp_info;	struct list_head *list;	struct ib_send_wr *bad_send_wr;	struct ib_mad_agent *mad_agent;	struct ib_sge *sge;	unsigned long flags;	int ret;	/* Set WR ID to find mad_send_wr upon completion */	qp_info = mad_send_wr->mad_agent_priv->qp_info;	mad_send_wr->send_wr.wr_id = (unsigned long)&mad_send_wr->mad_list;	mad_send_wr->mad_list.mad_queue = &qp_info->send_queue;	mad_agent = mad_send_wr->send_buf.mad_agent;	sge = mad_send_wr->sg_list;	sge[0].addr = dma_map_single(mad_agent->device->dma_device,				     mad_send_wr->send_buf.mad,				     sge[0].length,				     DMA_TO_DEVICE);	pci_unmap_addr_set(mad_send_wr, header_mapping, sge[0].addr);	sge[1].addr = dma_map_single(mad_agent->device->dma_device,				     ib_get_payload(mad_send_wr),				     sge[1].length,				     DMA_TO_DEVICE);	pci_unmap_addr_set(mad_send_wr, payload_mapping, sge[1].addr);	spin_lock_irqsave(&qp_info->send_queue.lock, flags);	if (qp_info->send_queue.count < qp_info->send_queue.max_active) {		ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr,				   &bad_send_wr);		list = &qp_info->send_queue.list;	} else {		ret = 0;		list = &qp_info->overflow_list;	}	if (!ret) {		qp_info->send_queue.count++;		list_add_tail(&mad_send_wr->mad_list.list, list);	}	spin_unlock_irqrestore(&qp_info->send_queue.lock, flags);	if (ret) {		dma_unmap_single(mad_agent->device->dma_device,				 pci_unmap_addr(mad_send_wr, header_mapping),				 sge[0].length, DMA_TO_DEVICE);		dma_unmap_single(mad_agent->device->dma_device,				 pci_unmap_addr(mad_send_wr, payload_mapping),				 sge[1].length, DMA_TO_DEVICE);	}	return ret;}/* * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated *  with the registered client */int ib_post_send_mad(struct ib_mad_send_buf *send_buf,		     struct ib_mad_send_buf **bad_send_buf){	struct ib_mad_agent_private *mad_agent_priv;	struct ib_mad_send_buf *next_send_buf;	struct ib_mad_send_wr_private *mad_send_wr;	unsigned long flags;	int ret = -EINVAL;	/* Walk list of send WRs and post each on send list */	for (; send_buf; send_buf = next_send_buf) {		mad_send_wr = container_of(send_buf,					   struct ib_mad_send_wr_private,					   send_buf);		mad_agent_priv = mad_send_wr->mad_agent_priv;		if (!send_buf->mad_agent->send_handler ||		    (send_buf->timeout_ms &&		     !send_buf->mad_agent->recv_handler)) {			ret = -EINVAL;			goto error;		}		if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) {			if (mad_agent_priv->agent.rmpp_version) {				ret = -EINVAL;				goto error;			}		}		/*		 * Save pointer to next work request to post in case the		 * current one completes, and the user modifies the work		 * request associated with the completion		 */		next_send_buf = send_buf->next;		mad_send_wr->send_wr.wr.ud.ah = send_buf->ah;		if (((struct ib_mad_hdr *) send_buf->mad)->mgmt_class ==		    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {			ret = handle_outgoing_dr_smp(mad_agent_priv,						     mad_send_wr);			if (ret < 0)		/* error */				goto error;			else if (ret == 1)	/* locally consumed */				continue;		}		mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;		/* Timeout will be updated after send completes */		mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);		mad_send_wr->retries = send_buf->retries;		/* Reference for work request to QP + response */		mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);		mad_send_wr->status = IB_WC_SUCCESS;		/* Reference MAD agent until send completes */		atomic_inc(&mad_agent_priv->refcount);		spin_lock_irqsave(&mad_agent_priv->lock, flags);		list_add_tail(&mad_send_wr->agent_list,			      &mad_agent_priv->send_list);		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);		if (mad_agent_priv->agent.rmpp_version) {			ret = ib_send_rmpp_mad(mad_send_wr);			if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED)				ret = ib_send_mad(mad_send_wr);		} else			ret = ib_send_mad(mad_send_wr);		if (ret < 0) {			/* Fail send request */			spin_lock_irqsave(&mad_agent_priv->lock, flags);			list_del(&mad_send_wr->agent_list);			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);			atomic_dec(&mad_agent_priv->refcount);			goto error;		}	}	return 0;error:	if (bad_send_buf)		*bad_send_buf = send_buf;	return ret;}EXPORT_SYMBOL(ib_post_send_mad);/* * ib_free_recv_mad - Returns data buffers used to receive *  a MAD to the access layer */void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc){	struct ib_mad_recv_buf *mad_recv_buf, *temp_recv_buf;	struct ib_mad_private_header *mad_priv_hdr;	struct ib_mad_private *priv;	struct list_head free_list;	INIT_LIST_HEAD(&free_list);	list_splice_init(&mad_recv_wc->rmpp_list, &free_list);	list_for_each_entry_safe(mad_recv_buf, temp_recv_buf,					&free_list, list) {		mad_recv_wc = container_of(mad_recv_buf, struct ib_mad_recv_wc,					   recv_buf);		mad_priv_hdr = container_of(mad_recv_wc,					    struct ib_mad_private_header,					    recv_wc);		priv = container_of(mad_priv_hdr, struct ib_mad_private,				    header);		kmem_cache_free(ib_mad_cache, priv);	}}EXPORT_SYMBOL(ib_free_recv_mad);struct ib_mad_agent *ib_redirect_mad_qp(struct ib_qp *qp,					u8 rmpp_version,					ib_mad_send_handler send_handler,					ib_mad_recv_handler recv_handler,					void *context){	return ERR_PTR(-EINVAL);	/* XXX: for now */}EXPORT_SYMBOL(ib_redirect_mad_qp);int ib_process_mad_wc(struct ib_mad_agent *mad_agent,		      struct ib_wc *wc){	printk(KERN_ERR PFX "ib_process_mad_wc() not implemented yet\n");	return 0;}EXPORT_SYMBOL(ib_process_mad_wc);static int method_in_use(struct ib_mad_mgmt_method_table **method,			 struct ib_mad_reg_req *mad_reg_req){	int i;	for (i = find_first_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS);	     i < IB_MGMT_MAX_METHODS;	     i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,			       1+i)) {		if ((*method)->agent[i]) {			printk(KERN_ERR PFX "Method %d already in use\n", i);			return -EINVAL;		}	}	return 0;}static int allocate_method_table(struct ib_mad_mgmt_method_table **method){	/* Allocate management method table */	*method = kzalloc(sizeof **method, GFP_ATOMIC);	if (!*method) {		printk(KERN_ERR PFX "No memory for "		       "ib_mad_mgmt_method_table\n");		return -ENOMEM;	}	return 0;}/* * Check to see if there are any methods still in use */static int check_method_table(struct ib_mad_mgmt_method_table *method){	int i;	for (i = 0; i < IB_MGMT_MAX_METHODS; i++)		if (method->agent[i])			return 1;	return 0;}/* * Check to see if there are any method tables for this class still in use */static int check_class_table(struct ib_mad_mgmt_class_table *class){	int i;	for (i = 0; i < MAX_MGMT_CLASS; i++)		if (class->method_table[i])			return 1;	return 0;}static int check_vendor_class(struct ib_mad_mgmt_vendor_class *vendor_class){	int i;	for (i = 0; i < MAX_MGMT_OUI; i++)		if (vendor_class->method_table[i])			return 1;	return 0;}static int find_vendor_oui(struct ib_mad_mgmt_vendor_class *vendor_class,			   char *oui){	int i;	for (i = 0; i < MAX_MGMT_OUI; i++)                /* Is there matching OUI for this vendor class ? */                if (!memcmp(vendor_class->oui[i], oui, 3))			return i;	return -1;}static int check_vendor_table(struct ib_mad_mgmt_vendor_class_table *vendor){	int i;	for (i = 0; i < MAX_MGMT_VENDOR_RANGE2; i++)		if (vendor->vendor_class[i])			return 1;	return 0;}static void remove_methods_mad_agent(struct ib_mad_mgmt_method_table *method,				     struct ib_mad_agent_private *agent){	int i;	/* Remove any methods for this mad agent */	for (i = 0; i < IB_MGMT_MAX_METHODS; i++) {		if (method->agent[i] == agent) {			method->agent[i] = NULL;		}	}}static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,			      struct ib_mad_agent_private *agent_priv,			      u8 mgmt_class){	struct ib_mad_port_private *port_priv;	struct ib_mad_mgmt_class_table **class;	struct ib_mad_mgmt_method_table **method;	int i, ret;	port_priv = agent_priv->qp_info->port_priv;	class = &port_priv->version[mad_reg_req->mgmt_class_version].class;	if (!*class) {		/* Allocate management class table for "new" class version */		*class = kzalloc(sizeof **class, GFP_ATOMIC);		if (!*class) {			printk(KERN_ERR PFX "No memory for "			       "ib_mad_mgmt_class_table\n");			ret = -ENOMEM;			goto error1;		}		/* Allocate method table for this management class */		method = &(*class)->method_table[mgmt_class];		if ((ret = allocate_method_table(method)))			goto error2;	} else {		method = &(*class)->method_table[mgmt_class];		if (!*method) {			/* Allocate method table for this management class */			if ((ret = allocate_method_table(method)))				goto error1;		}	}	/* Now, make sure methods are not already in use */	if (method_in_use(method, mad_reg_req))		goto error3;	/* Finally, add in methods being registered */	for (i = find_first_bit(mad_reg_req->method_mask,				IB_MGMT_MAX_METHODS);	     i < IB_MGMT_MAX_METHODS;	     i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,			       1+i)) {		(*method)->agent[i] = agent_priv;	}	return 0;error3:	/* Remove any methods for this mad agent */	remove_methods_mad_agent(*method, agent_priv);	/* Now, check to see if there are any methods in use */	if (!check_method_table(*method)) {		/* If not, release management method table */		kfree(*method);		*method = NULL;	}	ret = -EINVAL;	goto error1;error2:	kfree(*class);	*class = NULL;error1:	return ret;}static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,			   struct ib_mad_agent_private *agent_priv){	struct ib_mad_port_private *port_priv;	struct ib_mad_mgmt_vendor_class_table **vendor_table;	struct ib_mad_mgmt_vendor_class_table *vendor = NULL;	struct ib_mad_mgmt_vendor_class *vendor_class = NULL;	struct ib_mad_mgmt_method_table **method;	int i, ret = -ENOMEM;	u8 vclass;	/* "New" vendor (with OUI) class */	vclass = vendor_class_index(mad_reg_req->mgmt_class);	port_priv = agent_priv->qp_info->port_priv;	vendor_table = &port_priv->version[				mad_reg_req->mgmt_class_version].vendor;	if (!*vendor_table) {		/* Allocate mgmt vendor class table for "new" class version */		vendor = kzalloc(sizeof *vendor, GFP_ATOMIC);		if (!vendor) {			printk(KERN_ERR PFX "No memory for "			       "ib_mad_mgmt_vendor_class_table\n");			goto error1;		}

⌨️ 快捷键说明

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