linux/drivers/infiniband/sw/rdmavt/rc.c
<<
>>
Prefs
   1/*
   2 * Copyright(c) 2016 Intel Corporation.
   3 *
   4 * This file is provided under a dual BSD/GPLv2 license.  When using or
   5 * redistributing this file, you may do so under either license.
   6 *
   7 * GPL LICENSE SUMMARY
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of version 2 of the GNU General Public License as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful, but
  14 * WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16 * General Public License for more details.
  17 *
  18 * BSD LICENSE
  19 *
  20 * Redistribution and use in source and binary forms, with or without
  21 * modification, are permitted provided that the following conditions
  22 * are met:
  23 *
  24 *  - Redistributions of source code must retain the above copyright
  25 *    notice, this list of conditions and the following disclaimer.
  26 *  - Redistributions in binary form must reproduce the above copyright
  27 *    notice, this list of conditions and the following disclaimer in
  28 *    the documentation and/or other materials provided with the
  29 *    distribution.
  30 *  - Neither the name of Intel Corporation nor the names of its
  31 *    contributors may be used to endorse or promote products derived
  32 *    from this software without specific prior written permission.
  33 *
  34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  37 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  38 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45 *
  46 */
  47
  48#include <rdma/rdma_vt.h>
  49#include <rdma/ib_hdrs.h>
  50
  51/*
  52 * Convert the AETH credit code into the number of credits.
  53 */
  54static const u16 credit_table[31] = {
  55        0,                      /* 0 */
  56        1,                      /* 1 */
  57        2,                      /* 2 */
  58        3,                      /* 3 */
  59        4,                      /* 4 */
  60        6,                      /* 5 */
  61        8,                      /* 6 */
  62        12,                     /* 7 */
  63        16,                     /* 8 */
  64        24,                     /* 9 */
  65        32,                     /* A */
  66        48,                     /* B */
  67        64,                     /* C */
  68        96,                     /* D */
  69        128,                    /* E */
  70        192,                    /* F */
  71        256,                    /* 10 */
  72        384,                    /* 11 */
  73        512,                    /* 12 */
  74        768,                    /* 13 */
  75        1024,                   /* 14 */
  76        1536,                   /* 15 */
  77        2048,                   /* 16 */
  78        3072,                   /* 17 */
  79        4096,                   /* 18 */
  80        6144,                   /* 19 */
  81        8192,                   /* 1A */
  82        12288,                  /* 1B */
  83        16384,                  /* 1C */
  84        24576,                  /* 1D */
  85        32768                   /* 1E */
  86};
  87
  88/**
  89 * rvt_compute_aeth - compute the AETH (syndrome + MSN)
  90 * @qp: the queue pair to compute the AETH for
  91 *
  92 * Returns the AETH.
  93 */
  94__be32 rvt_compute_aeth(struct rvt_qp *qp)
  95{
  96        u32 aeth = qp->r_msn & IB_MSN_MASK;
  97
  98        if (qp->ibqp.srq) {
  99                /*
 100                 * Shared receive queues don't generate credits.
 101                 * Set the credit field to the invalid value.
 102                 */
 103                aeth |= IB_AETH_CREDIT_INVAL << IB_AETH_CREDIT_SHIFT;
 104        } else {
 105                u32 min, max, x;
 106                u32 credits;
 107                struct rvt_rwq *wq = qp->r_rq.wq;
 108                u32 head;
 109                u32 tail;
 110
 111                /* sanity check pointers before trusting them */
 112                head = wq->head;
 113                if (head >= qp->r_rq.size)
 114                        head = 0;
 115                tail = wq->tail;
 116                if (tail >= qp->r_rq.size)
 117                        tail = 0;
 118                /*
 119                 * Compute the number of credits available (RWQEs).
 120                 * There is a small chance that the pair of reads are
 121                 * not atomic, which is OK, since the fuzziness is
 122                 * resolved as further ACKs go out.
 123                 */
 124                credits = head - tail;
 125                if ((int)credits < 0)
 126                        credits += qp->r_rq.size;
 127                /*
 128                 * Binary search the credit table to find the code to
 129                 * use.
 130                 */
 131                min = 0;
 132                max = 31;
 133                for (;;) {
 134                        x = (min + max) / 2;
 135                        if (credit_table[x] == credits)
 136                                break;
 137                        if (credit_table[x] > credits) {
 138                                max = x;
 139                        } else {
 140                                if (min == x)
 141                                        break;
 142                                min = x;
 143                        }
 144                }
 145                aeth |= x << IB_AETH_CREDIT_SHIFT;
 146        }
 147        return cpu_to_be32(aeth);
 148}
 149EXPORT_SYMBOL(rvt_compute_aeth);
 150
 151/**
 152 * rvt_get_credit - flush the send work queue of a QP
 153 * @qp: the qp who's send work queue to flush
 154 * @aeth: the Acknowledge Extended Transport Header
 155 *
 156 * The QP s_lock should be held.
 157 */
 158void rvt_get_credit(struct rvt_qp *qp, u32 aeth)
 159{
 160        struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
 161        u32 credit = (aeth >> IB_AETH_CREDIT_SHIFT) & IB_AETH_CREDIT_MASK;
 162
 163        lockdep_assert_held(&qp->s_lock);
 164        /*
 165         * If the credit is invalid, we can send
 166         * as many packets as we like.  Otherwise, we have to
 167         * honor the credit field.
 168         */
 169        if (credit == IB_AETH_CREDIT_INVAL) {
 170                if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) {
 171                        qp->s_flags |= RVT_S_UNLIMITED_CREDIT;
 172                        if (qp->s_flags & RVT_S_WAIT_SSN_CREDIT) {
 173                                qp->s_flags &= ~RVT_S_WAIT_SSN_CREDIT;
 174                                rdi->driver_f.schedule_send(qp);
 175                        }
 176                }
 177        } else if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) {
 178                /* Compute new LSN (i.e., MSN + credit) */
 179                credit = (aeth + credit_table[credit]) & IB_MSN_MASK;
 180                if (rvt_cmp_msn(credit, qp->s_lsn) > 0) {
 181                        qp->s_lsn = credit;
 182                        if (qp->s_flags & RVT_S_WAIT_SSN_CREDIT) {
 183                                qp->s_flags &= ~RVT_S_WAIT_SSN_CREDIT;
 184                                rdi->driver_f.schedule_send(qp);
 185                        }
 186                }
 187        }
 188}
 189EXPORT_SYMBOL(rvt_get_credit);
 190