1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
* Copyright (c) 2018-2025 Advanced Micro Devices, Inc. All rights reserved.
*/
#ifndef IONIC_FW_H
#define IONIC_FW_H
#include "ionic_fw_types.h"
static inline int to_ionic_mr_flags(int access)
{
int flags = 0;
if (access & IBV_ACCESS_LOCAL_WRITE)
flags |= IONIC_MRF_LOCAL_WRITE;
if (access & IBV_ACCESS_REMOTE_READ)
flags |= IONIC_MRF_REMOTE_READ;
if (access & IBV_ACCESS_REMOTE_WRITE)
flags |= IONIC_MRF_REMOTE_WRITE;
if (access & IBV_ACCESS_REMOTE_ATOMIC)
flags |= IONIC_MRF_REMOTE_ATOMIC;
if (access & IBV_ACCESS_MW_BIND)
flags |= IONIC_MRF_MW_BIND;
if (access & IBV_ACCESS_ZERO_BASED)
flags |= IONIC_MRF_ZERO_BASED;
return flags;
}
static inline int ionic_to_ibv_status(int sts)
{
switch (sts) {
case IONIC_STS_OK:
return IBV_WC_SUCCESS;
case IONIC_STS_LOCAL_LEN_ERR:
return IBV_WC_LOC_LEN_ERR;
case IONIC_STS_LOCAL_QP_OPER_ERR:
return IBV_WC_LOC_QP_OP_ERR;
case IONIC_STS_LOCAL_PROT_ERR:
return IBV_WC_LOC_PROT_ERR;
case IONIC_STS_WQE_FLUSHED_ERR:
return IBV_WC_WR_FLUSH_ERR;
case IONIC_STS_MEM_MGMT_OPER_ERR:
return IBV_WC_MW_BIND_ERR;
case IONIC_STS_BAD_RESP_ERR:
return IBV_WC_BAD_RESP_ERR;
case IONIC_STS_LOCAL_ACC_ERR:
return IBV_WC_LOC_ACCESS_ERR;
case IONIC_STS_REMOTE_INV_REQ_ERR:
return IBV_WC_REM_INV_REQ_ERR;
case IONIC_STS_REMOTE_ACC_ERR:
return IBV_WC_REM_ACCESS_ERR;
case IONIC_STS_REMOTE_OPER_ERR:
return IBV_WC_REM_OP_ERR;
case IONIC_STS_RETRY_EXCEEDED:
return IBV_WC_RETRY_EXC_ERR;
case IONIC_STS_RNR_RETRY_EXCEEDED:
return IBV_WC_RNR_RETRY_EXC_ERR;
case IONIC_STS_XRC_VIO_ERR:
default:
return IBV_WC_GENERAL_ERR;
}
}
static inline bool ionic_v1_cqe_color(struct ionic_v1_cqe *cqe)
{
return !!(cqe->qid_type_flags & htobe32(IONIC_V1_CQE_COLOR));
}
static inline bool ionic_v1_cqe_error(struct ionic_v1_cqe *cqe)
{
return !!(cqe->qid_type_flags & htobe32(IONIC_V1_CQE_ERROR));
}
static inline bool ionic_v1_cqe_recv_is_ipv4(struct ionic_v1_cqe *cqe)
{
return !!(cqe->recv.src_qpn_op &
htobe32(IONIC_V1_CQE_RECV_IS_IPV4));
}
static inline bool ionic_v1_cqe_recv_is_vlan(struct ionic_v1_cqe *cqe)
{
return !!(cqe->recv.src_qpn_op &
htobe32(IONIC_V1_CQE_RECV_IS_VLAN));
}
static inline void ionic_v1_cqe_clean(struct ionic_v1_cqe *cqe)
{
cqe->qid_type_flags |= htobe32(~0u << IONIC_V1_CQE_QID_SHIFT);
}
static inline uint32_t ionic_v1_cqe_qtf(struct ionic_v1_cqe *cqe)
{
return be32toh(cqe->qid_type_flags);
}
static inline uint8_t ionic_v1_cqe_qtf_type(uint32_t qtf)
{
return (qtf >> IONIC_V1_CQE_TYPE_SHIFT) & IONIC_V1_CQE_TYPE_MASK;
}
static inline uint32_t ionic_v1_cqe_qtf_qid(uint32_t qtf)
{
return qtf >> IONIC_V1_CQE_QID_SHIFT;
}
static inline size_t ionic_v1_send_wqe_min_size(int min_sge, int min_data,
int spec, bool expdb)
{
size_t sz_wqe, sz_sgl, sz_data;
if (spec > IONIC_V1_SPEC_FIRST_SGE)
min_sge += IONIC_V1_SPEC_FIRST_SGE;
if (expdb) {
min_sge += 1;
min_data += IONIC_EXP_DBELL_SZ;
}
sz_wqe = sizeof(struct ionic_v1_wqe);
sz_sgl = offsetof(struct ionic_v1_wqe, common.pld.sgl[min_sge]);
sz_data = offsetof(struct ionic_v1_wqe, common.pld.data[min_data]);
if (sz_sgl > sz_wqe)
sz_wqe = sz_sgl;
if (sz_data > sz_wqe)
sz_wqe = sz_data;
return roundup_pow_of_two(sz_wqe);
}
static inline int ionic_v1_send_wqe_max_sge(uint8_t stride_log2, int spec, bool expdb)
{
struct ionic_v1_wqe *wqe = (void *)0;
struct ionic_sge *sge = (void *)(uintptr_t)(1ull << stride_log2);
int num_sge = 0;
if (expdb)
sge -= 1;
if (spec > IONIC_V1_SPEC_FIRST_SGE)
num_sge = IONIC_V1_SPEC_FIRST_SGE;
num_sge = sge - &wqe->common.pld.sgl[num_sge];
if (spec && num_sge > spec)
num_sge = spec;
return num_sge;
}
static inline int ionic_v1_send_wqe_max_data(uint8_t stride_log2, bool expdb)
{
struct ionic_v1_wqe *wqe = (void *)0;
__u8 *data = (void *)(uintptr_t)(1ull << stride_log2);
if (expdb)
data -= IONIC_EXP_DBELL_SZ;
return data - wqe->common.pld.data;
}
static inline size_t ionic_v1_recv_wqe_min_size(int min_sge, int spec, bool expdb)
{
size_t sz_wqe, sz_sgl;
if (spec > IONIC_V1_SPEC_FIRST_SGE)
min_sge += IONIC_V1_SPEC_FIRST_SGE;
if (expdb)
min_sge += 1;
sz_wqe = sizeof(struct ionic_v1_wqe);
sz_sgl = offsetof(struct ionic_v1_wqe, recv.pld.sgl[min_sge]);
if (sz_sgl > sz_wqe)
sz_wqe = sz_sgl;
return sz_wqe;
}
static inline int ionic_v1_recv_wqe_max_sge(uint8_t stride_log2, int spec, bool expdb)
{
struct ionic_v1_wqe *wqe = (void *)0;
struct ionic_sge *sge = (void *)(uintptr_t)(1ull << stride_log2);
int num_sge = 0;
if (expdb)
sge -= 1;
if (spec > IONIC_V1_SPEC_FIRST_SGE)
num_sge = IONIC_V1_SPEC_FIRST_SGE;
num_sge = sge - &wqe->recv.pld.sgl[num_sge];
if (spec && num_sge > spec)
num_sge = spec;
return num_sge;
}
static inline int ionic_v1_use_spec_sge(int min_sge, int spec)
{
if (!spec || min_sge > spec)
return 0;
if (min_sge <= IONIC_V1_SPEC_FIRST_SGE)
return IONIC_V1_SPEC_FIRST_SGE;
return spec;
}
#endif /* IONIC_FW_H */
|