2 * Copyright (c) 2005 Ammasso, Inc. All rights reserved.
3 * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <rdma/iw_cm.h>
37 static void handle_mq(struct c2_dev
*c2dev
, u32 index
);
38 static void handle_vq(struct c2_dev
*c2dev
, u32 mq_index
);
41 * Handle RNIC interrupts
43 void c2_rnic_interrupt(struct c2_dev
*c2dev
)
45 unsigned int mq_index
;
47 while (c2dev
->hints_read
!= be16_to_cpu(*c2dev
->hint_count
)) {
48 mq_index
= readl(c2dev
->regs
+ PCI_BAR0_HOST_HINT
);
49 if (mq_index
& 0x80000000) {
54 handle_mq(c2dev
, mq_index
);
60 * Top level MQ handler
62 static void handle_mq(struct c2_dev
*c2dev
, u32 mq_index
)
64 if (c2dev
->qptr_array
[mq_index
] == NULL
) {
65 pr_debug(KERN_INFO
"handle_mq: stray activity for mq_index=%d\n",
73 * An index of 0 in the activity queue
74 * indicates the req vq now has messages
77 * Wake up any waiters waiting on req VQ
78 * message availability.
80 wake_up(&c2dev
->req_vq_wo
);
83 handle_vq(c2dev
, mq_index
);
86 /* We have to purge the VQ in case there are pending
87 * accept reply requests that would result in the
88 * generation of an ESTABLISHED event. If we don't
89 * generate these first, a CLOSE event could end up
90 * being delivered before the ESTABLISHED event.
94 c2_ae_event(c2dev
, mq_index
);
97 /* There is no event synchronization between CQ events
98 * and AE or CM events. In fact, CQE could be
99 * delivered for all of the I/O up to and including the
100 * FLUSH for a peer disconenct prior to the ESTABLISHED
101 * event being delivered to the app. The reason for this
102 * is that CM events are delivered on a thread, while AE
103 * and CM events are delivered on interrupt context.
105 c2_cq_event(c2dev
, mq_index
);
113 * Handles verbs WR replies.
115 static void handle_vq(struct c2_dev
*c2dev
, u32 mq_index
)
117 void *adapter_msg
, *reply_msg
;
118 struct c2wr_hdr
*host_msg
;
120 struct c2_mq
*reply_vq
;
121 struct c2_vq_req
*req
;
122 struct iw_cm_event cm_event
;
125 reply_vq
= (struct c2_mq
*) c2dev
->qptr_array
[mq_index
];
128 * get next msg from mq_index into adapter_msg.
131 adapter_msg
= c2_mq_consume(reply_vq
);
132 if (adapter_msg
== NULL
) {
136 host_msg
= vq_repbuf_alloc(c2dev
);
139 * If we can't get a host buffer, then we'll still
140 * wakeup the waiter, we just won't give him the msg.
141 * It is assumed the waiter will deal with this...
144 pr_debug("handle_vq: no repbufs!\n");
147 * just copy the WR header into a local variable.
148 * this allows us to still demux on the context
151 memcpy(host_msg
, adapter_msg
, sizeof(tmp
));
154 memcpy(host_msg
, adapter_msg
, reply_vq
->msg_size
);
155 reply_msg
= host_msg
;
159 * consume the msg from the MQ
161 c2_mq_free(reply_vq
);
166 req
= (struct c2_vq_req
*) (unsigned long) host_msg
->context
;
169 * We should never get here, as the adapter should
170 * never send us a reply that we're not expecting.
172 vq_repbuf_free(c2dev
, host_msg
);
173 pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n");
177 err
= c2_errno(reply_msg
);
178 if (!err
) switch (req
->event
) {
179 case IW_CM_EVENT_ESTABLISHED
:
180 c2_set_qp_state(req
->qp
,
182 case IW_CM_EVENT_CLOSE
:
185 * Move the QP to RTS if this is
186 * the established event
188 cm_event
.event
= req
->event
;
190 cm_event
.local_addr
= req
->cm_id
->local_addr
;
191 cm_event
.remote_addr
= req
->cm_id
->remote_addr
;
192 cm_event
.private_data
= NULL
;
193 cm_event
.private_data_len
= 0;
194 req
->cm_id
->event_handler(req
->cm_id
, &cm_event
);
200 req
->reply_msg
= (u64
) (unsigned long) (reply_msg
);
201 atomic_set(&req
->reply_ready
, 1);
202 wake_up(&req
->wait_object
);
205 * If the request was cancelled, then this put will
206 * free the vq_req memory...and reply_msg!!!
208 vq_req_put(c2dev
, req
);