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 <linux/slab.h> 34#include <linux/spinlock.h> 35 36#include "c2_vq.h" 37#include "c2_provider.h" 38 39/* 40 * Verbs Request Objects: 41 * 42 * VQ Request Objects are allocated by the kernel verbs handlers. 43 * They contain a wait object, a refcnt, an atomic bool indicating that the 44 * adapter has replied, and a copy of the verb reply work request. 45 * A pointer to the VQ Request Object is passed down in the context 46 * field of the work request message, and reflected back by the adapter 47 * in the verbs reply message. The function handle_vq() in the interrupt 48 * path will use this pointer to: 49 * 1) append a copy of the verbs reply message 50 * 2) mark that the reply is ready 51 * 3) wake up the kernel verbs handler blocked awaiting the reply. 52 * 53 * 54 * The kernel verbs handlers do a "get" to put a 2nd reference on the 55 * VQ Request object. If the kernel verbs handler exits before the adapter 56 * can respond, this extra reference will keep the VQ Request object around 57 * until the adapter's reply can be processed. The reason we need this is 58 * because a pointer to this object is stuffed into the context field of 59 * the verbs work request message, and reflected back in the reply message. 60 * It is used in the interrupt handler (handle_vq()) to wake up the appropriate 61 * kernel verb handler that is blocked awaiting the verb reply. 62 * So handle_vq() will do a "put" on the object when it's done accessing it. 63 * NOTE: If we guarantee that the kernel verb handler will never bail before 64 * getting the reply, then we don't need these refcnts. 65 * 66 * 67 * VQ Request objects are freed by the kernel verbs handlers only 68 * after the verb has been processed, or when the adapter fails and 69 * does not reply. 70 * 71 * 72 * Verbs Reply Buffers: 73 * 74 * VQ Reply bufs are local host memory copies of a 75 * outstanding Verb Request reply 76 * message. The are always allocated by the kernel verbs handlers, and _may_ be 77 * freed by either the kernel verbs handler -or- the interrupt handler. The 78 * kernel verbs handler _must_ free the repbuf, then free the vq request object 79 * in that order. 80 */ 81 82int vq_init(struct c2_dev *c2dev) 83{ 84 sprintf(c2dev->vq_cache_name, "c2-vq:dev%c", 85 (char) ('0' + c2dev->devnum)); 86 c2dev->host_msg_cache = 87 kmem_cache_create(c2dev->vq_cache_name, c2dev->rep_vq.msg_size, 0, 88 SLAB_HWCACHE_ALIGN, NULL); 89 if (c2dev->host_msg_cache == NULL) { 90 return -ENOMEM; 91 } 92 return 0; 93} 94 95void vq_term(struct c2_dev *c2dev) 96{ 97 kmem_cache_destroy(c2dev->host_msg_cache); 98} 99 100/* vq_req_alloc - allocate a VQ Request Object and initialize it. 101 * The refcnt is set to 1. 102 */ 103struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev) 104{ 105 struct c2_vq_req *r; 106 107 r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL); 108 if (r) { 109 init_waitqueue_head(&r->wait_object); 110 r->reply_msg = 0; 111 r->event = 0; 112 r->cm_id = NULL; 113 r->qp = NULL; 114 atomic_set(&r->refcnt, 1); 115 atomic_set(&r->reply_ready, 0); 116 } 117 return r; 118} 119 120 121/* vq_req_free - free the VQ Request Object. It is assumed the verbs handler 122 * has already free the VQ Reply Buffer if it existed. 123 */ 124void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r) 125{ 126 r->reply_msg = 0; 127 if (atomic_dec_and_test(&r->refcnt)) { 128 kfree(r); 129 } 130} 131 132/* vq_req_get - reference a VQ Request Object. Done 133 * only in the kernel verbs handlers. 134 */ 135void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *r) 136{ 137 atomic_inc(&r->refcnt); 138} 139 140 141/* vq_req_put - dereference and potentially free a VQ Request Object. 142 * 143 * This is only called by handle_vq() on the 144 * interrupt when it is done processing 145 * a verb reply message. If the associated 146 * kernel verbs handler has already bailed, 147 * then this put will actually free the VQ 148 * Request object _and_ the VQ Reply Buffer 149 * if it exists. 150 */ 151void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r) 152{ 153 if (atomic_dec_and_test(&r->refcnt)) { 154 if (r->reply_msg != 0) 155 vq_repbuf_free(c2dev, 156 (void *) (unsigned long) r->reply_msg); 157 kfree(r); 158 } 159} 160 161 162/* 163 * vq_repbuf_alloc - allocate a VQ Reply Buffer. 164 */ 165void *vq_repbuf_alloc(struct c2_dev *c2dev) 166{ 167 return kmem_cache_alloc(c2dev->host_msg_cache, GFP_ATOMIC); 168} 169 170/* 171 * vq_send_wr - post a verbs request message to the Verbs Request Queue. 172 * If a message is not available in the MQ, then block until one is available. 173 * NOTE: handle_mq() on the interrupt context will wake up threads blocked here. 174 * When the adapter drains the Verbs Request Queue, 175 * it inserts MQ index 0 in to the 176 * adapter->host activity fifo and interrupts the host. 177 */ 178int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr) 179{ 180 void *msg; 181 wait_queue_t __wait; 182 183 /* 184 * grab adapter vq lock 185 */ 186 spin_lock(&c2dev->vqlock); 187 188 /* 189 * allocate msg 190 */ 191 msg = c2_mq_alloc(&c2dev->req_vq); 192 193 /* 194 * If we cannot get a msg, then we'll wait 195 * When a messages are available, the int handler will wake_up() 196 * any waiters. 197 */ 198 while (msg == NULL) { 199 pr_debug("%s:%d no available msg in VQ, waiting...\n", 200 __func__, __LINE__); 201 init_waitqueue_entry(&__wait, current); 202 add_wait_queue(&c2dev->req_vq_wo, &__wait); 203 spin_unlock(&c2dev->vqlock); 204 for (;;) { 205 set_current_state(TASK_INTERRUPTIBLE); 206 if (!c2_mq_full(&c2dev->req_vq)) { 207 break; 208 } 209 if (!signal_pending(current)) { 210 schedule_timeout(1 * HZ); /* 1 second... */ 211 continue; 212 } 213 set_current_state(TASK_RUNNING); 214 remove_wait_queue(&c2dev->req_vq_wo, &__wait); 215 return -EINTR; 216 } 217 set_current_state(TASK_RUNNING); 218 remove_wait_queue(&c2dev->req_vq_wo, &__wait); 219 spin_lock(&c2dev->vqlock); 220 msg = c2_mq_alloc(&c2dev->req_vq); 221 } 222 223 /* 224 * copy wr into adapter msg 225 */ 226 memcpy(msg, wr, c2dev->req_vq.msg_size); 227 228 /* 229 * post msg 230 */ 231 c2_mq_produce(&c2dev->req_vq); 232 233 /* 234 * release adapter vq lock 235 */ 236 spin_unlock(&c2dev->vqlock); 237 return 0; 238} 239 240 241/* 242 * vq_wait_for_reply - block until the adapter posts a Verb Reply Message. 243 */ 244int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req) 245{ 246 if (!wait_event_timeout(req->wait_object, 247 atomic_read(&req->reply_ready), 248 60*HZ)) 249 return -ETIMEDOUT; 250 251 return 0; 252} 253 254/* 255 * vq_repbuf_free - Free a Verbs Reply Buffer. 256 */ 257void vq_repbuf_free(struct c2_dev *c2dev, void *reply) 258{ 259 kmem_cache_free(c2dev->host_msg_cache, reply); 260} 261