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

📄 c2_intr.c

📁 linux内核源码
💻 C
字号:
/* * Copyright (c) 2005 Ammasso, Inc. All rights reserved. * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses.  You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * *     Redistribution and use in source and binary forms, with or *     without modification, are permitted provided that the following *     conditions are met: * *      - Redistributions of source code must retain the above *        copyright notice, this list of conditions and the following *        disclaimer. * *      - Redistributions in binary form must reproduce the above *        copyright notice, this list of conditions and the following *        disclaimer in the documentation and/or other materials *        provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */#include "c2.h"#include <rdma/iw_cm.h>#include "c2_vq.h"static void handle_mq(struct c2_dev *c2dev, u32 index);static void handle_vq(struct c2_dev *c2dev, u32 mq_index);/* * Handle RNIC interrupts */void c2_rnic_interrupt(struct c2_dev *c2dev){	unsigned int mq_index;	while (c2dev->hints_read != be16_to_cpu(*c2dev->hint_count)) {		mq_index = readl(c2dev->regs + PCI_BAR0_HOST_HINT);		if (mq_index & 0x80000000) {			break;		}		c2dev->hints_read++;		handle_mq(c2dev, mq_index);	}}/* * Top level MQ handler */static void handle_mq(struct c2_dev *c2dev, u32 mq_index){	if (c2dev->qptr_array[mq_index] == NULL) {		pr_debug(KERN_INFO "handle_mq: stray activity for mq_index=%d\n",			mq_index);		return;	}	switch (mq_index) {	case (0):		/*		 * An index of 0 in the activity queue		 * indicates the req vq now has messages		 * available...		 *		 * Wake up any waiters waiting on req VQ		 * message availability.		 */		wake_up(&c2dev->req_vq_wo);		break;	case (1):		handle_vq(c2dev, mq_index);		break;	case (2):		/* We have to purge the VQ in case there are pending		 * accept reply requests that would result in the		 * generation of an ESTABLISHED event. If we don't		 * generate these first, a CLOSE event could end up		 * being delivered before the ESTABLISHED event.		 */		handle_vq(c2dev, 1);		c2_ae_event(c2dev, mq_index);		break;	default:		/* There is no event synchronization between CQ events		 * and AE or CM events. In fact, CQE could be		 * delivered for all of the I/O up to and including the		 * FLUSH for a peer disconenct prior to the ESTABLISHED		 * event being delivered to the app. The reason for this		 * is that CM events are delivered on a thread, while AE		 * and CM events are delivered on interrupt context.		 */		c2_cq_event(c2dev, mq_index);		break;	}	return;}/* * Handles verbs WR replies. */static void handle_vq(struct c2_dev *c2dev, u32 mq_index){	void *adapter_msg, *reply_msg;	struct c2wr_hdr *host_msg;	struct c2wr_hdr tmp;	struct c2_mq *reply_vq;	struct c2_vq_req *req;	struct iw_cm_event cm_event;	int err;	reply_vq = (struct c2_mq *) c2dev->qptr_array[mq_index];	/*	 * get next msg from mq_index into adapter_msg.	 * don't free it yet.	 */	adapter_msg = c2_mq_consume(reply_vq);	if (adapter_msg == NULL) {		return;	}	host_msg = vq_repbuf_alloc(c2dev);	/*	 * If we can't get a host buffer, then we'll still	 * wakeup the waiter, we just won't give him the msg.	 * It is assumed the waiter will deal with this...	 */	if (!host_msg) {		pr_debug("handle_vq: no repbufs!\n");		/*		 * just copy the WR header into a local variable.		 * this allows us to still demux on the context		 */		host_msg = &tmp;		memcpy(host_msg, adapter_msg, sizeof(tmp));		reply_msg = NULL;	} else {		memcpy(host_msg, adapter_msg, reply_vq->msg_size);		reply_msg = host_msg;	}	/*	 * consume the msg from the MQ	 */	c2_mq_free(reply_vq);	/*	 * wakeup the waiter.	 */	req = (struct c2_vq_req *) (unsigned long) host_msg->context;	if (req == NULL) {		/*		 * We should never get here, as the adapter should		 * never send us a reply that we're not expecting.		 */		vq_repbuf_free(c2dev, host_msg);		pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n");		return;	}	err = c2_errno(reply_msg);	if (!err) switch (req->event) {	case IW_CM_EVENT_ESTABLISHED:		c2_set_qp_state(req->qp,				C2_QP_STATE_RTS);	case IW_CM_EVENT_CLOSE:		/*		 * Move the QP to RTS if this is		 * the established event		 */		cm_event.event = req->event;		cm_event.status = 0;		cm_event.local_addr = req->cm_id->local_addr;		cm_event.remote_addr = req->cm_id->remote_addr;		cm_event.private_data = NULL;		cm_event.private_data_len = 0;		req->cm_id->event_handler(req->cm_id, &cm_event);		break;	default:		break;	}	req->reply_msg = (u64) (unsigned long) (reply_msg);	atomic_set(&req->reply_ready, 1);	wake_up(&req->wait_object);	/*	 * If the request was cancelled, then this put will	 * free the vq_req memory...and reply_msg!!!	 */	vq_req_put(c2dev, req);}

⌨️ 快捷键说明

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