linux/drivers/infiniband/hw/amso1100/c2_cm.c
<<
>>
Prefs
   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 */
  34#include <linux/slab.h>
  35
  36#include "c2.h"
  37#include "c2_wr.h"
  38#include "c2_vq.h"
  39#include <rdma/iw_cm.h>
  40
  41int c2_llp_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
  42{
  43        struct c2_dev *c2dev = to_c2dev(cm_id->device);
  44        struct ib_qp *ibqp;
  45        struct c2_qp *qp;
  46        struct c2wr_qp_connect_req *wr; /* variable size needs a malloc. */
  47        struct c2_vq_req *vq_req;
  48        int err;
  49
  50        ibqp = c2_get_qp(cm_id->device, iw_param->qpn);
  51        if (!ibqp)
  52                return -EINVAL;
  53        qp = to_c2qp(ibqp);
  54
  55        /* Associate QP <--> CM_ID */
  56        cm_id->provider_data = qp;
  57        cm_id->add_ref(cm_id);
  58        qp->cm_id = cm_id;
  59
  60        /*
  61         * only support the max private_data length
  62         */
  63        if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) {
  64                err = -EINVAL;
  65                goto bail0;
  66        }
  67        /*
  68         * Set the rdma read limits
  69         */
  70        err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird);
  71        if (err)
  72                goto bail0;
  73
  74        /*
  75         * Create and send a WR_QP_CONNECT...
  76         */
  77        wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL);
  78        if (!wr) {
  79                err = -ENOMEM;
  80                goto bail0;
  81        }
  82
  83        vq_req = vq_req_alloc(c2dev);
  84        if (!vq_req) {
  85                err = -ENOMEM;
  86                goto bail1;
  87        }
  88
  89        c2_wr_set_id(wr, CCWR_QP_CONNECT);
  90        wr->hdr.context = 0;
  91        wr->rnic_handle = c2dev->adapter_handle;
  92        wr->qp_handle = qp->adapter_handle;
  93
  94        wr->remote_addr = cm_id->remote_addr.sin_addr.s_addr;
  95        wr->remote_port = cm_id->remote_addr.sin_port;
  96
  97        /*
  98         * Move any private data from the callers's buf into
  99         * the WR.
 100         */
 101        if (iw_param->private_data) {
 102                wr->private_data_length =
 103                        cpu_to_be32(iw_param->private_data_len);
 104                memcpy(&wr->private_data[0], iw_param->private_data,
 105                       iw_param->private_data_len);
 106        } else
 107                wr->private_data_length = 0;
 108
 109        /*
 110         * Send WR to adapter.  NOTE: There is no synch reply from
 111         * the adapter.
 112         */
 113        err = vq_send_wr(c2dev, (union c2wr *) wr);
 114        vq_req_free(c2dev, vq_req);
 115
 116 bail1:
 117        kfree(wr);
 118 bail0:
 119        if (err) {
 120                /*
 121                 * If we fail, release reference on QP and
 122                 * disassociate QP from CM_ID
 123                 */
 124                cm_id->provider_data = NULL;
 125                qp->cm_id = NULL;
 126                cm_id->rem_ref(cm_id);
 127        }
 128        return err;
 129}
 130
 131int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog)
 132{
 133        struct c2_dev *c2dev;
 134        struct c2wr_ep_listen_create_req wr;
 135        struct c2wr_ep_listen_create_rep *reply;
 136        struct c2_vq_req *vq_req;
 137        int err;
 138
 139        c2dev = to_c2dev(cm_id->device);
 140        if (c2dev == NULL)
 141                return -EINVAL;
 142
 143        /*
 144         * Allocate verbs request.
 145         */
 146        vq_req = vq_req_alloc(c2dev);
 147        if (!vq_req)
 148                return -ENOMEM;
 149
 150        /*
 151         * Build the WR
 152         */
 153        c2_wr_set_id(&wr, CCWR_EP_LISTEN_CREATE);
 154        wr.hdr.context = (u64) (unsigned long) vq_req;
 155        wr.rnic_handle = c2dev->adapter_handle;
 156        wr.local_addr = cm_id->local_addr.sin_addr.s_addr;
 157        wr.local_port = cm_id->local_addr.sin_port;
 158        wr.backlog = cpu_to_be32(backlog);
 159        wr.user_context = (u64) (unsigned long) cm_id;
 160
 161        /*
 162         * Reference the request struct.  Dereferenced in the int handler.
 163         */
 164        vq_req_get(c2dev, vq_req);
 165
 166        /*
 167         * Send WR to adapter
 168         */
 169        err = vq_send_wr(c2dev, (union c2wr *) & wr);
 170        if (err) {
 171                vq_req_put(c2dev, vq_req);
 172                goto bail0;
 173        }
 174
 175        /*
 176         * Wait for reply from adapter
 177         */
 178        err = vq_wait_for_reply(c2dev, vq_req);
 179        if (err)
 180                goto bail0;
 181
 182        /*
 183         * Process reply
 184         */
 185        reply =
 186            (struct c2wr_ep_listen_create_rep *) (unsigned long) vq_req->reply_msg;
 187        if (!reply) {
 188                err = -ENOMEM;
 189                goto bail1;
 190        }
 191
 192        if ((err = c2_errno(reply)) != 0)
 193                goto bail1;
 194
 195        /*
 196         * Keep the adapter handle. Used in subsequent destroy
 197         */
 198        cm_id->provider_data = (void*)(unsigned long) reply->ep_handle;
 199
 200        /*
 201         * free vq stuff
 202         */
 203        vq_repbuf_free(c2dev, reply);
 204        vq_req_free(c2dev, vq_req);
 205
 206        return 0;
 207
 208 bail1:
 209        vq_repbuf_free(c2dev, reply);
 210 bail0:
 211        vq_req_free(c2dev, vq_req);
 212        return err;
 213}
 214
 215
 216int c2_llp_service_destroy(struct iw_cm_id *cm_id)
 217{
 218
 219        struct c2_dev *c2dev;
 220        struct c2wr_ep_listen_destroy_req wr;
 221        struct c2wr_ep_listen_destroy_rep *reply;
 222        struct c2_vq_req *vq_req;
 223        int err;
 224
 225        c2dev = to_c2dev(cm_id->device);
 226        if (c2dev == NULL)
 227                return -EINVAL;
 228
 229        /*
 230         * Allocate verbs request.
 231         */
 232        vq_req = vq_req_alloc(c2dev);
 233        if (!vq_req)
 234                return -ENOMEM;
 235
 236        /*
 237         * Build the WR
 238         */
 239        c2_wr_set_id(&wr, CCWR_EP_LISTEN_DESTROY);
 240        wr.hdr.context = (unsigned long) vq_req;
 241        wr.rnic_handle = c2dev->adapter_handle;
 242        wr.ep_handle = (u32)(unsigned long)cm_id->provider_data;
 243
 244        /*
 245         * reference the request struct.  dereferenced in the int handler.
 246         */
 247        vq_req_get(c2dev, vq_req);
 248
 249        /*
 250         * Send WR to adapter
 251         */
 252        err = vq_send_wr(c2dev, (union c2wr *) & wr);
 253        if (err) {
 254                vq_req_put(c2dev, vq_req);
 255                goto bail0;
 256        }
 257
 258        /*
 259         * Wait for reply from adapter
 260         */
 261        err = vq_wait_for_reply(c2dev, vq_req);
 262        if (err)
 263                goto bail0;
 264
 265        /*
 266         * Process reply
 267         */
 268        reply=(struct c2wr_ep_listen_destroy_rep *)(unsigned long)vq_req->reply_msg;
 269        if (!reply) {
 270                err = -ENOMEM;
 271                goto bail0;
 272        }
 273        if ((err = c2_errno(reply)) != 0)
 274                goto bail1;
 275
 276 bail1:
 277        vq_repbuf_free(c2dev, reply);
 278 bail0:
 279        vq_req_free(c2dev, vq_req);
 280        return err;
 281}
 282
 283int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
 284{
 285        struct c2_dev *c2dev = to_c2dev(cm_id->device);
 286        struct c2_qp *qp;
 287        struct ib_qp *ibqp;
 288        struct c2wr_cr_accept_req *wr;  /* variable length WR */
 289        struct c2_vq_req *vq_req;
 290        struct c2wr_cr_accept_rep *reply;       /* VQ Reply msg ptr. */
 291        int err;
 292
 293        ibqp = c2_get_qp(cm_id->device, iw_param->qpn);
 294        if (!ibqp)
 295                return -EINVAL;
 296        qp = to_c2qp(ibqp);
 297
 298        /* Set the RDMA read limits */
 299        err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird);
 300        if (err)
 301                goto bail0;
 302
 303        /* Allocate verbs request. */
 304        vq_req = vq_req_alloc(c2dev);
 305        if (!vq_req) {
 306                err = -ENOMEM;
 307                goto bail0;
 308        }
 309        vq_req->qp = qp;
 310        vq_req->cm_id = cm_id;
 311        vq_req->event = IW_CM_EVENT_ESTABLISHED;
 312
 313        wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL);
 314        if (!wr) {
 315                err = -ENOMEM;
 316                goto bail1;
 317        }
 318
 319        /* Build the WR */
 320        c2_wr_set_id(wr, CCWR_CR_ACCEPT);
 321        wr->hdr.context = (unsigned long) vq_req;
 322        wr->rnic_handle = c2dev->adapter_handle;
 323        wr->ep_handle = (u32) (unsigned long) cm_id->provider_data;
 324        wr->qp_handle = qp->adapter_handle;
 325
 326        /* Replace the cr_handle with the QP after accept */
 327        cm_id->provider_data = qp;
 328        cm_id->add_ref(cm_id);
 329        qp->cm_id = cm_id;
 330
 331        cm_id->provider_data = qp;
 332
 333        /* Validate private_data length */
 334        if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) {
 335                err = -EINVAL;
 336                goto bail1;
 337        }
 338
 339        if (iw_param->private_data) {
 340                wr->private_data_length = cpu_to_be32(iw_param->private_data_len);
 341                memcpy(&wr->private_data[0],
 342                       iw_param->private_data, iw_param->private_data_len);
 343        } else
 344                wr->private_data_length = 0;
 345
 346        /* Reference the request struct.  Dereferenced in the int handler. */
 347        vq_req_get(c2dev, vq_req);
 348
 349        /* Send WR to adapter */
 350        err = vq_send_wr(c2dev, (union c2wr *) wr);
 351        if (err) {
 352                vq_req_put(c2dev, vq_req);
 353                goto bail1;
 354        }
 355
 356        /* Wait for reply from adapter */
 357        err = vq_wait_for_reply(c2dev, vq_req);
 358        if (err)
 359                goto bail1;
 360
 361        /* Check that reply is present */
 362        reply = (struct c2wr_cr_accept_rep *) (unsigned long) vq_req->reply_msg;
 363        if (!reply) {
 364                err = -ENOMEM;
 365                goto bail1;
 366        }
 367
 368        err = c2_errno(reply);
 369        vq_repbuf_free(c2dev, reply);
 370
 371        if (!err)
 372                c2_set_qp_state(qp, C2_QP_STATE_RTS);
 373 bail1:
 374        kfree(wr);
 375        vq_req_free(c2dev, vq_req);
 376 bail0:
 377        if (err) {
 378                /*
 379                 * If we fail, release reference on QP and
 380                 * disassociate QP from CM_ID
 381                 */
 382                cm_id->provider_data = NULL;
 383                qp->cm_id = NULL;
 384                cm_id->rem_ref(cm_id);
 385        }
 386        return err;
 387}
 388
 389int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
 390{
 391        struct c2_dev *c2dev;
 392        struct c2wr_cr_reject_req wr;
 393        struct c2_vq_req *vq_req;
 394        struct c2wr_cr_reject_rep *reply;
 395        int err;
 396
 397        c2dev = to_c2dev(cm_id->device);
 398
 399        /*
 400         * Allocate verbs request.
 401         */
 402        vq_req = vq_req_alloc(c2dev);
 403        if (!vq_req)
 404                return -ENOMEM;
 405
 406        /*
 407         * Build the WR
 408         */
 409        c2_wr_set_id(&wr, CCWR_CR_REJECT);
 410        wr.hdr.context = (unsigned long) vq_req;
 411        wr.rnic_handle = c2dev->adapter_handle;
 412        wr.ep_handle = (u32) (unsigned long) cm_id->provider_data;
 413
 414        /*
 415         * reference the request struct.  dereferenced in the int handler.
 416         */
 417        vq_req_get(c2dev, vq_req);
 418
 419        /*
 420         * Send WR to adapter
 421         */
 422        err = vq_send_wr(c2dev, (union c2wr *) & wr);
 423        if (err) {
 424                vq_req_put(c2dev, vq_req);
 425                goto bail0;
 426        }
 427
 428        /*
 429         * Wait for reply from adapter
 430         */
 431        err = vq_wait_for_reply(c2dev, vq_req);
 432        if (err)
 433                goto bail0;
 434
 435        /*
 436         * Process reply
 437         */
 438        reply = (struct c2wr_cr_reject_rep *) (unsigned long)
 439                vq_req->reply_msg;
 440        if (!reply) {
 441                err = -ENOMEM;
 442                goto bail0;
 443        }
 444        err = c2_errno(reply);
 445        /*
 446         * free vq stuff
 447         */
 448        vq_repbuf_free(c2dev, reply);
 449
 450 bail0:
 451        vq_req_free(c2dev, vq_req);
 452        return err;
 453}
 454