1/* 2 * Copyright (c) 2005 Ammasso, Inc. All rights reserved. 3 * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. 4 * 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: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 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. 23 * 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 31 * SOFTWARE. 32 */ 33#include "c2.h" 34#include <rdma/iw_cm.h> 35#include "c2_vq.h" 36 37static void handle_mq(struct c2_dev *c2dev, u32 index); 38static void handle_vq(struct c2_dev *c2dev, u32 mq_index); 39 40/* 41 * Handle RNIC interrupts 42 */ 43void c2_rnic_interrupt(struct c2_dev *c2dev) 44{ 45 unsigned int mq_index; 46 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) { 50 break; 51 } 52 53 c2dev->hints_read++; 54 handle_mq(c2dev, mq_index); 55 } 56 57} 58 59/* 60 * Top level MQ handler 61 */ 62static void handle_mq(struct c2_dev *c2dev, u32 mq_index) 63{ 64 if (c2dev->qptr_array[mq_index] == NULL) { 65 pr_debug("handle_mq: stray activity for mq_index=%d\n", 66 mq_index); 67 return; 68 } 69 70 switch (mq_index) { 71 case (0): 72 /* 73 * An index of 0 in the activity queue 74 * indicates the req vq now has messages 75 * available... 76 * 77 * Wake up any waiters waiting on req VQ 78 * message availability. 79 */ 80 wake_up(&c2dev->req_vq_wo); 81 break; 82 case (1): 83 handle_vq(c2dev, mq_index); 84 break; 85 case (2): 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. 91 */ 92 handle_vq(c2dev, 1); 93 94 c2_ae_event(c2dev, mq_index); 95 break; 96 default: 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. 104 */ 105 c2_cq_event(c2dev, mq_index); 106 break; 107 } 108 109 return; 110} 111 112/* 113 * Handles verbs WR replies. 114 */ 115static void handle_vq(struct c2_dev *c2dev, u32 mq_index) 116{ 117 void *adapter_msg, *reply_msg; 118 struct c2wr_hdr *host_msg; 119 struct c2wr_hdr tmp; 120 struct c2_mq *reply_vq; 121 struct c2_vq_req *req; 122 struct iw_cm_event cm_event; 123 int err; 124 125 reply_vq = (struct c2_mq *) c2dev->qptr_array[mq_index]; 126 127 /* 128 * get next msg from mq_index into adapter_msg. 129 * don't free it yet. 130 */ 131 adapter_msg = c2_mq_consume(reply_vq); 132 if (adapter_msg == NULL) { 133 return; 134 } 135 136 host_msg = vq_repbuf_alloc(c2dev); 137 138 /* 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... 142 */ 143 if (!host_msg) { 144 pr_debug("handle_vq: no repbufs!\n"); 145 146 /* 147 * just copy the WR header into a local variable. 148 * this allows us to still demux on the context 149 */ 150 host_msg = &tmp; 151 memcpy(host_msg, adapter_msg, sizeof(tmp)); 152 reply_msg = NULL; 153 } else { 154 memcpy(host_msg, adapter_msg, reply_vq->msg_size); 155 reply_msg = host_msg; 156 } 157 158 /* 159 * consume the msg from the MQ 160 */ 161 c2_mq_free(reply_vq); 162 163 /* 164 * wakeup the waiter. 165 */ 166 req = (struct c2_vq_req *) (unsigned long) host_msg->context; 167 if (req == NULL) { 168 /* 169 * We should never get here, as the adapter should 170 * never send us a reply that we're not expecting. 171 */ 172 if (reply_msg != NULL) 173 vq_repbuf_free(c2dev, host_msg); 174 pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n"); 175 return; 176 } 177 178 if (reply_msg) 179 err = c2_errno(reply_msg); 180 else 181 err = -ENOMEM; 182 183 if (!err) switch (req->event) { 184 case IW_CM_EVENT_ESTABLISHED: 185 c2_set_qp_state(req->qp, 186 C2_QP_STATE_RTS); 187 /* 188 * Until ird/ord negotiation via MPAv2 support is added, send 189 * max supported values 190 */ 191 cm_event.ird = cm_event.ord = 128; 192 case IW_CM_EVENT_CLOSE: 193 194 /* 195 * Move the QP to RTS if this is 196 * the established event 197 */ 198 cm_event.event = req->event; 199 cm_event.status = 0; 200 cm_event.local_addr = req->cm_id->local_addr; 201 cm_event.remote_addr = req->cm_id->remote_addr; 202 cm_event.private_data = NULL; 203 cm_event.private_data_len = 0; 204 req->cm_id->event_handler(req->cm_id, &cm_event); 205 break; 206 default: 207 break; 208 } 209 210 req->reply_msg = (u64) (unsigned long) (reply_msg); 211 atomic_set(&req->reply_ready, 1); 212 wake_up(&req->wait_object); 213 214 /* 215 * If the request was cancelled, then this put will 216 * free the vq_req memory...and reply_msg!!! 217 */ 218 vq_req_put(c2dev, req); 219} 220