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

📄 mad.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	mad_snoop_priv->agent.context = context;	mad_snoop_priv->agent.qp = port_priv->qp_info[qpn].qp;	mad_snoop_priv->agent.port_num = port_num;	mad_snoop_priv->mad_snoop_flags = mad_snoop_flags;	init_waitqueue_head(&mad_snoop_priv->wait);	mad_snoop_priv->snoop_index = register_snoop_agent(						&port_priv->qp_info[qpn],						mad_snoop_priv);	if (mad_snoop_priv->snoop_index < 0) {		ret = ERR_PTR(mad_snoop_priv->snoop_index);		goto error2;	}	atomic_set(&mad_snoop_priv->refcount, 1);	return &mad_snoop_priv->agent;error2:	kfree(mad_snoop_priv);error1:	return ret;}EXPORT_SYMBOL(ib_register_mad_snoop);static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv){	struct ib_mad_port_private *port_priv;	unsigned long flags;	/* Note that we could still be handling received MADs */	/*	 * Canceling all sends results in dropping received response	 * MADs, preventing us from queuing additional work	 */	cancel_mads(mad_agent_priv);	port_priv = mad_agent_priv->qp_info->port_priv;	cancel_delayed_work(&mad_agent_priv->timed_work);	spin_lock_irqsave(&port_priv->reg_lock, flags);	remove_mad_reg_req(mad_agent_priv);	list_del(&mad_agent_priv->agent_list);	spin_unlock_irqrestore(&port_priv->reg_lock, flags);	flush_workqueue(port_priv->wq);	ib_cancel_rmpp_recvs(mad_agent_priv);	atomic_dec(&mad_agent_priv->refcount);	wait_event(mad_agent_priv->wait,		   !atomic_read(&mad_agent_priv->refcount));	kfree(mad_agent_priv->reg_req);	ib_dereg_mr(mad_agent_priv->agent.mr);	kfree(mad_agent_priv);}static void unregister_mad_snoop(struct ib_mad_snoop_private *mad_snoop_priv){	struct ib_mad_qp_info *qp_info;	unsigned long flags;	qp_info = mad_snoop_priv->qp_info;	spin_lock_irqsave(&qp_info->snoop_lock, flags);	qp_info->snoop_table[mad_snoop_priv->snoop_index] = NULL;	atomic_dec(&qp_info->snoop_count);	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);	atomic_dec(&mad_snoop_priv->refcount);	wait_event(mad_snoop_priv->wait,		   !atomic_read(&mad_snoop_priv->refcount));	kfree(mad_snoop_priv);}/* * ib_unregister_mad_agent - Unregisters a client from using MAD services */int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent){	struct ib_mad_agent_private *mad_agent_priv;	struct ib_mad_snoop_private *mad_snoop_priv;	/* If the TID is zero, the agent can only snoop. */	if (mad_agent->hi_tid) {		mad_agent_priv = container_of(mad_agent,					      struct ib_mad_agent_private,					      agent);		unregister_mad_agent(mad_agent_priv);	} else {		mad_snoop_priv = container_of(mad_agent,					      struct ib_mad_snoop_private,					      agent);		unregister_mad_snoop(mad_snoop_priv);	}	return 0;}EXPORT_SYMBOL(ib_unregister_mad_agent);static inline int response_mad(struct ib_mad *mad){	/* Trap represses are responses although response bit is reset */	return ((mad->mad_hdr.method == IB_MGMT_METHOD_TRAP_REPRESS) ||		(mad->mad_hdr.method & IB_MGMT_METHOD_RESP));}static void dequeue_mad(struct ib_mad_list_head *mad_list){	struct ib_mad_queue *mad_queue;	unsigned long flags;	BUG_ON(!mad_list->mad_queue);	mad_queue = mad_list->mad_queue;	spin_lock_irqsave(&mad_queue->lock, flags);	list_del(&mad_list->list);	mad_queue->count--;	spin_unlock_irqrestore(&mad_queue->lock, flags);}static void snoop_send(struct ib_mad_qp_info *qp_info,		       struct ib_mad_send_buf *send_buf,		       struct ib_mad_send_wc *mad_send_wc,		       int mad_snoop_flags){	struct ib_mad_snoop_private *mad_snoop_priv;	unsigned long flags;	int i;	spin_lock_irqsave(&qp_info->snoop_lock, flags);	for (i = 0; i < qp_info->snoop_table_size; i++) {		mad_snoop_priv = qp_info->snoop_table[i];		if (!mad_snoop_priv ||		    !(mad_snoop_priv->mad_snoop_flags & mad_snoop_flags))			continue;		atomic_inc(&mad_snoop_priv->refcount);		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);		mad_snoop_priv->agent.snoop_handler(&mad_snoop_priv->agent,						    send_buf, mad_send_wc);		if (atomic_dec_and_test(&mad_snoop_priv->refcount))			wake_up(&mad_snoop_priv->wait);		spin_lock_irqsave(&qp_info->snoop_lock, flags);	}	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);}static void snoop_recv(struct ib_mad_qp_info *qp_info,		       struct ib_mad_recv_wc *mad_recv_wc,		       int mad_snoop_flags){	struct ib_mad_snoop_private *mad_snoop_priv;	unsigned long flags;	int i;	spin_lock_irqsave(&qp_info->snoop_lock, flags);	for (i = 0; i < qp_info->snoop_table_size; i++) {		mad_snoop_priv = qp_info->snoop_table[i];		if (!mad_snoop_priv ||		    !(mad_snoop_priv->mad_snoop_flags & mad_snoop_flags))			continue;		atomic_inc(&mad_snoop_priv->refcount);		spin_unlock_irqrestore(&qp_info->snoop_lock, flags);		mad_snoop_priv->agent.recv_handler(&mad_snoop_priv->agent,						   mad_recv_wc);		if (atomic_dec_and_test(&mad_snoop_priv->refcount))			wake_up(&mad_snoop_priv->wait);		spin_lock_irqsave(&qp_info->snoop_lock, flags);	}	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);}static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,			 struct ib_wc *wc){	memset(wc, 0, sizeof *wc);	wc->wr_id = wr_id;	wc->status = IB_WC_SUCCESS;	wc->opcode = IB_WC_RECV;	wc->pkey_index = pkey_index;	wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh);	wc->src_qp = IB_QP0;	wc->qp_num = IB_QP0;	wc->slid = slid;	wc->sl = 0;	wc->dlid_path_bits = 0;	wc->port_num = port_num;}/* * Return 0 if SMP is to be sent * Return 1 if SMP was consumed locally (whether or not solicited) * Return < 0 if error */static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,				  struct ib_mad_send_wr_private *mad_send_wr){	int ret;	struct ib_smp *smp = mad_send_wr->send_buf.mad;	unsigned long flags;	struct ib_mad_local_private *local;	struct ib_mad_private *mad_priv;	struct ib_mad_port_private *port_priv;	struct ib_mad_agent_private *recv_mad_agent = NULL;	struct ib_device *device = mad_agent_priv->agent.device;	u8 port_num = mad_agent_priv->agent.port_num;	struct ib_wc mad_wc;	struct ib_send_wr *send_wr = &mad_send_wr->send_wr;	if (!smi_handle_dr_smp_send(smp, device->node_type, port_num)) {		ret = -EINVAL;		printk(KERN_ERR PFX "Invalid directed route\n");		goto out;	}	/* Check to post send on QP or process locally */	ret = smi_check_local_dr_smp(smp, device, port_num);	if (!ret || !device->process_mad)		goto out;	local = kmalloc(sizeof *local, GFP_ATOMIC);	if (!local) {		ret = -ENOMEM;		printk(KERN_ERR PFX "No memory for ib_mad_local_private\n");		goto out;	}	local->mad_priv = NULL;	local->recv_mad_agent = NULL;	mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_ATOMIC);	if (!mad_priv) {		ret = -ENOMEM;		printk(KERN_ERR PFX "No memory for local response MAD\n");		kfree(local);		goto out;	}	build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),		     send_wr->wr.ud.pkey_index,		     send_wr->wr.ud.port_num, &mad_wc);	/* No GRH for DR SMP */	ret = device->process_mad(device, 0, port_num, &mad_wc, NULL,				  (struct ib_mad *)smp,				  (struct ib_mad *)&mad_priv->mad);	switch (ret)	{	case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY:		if (response_mad(&mad_priv->mad.mad) &&		    mad_agent_priv->agent.recv_handler) {			local->mad_priv = mad_priv;			local->recv_mad_agent = mad_agent_priv;			/*			 * Reference MAD agent until receive			 * side of local completion handled			 */			atomic_inc(&mad_agent_priv->refcount);		} else			kmem_cache_free(ib_mad_cache, mad_priv);		break;	case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED:		kmem_cache_free(ib_mad_cache, mad_priv);		break;	case IB_MAD_RESULT_SUCCESS:		/* Treat like an incoming receive MAD */		port_priv = ib_get_mad_port(mad_agent_priv->agent.device,					    mad_agent_priv->agent.port_num);		if (port_priv) {			mad_priv->mad.mad.mad_hdr.tid =				((struct ib_mad *)smp)->mad_hdr.tid;			recv_mad_agent = find_mad_agent(port_priv,						        &mad_priv->mad.mad);		}		if (!port_priv || !recv_mad_agent) {			kmem_cache_free(ib_mad_cache, mad_priv);			kfree(local);			ret = 0;			goto out;		}		local->mad_priv = mad_priv;		local->recv_mad_agent = recv_mad_agent;		break;	default:		kmem_cache_free(ib_mad_cache, mad_priv);		kfree(local);		ret = -EINVAL;		goto out;	}	local->mad_send_wr = mad_send_wr;	/* Reference MAD agent until send side of local completion handled */	atomic_inc(&mad_agent_priv->refcount);	/* Queue local completion to local list */	spin_lock_irqsave(&mad_agent_priv->lock, flags);	list_add_tail(&local->completion_list, &mad_agent_priv->local_list);	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);	queue_work(mad_agent_priv->qp_info->port_priv->wq,		   &mad_agent_priv->local_work);	ret = 1;out:	return ret;}static int get_buf_length(int hdr_len, int data_len){	int seg_size, pad;	seg_size = sizeof(struct ib_mad) - hdr_len;	if (data_len && seg_size) {		pad = seg_size - data_len % seg_size;		if (pad == seg_size)			pad = 0;	} else		pad = seg_size;	return hdr_len + data_len + pad;}struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,					    u32 remote_qpn, u16 pkey_index,					    int rmpp_active,					    int hdr_len, int data_len,					    gfp_t gfp_mask){	struct ib_mad_agent_private *mad_agent_priv;	struct ib_mad_send_wr_private *mad_send_wr;	int buf_size;	void *buf;	mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,				      agent);	buf_size = get_buf_length(hdr_len, data_len);	if ((!mad_agent->rmpp_version &&	     (rmpp_active || buf_size > sizeof(struct ib_mad))) ||	    (!rmpp_active && buf_size > sizeof(struct ib_mad)))		return ERR_PTR(-EINVAL);	buf = kzalloc(sizeof *mad_send_wr + buf_size, gfp_mask);	if (!buf)		return ERR_PTR(-ENOMEM);	mad_send_wr = buf + buf_size;	mad_send_wr->send_buf.mad = buf;	mad_send_wr->mad_agent_priv = mad_agent_priv;	mad_send_wr->sg_list[0].length = buf_size;	mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey;	mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr;	mad_send_wr->send_wr.sg_list = mad_send_wr->sg_list;	mad_send_wr->send_wr.num_sge = 1;	mad_send_wr->send_wr.opcode = IB_WR_SEND;	mad_send_wr->send_wr.send_flags = IB_SEND_SIGNALED;	mad_send_wr->send_wr.wr.ud.remote_qpn = remote_qpn;	mad_send_wr->send_wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;	mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index;	if (rmpp_active) {		struct ib_rmpp_mad *rmpp_mad = mad_send_wr->send_buf.mad;		rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(hdr_len -						   IB_MGMT_RMPP_HDR + data_len);		rmpp_mad->rmpp_hdr.rmpp_version = mad_agent->rmpp_version;		rmpp_mad->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_DATA;		ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr,				  IB_MGMT_RMPP_FLAG_ACTIVE);	}	mad_send_wr->send_buf.mad_agent = mad_agent;	atomic_inc(&mad_agent_priv->refcount);	return &mad_send_wr->send_buf;}EXPORT_SYMBOL(ib_create_send_mad);void ib_free_send_mad(struct ib_mad_send_buf *send_buf){	struct ib_mad_agent_private *mad_agent_priv;	mad_agent_priv = container_of(send_buf->mad_agent,				      struct ib_mad_agent_private, agent);	kfree(send_buf->mad);	if (atomic_dec_and_test(&mad_agent_priv->refcount))		wake_up(&mad_agent_priv->wait);}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->addr = dma_map_single(mad_agent->device->dma_device,				   mad_send_wr->send_buf.mad, sge->length,				   DMA_TO_DEVICE);	pci_unmap_addr_set(mad_send_wr, mapping, sge->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, mapping),				 sge->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;		}		/*		 * 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		 */

⌨️ 快捷键说明

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