Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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);