0001
0002
0003
0004
0005
0006 #include <rdma/rdmavt_qp.h>
0007 #include <rdma/ib_hdrs.h>
0008
0009
0010
0011
0012 static const u16 credit_table[31] = {
0013 0,
0014 1,
0015 2,
0016 3,
0017 4,
0018 6,
0019 8,
0020 12,
0021 16,
0022 24,
0023 32,
0024 48,
0025 64,
0026 96,
0027 128,
0028 192,
0029 256,
0030 384,
0031 512,
0032 768,
0033 1024,
0034 1536,
0035 2048,
0036 3072,
0037 4096,
0038 6144,
0039 8192,
0040 12288,
0041 16384,
0042 24576,
0043 32768
0044 };
0045
0046
0047
0048
0049
0050
0051
0052 __be32 rvt_compute_aeth(struct rvt_qp *qp)
0053 {
0054 u32 aeth = qp->r_msn & IB_MSN_MASK;
0055
0056 if (qp->ibqp.srq) {
0057
0058
0059
0060
0061 aeth |= IB_AETH_CREDIT_INVAL << IB_AETH_CREDIT_SHIFT;
0062 } else {
0063 u32 min, max, x;
0064 u32 credits;
0065 u32 head;
0066 u32 tail;
0067
0068 credits = READ_ONCE(qp->r_rq.kwq->count);
0069 if (credits == 0) {
0070
0071 if (qp->ip) {
0072 head = RDMA_READ_UAPI_ATOMIC(qp->r_rq.wq->head);
0073 tail = RDMA_READ_UAPI_ATOMIC(qp->r_rq.wq->tail);
0074 } else {
0075 head = READ_ONCE(qp->r_rq.kwq->head);
0076 tail = READ_ONCE(qp->r_rq.kwq->tail);
0077 }
0078 if (head >= qp->r_rq.size)
0079 head = 0;
0080 if (tail >= qp->r_rq.size)
0081 tail = 0;
0082
0083
0084
0085
0086
0087
0088 credits = rvt_get_rq_count(&qp->r_rq, head, tail);
0089 }
0090
0091
0092
0093
0094 min = 0;
0095 max = 31;
0096 for (;;) {
0097 x = (min + max) / 2;
0098 if (credit_table[x] == credits)
0099 break;
0100 if (credit_table[x] > credits) {
0101 max = x;
0102 } else {
0103 if (min == x)
0104 break;
0105 min = x;
0106 }
0107 }
0108 aeth |= x << IB_AETH_CREDIT_SHIFT;
0109 }
0110 return cpu_to_be32(aeth);
0111 }
0112 EXPORT_SYMBOL(rvt_compute_aeth);
0113
0114
0115
0116
0117
0118
0119
0120
0121 void rvt_get_credit(struct rvt_qp *qp, u32 aeth)
0122 {
0123 struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
0124 u32 credit = (aeth >> IB_AETH_CREDIT_SHIFT) & IB_AETH_CREDIT_MASK;
0125
0126 lockdep_assert_held(&qp->s_lock);
0127
0128
0129
0130
0131
0132 if (credit == IB_AETH_CREDIT_INVAL) {
0133 if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) {
0134 qp->s_flags |= RVT_S_UNLIMITED_CREDIT;
0135 if (qp->s_flags & RVT_S_WAIT_SSN_CREDIT) {
0136 qp->s_flags &= ~RVT_S_WAIT_SSN_CREDIT;
0137 rdi->driver_f.schedule_send(qp);
0138 }
0139 }
0140 } else if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT)) {
0141
0142 credit = (aeth + credit_table[credit]) & IB_MSN_MASK;
0143 if (rvt_cmp_msn(credit, qp->s_lsn) > 0) {
0144 qp->s_lsn = credit;
0145 if (qp->s_flags & RVT_S_WAIT_SSN_CREDIT) {
0146 qp->s_flags &= ~RVT_S_WAIT_SSN_CREDIT;
0147 rdi->driver_f.schedule_send(qp);
0148 }
0149 }
0150 }
0151 }
0152 EXPORT_SYMBOL(rvt_get_credit);
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 u32 rvt_restart_sge(struct rvt_sge_state *ss, struct rvt_swqe *wqe, u32 len)
0163 {
0164 ss->sge = wqe->sg_list[0];
0165 ss->sg_list = wqe->sg_list + 1;
0166 ss->num_sge = wqe->wr.num_sge;
0167 ss->total_len = wqe->length;
0168 rvt_skip_sge(ss, len, false);
0169 return wqe->length - len;
0170 }
0171 EXPORT_SYMBOL(rvt_restart_sge);
0172