/** * irdma_sc_suspend_resume_qps - suspend/resume all qp's on VSI * @vsi: the VSI struct pointer * @op: Set to IRDMA_OP_RESUME or IRDMA_OP_SUSPEND
*/ void irdma_sc_suspend_resume_qps(struct irdma_sc_vsi *vsi, u8 op)
{ struct irdma_sc_qp *qp = NULL;
u8 i;
for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
mutex_lock(&vsi->qos[i].qos_mutex);
qp = irdma_get_qp_from_list(&vsi->qos[i].qplist, qp); while (qp) { if (op == IRDMA_OP_RESUME) { if (!qp->dev->ws_add(vsi, i)) {
qp->qs_handle =
vsi->qos[qp->user_pri].qs_handle;
irdma_cqp_qp_suspend_resume(qp, op);
} else {
irdma_cqp_qp_suspend_resume(qp, op);
irdma_modify_qp_to_err(qp);
}
} elseif (op == IRDMA_OP_SUSPEND) { /* issue cqp suspend command */ if (!irdma_cqp_qp_suspend_resume(qp, op))
atomic_inc(&vsi->qp_suspend_reqs);
}
qp = irdma_get_qp_from_list(&vsi->qos[i].qplist, qp);
}
mutex_unlock(&vsi->qos[i].qos_mutex);
}
}
vsi->qos_rel_bw = l2p->vsi_rel_bw;
vsi->qos_prio_type = l2p->vsi_prio_type;
vsi->dscp_mode = l2p->dscp_mode; if (l2p->dscp_mode) {
memcpy(vsi->dscp_map, l2p->dscp_map, sizeof(vsi->dscp_map)); for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++)
l2p->up2tc[i] = i;
} for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { if (vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_1)
vsi->qos[i].qs_handle = l2p->qs_handle_list[i];
vsi->qos[i].traffic_class = l2p->up2tc[i];
vsi->qos[i].rel_bw =
l2p->tc_info[vsi->qos[i].traffic_class].rel_bw;
vsi->qos[i].prio_type =
l2p->tc_info[vsi->qos[i].traffic_class].prio_type;
vsi->qos[i].valid = false;
}
}
/** * irdma_change_l2params - given the new l2 parameters, change all qp * @vsi: RDMA VSI pointer * @l2params: New parameters from l2
*/ void irdma_change_l2params(struct irdma_sc_vsi *vsi, struct irdma_l2params *l2params)
{ if (l2params->mtu_changed) {
vsi->mtu = l2params->mtu; if (vsi->ieq)
irdma_reinitialize_ieq(vsi);
}
/** * irdma_qp_add_qos - called during setctx for qp to be added to qos * @qp: qp to be added to qos
*/ void irdma_qp_add_qos(struct irdma_sc_qp *qp)
{ struct irdma_sc_vsi *vsi = qp->vsi;
hdr = info->arp_index |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_MANAGE_ARP) |
FIELD_PREP(IRDMA_CQPSQ_MAT_PERMANENT, (info->permanent ? 1 : 0)) |
FIELD_PREP(IRDMA_CQPSQ_MAT_ENTRYVALID, 1) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_del_arp_cache_entry - dele arp cache entry * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @arp_index: arp index to delete arp entry * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_del_arp_cache_entry(struct irdma_sc_cqp *cqp, u64 scratch,
u16 arp_index, bool post_sq)
{
__le64 *wqe;
u64 hdr;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
hdr = arp_index |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_MANAGE_ARP) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_manage_apbvt_entry - for adding and deleting apbvt entries * @cqp: struct for cqp hw * @info: info for apbvt entry to add or delete * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_manage_apbvt_entry(struct irdma_sc_cqp *cqp, struct irdma_apbvt_info *info,
u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 hdr;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
set_64bit_val(wqe, 16, info->port);
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_MANAGE_APBVT) |
FIELD_PREP(IRDMA_CQPSQ_MAPT_ADDPORT, info->add) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_manage_qhash_table_entry - manage quad hash entries * @cqp: struct for cqp hw * @info: info for quad hash to manage * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring * * This is called before connection establishment is started. * For passive connections, when listener is created, it will * call with entry type of IRDMA_QHASH_TYPE_TCP_SYN with local * ip address and tcp port. When SYN is received (passive * connections) or sent (active connections), this routine is * called with entry type of IRDMA_QHASH_TYPE_TCP_ESTABLISHED * and quad is passed in info. * * When iwarp connection is done and its state moves to RTS, the * quad hash entry in the hardware will point to iwarp's qp * number and requires no calls from the driver.
*/ staticint
irdma_sc_manage_qhash_table_entry(struct irdma_sc_cqp *cqp, struct irdma_qhash_table_info *info,
u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 qw1 = 0;
u64 qw2 = 0;
u64 temp; struct irdma_sc_vsi *vsi = info->vsi;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
set_64bit_val(wqe, 8, qw1);
temp = FIELD_PREP(IRDMA_CQPSQ_QHASH_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_QHASH_OPCODE,
IRDMA_CQP_OP_MANAGE_QUAD_HASH_TABLE_ENTRY) |
FIELD_PREP(IRDMA_CQPSQ_QHASH_MANAGE, info->manage) |
FIELD_PREP(IRDMA_CQPSQ_QHASH_IPV4VALID, info->ipv4_valid) |
FIELD_PREP(IRDMA_CQPSQ_QHASH_VLANVALID, info->vlan_valid) |
FIELD_PREP(IRDMA_CQPSQ_QHASH_ENTRYTYPE, info->entry_type);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_qp_create - create qp * @qp: sc qp * @info: qp create info * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ int irdma_sc_qp_create(struct irdma_sc_qp *qp, struct irdma_create_qp_info *info,
u64 scratch, bool post_sq)
{ struct irdma_sc_cqp *cqp;
__le64 *wqe;
u64 hdr;
/** * irdma_sc_qp_destroy - cqp destroy qp * @qp: sc qp * @scratch: u64 saved to be used during cqp completion * @remove_hash_idx: flag if to remove hash idx * @ignore_mw_bnd: memory window bind flag * @post_sq: flag for cqp db to ring
*/ int irdma_sc_qp_destroy(struct irdma_sc_qp *qp, u64 scratch, bool remove_hash_idx, bool ignore_mw_bnd, bool post_sq)
{
__le64 *wqe; struct irdma_sc_cqp *cqp;
u64 hdr;
hdr = qp->qp_uk.qp_id |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_DESTROY_QP) |
FIELD_PREP(IRDMA_CQPSQ_QP_QPTYPE, qp->qp_uk.qp_type) |
FIELD_PREP(IRDMA_CQPSQ_QP_IGNOREMWBOUND, ignore_mw_bnd) |
FIELD_PREP(IRDMA_CQPSQ_QP_REMOVEHASHENTRY, remove_hash_idx) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_get_encoded_ird_size - * @ird_size: IRD size * The ird from the connection is rounded to a supported HW setting and then encoded * for ird_size field of qp_ctx. Consumers are expected to provide valid ird size based * on hardware attributes. IRD size defaults to a value of 4 in case of invalid input
*/ static u8 irdma_sc_get_encoded_ird_size(u16 ird_size)
{ switch (ird_size ?
roundup_pow_of_two(2 * ird_size) : 4) { case256: return IRDMA_IRD_HW_SIZE_256; case128: return IRDMA_IRD_HW_SIZE_128; case64: case32: return IRDMA_IRD_HW_SIZE_64; case16: case8: return IRDMA_IRD_HW_SIZE_16; case4: default: break;
}
/* irdma_sc_alloc_local_mac_entry - allocate a mac entry * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_alloc_local_mac_entry(struct irdma_sc_cqp *cqp, u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 hdr;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
if (post_sq)
irdma_sc_cqp_post_sq(cqp); return0;
}
/** * irdma_sc_add_local_mac_entry - add mac enry * @cqp: struct for cqp hw * @info:mac addr info * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_add_local_mac_entry(struct irdma_sc_cqp *cqp, struct irdma_local_mac_entry_info *info,
u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 header;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
if (post_sq)
irdma_sc_cqp_post_sq(cqp); return0;
}
/** * irdma_sc_del_local_mac_entry - cqp wqe to dele local mac * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @entry_idx: index of mac entry * @ignore_ref_count: to force mac adde delete * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_del_local_mac_entry(struct irdma_sc_cqp *cqp, u64 scratch,
u16 entry_idx, u8 ignore_ref_count, bool post_sq)
{
__le64 *wqe;
u64 header;
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_DEALLOC_STAG) |
FIELD_PREP(IRDMA_CQPSQ_STAG_MR, info->mr) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_ALLOC_STAG) |
FIELD_PREP(IRDMA_CQPSQ_STAG_MWTYPE, info->mw_wide) |
FIELD_PREP(IRDMA_CQPSQ_STAG_MW1_BIND_DONT_VLDT_KEY,
info->mw1_bind_dont_vldt_key) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = FIELD_PREP(IRDMAQPSQ_OPCODE, IRDMAQP_OP_NOP) |
FIELD_PREP(IRDMAQPSQ_LOCALFENCE, 1) |
FIELD_PREP(IRDMAQPSQ_VALID, qp->qp_uk.swqe_polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
wqe = qp_uk->sq_base[2].elem;
hdr = FIELD_PREP(IRDMAQPSQ_OPCODE, IRDMAQP_OP_GEN_RTS_AE) |
FIELD_PREP(IRDMAQPSQ_VALID, qp->qp_uk.swqe_polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = FIELD_PREP(IRDMAQPSQ_OPCODE, IRDMAQP_OP_RDMA_SEND) |
FIELD_PREP(IRDMAQPSQ_STREAMMODE, 1) |
FIELD_PREP(IRDMAQPSQ_WAITFORRCVPDU, 1) |
FIELD_PREP(IRDMAQPSQ_VALID, qp->qp_uk.swqe_polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_locate_mpa - return pointer to mpa in the pkt * @pkt: packet with data
*/ static u8 *irdma_locate_mpa(u8 *pkt)
{ /* skip over ethernet header */
pkt += IRDMA_MAC_HLEN;
/* Skip over IP and TCP headers */
pkt += 4 * (pkt[0] & 0x0f);
pkt += 4 * ((pkt[12] >> 4) & 0x0f);
return pkt;
}
/** * irdma_bld_termhdr_ctrl - setup terminate hdr control fields * @qp: sc qp ptr for pkt * @hdr: term hdr * @opcode: flush opcode for termhdr * @layer_etype: error layer + error type * @err: error cod ein the header
*/ staticvoid irdma_bld_termhdr_ctrl(struct irdma_sc_qp *qp, struct irdma_terminate_hdr *hdr, enum irdma_flush_opcode opcode,
u8 layer_etype, u8 err)
{
qp->flush_code = opcode;
hdr->layer_etype = layer_etype;
hdr->error_code = err;
}
/** * irdma_bld_termhdr_ddp_rdma - setup ddp and rdma hdrs in terminate hdr * @pkt: ptr to mpa in offending pkt * @hdr: term hdr * @copy_len: offending pkt length to be copied to term hdr * @is_tagged: DDP tagged or untagged
*/ staticvoid irdma_bld_termhdr_ddp_rdma(u8 *pkt, struct irdma_terminate_hdr *hdr, int *copy_len, u8 *is_tagged)
{
u16 ddp_seg_len;
staticvoid irdma_null_ws_reset(struct irdma_sc_vsi *vsi)
{ /* do nothing */
}
/** * irdma_sc_vsi_init - Init the vsi structure * @vsi: pointer to vsi structure to initialize * @info: the info used to initialize the vsi struct
*/ void irdma_sc_vsi_init(struct irdma_sc_vsi *vsi, struct irdma_vsi_init_info *info)
{ int i;
irdma_set_qos_info(vsi, info->params); for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) {
mutex_init(&vsi->qos[i].qos_mutex);
INIT_LIST_HEAD(&vsi->qos[i].qplist);
} if (vsi->register_qset) {
vsi->dev->ws_add = irdma_ws_add;
vsi->dev->ws_remove = irdma_ws_remove;
vsi->dev->ws_reset = irdma_ws_reset;
} else {
vsi->dev->ws_add = irdma_null_ws_add;
vsi->dev->ws_remove = irdma_null_ws_remove;
vsi->dev->ws_reset = irdma_null_ws_reset;
}
}
/** * irdma_get_stats_idx - Return stats index * @vsi: pointer to the vsi
*/ static u8 irdma_get_stats_idx(struct irdma_sc_vsi *vsi)
{ struct irdma_stats_inst_info stats_info = {}; struct irdma_sc_dev *dev = vsi->dev;
u8 i;
if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { if (!irdma_cqp_stats_inst_cmd(vsi, IRDMA_OP_STATS_ALLOCATE,
&stats_info)) return stats_info.stats_idx;
}
for (i = 0; i < IRDMA_MAX_STATS_COUNT_GEN_1; i++) { if (!dev->stats_idx_array[i]) {
dev->stats_idx_array[i] = true; return i;
}
}
return IRDMA_INVALID_STATS_IDX;
}
/** * irdma_hw_stats_init_gen1 - Initialize stat reg table used for gen1 * @vsi: vsi structure where hw_regs are set * * Populate the HW stats table
*/ staticvoid irdma_hw_stats_init_gen1(struct irdma_sc_vsi *vsi)
{ struct irdma_sc_dev *dev = vsi->dev; conststruct irdma_hw_stat_map *map;
u64 *stat_reg = vsi->hw_stats_regs;
u64 *regs = dev->hw_stats_regs;
u16 i, stats_reg_set = vsi->stats_idx;
map = dev->hw_stats_map;
/* First 4 stat instances are reserved for port level statistics. */
stats_reg_set += vsi->stats_inst_alloc ? IRDMA_FIRST_NON_PF_STAT : 0;
for (i = 0; i < dev->hw_attrs.max_stat_idx; i++) { if (map[i].bitmask <= IRDMA_MAX_STATS_32)
stat_reg[i] = regs[i] + stats_reg_set * sizeof(u32); else
stat_reg[i] = regs[i] + stats_reg_set * sizeof(u64);
}
}
/** * irdma_vsi_stats_init - Initialize the vsi statistics * @vsi: pointer to the vsi structure * @info: The info structure used for initialization
*/ int irdma_vsi_stats_init(struct irdma_sc_vsi *vsi, struct irdma_vsi_stats_info *info)
{ struct irdma_dma_mem *stats_buff_mem;
/* when stat allocation is not required default to fcn_id. */
vsi->stats_idx = info->fcn_id; if (info->alloc_stats_inst) {
u8 stats_idx = irdma_get_stats_idx(vsi);
/** * irdma_get_encoded_wqe_size - given wq size, returns hardware encoded size * @wqsize: size of the wq (sq, rq) to encoded_size * @queue_type: queue type selected for the calculation algorithm
*/
u8 irdma_get_encoded_wqe_size(u32 wqsize, enum irdma_queue_type queue_type)
{
u8 encoded_size = 0;
/* cqp sq's hw coded value starts from 1 for size of 4 * while it starts from 0 for qp' wq's.
*/ if (queue_type == IRDMA_QUEUE_TYPE_CQP)
encoded_size = 1;
wqsize >>= 2; while (wqsize >>= 1)
encoded_size++;
return encoded_size;
}
/** * irdma_sc_gather_stats - collect the statistics * @cqp: struct for cqp hw * @info: gather stats info structure * @scratch: u64 saved to be used during cqp completion
*/ staticint irdma_sc_gather_stats(struct irdma_sc_cqp *cqp, struct irdma_stats_gather_info *info,
u64 scratch)
{
__le64 *wqe;
u64 temp;
if (info->stats_buff_mem.size < IRDMA_GATHER_STATS_BUF_SIZE) return -ENOMEM;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
temp = FIELD_PREP(IRDMA_CQPSQ_STATS_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_STATS_USE_INST, info->use_stats_inst) |
FIELD_PREP(IRDMA_CQPSQ_STATS_INST_INDEX,
info->stats_inst_index) |
FIELD_PREP(IRDMA_CQPSQ_STATS_USE_HMC_FCN_INDEX,
info->use_hmc_fcn_index) |
FIELD_PREP(IRDMA_CQPSQ_STATS_OP, IRDMA_CQP_OP_GATHER_STATS);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_set_up_map - set the up map table * @cqp: struct for cqp hw * @info: User priority map info * @scratch: u64 saved to be used during cqp completion
*/ staticint irdma_sc_set_up_map(struct irdma_sc_cqp *cqp, struct irdma_up_info *info, u64 scratch)
{
__le64 *wqe;
u64 temp = 0; int i;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++)
temp |= (u64)info->map[i] << (i * 8);
temp = FIELD_PREP(IRDMA_CQPSQ_UP_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_UP_USEVLAN, info->use_vlan) |
FIELD_PREP(IRDMA_CQPSQ_UP_USEOVERRIDE,
info->use_cnp_up_override) |
FIELD_PREP(IRDMA_CQPSQ_UP_OP, IRDMA_CQP_OP_UP_MAP);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = qp->qp_uk.qp_id |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_FLUSH_WQES) |
FIELD_PREP(IRDMA_CQPSQ_FWQE_GENERATE_AE, info->generate_ae) |
FIELD_PREP(IRDMA_CQPSQ_FWQE_USERFLCODE, info->userflushcode) |
FIELD_PREP(IRDMA_CQPSQ_FWQE_FLUSHSQ, flush_sq) |
FIELD_PREP(IRDMA_CQPSQ_FWQE_FLUSHRQ, flush_rq) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_gen_ae - generate AE, uses flush WQE CQP OP * @qp: sc qp * @info: gen ae information * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_gen_ae(struct irdma_sc_qp *qp, struct irdma_gen_ae_info *info, u64 scratch, bool post_sq)
{
u64 temp;
__le64 *wqe; struct irdma_sc_cqp *cqp;
u64 hdr;
hdr = qp->qp_uk.qp_id | FIELD_PREP(IRDMA_CQPSQ_OPCODE,
IRDMA_CQP_OP_GEN_AE) |
FIELD_PREP(IRDMA_CQPSQ_FWQE_GENERATE_AE, 1) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = FIELD_PREP(IRDMA_CQPSQ_UCTX_QPID, info->qp_id) |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_UPLOAD_CONTEXT) |
FIELD_PREP(IRDMA_CQPSQ_UCTX_QPTYPE, info->qp_type) |
FIELD_PREP(IRDMA_CQPSQ_UCTX_RAWFORMAT, info->raw_format) |
FIELD_PREP(IRDMA_CQPSQ_UCTX_FREEZEQP, info->freeze_qp) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_manage_push_page - Handle push page * @cqp: struct for cqp hw * @info: push page info * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_manage_push_page(struct irdma_sc_cqp *cqp, struct irdma_cqp_manage_push_page_info *info,
u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 hdr;
if (info->free_page &&
info->push_idx >= cqp->dev->hw_attrs.max_hw_device_pages) return -EINVAL;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
set_64bit_val(wqe, 16, info->qs_handle);
hdr = FIELD_PREP(IRDMA_CQPSQ_MPP_PPIDX, info->push_idx) |
FIELD_PREP(IRDMA_CQPSQ_MPP_PPTYPE, info->push_page_type) |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_MANAGE_PUSH_PAGES) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_MPP_FREE_PAGE, info->free_page);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_suspend_qp - suspend qp for param change * @cqp: struct for cqp hw * @qp: sc qp struct * @scratch: u64 saved to be used during cqp completion
*/ staticint irdma_sc_suspend_qp(struct irdma_sc_cqp *cqp, struct irdma_sc_qp *qp,
u64 scratch)
{
u64 hdr;
__le64 *wqe;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
hdr = FIELD_PREP(IRDMA_CQPSQ_SUSPENDQP_QPID, qp->qp_uk.qp_id) |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_SUSPEND_QP) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
hdr = FIELD_PREP(IRDMA_CQPSQ_RESUMEQP_QPID, qp->qp_uk.qp_id) |
FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_RESUME_QP) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_cq_destroy - destroy completion q * @cq: cq struct * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ int irdma_sc_cq_destroy(struct irdma_sc_cq *cq, u64 scratch, bool post_sq)
{ struct irdma_sc_cqp *cqp;
__le64 *wqe;
u64 hdr; struct irdma_sc_ceq *ceq;
/* searching for the last object in HMC to find the size of the HMC area. */ for (i = IRDMA_HMC_IW_QP; i < IRDMA_HMC_IW_MAX; i++) { if (info[i].base > max_base) {
max_base = info[i].base;
last_hmc_obj = i;
}
}
/** * irdma_sc_decode_fpm_query() - Decode a 64 bit value into max count and size * @buf: ptr to fpm query buffer * @buf_idx: index into buf * @obj_info: ptr to irdma_hmc_obj_info struct * @rsrc_idx: resource index into info * * Decode a 64 bit value from fpm query buffer into max count and size
*/ static u64 irdma_sc_decode_fpm_query(__le64 *buf, u32 buf_idx, struct irdma_hmc_obj_info *obj_info,
u32 rsrc_idx)
{
u64 temp;
u32 size;
/** * irdma_sc_cqp_init - Initialize buffers for a control Queue Pair * @cqp: IWARP control queue pair pointer * @info: IWARP control queue pair init info pointer * * Initializes the object and context buffers for a control Queue Pair.
*/ int irdma_sc_cqp_init(struct irdma_sc_cqp *cqp, struct irdma_cqp_init_info *info)
{
u8 hw_sq_size;
/** * irdma_sc_cqp_create - create cqp during bringup * @cqp: struct for cqp hw * @maj_err: If error, major err number * @min_err: If error, minor err number
*/ int irdma_sc_cqp_create(struct irdma_sc_cqp *cqp, u16 *maj_err, u16 *min_err)
{
u64 temp;
u8 hw_rev;
u32 cnt = 0, p1, p2, val = 0, err_code; int ret_code;
do { if (cnt++ > cqp->dev->hw_attrs.max_done_count) {
ret_code = -ETIMEDOUT; goto err;
}
udelay(cqp->dev->hw_attrs.max_sleep_count);
val = readl(cqp->dev->hw_regs[IRDMA_CCQPSTATUS]);
} while (!val);
/** * irdma_sc_cqp_get_next_send_wqe_idx - get next wqe on cqp sq * and pass back index * @cqp: CQP HW structure * @scratch: private data for CQP WQE * @wqe_idx: WQE index of CQP SQ
*/
__le64 *irdma_sc_cqp_get_next_send_wqe_idx(struct irdma_sc_cqp *cqp, u64 scratch,
u32 *wqe_idx)
{
__le64 *wqe = NULL; int ret_code;
if (IRDMA_RING_FULL_ERR(cqp->sq_ring)) {
ibdev_dbg(to_ibdev(cqp->dev), "WQE: CQP SQ is full, head 0x%x tail 0x%x size 0x%x\n",
cqp->sq_ring.head, cqp->sq_ring.tail,
cqp->sq_ring.size); return NULL;
}
IRDMA_ATOMIC_RING_MOVE_HEAD(cqp->sq_ring, *wqe_idx, ret_code); if (ret_code) return NULL;
/* move the head for cq */
IRDMA_RING_MOVE_HEAD(ccq->cq_uk.cq_ring, ret_code); if (!IRDMA_RING_CURRENT_HEAD(ccq->cq_uk.cq_ring))
ccq->cq_uk.polarity ^= 1;
/* update cq tail in cq shadow memory also */
IRDMA_RING_MOVE_TAIL(ccq->cq_uk.cq_ring);
set_64bit_val(ccq->cq_uk.shadow_area, 0,
IRDMA_RING_CURRENT_HEAD(ccq->cq_uk.cq_ring));
dma_wmb(); /* make sure shadow area is updated before moving tail */
/** * irdma_sc_poll_for_cqp_op_done - Waits for last write to complete in CQP SQ * @cqp: struct for cqp hw * @op_code: cqp opcode for completion * @compl_info: completion q entry to return
*/ int irdma_sc_poll_for_cqp_op_done(struct irdma_sc_cqp *cqp, u8 op_code, struct irdma_ccq_cqe_info *compl_info)
{ struct irdma_ccq_cqe_info info = {}; struct irdma_sc_cq *ccq; int ret_code = 0;
u32 cnt = 0;
ccq = cqp->dev->ccq; while (1) { if (cnt++ > 100 * cqp->dev->hw_attrs.max_done_count) return -ETIMEDOUT;
if (irdma_sc_ccq_get_cqe_info(ccq, &info)) {
udelay(cqp->dev->hw_attrs.max_sleep_count); continue;
} if (info.error && info.op_code != IRDMA_CQP_OP_QUERY_STAG) {
ret_code = -EIO; break;
} /* make sure op code matches*/ if (op_code == info.op_code) break;
ibdev_dbg(to_ibdev(cqp->dev), "WQE: opcode mismatch for my op code 0x%x, returned opcode %x\n",
op_code, info.op_code);
}
if (compl_info)
memcpy(compl_info, &info, sizeof(*compl_info));
return ret_code;
}
/** * irdma_sc_manage_hmc_pm_func_table - manage of function table * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @info: info for the manage function table operation * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_manage_hmc_pm_func_table(struct irdma_sc_cqp *cqp, struct irdma_hmc_fcn_info *info,
u64 scratch, bool post_sq)
{
__le64 *wqe;
u64 hdr;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
hdr = FIELD_PREP(IRDMA_CQPSQ_MHMC_VFIDX, info->vf_id) |
FIELD_PREP(IRDMA_CQPSQ_OPCODE,
IRDMA_CQP_OP_MANAGE_HMC_PM_FUNC_TABLE) |
FIELD_PREP(IRDMA_CQPSQ_MHMC_FREEPMFN, info->free_fcn) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_commit_fpm_val_done - wait for cqp eqe completion * for fpm commit * @cqp: struct for cqp hw
*/ staticint irdma_sc_commit_fpm_val_done(struct irdma_sc_cqp *cqp)
{ return irdma_sc_poll_for_cqp_op_done(cqp, IRDMA_CQP_OP_COMMIT_FPM_VAL,
NULL);
}
/** * irdma_sc_commit_fpm_val - cqp wqe for commit fpm values * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @hmc_fn_id: hmc function id * @commit_fpm_mem: Memory for fpm values * @post_sq: flag for cqp db to ring * @wait_type: poll ccq or cqp registers for cqp completion
*/ staticint irdma_sc_commit_fpm_val(struct irdma_sc_cqp *cqp, u64 scratch,
u8 hmc_fn_id, struct irdma_dma_mem *commit_fpm_mem, bool post_sq, u8 wait_type)
{
__le64 *wqe;
u64 hdr;
u32 tail, val, error; int ret_code = 0;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_QUERY_FPM_VAL) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_ceq_create - create ceq wqe * @ceq: ceq sc structure * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/
/** * irdma_sc_cceq_create - create cceq * @ceq: ceq sc structure * @scratch: u64 saved to be used during cqp completion
*/ int irdma_sc_cceq_create(struct irdma_sc_ceq *ceq, u64 scratch)
{ int ret_code; struct irdma_sc_dev *dev = ceq->dev;
dev->ccq->vsi = ceq->vsi; if (ceq->reg_cq) {
ret_code = irdma_sc_add_cq_ctx(ceq, ceq->dev->ccq); if (ret_code) return ret_code;
}
ret_code = irdma_sc_ceq_create(ceq, scratch, true); if (!ret_code) return irdma_sc_cceq_create_done(ceq);
return ret_code;
}
/** * irdma_sc_ceq_destroy - destroy ceq * @ceq: ceq sc structure * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ int irdma_sc_ceq_destroy(struct irdma_sc_ceq *ceq, u64 scratch, bool post_sq)
{ struct irdma_sc_cqp *cqp;
__le64 *wqe;
u64 hdr;
IRDMA_RING_MOVE_TAIL(ceq->ceq_ring); if (!IRDMA_RING_CURRENT_TAIL(ceq->ceq_ring))
ceq->polarity ^= 1;
} while (cq_idx == IRDMA_INVALID_CQ_IDX);
if (cq)
irdma_sc_cq_ack(cq); return cq;
}
/** * irdma_sc_cleanup_ceqes - clear the valid ceqes ctx matching the cq * @cq: cq for which the ceqes need to be cleaned up * @ceq: ceq ptr * * The function is called after the cq is destroyed to cleanup * its pending ceqe entries. It is expected caller serializes this * function with process_ceq() in interrupt context.
*/ void irdma_sc_cleanup_ceqes(struct irdma_sc_cq *cq, struct irdma_sc_ceq *ceq)
{ struct irdma_sc_cq *next_cq;
u8 ceq_polarity = ceq->polarity;
__le64 *ceqe;
u8 polarity;
u64 temp; int next;
u32 i;
next = IRDMA_RING_GET_NEXT_TAIL(ceq->ceq_ring, 0);
for (i = 1; i <= IRDMA_RING_SIZE(*ceq); i++) {
ceqe = IRDMA_GET_CEQ_ELEM_AT_POS(ceq, next);
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_CREATE_AEQ) |
FIELD_PREP(IRDMA_CQPSQ_AEQ_LPBLSIZE, aeq->pbl_chunk_size) |
FIELD_PREP(IRDMA_CQPSQ_AEQ_VMAP, aeq->virtual_map) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_aeq_destroy - destroy aeq during close * @aeq: aeq structure ptr * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ staticint irdma_sc_aeq_destroy(struct irdma_sc_aeq *aeq, u64 scratch, bool post_sq)
{
__le64 *wqe; struct irdma_sc_cqp *cqp; struct irdma_sc_dev *dev;
u64 hdr;
dev = aeq->dev;
writel(0, dev->hw_regs[IRDMA_PFINT_AEQCTL]);
cqp = dev->cqp;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
set_64bit_val(wqe, 16, aeq->elem_cnt);
set_64bit_val(wqe, 48, aeq->first_pm_pbl_idx);
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_DESTROY_AEQ) |
FIELD_PREP(IRDMA_CQPSQ_AEQ_LPBLSIZE, aeq->pbl_chunk_size) |
FIELD_PREP(IRDMA_CQPSQ_AEQ_VMAP, aeq->virtual_map) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
info->ae_src = ae_src; switch (info->ae_id) { case IRDMA_AE_PRIV_OPERATION_DENIED: case IRDMA_AE_AMP_INVALIDATE_TYPE1_MW: case IRDMA_AE_AMP_MWBIND_ZERO_BASED_TYPE1_MW: case IRDMA_AE_AMP_FASTREG_INVALID_PBL_HPS_CFG: case IRDMA_AE_AMP_FASTREG_PBLE_MISMATCH: case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: case IRDMA_AE_UDA_XMIT_BAD_PD: case IRDMA_AE_UDA_XMIT_DGRAM_TOO_SHORT: case IRDMA_AE_BAD_CLOSE: case IRDMA_AE_RDMA_READ_WHILE_ORD_ZERO: case IRDMA_AE_STAG_ZERO_INVALID: case IRDMA_AE_IB_RREQ_AND_Q1_FULL: case IRDMA_AE_IB_INVALID_REQUEST: case IRDMA_AE_WQE_UNEXPECTED_OPCODE: case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: case IRDMA_AE_IB_REMOTE_OP_ERROR: case IRDMA_AE_DDP_UBE_INVALID_DDP_VERSION: case IRDMA_AE_DDP_UBE_INVALID_MO: case IRDMA_AE_DDP_UBE_INVALID_QN: case IRDMA_AE_DDP_NO_L_BIT: case IRDMA_AE_RDMAP_ROE_INVALID_RDMAP_VERSION: case IRDMA_AE_RDMAP_ROE_UNEXPECTED_OPCODE: case IRDMA_AE_ROE_INVALID_RDMA_READ_REQUEST: case IRDMA_AE_ROE_INVALID_RDMA_WRITE_OR_READ_RESP: case IRDMA_AE_ROCE_RSP_LENGTH_ERROR: case IRDMA_AE_INVALID_ARP_ENTRY: case IRDMA_AE_INVALID_TCP_OPTION_RCVD: case IRDMA_AE_STALE_ARP_ENTRY: case IRDMA_AE_INVALID_AH_ENTRY: case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: case IRDMA_AE_LLP_SEGMENT_TOO_SMALL: case IRDMA_AE_LLP_TOO_MANY_RETRIES: case IRDMA_AE_LLP_DOUBT_REACHABILITY: case IRDMA_AE_LLP_CONNECTION_ESTABLISHED: case IRDMA_AE_RESET_SENT: case IRDMA_AE_TERMINATE_SENT: case IRDMA_AE_RESET_NOT_SENT: case IRDMA_AE_LCE_QP_CATASTROPHIC: case IRDMA_AE_QP_SUSPEND_COMPLETE: case IRDMA_AE_UDA_L4LEN_INVALID:
info->qp = true;
info->compl_ctx = compl_ctx; break; case IRDMA_AE_LCE_CQ_CATASTROPHIC:
info->cq = true;
info->compl_ctx = compl_ctx << 1;
ae_src = IRDMA_AE_SOURCE_RSVD; break; case IRDMA_AE_ROCE_EMPTY_MCG: case IRDMA_AE_ROCE_BAD_MC_IP_ADDR: case IRDMA_AE_ROCE_BAD_MC_QPID: case IRDMA_AE_MCG_QP_PROTOCOL_MISMATCH:
fallthrough; case IRDMA_AE_LLP_CONNECTION_RESET: case IRDMA_AE_LLP_SYN_RECEIVED: case IRDMA_AE_LLP_FIN_RECEIVED: case IRDMA_AE_LLP_CLOSE_COMPLETE: case IRDMA_AE_LLP_TERMINATE_RECEIVED: case IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE:
ae_src = IRDMA_AE_SOURCE_RSVD;
info->qp = true;
info->compl_ctx = compl_ctx; break; default: break;
}
switch (ae_src) { case IRDMA_AE_SOURCE_RQ: case IRDMA_AE_SOURCE_RQ_0011:
info->qp = true;
info->rq = true;
info->compl_ctx = compl_ctx; break; case IRDMA_AE_SOURCE_CQ: case IRDMA_AE_SOURCE_CQ_0110: case IRDMA_AE_SOURCE_CQ_1010: case IRDMA_AE_SOURCE_CQ_1110:
info->cq = true;
info->compl_ctx = compl_ctx << 1; break; case IRDMA_AE_SOURCE_SQ: case IRDMA_AE_SOURCE_SQ_0111:
info->qp = true;
info->sq = true;
info->compl_ctx = compl_ctx; break; case IRDMA_AE_SOURCE_IN_RR_WR: case IRDMA_AE_SOURCE_IN_RR_WR_1011:
info->qp = true;
info->compl_ctx = compl_ctx;
info->in_rdrsp_wr = true; break; case IRDMA_AE_SOURCE_OUT_RR: case IRDMA_AE_SOURCE_OUT_RR_1111:
info->qp = true;
info->compl_ctx = compl_ctx;
info->out_rdrsp = true; break; case IRDMA_AE_SOURCE_RSVD: default: break;
}
IRDMA_RING_MOVE_TAIL(aeq->aeq_ring); if (!IRDMA_RING_CURRENT_TAIL(aeq->aeq_ring))
aeq->polarity ^= 1;
/** * irdma_sc_ccq_create - create control cq * @ccq: ccq sc struct * @scratch: u64 saved to be used during cqp completion * @check_overflow: overlow flag for ccq * @post_sq: flag for cqp db to ring
*/ int irdma_sc_ccq_create(struct irdma_sc_cq *ccq, u64 scratch, bool check_overflow, bool post_sq)
{ int ret_code;
ret_code = irdma_sc_cq_create(ccq, scratch, check_overflow, post_sq); if (ret_code) return ret_code;
if (post_sq) {
ret_code = irdma_sc_ccq_create_done(ccq); if (ret_code) return ret_code;
}
ccq->dev->cqp->process_cqp_sds = irdma_cqp_sds_cmd;
return0;
}
/** * irdma_sc_ccq_destroy - destroy ccq during close * @ccq: ccq sc struct * @scratch: u64 saved to be used during cqp completion * @post_sq: flag for cqp db to ring
*/ int irdma_sc_ccq_destroy(struct irdma_sc_cq *ccq, u64 scratch, bool post_sq)
{ struct irdma_sc_cqp *cqp;
__le64 *wqe;
u64 hdr; int ret_code = 0;
u32 tail, val, error;
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_UPDATE_PE_SDS) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_UPESD_ENTRY_COUNT, mem_entries);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_sc_static_hmc_pages_allocated - cqp wqe to allocate hmc pages * @cqp: struct for cqp hw * @scratch: u64 saved to be used during cqp completion * @hmc_fn_id: hmc function id * @post_sq: flag for cqp db to ring * @poll_registers: flag to poll register for cqp completion
*/ int irdma_sc_static_hmc_pages_allocated(struct irdma_sc_cqp *cqp, u64 scratch,
u8 hmc_fn_id, bool post_sq, bool poll_registers)
{
u64 hdr;
__le64 *wqe;
u32 tail, val, error;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE,
IRDMA_CQP_OP_SHMC_PAGES_ALLOCATED) |
FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity);
dma_wmb(); /* make sure WQE is written before valid bit is set */
if (post_sq) {
irdma_sc_cqp_post_sq(cqp); if (poll_registers) /* check for cqp sq tail update */ return irdma_cqp_poll_registers(cqp, tail,
cqp->dev->hw_attrs.max_done_count); else return irdma_sc_poll_for_cqp_op_done(cqp,
IRDMA_CQP_OP_SHMC_PAGES_ALLOCATED,
NULL);
}
return0;
}
/** * irdma_cqp_ring_full - check if cqp ring is full * @cqp: struct for cqp hw
*/ staticbool irdma_cqp_ring_full(struct irdma_sc_cqp *cqp)
{ return IRDMA_RING_FULL_ERR(cqp->sq_ring);
}
/** * irdma_est_sd - returns approximate number of SDs for HMC * @dev: sc device struct * @hmc_info: hmc structure, size and count for HMC objects
*/ static u32 irdma_est_sd(struct irdma_sc_dev *dev, struct irdma_hmc_info *hmc_info)
{ int i;
u64 size = 0;
u64 sd;
for (i = IRDMA_HMC_IW_QP; i < IRDMA_HMC_IW_MAX; i++) if (i != IRDMA_HMC_IW_PBLE)
size += round_up(hmc_info->hmc_obj[i].cnt *
hmc_info->hmc_obj[i].size, 512);
size += round_up(hmc_info->hmc_obj[IRDMA_HMC_IW_PBLE].cnt *
hmc_info->hmc_obj[IRDMA_HMC_IW_PBLE].size, 512); if (size & 0x1FFFFF)
sd = (size >> 21) + 1; /* add 1 for remainder */ else
sd = size >> 21; if (sd > 0xFFFFFFFF) {
ibdev_dbg(to_ibdev(dev), "HMC: sd overflow[%lld]\n", sd);
sd = 0xFFFFFFFF - 1;
}
return (u32)sd;
}
/** * irdma_sc_query_rdma_features_done - poll cqp for query features done * @cqp: struct for cqp hw
*/ staticint irdma_sc_query_rdma_features_done(struct irdma_sc_cqp *cqp)
{ return irdma_sc_poll_for_cqp_op_done(cqp,
IRDMA_CQP_OP_QUERY_RDMA_FEATURES,
NULL);
}
/** * irdma_sc_query_rdma_features - query RDMA features and FW ver * @cqp: struct for cqp hw * @buf: buffer to hold query info * @scratch: u64 saved to be used during cqp completion
*/ staticint irdma_sc_query_rdma_features(struct irdma_sc_cqp *cqp, struct irdma_dma_mem *buf, u64 scratch)
{
__le64 *wqe;
u64 temp;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOMEM;
temp = buf->pa;
set_64bit_val(wqe, 32, temp);
temp = FIELD_PREP(IRDMA_CQPSQ_QUERY_RDMA_FEATURES_WQEVALID,
cqp->polarity) |
FIELD_PREP(IRDMA_CQPSQ_QUERY_RDMA_FEATURES_BUF_LEN, buf->size) |
FIELD_PREP(IRDMA_CQPSQ_UP_OP, IRDMA_CQP_OP_QUERY_RDMA_FEATURES);
dma_wmb(); /* make sure WQE is written before valid bit is set */
/** * irdma_exec_cqp_cmd - execute cqp cmd when wqe are available * @dev: rdma device * @pcmdinfo: cqp command info
*/ staticint irdma_exec_cqp_cmd(struct irdma_sc_dev *dev, struct cqp_cmds_info *pcmdinfo)
{ int status; struct irdma_dma_mem val_mem; bool alloc = false;
dev->cqp_cmd_stats[pcmdinfo->cqp_cmd]++; switch (pcmdinfo->cqp_cmd) { case IRDMA_OP_CEQ_DESTROY:
status = irdma_sc_ceq_destroy(pcmdinfo->in.u.ceq_destroy.ceq,
pcmdinfo->in.u.ceq_destroy.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_AEQ_DESTROY:
status = irdma_sc_aeq_destroy(pcmdinfo->in.u.aeq_destroy.aeq,
pcmdinfo->in.u.aeq_destroy.scratch,
pcmdinfo->post_sq);
break; case IRDMA_OP_CEQ_CREATE:
status = irdma_sc_ceq_create(pcmdinfo->in.u.ceq_create.ceq,
pcmdinfo->in.u.ceq_create.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_AEQ_CREATE:
status = irdma_sc_aeq_create(pcmdinfo->in.u.aeq_create.aeq,
pcmdinfo->in.u.aeq_create.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_QP_UPLOAD_CONTEXT:
status = irdma_sc_qp_upload_context(pcmdinfo->in.u.qp_upload_context.dev,
&pcmdinfo->in.u.qp_upload_context.info,
pcmdinfo->in.u.qp_upload_context.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_CQ_CREATE:
status = irdma_sc_cq_create(pcmdinfo->in.u.cq_create.cq,
pcmdinfo->in.u.cq_create.scratch,
pcmdinfo->in.u.cq_create.check_overflow,
pcmdinfo->post_sq); break; case IRDMA_OP_CQ_MODIFY:
status = irdma_sc_cq_modify(pcmdinfo->in.u.cq_modify.cq,
&pcmdinfo->in.u.cq_modify.info,
pcmdinfo->in.u.cq_modify.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_CQ_DESTROY:
status = irdma_sc_cq_destroy(pcmdinfo->in.u.cq_destroy.cq,
pcmdinfo->in.u.cq_destroy.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_QP_FLUSH_WQES:
status = irdma_sc_qp_flush_wqes(pcmdinfo->in.u.qp_flush_wqes.qp,
&pcmdinfo->in.u.qp_flush_wqes.info,
pcmdinfo->in.u.qp_flush_wqes.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_GEN_AE:
status = irdma_sc_gen_ae(pcmdinfo->in.u.gen_ae.qp,
&pcmdinfo->in.u.gen_ae.info,
pcmdinfo->in.u.gen_ae.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_MANAGE_PUSH_PAGE:
status = irdma_sc_manage_push_page(pcmdinfo->in.u.manage_push_page.cqp,
&pcmdinfo->in.u.manage_push_page.info,
pcmdinfo->in.u.manage_push_page.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_UPDATE_PE_SDS:
status = irdma_update_pe_sds(pcmdinfo->in.u.update_pe_sds.dev,
&pcmdinfo->in.u.update_pe_sds.info,
pcmdinfo->in.u.update_pe_sds.scratch); break; case IRDMA_OP_MANAGE_HMC_PM_FUNC_TABLE: /* switch to calling through the call table */
status =
irdma_sc_manage_hmc_pm_func_table(pcmdinfo->in.u.manage_hmc_pm.dev->cqp,
&pcmdinfo->in.u.manage_hmc_pm.info,
pcmdinfo->in.u.manage_hmc_pm.scratch, true); break; case IRDMA_OP_SUSPEND:
status = irdma_sc_suspend_qp(pcmdinfo->in.u.suspend_resume.cqp,
pcmdinfo->in.u.suspend_resume.qp,
pcmdinfo->in.u.suspend_resume.scratch); break; case IRDMA_OP_RESUME:
status = irdma_sc_resume_qp(pcmdinfo->in.u.suspend_resume.cqp,
pcmdinfo->in.u.suspend_resume.qp,
pcmdinfo->in.u.suspend_resume.scratch); break; case IRDMA_OP_QUERY_FPM_VAL:
val_mem.pa = pcmdinfo->in.u.query_fpm_val.fpm_val_pa;
val_mem.va = pcmdinfo->in.u.query_fpm_val.fpm_val_va;
status = irdma_sc_query_fpm_val(pcmdinfo->in.u.query_fpm_val.cqp,
pcmdinfo->in.u.query_fpm_val.scratch,
pcmdinfo->in.u.query_fpm_val.hmc_fn_id,
&val_mem, true, IRDMA_CQP_WAIT_EVENT); break; case IRDMA_OP_COMMIT_FPM_VAL:
val_mem.pa = pcmdinfo->in.u.commit_fpm_val.fpm_val_pa;
val_mem.va = pcmdinfo->in.u.commit_fpm_val.fpm_val_va;
status = irdma_sc_commit_fpm_val(pcmdinfo->in.u.commit_fpm_val.cqp,
pcmdinfo->in.u.commit_fpm_val.scratch,
pcmdinfo->in.u.commit_fpm_val.hmc_fn_id,
&val_mem, true,
IRDMA_CQP_WAIT_EVENT); break; case IRDMA_OP_STATS_ALLOCATE:
alloc = true;
fallthrough; case IRDMA_OP_STATS_FREE:
status = irdma_sc_manage_stats_inst(pcmdinfo->in.u.stats_manage.cqp,
&pcmdinfo->in.u.stats_manage.info,
alloc,
pcmdinfo->in.u.stats_manage.scratch); break; case IRDMA_OP_STATS_GATHER:
status = irdma_sc_gather_stats(pcmdinfo->in.u.stats_gather.cqp,
&pcmdinfo->in.u.stats_gather.info,
pcmdinfo->in.u.stats_gather.scratch); break; case IRDMA_OP_WS_MODIFY_NODE:
status = irdma_sc_manage_ws_node(pcmdinfo->in.u.ws_node.cqp,
&pcmdinfo->in.u.ws_node.info,
IRDMA_MODIFY_NODE,
pcmdinfo->in.u.ws_node.scratch); break; case IRDMA_OP_WS_DELETE_NODE:
status = irdma_sc_manage_ws_node(pcmdinfo->in.u.ws_node.cqp,
&pcmdinfo->in.u.ws_node.info,
IRDMA_DEL_NODE,
pcmdinfo->in.u.ws_node.scratch); break; case IRDMA_OP_WS_ADD_NODE:
status = irdma_sc_manage_ws_node(pcmdinfo->in.u.ws_node.cqp,
&pcmdinfo->in.u.ws_node.info,
IRDMA_ADD_NODE,
pcmdinfo->in.u.ws_node.scratch); break; case IRDMA_OP_SET_UP_MAP:
status = irdma_sc_set_up_map(pcmdinfo->in.u.up_map.cqp,
&pcmdinfo->in.u.up_map.info,
pcmdinfo->in.u.up_map.scratch); break; case IRDMA_OP_QUERY_RDMA_FEATURES:
status = irdma_sc_query_rdma_features(pcmdinfo->in.u.query_rdma.cqp,
&pcmdinfo->in.u.query_rdma.query_buff_mem,
pcmdinfo->in.u.query_rdma.scratch); break; case IRDMA_OP_DELETE_ARP_CACHE_ENTRY:
status = irdma_sc_del_arp_cache_entry(pcmdinfo->in.u.del_arp_cache_entry.cqp,
pcmdinfo->in.u.del_arp_cache_entry.scratch,
pcmdinfo->in.u.del_arp_cache_entry.arp_index,
pcmdinfo->post_sq); break; case IRDMA_OP_MANAGE_APBVT_ENTRY:
status = irdma_sc_manage_apbvt_entry(pcmdinfo->in.u.manage_apbvt_entry.cqp,
&pcmdinfo->in.u.manage_apbvt_entry.info,
pcmdinfo->in.u.manage_apbvt_entry.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY:
status = irdma_sc_manage_qhash_table_entry(pcmdinfo->in.u.manage_qhash_table_entry.cqp,
&pcmdinfo->in.u.manage_qhash_table_entry.info,
pcmdinfo->in.u.manage_qhash_table_entry.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_QP_MODIFY:
status = irdma_sc_qp_modify(pcmdinfo->in.u.qp_modify.qp,
&pcmdinfo->in.u.qp_modify.info,
pcmdinfo->in.u.qp_modify.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_QP_CREATE:
status = irdma_sc_qp_create(pcmdinfo->in.u.qp_create.qp,
&pcmdinfo->in.u.qp_create.info,
pcmdinfo->in.u.qp_create.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_QP_DESTROY:
status = irdma_sc_qp_destroy(pcmdinfo->in.u.qp_destroy.qp,
pcmdinfo->in.u.qp_destroy.scratch,
pcmdinfo->in.u.qp_destroy.remove_hash_idx,
pcmdinfo->in.u.qp_destroy.ignore_mw_bnd,
pcmdinfo->post_sq); break; case IRDMA_OP_ALLOC_STAG:
status = irdma_sc_alloc_stag(pcmdinfo->in.u.alloc_stag.dev,
&pcmdinfo->in.u.alloc_stag.info,
pcmdinfo->in.u.alloc_stag.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_MR_REG_NON_SHARED:
status = irdma_sc_mr_reg_non_shared(pcmdinfo->in.u.mr_reg_non_shared.dev,
&pcmdinfo->in.u.mr_reg_non_shared.info,
pcmdinfo->in.u.mr_reg_non_shared.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_DEALLOC_STAG:
status = irdma_sc_dealloc_stag(pcmdinfo->in.u.dealloc_stag.dev,
&pcmdinfo->in.u.dealloc_stag.info,
pcmdinfo->in.u.dealloc_stag.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_MW_ALLOC:
status = irdma_sc_mw_alloc(pcmdinfo->in.u.mw_alloc.dev,
&pcmdinfo->in.u.mw_alloc.info,
pcmdinfo->in.u.mw_alloc.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_ADD_ARP_CACHE_ENTRY:
status = irdma_sc_add_arp_cache_entry(pcmdinfo->in.u.add_arp_cache_entry.cqp,
&pcmdinfo->in.u.add_arp_cache_entry.info,
pcmdinfo->in.u.add_arp_cache_entry.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY:
status = irdma_sc_alloc_local_mac_entry(pcmdinfo->in.u.alloc_local_mac_entry.cqp,
pcmdinfo->in.u.alloc_local_mac_entry.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_ADD_LOCAL_MAC_ENTRY:
status = irdma_sc_add_local_mac_entry(pcmdinfo->in.u.add_local_mac_entry.cqp,
&pcmdinfo->in.u.add_local_mac_entry.info,
pcmdinfo->in.u.add_local_mac_entry.scratch,
pcmdinfo->post_sq); break; case IRDMA_OP_DELETE_LOCAL_MAC_ENTRY:
status = irdma_sc_del_local_mac_entry(pcmdinfo->in.u.del_local_mac_entry.cqp,
pcmdinfo->in.u.del_local_mac_entry.scratch,
pcmdinfo->in.u.del_local_mac_entry.entry_idx,
pcmdinfo->in.u.del_local_mac_entry.ignore_ref_count,
pcmdinfo->post_sq); break; case IRDMA_OP_AH_CREATE:
status = irdma_sc_create_ah(pcmdinfo->in.u.ah_create.cqp,
&pcmdinfo->in.u.ah_create.info,
pcmdinfo->in.u.ah_create.scratch); break; case IRDMA_OP_AH_DESTROY:
status = irdma_sc_destroy_ah(pcmdinfo->in.u.ah_destroy.cqp,
&pcmdinfo->in.u.ah_destroy.info,
pcmdinfo->in.u.ah_destroy.scratch); break; case IRDMA_OP_MC_CREATE:
status = irdma_sc_create_mcast_grp(pcmdinfo->in.u.mc_create.cqp,
&pcmdinfo->in.u.mc_create.info,
pcmdinfo->in.u.mc_create.scratch); break; case IRDMA_OP_MC_DESTROY:
status = irdma_sc_destroy_mcast_grp(pcmdinfo->in.u.mc_destroy.cqp,
&pcmdinfo->in.u.mc_destroy.info,
pcmdinfo->in.u.mc_destroy.scratch); break; case IRDMA_OP_MC_MODIFY:
status = irdma_sc_modify_mcast_grp(pcmdinfo->in.u.mc_modify.cqp,
&pcmdinfo->in.u.mc_modify.info,
pcmdinfo->in.u.mc_modify.scratch); break; default:
status = -EOPNOTSUPP; break;
}
return status;
}
/** * irdma_process_cqp_cmd - process all cqp commands * @dev: sc device struct * @pcmdinfo: cqp command info
*/ int irdma_process_cqp_cmd(struct irdma_sc_dev *dev, struct cqp_cmds_info *pcmdinfo)
{ int status = 0; unsignedlong flags;
spin_lock_irqsave(&dev->cqp_lock, flags); if (list_empty(&dev->cqp_cmd_head) && !irdma_cqp_ring_full(dev->cqp))
status = irdma_exec_cqp_cmd(dev, pcmdinfo); else
list_add_tail(&pcmdinfo->cqp_cmd_entry, &dev->cqp_cmd_head);
spin_unlock_irqrestore(&dev->cqp_lock, flags); return status;
}
/** * irdma_process_bh - called from tasklet for cqp list * @dev: sc device struct
*/ int irdma_process_bh(struct irdma_sc_dev *dev)
{ int status = 0; struct cqp_cmds_info *pcmdinfo; unsignedlong flags;
spin_lock_irqsave(&dev->cqp_lock, flags); while (!list_empty(&dev->cqp_cmd_head) &&
!irdma_cqp_ring_full(dev->cqp)) {
pcmdinfo = (struct cqp_cmds_info *)irdma_remove_cqp_head(dev);
status = irdma_exec_cqp_cmd(dev, pcmdinfo); if (status) break;
}
spin_unlock_irqrestore(&dev->cqp_lock, flags); return status;
}
/** * irdma_cfg_aeq- Configure AEQ interrupt * @dev: pointer to the device structure * @idx: vector index * @enable: True to enable, False disables
*/ void irdma_cfg_aeq(struct irdma_sc_dev *dev, u32 idx, bool enable)
{
u32 reg_val;
val = readl(dev->hw_regs[IRDMA_GLPCI_LBARCTRL]);
db_size = (u8)FIELD_GET(IRDMA_GLPCI_LBARCTRL_PE_DB_SIZE, val); if (db_size != IRDMA_PE_DB_SIZE_4M && db_size != IRDMA_PE_DB_SIZE_8M) {
ibdev_dbg(to_ibdev(dev), "DEV: RDMA PE doorbell is not enabled in CSR val 0x%x db_size=%d\n",
val, db_size); return -ENODEV;
}
dev->db_addr = dev->hw->hw_addr + (uintptr_t)dev->hw_regs[IRDMA_DB_ADDR_OFFSET];
return ret_code;
}
/** * irdma_stat_val - Extract HW counter value from statistics buffer * @stats_val: pointer to statistics buffer * @byteoff: byte offset of counter value in the buffer (8B-aligned) * @bitoff: bit offset of counter value within 8B entry * @bitmask: maximum counter value (e.g. 0xffffff for 24-bit counter)
*/ staticinline u64 irdma_stat_val(const u64 *stats_val, u16 byteoff, u8 bitoff,
u64 bitmask)
{
u16 idx = byteoff / sizeof(*stats_val);
return (stats_val[idx] >> bitoff) & bitmask;
}
/** * irdma_stat_delta - Calculate counter delta * @new_val: updated counter value * @old_val: last counter value * @max_val: maximum counter value (e.g. 0xffffff for 24-bit counter)
*/ staticinline u64 irdma_stat_delta(u64 new_val, u64 old_val, u64 max_val)
{ if (new_val >= old_val) return new_val - old_val;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.