162306a36Sopenharmony_ci/* This file is part of the Emulex RoCE Device Driver for
262306a36Sopenharmony_ci * RoCE (RDMA over Converged Ethernet) adapters.
362306a36Sopenharmony_ci * Copyright (C) 2012-2015 Emulex. All rights reserved.
462306a36Sopenharmony_ci * EMULEX and SLI are trademarks of Emulex.
562306a36Sopenharmony_ci * www.emulex.com
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * This software is available to you under a choice of one of two licenses.
862306a36Sopenharmony_ci * You may choose to be licensed under the terms of the GNU General Public
962306a36Sopenharmony_ci * License (GPL) Version 2, available from the file COPYING in the main
1062306a36Sopenharmony_ci * directory of this source tree, or the BSD license below:
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
1362306a36Sopenharmony_ci * modification, are permitted provided that the following conditions
1462306a36Sopenharmony_ci * are met:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * - Redistributions of source code must retain the above copyright notice,
1762306a36Sopenharmony_ci *   this list of conditions and the following disclaimer.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above copyright
2062306a36Sopenharmony_ci *   notice, this list of conditions and the following disclaimer in
2162306a36Sopenharmony_ci *   the documentation and/or other materials provided with the distribution.
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2462306a36Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
2562306a36Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2662306a36Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2762306a36Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2862306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2962306a36Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3062306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3162306a36Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3262306a36Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3362306a36Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * Contact Information:
3662306a36Sopenharmony_ci * linux-drivers@emulex.com
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * Emulex
3962306a36Sopenharmony_ci * 3333 Susan Street
4062306a36Sopenharmony_ci * Costa Mesa, CA 92626
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#include <linux/sched.h>
4462306a36Sopenharmony_ci#include <linux/interrupt.h>
4562306a36Sopenharmony_ci#include <linux/log2.h>
4662306a36Sopenharmony_ci#include <linux/dma-mapping.h>
4762306a36Sopenharmony_ci#include <linux/if_ether.h>
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#include <rdma/ib_verbs.h>
5062306a36Sopenharmony_ci#include <rdma/ib_user_verbs.h>
5162306a36Sopenharmony_ci#include <rdma/ib_cache.h>
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#include "ocrdma.h"
5462306a36Sopenharmony_ci#include "ocrdma_hw.h"
5562306a36Sopenharmony_ci#include "ocrdma_verbs.h"
5662306a36Sopenharmony_ci#include "ocrdma_ah.h"
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cienum mbx_status {
5962306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_FAILED		= 1,
6062306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_ILLEGAL_FIELD		= 3,
6162306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_OOR			= 100,
6262306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_PD		= 101,
6362306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_PD_INUSE		= 102,
6462306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_CQ		= 103,
6562306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_QP		= 104,
6662306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_LKEY		= 105,
6762306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_ORD_EXCEEDS		= 106,
6862306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_IRD_EXCEEDS		= 107,
6962306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SENDQ_WQE_EXCEEDS	= 108,
7062306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_RECVQ_RQE_EXCEEDS	= 109,
7162306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SGE_SEND_EXCEEDS	= 110,
7262306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SGE_WRITE_EXCEEDS	= 111,
7362306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SGE_RECV_EXCEEDS	= 112,
7462306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_STATE_CHANGE	= 113,
7562306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_MW_BOUND		= 114,
7662306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_VA		= 115,
7762306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_LENGTH	= 116,
7862306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_FBO		= 117,
7962306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_ACC_RIGHTS	= 118,
8062306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_PBE_SIZE	= 119,
8162306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_PBL_ENTRY	= 120,
8262306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_PBL_SHIFT	= 121,
8362306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_SRQ_ID	= 129,
8462306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SRQ_ERROR		= 133,
8562306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_RQE_EXCEEDS		= 134,
8662306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_MTU_EXCEEDS		= 135,
8762306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_MAX_QP_EXCEEDS	= 136,
8862306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SRQ_LIMIT_EXCEEDS	= 137,
8962306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_SRQ_SIZE_UNDERUNS	= 138,
9062306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_QP_BOUND		= 130,
9162306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_CHANGE	= 139,
9262306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_ATOMIC_OPS_UNSUP	= 140,
9362306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_INVALID_RNR_NAK_TIMER	= 141,
9462306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_MW_STILL_BOUND	= 142,
9562306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_PKEY_INDEX_INVALID	= 143,
9662306a36Sopenharmony_ci	OCRDMA_MBX_STATUS_PKEY_INDEX_EXCEEDS	= 144
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cienum additional_status {
10062306a36Sopenharmony_ci	OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES = 22
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cienum cqe_status {
10462306a36Sopenharmony_ci	OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_PRIVILEDGES	= 1,
10562306a36Sopenharmony_ci	OCRDMA_MBX_CQE_STATUS_INVALID_PARAMETER		= 2,
10662306a36Sopenharmony_ci	OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_RESOURCES	= 3,
10762306a36Sopenharmony_ci	OCRDMA_MBX_CQE_STATUS_QUEUE_FLUSHING		= 4,
10862306a36Sopenharmony_ci	OCRDMA_MBX_CQE_STATUS_DMA_FAILED		= 5
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic inline void *ocrdma_get_eqe(struct ocrdma_eq *eq)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	return eq->q.va + (eq->q.tail * sizeof(struct ocrdma_eqe));
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic inline void ocrdma_eq_inc_tail(struct ocrdma_eq *eq)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	eq->q.tail = (eq->q.tail + 1) & (OCRDMA_EQ_LEN - 1);
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic inline void *ocrdma_get_mcqe(struct ocrdma_dev *dev)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	struct ocrdma_mcqe *cqe = (struct ocrdma_mcqe *)
12462306a36Sopenharmony_ci	    (dev->mq.cq.va + (dev->mq.cq.tail * sizeof(struct ocrdma_mcqe)));
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (!(le32_to_cpu(cqe->valid_ae_cmpl_cons) & OCRDMA_MCQE_VALID_MASK))
12762306a36Sopenharmony_ci		return NULL;
12862306a36Sopenharmony_ci	return cqe;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic inline void ocrdma_mcq_inc_tail(struct ocrdma_dev *dev)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	dev->mq.cq.tail = (dev->mq.cq.tail + 1) & (OCRDMA_MQ_CQ_LEN - 1);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic inline struct ocrdma_mqe *ocrdma_get_mqe(struct ocrdma_dev *dev)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	return dev->mq.sq.va + (dev->mq.sq.head * sizeof(struct ocrdma_mqe));
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic inline void ocrdma_mq_inc_head(struct ocrdma_dev *dev)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	dev->mq.sq.head = (dev->mq.sq.head + 1) & (OCRDMA_MQ_LEN - 1);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline void *ocrdma_get_mqe_rsp(struct ocrdma_dev *dev)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	return dev->mq.sq.va + (dev->mqe_ctx.tag * sizeof(struct ocrdma_mqe));
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cienum ib_qp_state get_ibqp_state(enum ocrdma_qp_state qps)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	switch (qps) {
15462306a36Sopenharmony_ci	case OCRDMA_QPS_RST:
15562306a36Sopenharmony_ci		return IB_QPS_RESET;
15662306a36Sopenharmony_ci	case OCRDMA_QPS_INIT:
15762306a36Sopenharmony_ci		return IB_QPS_INIT;
15862306a36Sopenharmony_ci	case OCRDMA_QPS_RTR:
15962306a36Sopenharmony_ci		return IB_QPS_RTR;
16062306a36Sopenharmony_ci	case OCRDMA_QPS_RTS:
16162306a36Sopenharmony_ci		return IB_QPS_RTS;
16262306a36Sopenharmony_ci	case OCRDMA_QPS_SQD:
16362306a36Sopenharmony_ci	case OCRDMA_QPS_SQ_DRAINING:
16462306a36Sopenharmony_ci		return IB_QPS_SQD;
16562306a36Sopenharmony_ci	case OCRDMA_QPS_SQE:
16662306a36Sopenharmony_ci		return IB_QPS_SQE;
16762306a36Sopenharmony_ci	case OCRDMA_QPS_ERR:
16862306a36Sopenharmony_ci		return IB_QPS_ERR;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	return IB_QPS_ERR;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic enum ocrdma_qp_state get_ocrdma_qp_state(enum ib_qp_state qps)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	switch (qps) {
17662306a36Sopenharmony_ci	case IB_QPS_RESET:
17762306a36Sopenharmony_ci		return OCRDMA_QPS_RST;
17862306a36Sopenharmony_ci	case IB_QPS_INIT:
17962306a36Sopenharmony_ci		return OCRDMA_QPS_INIT;
18062306a36Sopenharmony_ci	case IB_QPS_RTR:
18162306a36Sopenharmony_ci		return OCRDMA_QPS_RTR;
18262306a36Sopenharmony_ci	case IB_QPS_RTS:
18362306a36Sopenharmony_ci		return OCRDMA_QPS_RTS;
18462306a36Sopenharmony_ci	case IB_QPS_SQD:
18562306a36Sopenharmony_ci		return OCRDMA_QPS_SQD;
18662306a36Sopenharmony_ci	case IB_QPS_SQE:
18762306a36Sopenharmony_ci		return OCRDMA_QPS_SQE;
18862306a36Sopenharmony_ci	case IB_QPS_ERR:
18962306a36Sopenharmony_ci		return OCRDMA_QPS_ERR;
19062306a36Sopenharmony_ci	}
19162306a36Sopenharmony_ci	return OCRDMA_QPS_ERR;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic int ocrdma_get_mbx_errno(u32 status)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	int err_num;
19762306a36Sopenharmony_ci	u8 mbox_status = (status & OCRDMA_MBX_RSP_STATUS_MASK) >>
19862306a36Sopenharmony_ci					OCRDMA_MBX_RSP_STATUS_SHIFT;
19962306a36Sopenharmony_ci	u8 add_status = (status & OCRDMA_MBX_RSP_ASTATUS_MASK) >>
20062306a36Sopenharmony_ci					OCRDMA_MBX_RSP_ASTATUS_SHIFT;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	switch (mbox_status) {
20362306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_OOR:
20462306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_MAX_QP_EXCEEDS:
20562306a36Sopenharmony_ci		err_num = -EAGAIN;
20662306a36Sopenharmony_ci		break;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_PD:
20962306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_CQ:
21062306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_SRQ_ID:
21162306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_QP:
21262306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_CHANGE:
21362306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_MTU_EXCEEDS:
21462306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_RNR_NAK_TIMER:
21562306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_PKEY_INDEX_INVALID:
21662306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_PKEY_INDEX_EXCEEDS:
21762306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_ILLEGAL_FIELD:
21862306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_PBL_ENTRY:
21962306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_LKEY:
22062306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_VA:
22162306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_LENGTH:
22262306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_FBO:
22362306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_ACC_RIGHTS:
22462306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_INVALID_PBE_SIZE:
22562306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_ATOMIC_OPS_UNSUP:
22662306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SRQ_ERROR:
22762306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SRQ_SIZE_UNDERUNS:
22862306a36Sopenharmony_ci		err_num = -EINVAL;
22962306a36Sopenharmony_ci		break;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_PD_INUSE:
23262306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_QP_BOUND:
23362306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_MW_STILL_BOUND:
23462306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_MW_BOUND:
23562306a36Sopenharmony_ci		err_num = -EBUSY;
23662306a36Sopenharmony_ci		break;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_RECVQ_RQE_EXCEEDS:
23962306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SGE_RECV_EXCEEDS:
24062306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_RQE_EXCEEDS:
24162306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SRQ_LIMIT_EXCEEDS:
24262306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_ORD_EXCEEDS:
24362306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_IRD_EXCEEDS:
24462306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SENDQ_WQE_EXCEEDS:
24562306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SGE_SEND_EXCEEDS:
24662306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_SGE_WRITE_EXCEEDS:
24762306a36Sopenharmony_ci		err_num = -ENOBUFS;
24862306a36Sopenharmony_ci		break;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	case OCRDMA_MBX_STATUS_FAILED:
25162306a36Sopenharmony_ci		switch (add_status) {
25262306a36Sopenharmony_ci		case OCRDMA_MBX_ADDI_STATUS_INSUFFICIENT_RESOURCES:
25362306a36Sopenharmony_ci			err_num = -EAGAIN;
25462306a36Sopenharmony_ci			break;
25562306a36Sopenharmony_ci		default:
25662306a36Sopenharmony_ci			err_num = -EFAULT;
25762306a36Sopenharmony_ci		}
25862306a36Sopenharmony_ci		break;
25962306a36Sopenharmony_ci	default:
26062306a36Sopenharmony_ci		err_num = -EFAULT;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci	return err_num;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cichar *port_speed_string(struct ocrdma_dev *dev)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	char *str = "";
26862306a36Sopenharmony_ci	u16 speeds_supported;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	speeds_supported = dev->phy.fixed_speeds_supported |
27162306a36Sopenharmony_ci				dev->phy.auto_speeds_supported;
27262306a36Sopenharmony_ci	if (speeds_supported & OCRDMA_PHY_SPEED_40GBPS)
27362306a36Sopenharmony_ci		str = "40Gbps ";
27462306a36Sopenharmony_ci	else if (speeds_supported & OCRDMA_PHY_SPEED_10GBPS)
27562306a36Sopenharmony_ci		str = "10Gbps ";
27662306a36Sopenharmony_ci	else if (speeds_supported & OCRDMA_PHY_SPEED_1GBPS)
27762306a36Sopenharmony_ci		str = "1Gbps ";
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	return str;
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistatic int ocrdma_get_mbx_cqe_errno(u16 cqe_status)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	int err_num = -EINVAL;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	switch (cqe_status) {
28762306a36Sopenharmony_ci	case OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_PRIVILEDGES:
28862306a36Sopenharmony_ci		err_num = -EPERM;
28962306a36Sopenharmony_ci		break;
29062306a36Sopenharmony_ci	case OCRDMA_MBX_CQE_STATUS_INVALID_PARAMETER:
29162306a36Sopenharmony_ci		err_num = -EINVAL;
29262306a36Sopenharmony_ci		break;
29362306a36Sopenharmony_ci	case OCRDMA_MBX_CQE_STATUS_INSUFFICIENT_RESOURCES:
29462306a36Sopenharmony_ci	case OCRDMA_MBX_CQE_STATUS_QUEUE_FLUSHING:
29562306a36Sopenharmony_ci		err_num = -EINVAL;
29662306a36Sopenharmony_ci		break;
29762306a36Sopenharmony_ci	case OCRDMA_MBX_CQE_STATUS_DMA_FAILED:
29862306a36Sopenharmony_ci	default:
29962306a36Sopenharmony_ci		err_num = -EINVAL;
30062306a36Sopenharmony_ci		break;
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci	return err_num;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_civoid ocrdma_ring_cq_db(struct ocrdma_dev *dev, u16 cq_id, bool armed,
30662306a36Sopenharmony_ci		       bool solicited, u16 cqe_popped)
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	u32 val = cq_id & OCRDMA_DB_CQ_RING_ID_MASK;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	val |= ((cq_id & OCRDMA_DB_CQ_RING_ID_EXT_MASK) <<
31162306a36Sopenharmony_ci	     OCRDMA_DB_CQ_RING_ID_EXT_MASK_SHIFT);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	if (armed)
31462306a36Sopenharmony_ci		val |= (1 << OCRDMA_DB_CQ_REARM_SHIFT);
31562306a36Sopenharmony_ci	if (solicited)
31662306a36Sopenharmony_ci		val |= (1 << OCRDMA_DB_CQ_SOLICIT_SHIFT);
31762306a36Sopenharmony_ci	val |= (cqe_popped << OCRDMA_DB_CQ_NUM_POPPED_SHIFT);
31862306a36Sopenharmony_ci	iowrite32(val, dev->nic_info.db + OCRDMA_DB_CQ_OFFSET);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic void ocrdma_ring_mq_db(struct ocrdma_dev *dev)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	u32 val = 0;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	val |= dev->mq.sq.id & OCRDMA_MQ_ID_MASK;
32662306a36Sopenharmony_ci	val |= 1 << OCRDMA_MQ_NUM_MQE_SHIFT;
32762306a36Sopenharmony_ci	iowrite32(val, dev->nic_info.db + OCRDMA_DB_MQ_OFFSET);
32862306a36Sopenharmony_ci}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_cistatic void ocrdma_ring_eq_db(struct ocrdma_dev *dev, u16 eq_id,
33162306a36Sopenharmony_ci			      bool arm, bool clear_int, u16 num_eqe)
33262306a36Sopenharmony_ci{
33362306a36Sopenharmony_ci	u32 val = 0;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	val |= eq_id & OCRDMA_EQ_ID_MASK;
33662306a36Sopenharmony_ci	val |= ((eq_id & OCRDMA_EQ_ID_EXT_MASK) << OCRDMA_EQ_ID_EXT_MASK_SHIFT);
33762306a36Sopenharmony_ci	if (arm)
33862306a36Sopenharmony_ci		val |= (1 << OCRDMA_REARM_SHIFT);
33962306a36Sopenharmony_ci	if (clear_int)
34062306a36Sopenharmony_ci		val |= (1 << OCRDMA_EQ_CLR_SHIFT);
34162306a36Sopenharmony_ci	val |= (1 << OCRDMA_EQ_TYPE_SHIFT);
34262306a36Sopenharmony_ci	val |= (num_eqe << OCRDMA_NUM_EQE_SHIFT);
34362306a36Sopenharmony_ci	iowrite32(val, dev->nic_info.db + OCRDMA_DB_EQ_OFFSET);
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic void ocrdma_init_mch(struct ocrdma_mbx_hdr *cmd_hdr,
34762306a36Sopenharmony_ci			    u8 opcode, u8 subsys, u32 cmd_len)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	cmd_hdr->subsys_op = (opcode | (subsys << OCRDMA_MCH_SUBSYS_SHIFT));
35062306a36Sopenharmony_ci	cmd_hdr->timeout = 20; /* seconds */
35162306a36Sopenharmony_ci	cmd_hdr->cmd_len = cmd_len - sizeof(struct ocrdma_mbx_hdr);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic void *ocrdma_init_emb_mqe(u8 opcode, u32 cmd_len)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct ocrdma_mqe *mqe;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	mqe = kzalloc(sizeof(struct ocrdma_mqe), GFP_KERNEL);
35962306a36Sopenharmony_ci	if (!mqe)
36062306a36Sopenharmony_ci		return NULL;
36162306a36Sopenharmony_ci	mqe->hdr.spcl_sge_cnt_emb |=
36262306a36Sopenharmony_ci		(OCRDMA_MQE_EMBEDDED << OCRDMA_MQE_HDR_EMB_SHIFT) &
36362306a36Sopenharmony_ci					OCRDMA_MQE_HDR_EMB_MASK;
36462306a36Sopenharmony_ci	mqe->hdr.pyld_len = cmd_len - sizeof(struct ocrdma_mqe_hdr);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	ocrdma_init_mch(&mqe->u.emb_req.mch, opcode, OCRDMA_SUBSYS_ROCE,
36762306a36Sopenharmony_ci			mqe->hdr.pyld_len);
36862306a36Sopenharmony_ci	return mqe;
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic void ocrdma_free_q(struct ocrdma_dev *dev, struct ocrdma_queue_info *q)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	dma_free_coherent(&dev->nic_info.pdev->dev, q->size, q->va, q->dma);
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_cistatic int ocrdma_alloc_q(struct ocrdma_dev *dev,
37762306a36Sopenharmony_ci			  struct ocrdma_queue_info *q, u16 len, u16 entry_size)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	memset(q, 0, sizeof(*q));
38062306a36Sopenharmony_ci	q->len = len;
38162306a36Sopenharmony_ci	q->entry_size = entry_size;
38262306a36Sopenharmony_ci	q->size = len * entry_size;
38362306a36Sopenharmony_ci	q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size, &q->dma,
38462306a36Sopenharmony_ci				   GFP_KERNEL);
38562306a36Sopenharmony_ci	if (!q->va)
38662306a36Sopenharmony_ci		return -ENOMEM;
38762306a36Sopenharmony_ci	return 0;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic void ocrdma_build_q_pages(struct ocrdma_pa *q_pa, int cnt,
39162306a36Sopenharmony_ci					dma_addr_t host_pa, int hw_page_size)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	int i;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	for (i = 0; i < cnt; i++) {
39662306a36Sopenharmony_ci		q_pa[i].lo = (u32) (host_pa & 0xffffffff);
39762306a36Sopenharmony_ci		q_pa[i].hi = (u32) upper_32_bits(host_pa);
39862306a36Sopenharmony_ci		host_pa += hw_page_size;
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic int ocrdma_mbx_delete_q(struct ocrdma_dev *dev,
40362306a36Sopenharmony_ci			       struct ocrdma_queue_info *q, int queue_type)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	u8 opcode = 0;
40662306a36Sopenharmony_ci	int status;
40762306a36Sopenharmony_ci	struct ocrdma_delete_q_req *cmd = dev->mbx_cmd;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	switch (queue_type) {
41062306a36Sopenharmony_ci	case QTYPE_MCCQ:
41162306a36Sopenharmony_ci		opcode = OCRDMA_CMD_DELETE_MQ;
41262306a36Sopenharmony_ci		break;
41362306a36Sopenharmony_ci	case QTYPE_CQ:
41462306a36Sopenharmony_ci		opcode = OCRDMA_CMD_DELETE_CQ;
41562306a36Sopenharmony_ci		break;
41662306a36Sopenharmony_ci	case QTYPE_EQ:
41762306a36Sopenharmony_ci		opcode = OCRDMA_CMD_DELETE_EQ;
41862306a36Sopenharmony_ci		break;
41962306a36Sopenharmony_ci	default:
42062306a36Sopenharmony_ci		BUG();
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci	memset(cmd, 0, sizeof(*cmd));
42362306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->req, opcode, OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
42462306a36Sopenharmony_ci	cmd->id = q->id;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	status = be_roce_mcc_cmd(dev->nic_info.netdev,
42762306a36Sopenharmony_ci				 cmd, sizeof(*cmd), NULL, NULL);
42862306a36Sopenharmony_ci	if (!status)
42962306a36Sopenharmony_ci		q->created = false;
43062306a36Sopenharmony_ci	return status;
43162306a36Sopenharmony_ci}
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cistatic int ocrdma_mbx_create_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	int status;
43662306a36Sopenharmony_ci	struct ocrdma_create_eq_req *cmd = dev->mbx_cmd;
43762306a36Sopenharmony_ci	struct ocrdma_create_eq_rsp *rsp = dev->mbx_cmd;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	memset(cmd, 0, sizeof(*cmd));
44062306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_EQ, OCRDMA_SUBSYS_COMMON,
44162306a36Sopenharmony_ci			sizeof(*cmd));
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	cmd->req.rsvd_version = 2;
44462306a36Sopenharmony_ci	cmd->num_pages = 4;
44562306a36Sopenharmony_ci	cmd->valid = OCRDMA_CREATE_EQ_VALID;
44662306a36Sopenharmony_ci	cmd->cnt = 4 << OCRDMA_CREATE_EQ_CNT_SHIFT;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->pa[0], cmd->num_pages, eq->q.dma,
44962306a36Sopenharmony_ci			     PAGE_SIZE_4K);
45062306a36Sopenharmony_ci	status = be_roce_mcc_cmd(dev->nic_info.netdev, cmd, sizeof(*cmd), NULL,
45162306a36Sopenharmony_ci				 NULL);
45262306a36Sopenharmony_ci	if (!status) {
45362306a36Sopenharmony_ci		eq->q.id = rsp->vector_eqid & 0xffff;
45462306a36Sopenharmony_ci		eq->vector = (rsp->vector_eqid >> 16) & 0xffff;
45562306a36Sopenharmony_ci		eq->q.created = true;
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci	return status;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic int ocrdma_create_eq(struct ocrdma_dev *dev,
46162306a36Sopenharmony_ci			    struct ocrdma_eq *eq, u16 q_len)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	int status;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	status = ocrdma_alloc_q(dev, &eq->q, OCRDMA_EQ_LEN,
46662306a36Sopenharmony_ci				sizeof(struct ocrdma_eqe));
46762306a36Sopenharmony_ci	if (status)
46862306a36Sopenharmony_ci		return status;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	status = ocrdma_mbx_create_eq(dev, eq);
47162306a36Sopenharmony_ci	if (status)
47262306a36Sopenharmony_ci		goto mbx_err;
47362306a36Sopenharmony_ci	eq->dev = dev;
47462306a36Sopenharmony_ci	ocrdma_ring_eq_db(dev, eq->q.id, true, true, 0);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	return 0;
47762306a36Sopenharmony_cimbx_err:
47862306a36Sopenharmony_ci	ocrdma_free_q(dev, &eq->q);
47962306a36Sopenharmony_ci	return status;
48062306a36Sopenharmony_ci}
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ciint ocrdma_get_irq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci	int irq;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX)
48762306a36Sopenharmony_ci		irq = dev->nic_info.pdev->irq;
48862306a36Sopenharmony_ci	else
48962306a36Sopenharmony_ci		irq = dev->nic_info.msix.vector_list[eq->vector];
49062306a36Sopenharmony_ci	return irq;
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic void _ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	if (eq->q.created) {
49662306a36Sopenharmony_ci		ocrdma_mbx_delete_q(dev, &eq->q, QTYPE_EQ);
49762306a36Sopenharmony_ci		ocrdma_free_q(dev, &eq->q);
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic void ocrdma_destroy_eq(struct ocrdma_dev *dev, struct ocrdma_eq *eq)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	int irq;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	/* disarm EQ so that interrupts are not generated
50662306a36Sopenharmony_ci	 * during freeing and EQ delete is in progress.
50762306a36Sopenharmony_ci	 */
50862306a36Sopenharmony_ci	ocrdma_ring_eq_db(dev, eq->q.id, false, false, 0);
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	irq = ocrdma_get_irq(dev, eq);
51162306a36Sopenharmony_ci	free_irq(irq, eq);
51262306a36Sopenharmony_ci	_ocrdma_destroy_eq(dev, eq);
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic void ocrdma_destroy_eqs(struct ocrdma_dev *dev)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	int i;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	for (i = 0; i < dev->eq_cnt; i++)
52062306a36Sopenharmony_ci		ocrdma_destroy_eq(dev, &dev->eq_tbl[i]);
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int ocrdma_mbx_mq_cq_create(struct ocrdma_dev *dev,
52462306a36Sopenharmony_ci				   struct ocrdma_queue_info *cq,
52562306a36Sopenharmony_ci				   struct ocrdma_queue_info *eq)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	struct ocrdma_create_cq_cmd *cmd = dev->mbx_cmd;
52862306a36Sopenharmony_ci	struct ocrdma_create_cq_cmd_rsp *rsp = dev->mbx_cmd;
52962306a36Sopenharmony_ci	int status;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	memset(cmd, 0, sizeof(*cmd));
53262306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_CQ,
53362306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	cmd->req.rsvd_version = OCRDMA_CREATE_CQ_VER2;
53662306a36Sopenharmony_ci	cmd->pgsz_pgcnt = (cq->size / OCRDMA_MIN_Q_PAGE_SIZE) <<
53762306a36Sopenharmony_ci		OCRDMA_CREATE_CQ_PAGE_SIZE_SHIFT;
53862306a36Sopenharmony_ci	cmd->pgsz_pgcnt |= PAGES_4K_SPANNED(cq->va, cq->size);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	cmd->ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
54162306a36Sopenharmony_ci	cmd->eqn = eq->id;
54262306a36Sopenharmony_ci	cmd->pdid_cqecnt = cq->size / sizeof(struct ocrdma_mcqe);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->pa[0], cq->size / OCRDMA_MIN_Q_PAGE_SIZE,
54562306a36Sopenharmony_ci			     cq->dma, PAGE_SIZE_4K);
54662306a36Sopenharmony_ci	status = be_roce_mcc_cmd(dev->nic_info.netdev,
54762306a36Sopenharmony_ci				 cmd, sizeof(*cmd), NULL, NULL);
54862306a36Sopenharmony_ci	if (!status) {
54962306a36Sopenharmony_ci		cq->id = (u16) (rsp->cq_id & OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK);
55062306a36Sopenharmony_ci		cq->created = true;
55162306a36Sopenharmony_ci	}
55262306a36Sopenharmony_ci	return status;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_cistatic u32 ocrdma_encoded_q_len(int q_len)
55662306a36Sopenharmony_ci{
55762306a36Sopenharmony_ci	u32 len_encoded = fls(q_len);	/* log2(len) + 1 */
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	if (len_encoded == 16)
56062306a36Sopenharmony_ci		len_encoded = 0;
56162306a36Sopenharmony_ci	return len_encoded;
56262306a36Sopenharmony_ci}
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_cistatic int ocrdma_mbx_create_mq(struct ocrdma_dev *dev,
56562306a36Sopenharmony_ci				struct ocrdma_queue_info *mq,
56662306a36Sopenharmony_ci				struct ocrdma_queue_info *cq)
56762306a36Sopenharmony_ci{
56862306a36Sopenharmony_ci	int num_pages, status;
56962306a36Sopenharmony_ci	struct ocrdma_create_mq_req *cmd = dev->mbx_cmd;
57062306a36Sopenharmony_ci	struct ocrdma_create_mq_rsp *rsp = dev->mbx_cmd;
57162306a36Sopenharmony_ci	struct ocrdma_pa *pa;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	memset(cmd, 0, sizeof(*cmd));
57462306a36Sopenharmony_ci	num_pages = PAGES_4K_SPANNED(mq->va, mq->size);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->req, OCRDMA_CMD_CREATE_MQ_EXT,
57762306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
57862306a36Sopenharmony_ci	cmd->req.rsvd_version = 1;
57962306a36Sopenharmony_ci	cmd->cqid_pages = num_pages;
58062306a36Sopenharmony_ci	cmd->cqid_pages |= (cq->id << OCRDMA_CREATE_MQ_CQ_ID_SHIFT);
58162306a36Sopenharmony_ci	cmd->async_cqid_valid = OCRDMA_CREATE_MQ_ASYNC_CQ_VALID;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	cmd->async_event_bitmap = BIT(OCRDMA_ASYNC_GRP5_EVE_CODE);
58462306a36Sopenharmony_ci	cmd->async_event_bitmap |= BIT(OCRDMA_ASYNC_RDMA_EVE_CODE);
58562306a36Sopenharmony_ci	/* Request link events on this  MQ. */
58662306a36Sopenharmony_ci	cmd->async_event_bitmap |= BIT(OCRDMA_ASYNC_LINK_EVE_CODE);
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	cmd->async_cqid_ringsize = cq->id;
58962306a36Sopenharmony_ci	cmd->async_cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) <<
59062306a36Sopenharmony_ci				OCRDMA_CREATE_MQ_RING_SIZE_SHIFT);
59162306a36Sopenharmony_ci	cmd->valid = OCRDMA_CREATE_MQ_VALID;
59262306a36Sopenharmony_ci	pa = &cmd->pa[0];
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	ocrdma_build_q_pages(pa, num_pages, mq->dma, PAGE_SIZE_4K);
59562306a36Sopenharmony_ci	status = be_roce_mcc_cmd(dev->nic_info.netdev,
59662306a36Sopenharmony_ci				 cmd, sizeof(*cmd), NULL, NULL);
59762306a36Sopenharmony_ci	if (!status) {
59862306a36Sopenharmony_ci		mq->id = rsp->id;
59962306a36Sopenharmony_ci		mq->created = true;
60062306a36Sopenharmony_ci	}
60162306a36Sopenharmony_ci	return status;
60262306a36Sopenharmony_ci}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic int ocrdma_create_mq(struct ocrdma_dev *dev)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	int status;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	/* Alloc completion queue for Mailbox queue */
60962306a36Sopenharmony_ci	status = ocrdma_alloc_q(dev, &dev->mq.cq, OCRDMA_MQ_CQ_LEN,
61062306a36Sopenharmony_ci				sizeof(struct ocrdma_mcqe));
61162306a36Sopenharmony_ci	if (status)
61262306a36Sopenharmony_ci		goto alloc_err;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	dev->eq_tbl[0].cq_cnt++;
61562306a36Sopenharmony_ci	status = ocrdma_mbx_mq_cq_create(dev, &dev->mq.cq, &dev->eq_tbl[0].q);
61662306a36Sopenharmony_ci	if (status)
61762306a36Sopenharmony_ci		goto mbx_cq_free;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	memset(&dev->mqe_ctx, 0, sizeof(dev->mqe_ctx));
62062306a36Sopenharmony_ci	init_waitqueue_head(&dev->mqe_ctx.cmd_wait);
62162306a36Sopenharmony_ci	mutex_init(&dev->mqe_ctx.lock);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	/* Alloc Mailbox queue */
62462306a36Sopenharmony_ci	status = ocrdma_alloc_q(dev, &dev->mq.sq, OCRDMA_MQ_LEN,
62562306a36Sopenharmony_ci				sizeof(struct ocrdma_mqe));
62662306a36Sopenharmony_ci	if (status)
62762306a36Sopenharmony_ci		goto mbx_cq_destroy;
62862306a36Sopenharmony_ci	status = ocrdma_mbx_create_mq(dev, &dev->mq.sq, &dev->mq.cq);
62962306a36Sopenharmony_ci	if (status)
63062306a36Sopenharmony_ci		goto mbx_q_free;
63162306a36Sopenharmony_ci	ocrdma_ring_cq_db(dev, dev->mq.cq.id, true, false, 0);
63262306a36Sopenharmony_ci	return 0;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_cimbx_q_free:
63562306a36Sopenharmony_ci	ocrdma_free_q(dev, &dev->mq.sq);
63662306a36Sopenharmony_cimbx_cq_destroy:
63762306a36Sopenharmony_ci	ocrdma_mbx_delete_q(dev, &dev->mq.cq, QTYPE_CQ);
63862306a36Sopenharmony_cimbx_cq_free:
63962306a36Sopenharmony_ci	ocrdma_free_q(dev, &dev->mq.cq);
64062306a36Sopenharmony_cialloc_err:
64162306a36Sopenharmony_ci	return status;
64262306a36Sopenharmony_ci}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_cistatic void ocrdma_destroy_mq(struct ocrdma_dev *dev)
64562306a36Sopenharmony_ci{
64662306a36Sopenharmony_ci	struct ocrdma_queue_info *mbxq, *cq;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	/* mqe_ctx lock synchronizes with any other pending cmds. */
64962306a36Sopenharmony_ci	mutex_lock(&dev->mqe_ctx.lock);
65062306a36Sopenharmony_ci	mbxq = &dev->mq.sq;
65162306a36Sopenharmony_ci	if (mbxq->created) {
65262306a36Sopenharmony_ci		ocrdma_mbx_delete_q(dev, mbxq, QTYPE_MCCQ);
65362306a36Sopenharmony_ci		ocrdma_free_q(dev, mbxq);
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci	mutex_unlock(&dev->mqe_ctx.lock);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	cq = &dev->mq.cq;
65862306a36Sopenharmony_ci	if (cq->created) {
65962306a36Sopenharmony_ci		ocrdma_mbx_delete_q(dev, cq, QTYPE_CQ);
66062306a36Sopenharmony_ci		ocrdma_free_q(dev, cq);
66162306a36Sopenharmony_ci	}
66262306a36Sopenharmony_ci}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_cistatic void ocrdma_process_qpcat_error(struct ocrdma_dev *dev,
66562306a36Sopenharmony_ci				       struct ocrdma_qp *qp)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	enum ib_qp_state new_ib_qps = IB_QPS_ERR;
66862306a36Sopenharmony_ci	enum ib_qp_state old_ib_qps;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	if (qp == NULL)
67162306a36Sopenharmony_ci		BUG();
67262306a36Sopenharmony_ci	ocrdma_qp_state_change(qp, new_ib_qps, &old_ib_qps);
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev,
67662306a36Sopenharmony_ci				    struct ocrdma_ae_mcqe *cqe)
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	struct ocrdma_qp *qp = NULL;
67962306a36Sopenharmony_ci	struct ocrdma_cq *cq = NULL;
68062306a36Sopenharmony_ci	struct ib_event ib_evt;
68162306a36Sopenharmony_ci	int cq_event = 0;
68262306a36Sopenharmony_ci	int qp_event = 1;
68362306a36Sopenharmony_ci	int srq_event = 0;
68462306a36Sopenharmony_ci	int dev_event = 0;
68562306a36Sopenharmony_ci	int type = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_TYPE_MASK) >>
68662306a36Sopenharmony_ci	    OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT;
68762306a36Sopenharmony_ci	u16 qpid = cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPID_MASK;
68862306a36Sopenharmony_ci	u16 cqid = cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQID_MASK;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	/*
69162306a36Sopenharmony_ci	 * Some FW version returns wrong qp or cq ids in CQEs.
69262306a36Sopenharmony_ci	 * Checking whether the IDs are valid
69362306a36Sopenharmony_ci	 */
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	if (cqe->qpvalid_qpid & OCRDMA_AE_MCQE_QPVALID) {
69662306a36Sopenharmony_ci		if (qpid < dev->attr.max_qp)
69762306a36Sopenharmony_ci			qp = dev->qp_tbl[qpid];
69862306a36Sopenharmony_ci		if (qp == NULL) {
69962306a36Sopenharmony_ci			pr_err("ocrdma%d:Async event - qpid %u is not valid\n",
70062306a36Sopenharmony_ci			       dev->id, qpid);
70162306a36Sopenharmony_ci			return;
70262306a36Sopenharmony_ci		}
70362306a36Sopenharmony_ci	}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	if (cqe->cqvalid_cqid & OCRDMA_AE_MCQE_CQVALID) {
70662306a36Sopenharmony_ci		if (cqid < dev->attr.max_cq)
70762306a36Sopenharmony_ci			cq = dev->cq_tbl[cqid];
70862306a36Sopenharmony_ci		if (cq == NULL) {
70962306a36Sopenharmony_ci			pr_err("ocrdma%d:Async event - cqid %u is not valid\n",
71062306a36Sopenharmony_ci			       dev->id, cqid);
71162306a36Sopenharmony_ci			return;
71262306a36Sopenharmony_ci		}
71362306a36Sopenharmony_ci	}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	memset(&ib_evt, 0, sizeof(ib_evt));
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	ib_evt.device = &dev->ibdev;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	switch (type) {
72062306a36Sopenharmony_ci	case OCRDMA_CQ_ERROR:
72162306a36Sopenharmony_ci		ib_evt.element.cq = &cq->ibcq;
72262306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_CQ_ERR;
72362306a36Sopenharmony_ci		cq_event = 1;
72462306a36Sopenharmony_ci		qp_event = 0;
72562306a36Sopenharmony_ci		break;
72662306a36Sopenharmony_ci	case OCRDMA_CQ_OVERRUN_ERROR:
72762306a36Sopenharmony_ci		ib_evt.element.cq = &cq->ibcq;
72862306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_CQ_ERR;
72962306a36Sopenharmony_ci		cq_event = 1;
73062306a36Sopenharmony_ci		qp_event = 0;
73162306a36Sopenharmony_ci		break;
73262306a36Sopenharmony_ci	case OCRDMA_CQ_QPCAT_ERROR:
73362306a36Sopenharmony_ci		ib_evt.element.qp = &qp->ibqp;
73462306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_QP_FATAL;
73562306a36Sopenharmony_ci		ocrdma_process_qpcat_error(dev, qp);
73662306a36Sopenharmony_ci		break;
73762306a36Sopenharmony_ci	case OCRDMA_QP_ACCESS_ERROR:
73862306a36Sopenharmony_ci		ib_evt.element.qp = &qp->ibqp;
73962306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_QP_ACCESS_ERR;
74062306a36Sopenharmony_ci		break;
74162306a36Sopenharmony_ci	case OCRDMA_QP_COMM_EST_EVENT:
74262306a36Sopenharmony_ci		ib_evt.element.qp = &qp->ibqp;
74362306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_COMM_EST;
74462306a36Sopenharmony_ci		break;
74562306a36Sopenharmony_ci	case OCRDMA_SQ_DRAINED_EVENT:
74662306a36Sopenharmony_ci		ib_evt.element.qp = &qp->ibqp;
74762306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_SQ_DRAINED;
74862306a36Sopenharmony_ci		break;
74962306a36Sopenharmony_ci	case OCRDMA_DEVICE_FATAL_EVENT:
75062306a36Sopenharmony_ci		ib_evt.element.port_num = 1;
75162306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_DEVICE_FATAL;
75262306a36Sopenharmony_ci		qp_event = 0;
75362306a36Sopenharmony_ci		dev_event = 1;
75462306a36Sopenharmony_ci		break;
75562306a36Sopenharmony_ci	case OCRDMA_SRQCAT_ERROR:
75662306a36Sopenharmony_ci		ib_evt.element.srq = &qp->srq->ibsrq;
75762306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_SRQ_ERR;
75862306a36Sopenharmony_ci		srq_event = 1;
75962306a36Sopenharmony_ci		qp_event = 0;
76062306a36Sopenharmony_ci		break;
76162306a36Sopenharmony_ci	case OCRDMA_SRQ_LIMIT_EVENT:
76262306a36Sopenharmony_ci		ib_evt.element.srq = &qp->srq->ibsrq;
76362306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_SRQ_LIMIT_REACHED;
76462306a36Sopenharmony_ci		srq_event = 1;
76562306a36Sopenharmony_ci		qp_event = 0;
76662306a36Sopenharmony_ci		break;
76762306a36Sopenharmony_ci	case OCRDMA_QP_LAST_WQE_EVENT:
76862306a36Sopenharmony_ci		ib_evt.element.qp = &qp->ibqp;
76962306a36Sopenharmony_ci		ib_evt.event = IB_EVENT_QP_LAST_WQE_REACHED;
77062306a36Sopenharmony_ci		break;
77162306a36Sopenharmony_ci	default:
77262306a36Sopenharmony_ci		cq_event = 0;
77362306a36Sopenharmony_ci		qp_event = 0;
77462306a36Sopenharmony_ci		srq_event = 0;
77562306a36Sopenharmony_ci		dev_event = 0;
77662306a36Sopenharmony_ci		pr_err("%s() unknown type=0x%x\n", __func__, type);
77762306a36Sopenharmony_ci		break;
77862306a36Sopenharmony_ci	}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	if (type < OCRDMA_MAX_ASYNC_ERRORS)
78162306a36Sopenharmony_ci		atomic_inc(&dev->async_err_stats[type]);
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	if (qp_event) {
78462306a36Sopenharmony_ci		if (qp->ibqp.event_handler)
78562306a36Sopenharmony_ci			qp->ibqp.event_handler(&ib_evt, qp->ibqp.qp_context);
78662306a36Sopenharmony_ci	} else if (cq_event) {
78762306a36Sopenharmony_ci		if (cq->ibcq.event_handler)
78862306a36Sopenharmony_ci			cq->ibcq.event_handler(&ib_evt, cq->ibcq.cq_context);
78962306a36Sopenharmony_ci	} else if (srq_event) {
79062306a36Sopenharmony_ci		if (qp->srq->ibsrq.event_handler)
79162306a36Sopenharmony_ci			qp->srq->ibsrq.event_handler(&ib_evt,
79262306a36Sopenharmony_ci						     qp->srq->ibsrq.
79362306a36Sopenharmony_ci						     srq_context);
79462306a36Sopenharmony_ci	} else if (dev_event) {
79562306a36Sopenharmony_ci		dev_err(&dev->ibdev.dev, "Fatal event received\n");
79662306a36Sopenharmony_ci		ib_dispatch_event(&ib_evt);
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic void ocrdma_process_grp5_aync(struct ocrdma_dev *dev,
80262306a36Sopenharmony_ci					struct ocrdma_ae_mcqe *cqe)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	struct ocrdma_ae_pvid_mcqe *evt;
80562306a36Sopenharmony_ci	int type = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_TYPE_MASK) >>
80662306a36Sopenharmony_ci			OCRDMA_AE_MCQE_EVENT_TYPE_SHIFT;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	switch (type) {
80962306a36Sopenharmony_ci	case OCRDMA_ASYNC_EVENT_PVID_STATE:
81062306a36Sopenharmony_ci		evt = (struct ocrdma_ae_pvid_mcqe *)cqe;
81162306a36Sopenharmony_ci		if ((evt->tag_enabled & OCRDMA_AE_PVID_MCQE_ENABLED_MASK) >>
81262306a36Sopenharmony_ci			OCRDMA_AE_PVID_MCQE_ENABLED_SHIFT)
81362306a36Sopenharmony_ci			dev->pvid = ((evt->tag_enabled &
81462306a36Sopenharmony_ci					OCRDMA_AE_PVID_MCQE_TAG_MASK) >>
81562306a36Sopenharmony_ci					OCRDMA_AE_PVID_MCQE_TAG_SHIFT);
81662306a36Sopenharmony_ci		break;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	case OCRDMA_ASYNC_EVENT_COS_VALUE:
81962306a36Sopenharmony_ci		atomic_set(&dev->update_sl, 1);
82062306a36Sopenharmony_ci		break;
82162306a36Sopenharmony_ci	default:
82262306a36Sopenharmony_ci		/* Not interested evts. */
82362306a36Sopenharmony_ci		break;
82462306a36Sopenharmony_ci	}
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistatic void ocrdma_process_link_state(struct ocrdma_dev *dev,
82862306a36Sopenharmony_ci				      struct ocrdma_ae_mcqe *cqe)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	struct ocrdma_ae_lnkst_mcqe *evt;
83162306a36Sopenharmony_ci	u8 lstate;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	evt = (struct ocrdma_ae_lnkst_mcqe *)cqe;
83462306a36Sopenharmony_ci	lstate = ocrdma_get_ae_link_state(evt->speed_state_ptn);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	if (!(lstate & OCRDMA_AE_LSC_LLINK_MASK))
83762306a36Sopenharmony_ci		return;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	if (dev->flags & OCRDMA_FLAGS_LINK_STATUS_INIT)
84062306a36Sopenharmony_ci		ocrdma_update_link_state(dev, (lstate & OCRDMA_LINK_ST_MASK));
84162306a36Sopenharmony_ci}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_cistatic void ocrdma_process_acqe(struct ocrdma_dev *dev, void *ae_cqe)
84462306a36Sopenharmony_ci{
84562306a36Sopenharmony_ci	/* async CQE processing */
84662306a36Sopenharmony_ci	struct ocrdma_ae_mcqe *cqe = ae_cqe;
84762306a36Sopenharmony_ci	u32 evt_code = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_CODE_MASK) >>
84862306a36Sopenharmony_ci			OCRDMA_AE_MCQE_EVENT_CODE_SHIFT;
84962306a36Sopenharmony_ci	switch (evt_code) {
85062306a36Sopenharmony_ci	case OCRDMA_ASYNC_LINK_EVE_CODE:
85162306a36Sopenharmony_ci		ocrdma_process_link_state(dev, cqe);
85262306a36Sopenharmony_ci		break;
85362306a36Sopenharmony_ci	case OCRDMA_ASYNC_RDMA_EVE_CODE:
85462306a36Sopenharmony_ci		ocrdma_dispatch_ibevent(dev, cqe);
85562306a36Sopenharmony_ci		break;
85662306a36Sopenharmony_ci	case OCRDMA_ASYNC_GRP5_EVE_CODE:
85762306a36Sopenharmony_ci		ocrdma_process_grp5_aync(dev, cqe);
85862306a36Sopenharmony_ci		break;
85962306a36Sopenharmony_ci	default:
86062306a36Sopenharmony_ci		pr_err("%s(%d) invalid evt code=0x%x\n", __func__,
86162306a36Sopenharmony_ci		       dev->id, evt_code);
86262306a36Sopenharmony_ci	}
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistatic void ocrdma_process_mcqe(struct ocrdma_dev *dev, struct ocrdma_mcqe *cqe)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	if (dev->mqe_ctx.tag == cqe->tag_lo && dev->mqe_ctx.cmd_done == false) {
86862306a36Sopenharmony_ci		dev->mqe_ctx.cqe_status = (cqe->status &
86962306a36Sopenharmony_ci		     OCRDMA_MCQE_STATUS_MASK) >> OCRDMA_MCQE_STATUS_SHIFT;
87062306a36Sopenharmony_ci		dev->mqe_ctx.ext_status =
87162306a36Sopenharmony_ci		    (cqe->status & OCRDMA_MCQE_ESTATUS_MASK)
87262306a36Sopenharmony_ci		    >> OCRDMA_MCQE_ESTATUS_SHIFT;
87362306a36Sopenharmony_ci		dev->mqe_ctx.cmd_done = true;
87462306a36Sopenharmony_ci		wake_up(&dev->mqe_ctx.cmd_wait);
87562306a36Sopenharmony_ci	} else
87662306a36Sopenharmony_ci		pr_err("%s() cqe for invalid tag0x%x.expected=0x%x\n",
87762306a36Sopenharmony_ci		       __func__, cqe->tag_lo, dev->mqe_ctx.tag);
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic int ocrdma_mq_cq_handler(struct ocrdma_dev *dev, u16 cq_id)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	u16 cqe_popped = 0;
88362306a36Sopenharmony_ci	struct ocrdma_mcqe *cqe;
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	while (1) {
88662306a36Sopenharmony_ci		cqe = ocrdma_get_mcqe(dev);
88762306a36Sopenharmony_ci		if (cqe == NULL)
88862306a36Sopenharmony_ci			break;
88962306a36Sopenharmony_ci		ocrdma_le32_to_cpu(cqe, sizeof(*cqe));
89062306a36Sopenharmony_ci		cqe_popped += 1;
89162306a36Sopenharmony_ci		if (cqe->valid_ae_cmpl_cons & OCRDMA_MCQE_AE_MASK)
89262306a36Sopenharmony_ci			ocrdma_process_acqe(dev, cqe);
89362306a36Sopenharmony_ci		else if (cqe->valid_ae_cmpl_cons & OCRDMA_MCQE_CMPL_MASK)
89462306a36Sopenharmony_ci			ocrdma_process_mcqe(dev, cqe);
89562306a36Sopenharmony_ci		memset(cqe, 0, sizeof(struct ocrdma_mcqe));
89662306a36Sopenharmony_ci		ocrdma_mcq_inc_tail(dev);
89762306a36Sopenharmony_ci	}
89862306a36Sopenharmony_ci	ocrdma_ring_cq_db(dev, dev->mq.cq.id, true, false, cqe_popped);
89962306a36Sopenharmony_ci	return 0;
90062306a36Sopenharmony_ci}
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_cistatic struct ocrdma_cq *_ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
90362306a36Sopenharmony_ci				struct ocrdma_cq *cq, bool sq)
90462306a36Sopenharmony_ci{
90562306a36Sopenharmony_ci	struct ocrdma_qp *qp;
90662306a36Sopenharmony_ci	struct list_head *cur;
90762306a36Sopenharmony_ci	struct ocrdma_cq *bcq = NULL;
90862306a36Sopenharmony_ci	struct list_head *head = sq?(&cq->sq_head):(&cq->rq_head);
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	list_for_each(cur, head) {
91162306a36Sopenharmony_ci		if (sq)
91262306a36Sopenharmony_ci			qp = list_entry(cur, struct ocrdma_qp, sq_entry);
91362306a36Sopenharmony_ci		else
91462306a36Sopenharmony_ci			qp = list_entry(cur, struct ocrdma_qp, rq_entry);
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci		if (qp->srq)
91762306a36Sopenharmony_ci			continue;
91862306a36Sopenharmony_ci		/* if wq and rq share the same cq, than comp_handler
91962306a36Sopenharmony_ci		 * is already invoked.
92062306a36Sopenharmony_ci		 */
92162306a36Sopenharmony_ci		if (qp->sq_cq == qp->rq_cq)
92262306a36Sopenharmony_ci			continue;
92362306a36Sopenharmony_ci		/* if completion came on sq, rq's cq is buddy cq.
92462306a36Sopenharmony_ci		 * if completion came on rq, sq's cq is buddy cq.
92562306a36Sopenharmony_ci		 */
92662306a36Sopenharmony_ci		if (qp->sq_cq == cq)
92762306a36Sopenharmony_ci			bcq = qp->rq_cq;
92862306a36Sopenharmony_ci		else
92962306a36Sopenharmony_ci			bcq = qp->sq_cq;
93062306a36Sopenharmony_ci		return bcq;
93162306a36Sopenharmony_ci	}
93262306a36Sopenharmony_ci	return NULL;
93362306a36Sopenharmony_ci}
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_cistatic void ocrdma_qp_buddy_cq_handler(struct ocrdma_dev *dev,
93662306a36Sopenharmony_ci				       struct ocrdma_cq *cq)
93762306a36Sopenharmony_ci{
93862306a36Sopenharmony_ci	unsigned long flags;
93962306a36Sopenharmony_ci	struct ocrdma_cq *bcq = NULL;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	/* Go through list of QPs in error state which are using this CQ
94262306a36Sopenharmony_ci	 * and invoke its callback handler to trigger CQE processing for
94362306a36Sopenharmony_ci	 * error/flushed CQE. It is rare to find more than few entries in
94462306a36Sopenharmony_ci	 * this list as most consumers stops after getting error CQE.
94562306a36Sopenharmony_ci	 * List is traversed only once when a matching buddy cq found for a QP.
94662306a36Sopenharmony_ci	 */
94762306a36Sopenharmony_ci	spin_lock_irqsave(&dev->flush_q_lock, flags);
94862306a36Sopenharmony_ci	/* Check if buddy CQ is present.
94962306a36Sopenharmony_ci	 * true - Check for  SQ CQ
95062306a36Sopenharmony_ci	 * false - Check for RQ CQ
95162306a36Sopenharmony_ci	 */
95262306a36Sopenharmony_ci	bcq = _ocrdma_qp_buddy_cq_handler(dev, cq, true);
95362306a36Sopenharmony_ci	if (bcq == NULL)
95462306a36Sopenharmony_ci		bcq = _ocrdma_qp_buddy_cq_handler(dev, cq, false);
95562306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->flush_q_lock, flags);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	/* if there is valid buddy cq, look for its completion handler */
95862306a36Sopenharmony_ci	if (bcq && bcq->ibcq.comp_handler) {
95962306a36Sopenharmony_ci		spin_lock_irqsave(&bcq->comp_handler_lock, flags);
96062306a36Sopenharmony_ci		(*bcq->ibcq.comp_handler) (&bcq->ibcq, bcq->ibcq.cq_context);
96162306a36Sopenharmony_ci		spin_unlock_irqrestore(&bcq->comp_handler_lock, flags);
96262306a36Sopenharmony_ci	}
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_cistatic void ocrdma_qp_cq_handler(struct ocrdma_dev *dev, u16 cq_idx)
96662306a36Sopenharmony_ci{
96762306a36Sopenharmony_ci	unsigned long flags;
96862306a36Sopenharmony_ci	struct ocrdma_cq *cq;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	if (cq_idx >= OCRDMA_MAX_CQ)
97162306a36Sopenharmony_ci		BUG();
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	cq = dev->cq_tbl[cq_idx];
97462306a36Sopenharmony_ci	if (cq == NULL)
97562306a36Sopenharmony_ci		return;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	if (cq->ibcq.comp_handler) {
97862306a36Sopenharmony_ci		spin_lock_irqsave(&cq->comp_handler_lock, flags);
97962306a36Sopenharmony_ci		(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
98062306a36Sopenharmony_ci		spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
98162306a36Sopenharmony_ci	}
98262306a36Sopenharmony_ci	ocrdma_qp_buddy_cq_handler(dev, cq);
98362306a36Sopenharmony_ci}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_cistatic void ocrdma_cq_handler(struct ocrdma_dev *dev, u16 cq_id)
98662306a36Sopenharmony_ci{
98762306a36Sopenharmony_ci	/* process the MQ-CQE. */
98862306a36Sopenharmony_ci	if (cq_id == dev->mq.cq.id)
98962306a36Sopenharmony_ci		ocrdma_mq_cq_handler(dev, cq_id);
99062306a36Sopenharmony_ci	else
99162306a36Sopenharmony_ci		ocrdma_qp_cq_handler(dev, cq_id);
99262306a36Sopenharmony_ci}
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_cistatic irqreturn_t ocrdma_irq_handler(int irq, void *handle)
99562306a36Sopenharmony_ci{
99662306a36Sopenharmony_ci	struct ocrdma_eq *eq = handle;
99762306a36Sopenharmony_ci	struct ocrdma_dev *dev = eq->dev;
99862306a36Sopenharmony_ci	struct ocrdma_eqe eqe;
99962306a36Sopenharmony_ci	struct ocrdma_eqe *ptr;
100062306a36Sopenharmony_ci	u16 cq_id;
100162306a36Sopenharmony_ci	u8 mcode;
100262306a36Sopenharmony_ci	int budget = eq->cq_cnt;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	do {
100562306a36Sopenharmony_ci		ptr = ocrdma_get_eqe(eq);
100662306a36Sopenharmony_ci		eqe = *ptr;
100762306a36Sopenharmony_ci		ocrdma_le32_to_cpu(&eqe, sizeof(eqe));
100862306a36Sopenharmony_ci		mcode = (eqe.id_valid & OCRDMA_EQE_MAJOR_CODE_MASK)
100962306a36Sopenharmony_ci				>> OCRDMA_EQE_MAJOR_CODE_SHIFT;
101062306a36Sopenharmony_ci		if (mcode == OCRDMA_MAJOR_CODE_SENTINAL)
101162306a36Sopenharmony_ci			pr_err("EQ full on eqid = 0x%x, eqe = 0x%x\n",
101262306a36Sopenharmony_ci			       eq->q.id, eqe.id_valid);
101362306a36Sopenharmony_ci		if ((eqe.id_valid & OCRDMA_EQE_VALID_MASK) == 0)
101462306a36Sopenharmony_ci			break;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci		ptr->id_valid = 0;
101762306a36Sopenharmony_ci		/* ring eq doorbell as soon as its consumed. */
101862306a36Sopenharmony_ci		ocrdma_ring_eq_db(dev, eq->q.id, false, true, 1);
101962306a36Sopenharmony_ci		/* check whether its CQE or not. */
102062306a36Sopenharmony_ci		if ((eqe.id_valid & OCRDMA_EQE_FOR_CQE_MASK) == 0) {
102162306a36Sopenharmony_ci			cq_id = eqe.id_valid >> OCRDMA_EQE_RESOURCE_ID_SHIFT;
102262306a36Sopenharmony_ci			ocrdma_cq_handler(dev, cq_id);
102362306a36Sopenharmony_ci		}
102462306a36Sopenharmony_ci		ocrdma_eq_inc_tail(eq);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci		/* There can be a stale EQE after the last bound CQ is
102762306a36Sopenharmony_ci		 * destroyed. EQE valid and budget == 0 implies this.
102862306a36Sopenharmony_ci		 */
102962306a36Sopenharmony_ci		if (budget)
103062306a36Sopenharmony_ci			budget--;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	} while (budget);
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	eq->aic_obj.eq_intr_cnt++;
103562306a36Sopenharmony_ci	ocrdma_ring_eq_db(dev, eq->q.id, true, true, 0);
103662306a36Sopenharmony_ci	return IRQ_HANDLED;
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic void ocrdma_post_mqe(struct ocrdma_dev *dev, struct ocrdma_mqe *cmd)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	struct ocrdma_mqe *mqe;
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci	dev->mqe_ctx.tag = dev->mq.sq.head;
104462306a36Sopenharmony_ci	dev->mqe_ctx.cmd_done = false;
104562306a36Sopenharmony_ci	mqe = ocrdma_get_mqe(dev);
104662306a36Sopenharmony_ci	cmd->hdr.tag_lo = dev->mq.sq.head;
104762306a36Sopenharmony_ci	ocrdma_copy_cpu_to_le32(mqe, cmd, sizeof(*mqe));
104862306a36Sopenharmony_ci	/* make sure descriptor is written before ringing doorbell */
104962306a36Sopenharmony_ci	wmb();
105062306a36Sopenharmony_ci	ocrdma_mq_inc_head(dev);
105162306a36Sopenharmony_ci	ocrdma_ring_mq_db(dev);
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic int ocrdma_wait_mqe_cmpl(struct ocrdma_dev *dev)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	long status;
105762306a36Sopenharmony_ci	/* 30 sec timeout */
105862306a36Sopenharmony_ci	status = wait_event_timeout(dev->mqe_ctx.cmd_wait,
105962306a36Sopenharmony_ci				    (dev->mqe_ctx.cmd_done != false),
106062306a36Sopenharmony_ci				    msecs_to_jiffies(30000));
106162306a36Sopenharmony_ci	if (status)
106262306a36Sopenharmony_ci		return 0;
106362306a36Sopenharmony_ci	else {
106462306a36Sopenharmony_ci		dev->mqe_ctx.fw_error_state = true;
106562306a36Sopenharmony_ci		pr_err("%s(%d) mailbox timeout: fw not responding\n",
106662306a36Sopenharmony_ci		       __func__, dev->id);
106762306a36Sopenharmony_ci		return -1;
106862306a36Sopenharmony_ci	}
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci/* issue a mailbox command on the MQ */
107262306a36Sopenharmony_cistatic int ocrdma_mbx_cmd(struct ocrdma_dev *dev, struct ocrdma_mqe *mqe)
107362306a36Sopenharmony_ci{
107462306a36Sopenharmony_ci	int status = 0;
107562306a36Sopenharmony_ci	u16 cqe_status, ext_status;
107662306a36Sopenharmony_ci	struct ocrdma_mqe *rsp_mqe;
107762306a36Sopenharmony_ci	struct ocrdma_mbx_rsp *rsp = NULL;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	mutex_lock(&dev->mqe_ctx.lock);
108062306a36Sopenharmony_ci	if (dev->mqe_ctx.fw_error_state)
108162306a36Sopenharmony_ci		goto mbx_err;
108262306a36Sopenharmony_ci	ocrdma_post_mqe(dev, mqe);
108362306a36Sopenharmony_ci	status = ocrdma_wait_mqe_cmpl(dev);
108462306a36Sopenharmony_ci	if (status)
108562306a36Sopenharmony_ci		goto mbx_err;
108662306a36Sopenharmony_ci	cqe_status = dev->mqe_ctx.cqe_status;
108762306a36Sopenharmony_ci	ext_status = dev->mqe_ctx.ext_status;
108862306a36Sopenharmony_ci	rsp_mqe = ocrdma_get_mqe_rsp(dev);
108962306a36Sopenharmony_ci	ocrdma_copy_le32_to_cpu(mqe, rsp_mqe, (sizeof(*mqe)));
109062306a36Sopenharmony_ci	if ((mqe->hdr.spcl_sge_cnt_emb & OCRDMA_MQE_HDR_EMB_MASK) >>
109162306a36Sopenharmony_ci				OCRDMA_MQE_HDR_EMB_SHIFT)
109262306a36Sopenharmony_ci		rsp = &mqe->u.rsp;
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	if (cqe_status || ext_status) {
109562306a36Sopenharmony_ci		pr_err("%s() cqe_status=0x%x, ext_status=0x%x,\n",
109662306a36Sopenharmony_ci		       __func__, cqe_status, ext_status);
109762306a36Sopenharmony_ci		if (rsp) {
109862306a36Sopenharmony_ci			/* This is for embedded cmds. */
109962306a36Sopenharmony_ci			pr_err("opcode=0x%x, subsystem=0x%x\n",
110062306a36Sopenharmony_ci			       (rsp->subsys_op & OCRDMA_MBX_RSP_OPCODE_MASK) >>
110162306a36Sopenharmony_ci				OCRDMA_MBX_RSP_OPCODE_SHIFT,
110262306a36Sopenharmony_ci				(rsp->subsys_op & OCRDMA_MBX_RSP_SUBSYS_MASK) >>
110362306a36Sopenharmony_ci				OCRDMA_MBX_RSP_SUBSYS_SHIFT);
110462306a36Sopenharmony_ci		}
110562306a36Sopenharmony_ci		status = ocrdma_get_mbx_cqe_errno(cqe_status);
110662306a36Sopenharmony_ci		goto mbx_err;
110762306a36Sopenharmony_ci	}
110862306a36Sopenharmony_ci	/* For non embedded, rsp errors are handled in ocrdma_nonemb_mbx_cmd */
110962306a36Sopenharmony_ci	if (rsp && (mqe->u.rsp.status & OCRDMA_MBX_RSP_STATUS_MASK))
111062306a36Sopenharmony_ci		status = ocrdma_get_mbx_errno(mqe->u.rsp.status);
111162306a36Sopenharmony_cimbx_err:
111262306a36Sopenharmony_ci	mutex_unlock(&dev->mqe_ctx.lock);
111362306a36Sopenharmony_ci	return status;
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_cistatic int ocrdma_nonemb_mbx_cmd(struct ocrdma_dev *dev, struct ocrdma_mqe *mqe,
111762306a36Sopenharmony_ci				 void *payload_va)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	int status;
112062306a36Sopenharmony_ci	struct ocrdma_mbx_rsp *rsp = payload_va;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	if ((mqe->hdr.spcl_sge_cnt_emb & OCRDMA_MQE_HDR_EMB_MASK) >>
112362306a36Sopenharmony_ci				OCRDMA_MQE_HDR_EMB_SHIFT)
112462306a36Sopenharmony_ci		BUG();
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, mqe);
112762306a36Sopenharmony_ci	if (!status)
112862306a36Sopenharmony_ci		/* For non embedded, only CQE failures are handled in
112962306a36Sopenharmony_ci		 * ocrdma_mbx_cmd. We need to check for RSP errors.
113062306a36Sopenharmony_ci		 */
113162306a36Sopenharmony_ci		if (rsp->status & OCRDMA_MBX_RSP_STATUS_MASK)
113262306a36Sopenharmony_ci			status = ocrdma_get_mbx_errno(rsp->status);
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (status)
113562306a36Sopenharmony_ci		pr_err("opcode=0x%x, subsystem=0x%x\n",
113662306a36Sopenharmony_ci		       (rsp->subsys_op & OCRDMA_MBX_RSP_OPCODE_MASK) >>
113762306a36Sopenharmony_ci			OCRDMA_MBX_RSP_OPCODE_SHIFT,
113862306a36Sopenharmony_ci			(rsp->subsys_op & OCRDMA_MBX_RSP_SUBSYS_MASK) >>
113962306a36Sopenharmony_ci			OCRDMA_MBX_RSP_SUBSYS_SHIFT);
114062306a36Sopenharmony_ci	return status;
114162306a36Sopenharmony_ci}
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_cistatic void ocrdma_get_attr(struct ocrdma_dev *dev,
114462306a36Sopenharmony_ci			      struct ocrdma_dev_attr *attr,
114562306a36Sopenharmony_ci			      struct ocrdma_mbx_query_config *rsp)
114662306a36Sopenharmony_ci{
114762306a36Sopenharmony_ci	attr->max_pd =
114862306a36Sopenharmony_ci	    (rsp->max_pd_ca_ack_delay & OCRDMA_MBX_QUERY_CFG_MAX_PD_MASK) >>
114962306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_PD_SHIFT;
115062306a36Sopenharmony_ci	attr->udp_encap = (rsp->max_pd_ca_ack_delay &
115162306a36Sopenharmony_ci			   OCRDMA_MBX_QUERY_CFG_L3_TYPE_MASK) >>
115262306a36Sopenharmony_ci			   OCRDMA_MBX_QUERY_CFG_L3_TYPE_SHIFT;
115362306a36Sopenharmony_ci	attr->max_dpp_pds =
115462306a36Sopenharmony_ci	   (rsp->max_dpp_pds_credits & OCRDMA_MBX_QUERY_CFG_MAX_DPP_PDS_MASK) >>
115562306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_DPP_PDS_OFFSET;
115662306a36Sopenharmony_ci	attr->max_qp =
115762306a36Sopenharmony_ci	    (rsp->qp_srq_cq_ird_ord & OCRDMA_MBX_QUERY_CFG_MAX_QP_MASK) >>
115862306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_QP_SHIFT;
115962306a36Sopenharmony_ci	attr->max_srq =
116062306a36Sopenharmony_ci		(rsp->max_srq_rpir_qps & OCRDMA_MBX_QUERY_CFG_MAX_SRQ_MASK) >>
116162306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_SRQ_OFFSET;
116262306a36Sopenharmony_ci	attr->max_send_sge = ((rsp->max_recv_send_sge &
116362306a36Sopenharmony_ci			       OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_MASK) >>
116462306a36Sopenharmony_ci			      OCRDMA_MBX_QUERY_CFG_MAX_SEND_SGE_SHIFT);
116562306a36Sopenharmony_ci	attr->max_recv_sge = (rsp->max_recv_send_sge &
116662306a36Sopenharmony_ci			      OCRDMA_MBX_QUERY_CFG_MAX_RECV_SGE_MASK) >>
116762306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_RECV_SGE_SHIFT;
116862306a36Sopenharmony_ci	attr->max_srq_sge = (rsp->max_srq_rqe_sge &
116962306a36Sopenharmony_ci			      OCRDMA_MBX_QUERY_CFG_MAX_SRQ_SGE_MASK) >>
117062306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_SRQ_SGE_OFFSET;
117162306a36Sopenharmony_ci	attr->max_rdma_sge = (rsp->max_wr_rd_sge &
117262306a36Sopenharmony_ci			      OCRDMA_MBX_QUERY_CFG_MAX_RD_SGE_MASK) >>
117362306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_RD_SGE_SHIFT;
117462306a36Sopenharmony_ci	attr->max_ord_per_qp = (rsp->max_ird_ord_per_qp &
117562306a36Sopenharmony_ci				OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_MASK) >>
117662306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_ORD_PER_QP_SHIFT;
117762306a36Sopenharmony_ci	attr->max_ird_per_qp = (rsp->max_ird_ord_per_qp &
117862306a36Sopenharmony_ci				OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_MASK) >>
117962306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_MAX_IRD_PER_QP_SHIFT;
118062306a36Sopenharmony_ci	attr->cq_overflow_detect = (rsp->qp_srq_cq_ird_ord &
118162306a36Sopenharmony_ci				    OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_MASK) >>
118262306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_SHIFT;
118362306a36Sopenharmony_ci	attr->srq_supported = (rsp->qp_srq_cq_ird_ord &
118462306a36Sopenharmony_ci			       OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_MASK) >>
118562306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_SRQ_SUPPORTED_SHIFT;
118662306a36Sopenharmony_ci	attr->local_ca_ack_delay = (rsp->max_pd_ca_ack_delay &
118762306a36Sopenharmony_ci				    OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_MASK) >>
118862306a36Sopenharmony_ci	    OCRDMA_MBX_QUERY_CFG_CA_ACK_DELAY_SHIFT;
118962306a36Sopenharmony_ci	attr->max_mw = rsp->max_mw;
119062306a36Sopenharmony_ci	attr->max_mr = rsp->max_mr;
119162306a36Sopenharmony_ci	attr->max_mr_size = ((u64)rsp->max_mr_size_hi << 32) |
119262306a36Sopenharmony_ci			      rsp->max_mr_size_lo;
119362306a36Sopenharmony_ci	attr->max_pages_per_frmr = rsp->max_pages_per_frmr;
119462306a36Sopenharmony_ci	attr->max_num_mr_pbl = rsp->max_num_mr_pbl;
119562306a36Sopenharmony_ci	attr->max_cqe = rsp->max_cq_cqes_per_cq &
119662306a36Sopenharmony_ci			OCRDMA_MBX_QUERY_CFG_MAX_CQES_PER_CQ_MASK;
119762306a36Sopenharmony_ci	attr->max_cq = (rsp->max_cq_cqes_per_cq &
119862306a36Sopenharmony_ci			OCRDMA_MBX_QUERY_CFG_MAX_CQ_MASK) >>
119962306a36Sopenharmony_ci			OCRDMA_MBX_QUERY_CFG_MAX_CQ_OFFSET;
120062306a36Sopenharmony_ci	attr->wqe_size = ((rsp->wqe_rqe_stride_max_dpp_cqs &
120162306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_MASK) >>
120262306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_WQE_SIZE_OFFSET) *
120362306a36Sopenharmony_ci		OCRDMA_WQE_STRIDE;
120462306a36Sopenharmony_ci	attr->rqe_size = ((rsp->wqe_rqe_stride_max_dpp_cqs &
120562306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_MASK) >>
120662306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_RQE_SIZE_OFFSET) *
120762306a36Sopenharmony_ci		OCRDMA_WQE_STRIDE;
120862306a36Sopenharmony_ci	attr->max_inline_data =
120962306a36Sopenharmony_ci	    attr->wqe_size - (sizeof(struct ocrdma_hdr_wqe) +
121062306a36Sopenharmony_ci			      sizeof(struct ocrdma_sge));
121162306a36Sopenharmony_ci	if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) {
121262306a36Sopenharmony_ci		attr->ird = 1;
121362306a36Sopenharmony_ci		attr->ird_page_size = OCRDMA_MIN_Q_PAGE_SIZE;
121462306a36Sopenharmony_ci		attr->num_ird_pages = MAX_OCRDMA_IRD_PAGES;
121562306a36Sopenharmony_ci	}
121662306a36Sopenharmony_ci	dev->attr.max_wqe = rsp->max_wqes_rqes_per_q >>
121762306a36Sopenharmony_ci		 OCRDMA_MBX_QUERY_CFG_MAX_WQES_PER_WQ_OFFSET;
121862306a36Sopenharmony_ci	dev->attr.max_rqe = rsp->max_wqes_rqes_per_q &
121962306a36Sopenharmony_ci		OCRDMA_MBX_QUERY_CFG_MAX_RQES_PER_RQ_MASK;
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cistatic int ocrdma_check_fw_config(struct ocrdma_dev *dev,
122362306a36Sopenharmony_ci				   struct ocrdma_fw_conf_rsp *conf)
122462306a36Sopenharmony_ci{
122562306a36Sopenharmony_ci	u32 fn_mode;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	fn_mode = conf->fn_mode & OCRDMA_FN_MODE_RDMA;
122862306a36Sopenharmony_ci	if (fn_mode != OCRDMA_FN_MODE_RDMA)
122962306a36Sopenharmony_ci		return -EINVAL;
123062306a36Sopenharmony_ci	dev->base_eqid = conf->base_eqid;
123162306a36Sopenharmony_ci	dev->max_eq = conf->max_eq;
123262306a36Sopenharmony_ci	return 0;
123362306a36Sopenharmony_ci}
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci/* can be issued only during init time. */
123662306a36Sopenharmony_cistatic int ocrdma_mbx_query_fw_ver(struct ocrdma_dev *dev)
123762306a36Sopenharmony_ci{
123862306a36Sopenharmony_ci	int status = -ENOMEM;
123962306a36Sopenharmony_ci	struct ocrdma_mqe *cmd;
124062306a36Sopenharmony_ci	struct ocrdma_fw_ver_rsp *rsp;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_GET_FW_VER, sizeof(*cmd));
124362306a36Sopenharmony_ci	if (!cmd)
124462306a36Sopenharmony_ci		return -ENOMEM;
124562306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
124662306a36Sopenharmony_ci			OCRDMA_CMD_GET_FW_VER,
124762306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
125062306a36Sopenharmony_ci	if (status)
125162306a36Sopenharmony_ci		goto mbx_err;
125262306a36Sopenharmony_ci	rsp = (struct ocrdma_fw_ver_rsp *)cmd;
125362306a36Sopenharmony_ci	memset(&dev->attr.fw_ver[0], 0, sizeof(dev->attr.fw_ver));
125462306a36Sopenharmony_ci	memcpy(&dev->attr.fw_ver[0], &rsp->running_ver[0],
125562306a36Sopenharmony_ci	       sizeof(rsp->running_ver));
125662306a36Sopenharmony_ci	ocrdma_le32_to_cpu(dev->attr.fw_ver, sizeof(rsp->running_ver));
125762306a36Sopenharmony_cimbx_err:
125862306a36Sopenharmony_ci	kfree(cmd);
125962306a36Sopenharmony_ci	return status;
126062306a36Sopenharmony_ci}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci/* can be issued only during init time. */
126362306a36Sopenharmony_cistatic int ocrdma_mbx_query_fw_config(struct ocrdma_dev *dev)
126462306a36Sopenharmony_ci{
126562306a36Sopenharmony_ci	int status = -ENOMEM;
126662306a36Sopenharmony_ci	struct ocrdma_mqe *cmd;
126762306a36Sopenharmony_ci	struct ocrdma_fw_conf_rsp *rsp;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_GET_FW_CONFIG, sizeof(*cmd));
127062306a36Sopenharmony_ci	if (!cmd)
127162306a36Sopenharmony_ci		return -ENOMEM;
127262306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
127362306a36Sopenharmony_ci			OCRDMA_CMD_GET_FW_CONFIG,
127462306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
127562306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
127662306a36Sopenharmony_ci	if (status)
127762306a36Sopenharmony_ci		goto mbx_err;
127862306a36Sopenharmony_ci	rsp = (struct ocrdma_fw_conf_rsp *)cmd;
127962306a36Sopenharmony_ci	status = ocrdma_check_fw_config(dev, rsp);
128062306a36Sopenharmony_cimbx_err:
128162306a36Sopenharmony_ci	kfree(cmd);
128262306a36Sopenharmony_ci	return status;
128362306a36Sopenharmony_ci}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ciint ocrdma_mbx_rdma_stats(struct ocrdma_dev *dev, bool reset)
128662306a36Sopenharmony_ci{
128762306a36Sopenharmony_ci	struct ocrdma_rdma_stats_req *req = dev->stats_mem.va;
128862306a36Sopenharmony_ci	struct ocrdma_mqe *mqe = &dev->stats_mem.mqe;
128962306a36Sopenharmony_ci	struct ocrdma_rdma_stats_resp *old_stats;
129062306a36Sopenharmony_ci	int status;
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	old_stats = kmalloc(sizeof(*old_stats), GFP_KERNEL);
129362306a36Sopenharmony_ci	if (old_stats == NULL)
129462306a36Sopenharmony_ci		return -ENOMEM;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	memset(mqe, 0, sizeof(*mqe));
129762306a36Sopenharmony_ci	mqe->hdr.pyld_len = dev->stats_mem.size;
129862306a36Sopenharmony_ci	mqe->hdr.spcl_sge_cnt_emb |=
129962306a36Sopenharmony_ci			(1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) &
130062306a36Sopenharmony_ci				OCRDMA_MQE_HDR_SGE_CNT_MASK;
130162306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].pa_lo = (u32) (dev->stats_mem.pa & 0xffffffff);
130262306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].pa_hi = (u32) upper_32_bits(dev->stats_mem.pa);
130362306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].len = dev->stats_mem.size;
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	/* Cache the old stats */
130662306a36Sopenharmony_ci	memcpy(old_stats, req, sizeof(struct ocrdma_rdma_stats_resp));
130762306a36Sopenharmony_ci	memset(req, 0, dev->stats_mem.size);
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)req,
131062306a36Sopenharmony_ci			OCRDMA_CMD_GET_RDMA_STATS,
131162306a36Sopenharmony_ci			OCRDMA_SUBSYS_ROCE,
131262306a36Sopenharmony_ci			dev->stats_mem.size);
131362306a36Sopenharmony_ci	if (reset)
131462306a36Sopenharmony_ci		req->reset_stats = reset;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	status = ocrdma_nonemb_mbx_cmd(dev, mqe, dev->stats_mem.va);
131762306a36Sopenharmony_ci	if (status)
131862306a36Sopenharmony_ci		/* Copy from cache, if mbox fails */
131962306a36Sopenharmony_ci		memcpy(req, old_stats, sizeof(struct ocrdma_rdma_stats_resp));
132062306a36Sopenharmony_ci	else
132162306a36Sopenharmony_ci		ocrdma_le32_to_cpu(req, dev->stats_mem.size);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	kfree(old_stats);
132462306a36Sopenharmony_ci	return status;
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_cistatic int ocrdma_mbx_get_ctrl_attribs(struct ocrdma_dev *dev)
132862306a36Sopenharmony_ci{
132962306a36Sopenharmony_ci	int status = -ENOMEM;
133062306a36Sopenharmony_ci	struct ocrdma_dma_mem dma;
133162306a36Sopenharmony_ci	struct ocrdma_mqe *mqe;
133262306a36Sopenharmony_ci	struct ocrdma_get_ctrl_attribs_rsp *ctrl_attr_rsp;
133362306a36Sopenharmony_ci	struct mgmt_hba_attribs *hba_attribs;
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci	mqe = kzalloc(sizeof(struct ocrdma_mqe), GFP_KERNEL);
133662306a36Sopenharmony_ci	if (!mqe)
133762306a36Sopenharmony_ci		return status;
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci	dma.size = sizeof(struct ocrdma_get_ctrl_attribs_rsp);
134062306a36Sopenharmony_ci	dma.va	 = dma_alloc_coherent(&dev->nic_info.pdev->dev,
134162306a36Sopenharmony_ci					dma.size, &dma.pa, GFP_KERNEL);
134262306a36Sopenharmony_ci	if (!dma.va)
134362306a36Sopenharmony_ci		goto free_mqe;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	mqe->hdr.pyld_len = dma.size;
134662306a36Sopenharmony_ci	mqe->hdr.spcl_sge_cnt_emb |=
134762306a36Sopenharmony_ci			(1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) &
134862306a36Sopenharmony_ci			OCRDMA_MQE_HDR_SGE_CNT_MASK;
134962306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].pa_lo = (u32) (dma.pa & 0xffffffff);
135062306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].pa_hi = (u32) upper_32_bits(dma.pa);
135162306a36Sopenharmony_ci	mqe->u.nonemb_req.sge[0].len = dma.size;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)dma.va,
135462306a36Sopenharmony_ci			OCRDMA_CMD_GET_CTRL_ATTRIBUTES,
135562306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON,
135662306a36Sopenharmony_ci			dma.size);
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	status = ocrdma_nonemb_mbx_cmd(dev, mqe, dma.va);
135962306a36Sopenharmony_ci	if (!status) {
136062306a36Sopenharmony_ci		ctrl_attr_rsp = (struct ocrdma_get_ctrl_attribs_rsp *)dma.va;
136162306a36Sopenharmony_ci		hba_attribs = &ctrl_attr_rsp->ctrl_attribs.hba_attribs;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci		dev->hba_port_num = (hba_attribs->ptpnum_maxdoms_hbast_cv &
136462306a36Sopenharmony_ci					OCRDMA_HBA_ATTRB_PTNUM_MASK)
136562306a36Sopenharmony_ci					>> OCRDMA_HBA_ATTRB_PTNUM_SHIFT;
136662306a36Sopenharmony_ci		strscpy(dev->model_number,
136762306a36Sopenharmony_ci			hba_attribs->controller_model_number,
136862306a36Sopenharmony_ci			sizeof(dev->model_number));
136962306a36Sopenharmony_ci	}
137062306a36Sopenharmony_ci	dma_free_coherent(&dev->nic_info.pdev->dev, dma.size, dma.va, dma.pa);
137162306a36Sopenharmony_cifree_mqe:
137262306a36Sopenharmony_ci	kfree(mqe);
137362306a36Sopenharmony_ci	return status;
137462306a36Sopenharmony_ci}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_cistatic int ocrdma_mbx_query_dev(struct ocrdma_dev *dev)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	int status = -ENOMEM;
137962306a36Sopenharmony_ci	struct ocrdma_mbx_query_config *rsp;
138062306a36Sopenharmony_ci	struct ocrdma_mqe *cmd;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_CONFIG, sizeof(*cmd));
138362306a36Sopenharmony_ci	if (!cmd)
138462306a36Sopenharmony_ci		return status;
138562306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
138662306a36Sopenharmony_ci	if (status)
138762306a36Sopenharmony_ci		goto mbx_err;
138862306a36Sopenharmony_ci	rsp = (struct ocrdma_mbx_query_config *)cmd;
138962306a36Sopenharmony_ci	ocrdma_get_attr(dev, &dev->attr, rsp);
139062306a36Sopenharmony_cimbx_err:
139162306a36Sopenharmony_ci	kfree(cmd);
139262306a36Sopenharmony_ci	return status;
139362306a36Sopenharmony_ci}
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ciint ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed,
139662306a36Sopenharmony_ci			      u8 *lnk_state)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	int status = -ENOMEM;
139962306a36Sopenharmony_ci	struct ocrdma_get_link_speed_rsp *rsp;
140062306a36Sopenharmony_ci	struct ocrdma_mqe *cmd;
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_NTWK_LINK_CONFIG_V1,
140362306a36Sopenharmony_ci				  sizeof(*cmd));
140462306a36Sopenharmony_ci	if (!cmd)
140562306a36Sopenharmony_ci		return status;
140662306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
140762306a36Sopenharmony_ci			OCRDMA_CMD_QUERY_NTWK_LINK_CONFIG_V1,
140862306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	((struct ocrdma_mbx_hdr *)cmd->u.cmd)->rsvd_version = 0x1;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
141362306a36Sopenharmony_ci	if (status)
141462306a36Sopenharmony_ci		goto mbx_err;
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	rsp = (struct ocrdma_get_link_speed_rsp *)cmd;
141762306a36Sopenharmony_ci	if (lnk_speed)
141862306a36Sopenharmony_ci		*lnk_speed = (rsp->pflt_pps_ld_pnum & OCRDMA_PHY_PS_MASK)
141962306a36Sopenharmony_ci			      >> OCRDMA_PHY_PS_SHIFT;
142062306a36Sopenharmony_ci	if (lnk_state)
142162306a36Sopenharmony_ci		*lnk_state = (rsp->res_lnk_st & OCRDMA_LINK_ST_MASK);
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_cimbx_err:
142462306a36Sopenharmony_ci	kfree(cmd);
142562306a36Sopenharmony_ci	return status;
142662306a36Sopenharmony_ci}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_cistatic int ocrdma_mbx_get_phy_info(struct ocrdma_dev *dev)
142962306a36Sopenharmony_ci{
143062306a36Sopenharmony_ci	int status = -ENOMEM;
143162306a36Sopenharmony_ci	struct ocrdma_mqe *cmd;
143262306a36Sopenharmony_ci	struct ocrdma_get_phy_info_rsp *rsp;
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_PHY_DETAILS, sizeof(*cmd));
143562306a36Sopenharmony_ci	if (!cmd)
143662306a36Sopenharmony_ci		return status;
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	ocrdma_init_mch((struct ocrdma_mbx_hdr *)&cmd->u.cmd[0],
143962306a36Sopenharmony_ci			OCRDMA_CMD_PHY_DETAILS, OCRDMA_SUBSYS_COMMON,
144062306a36Sopenharmony_ci			sizeof(*cmd));
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
144362306a36Sopenharmony_ci	if (status)
144462306a36Sopenharmony_ci		goto mbx_err;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	rsp = (struct ocrdma_get_phy_info_rsp *)cmd;
144762306a36Sopenharmony_ci	dev->phy.phy_type =
144862306a36Sopenharmony_ci			(rsp->ityp_ptyp & OCRDMA_PHY_TYPE_MASK);
144962306a36Sopenharmony_ci	dev->phy.interface_type =
145062306a36Sopenharmony_ci			(rsp->ityp_ptyp & OCRDMA_IF_TYPE_MASK)
145162306a36Sopenharmony_ci				>> OCRDMA_IF_TYPE_SHIFT;
145262306a36Sopenharmony_ci	dev->phy.auto_speeds_supported  =
145362306a36Sopenharmony_ci			(rsp->fspeed_aspeed & OCRDMA_ASPEED_SUPP_MASK);
145462306a36Sopenharmony_ci	dev->phy.fixed_speeds_supported =
145562306a36Sopenharmony_ci			(rsp->fspeed_aspeed & OCRDMA_FSPEED_SUPP_MASK)
145662306a36Sopenharmony_ci				>> OCRDMA_FSPEED_SUPP_SHIFT;
145762306a36Sopenharmony_cimbx_err:
145862306a36Sopenharmony_ci	kfree(cmd);
145962306a36Sopenharmony_ci	return status;
146062306a36Sopenharmony_ci}
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ciint ocrdma_mbx_alloc_pd(struct ocrdma_dev *dev, struct ocrdma_pd *pd)
146362306a36Sopenharmony_ci{
146462306a36Sopenharmony_ci	int status = -ENOMEM;
146562306a36Sopenharmony_ci	struct ocrdma_alloc_pd *cmd;
146662306a36Sopenharmony_ci	struct ocrdma_alloc_pd_rsp *rsp;
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_PD, sizeof(*cmd));
146962306a36Sopenharmony_ci	if (!cmd)
147062306a36Sopenharmony_ci		return status;
147162306a36Sopenharmony_ci	if (pd->dpp_enabled)
147262306a36Sopenharmony_ci		cmd->enable_dpp_rsvd |= OCRDMA_ALLOC_PD_ENABLE_DPP;
147362306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
147462306a36Sopenharmony_ci	if (status)
147562306a36Sopenharmony_ci		goto mbx_err;
147662306a36Sopenharmony_ci	rsp = (struct ocrdma_alloc_pd_rsp *)cmd;
147762306a36Sopenharmony_ci	pd->id = rsp->dpp_page_pdid & OCRDMA_ALLOC_PD_RSP_PDID_MASK;
147862306a36Sopenharmony_ci	if (rsp->dpp_page_pdid & OCRDMA_ALLOC_PD_RSP_DPP) {
147962306a36Sopenharmony_ci		pd->dpp_enabled = true;
148062306a36Sopenharmony_ci		pd->dpp_page = rsp->dpp_page_pdid >>
148162306a36Sopenharmony_ci				OCRDMA_ALLOC_PD_RSP_DPP_PAGE_SHIFT;
148262306a36Sopenharmony_ci	} else {
148362306a36Sopenharmony_ci		pd->dpp_enabled = false;
148462306a36Sopenharmony_ci		pd->num_dpp_qp = 0;
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_cimbx_err:
148762306a36Sopenharmony_ci	kfree(cmd);
148862306a36Sopenharmony_ci	return status;
148962306a36Sopenharmony_ci}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ciint ocrdma_mbx_dealloc_pd(struct ocrdma_dev *dev, struct ocrdma_pd *pd)
149262306a36Sopenharmony_ci{
149362306a36Sopenharmony_ci	int status = -ENOMEM;
149462306a36Sopenharmony_ci	struct ocrdma_dealloc_pd *cmd;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_PD, sizeof(*cmd));
149762306a36Sopenharmony_ci	if (!cmd)
149862306a36Sopenharmony_ci		return status;
149962306a36Sopenharmony_ci	cmd->id = pd->id;
150062306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
150162306a36Sopenharmony_ci	kfree(cmd);
150262306a36Sopenharmony_ci	return status;
150362306a36Sopenharmony_ci}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_cistatic int ocrdma_mbx_alloc_pd_range(struct ocrdma_dev *dev)
150762306a36Sopenharmony_ci{
150862306a36Sopenharmony_ci	int status = -ENOMEM;
150962306a36Sopenharmony_ci	struct ocrdma_alloc_pd_range *cmd;
151062306a36Sopenharmony_ci	struct ocrdma_alloc_pd_range_rsp *rsp;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	/* Pre allocate the DPP PDs */
151362306a36Sopenharmony_ci	if (dev->attr.max_dpp_pds) {
151462306a36Sopenharmony_ci		cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_PD_RANGE,
151562306a36Sopenharmony_ci					  sizeof(*cmd));
151662306a36Sopenharmony_ci		if (!cmd)
151762306a36Sopenharmony_ci			return -ENOMEM;
151862306a36Sopenharmony_ci		cmd->pd_count = dev->attr.max_dpp_pds;
151962306a36Sopenharmony_ci		cmd->enable_dpp_rsvd |= OCRDMA_ALLOC_PD_ENABLE_DPP;
152062306a36Sopenharmony_ci		status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
152162306a36Sopenharmony_ci		rsp = (struct ocrdma_alloc_pd_range_rsp *)cmd;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci		if (!status && (rsp->dpp_page_pdid & OCRDMA_ALLOC_PD_RSP_DPP) &&
152462306a36Sopenharmony_ci		    rsp->pd_count) {
152562306a36Sopenharmony_ci			dev->pd_mgr->dpp_page_index = rsp->dpp_page_pdid >>
152662306a36Sopenharmony_ci					OCRDMA_ALLOC_PD_RSP_DPP_PAGE_SHIFT;
152762306a36Sopenharmony_ci			dev->pd_mgr->pd_dpp_start = rsp->dpp_page_pdid &
152862306a36Sopenharmony_ci					OCRDMA_ALLOC_PD_RNG_RSP_START_PDID_MASK;
152962306a36Sopenharmony_ci			dev->pd_mgr->max_dpp_pd = rsp->pd_count;
153062306a36Sopenharmony_ci			dev->pd_mgr->pd_dpp_bitmap = bitmap_zalloc(rsp->pd_count,
153162306a36Sopenharmony_ci								   GFP_KERNEL);
153262306a36Sopenharmony_ci		}
153362306a36Sopenharmony_ci		kfree(cmd);
153462306a36Sopenharmony_ci	}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_PD_RANGE, sizeof(*cmd));
153762306a36Sopenharmony_ci	if (!cmd)
153862306a36Sopenharmony_ci		return -ENOMEM;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	cmd->pd_count = dev->attr.max_pd - dev->attr.max_dpp_pds;
154162306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
154262306a36Sopenharmony_ci	rsp = (struct ocrdma_alloc_pd_range_rsp *)cmd;
154362306a36Sopenharmony_ci	if (!status && rsp->pd_count) {
154462306a36Sopenharmony_ci		dev->pd_mgr->pd_norm_start = rsp->dpp_page_pdid &
154562306a36Sopenharmony_ci					OCRDMA_ALLOC_PD_RNG_RSP_START_PDID_MASK;
154662306a36Sopenharmony_ci		dev->pd_mgr->max_normal_pd = rsp->pd_count;
154762306a36Sopenharmony_ci		dev->pd_mgr->pd_norm_bitmap = bitmap_zalloc(rsp->pd_count,
154862306a36Sopenharmony_ci							    GFP_KERNEL);
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci	kfree(cmd);
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	if (dev->pd_mgr->pd_norm_bitmap || dev->pd_mgr->pd_dpp_bitmap) {
155362306a36Sopenharmony_ci		/* Enable PD resource manager */
155462306a36Sopenharmony_ci		dev->pd_mgr->pd_prealloc_valid = true;
155562306a36Sopenharmony_ci		return 0;
155662306a36Sopenharmony_ci	}
155762306a36Sopenharmony_ci	return status;
155862306a36Sopenharmony_ci}
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_cistatic void ocrdma_mbx_dealloc_pd_range(struct ocrdma_dev *dev)
156162306a36Sopenharmony_ci{
156262306a36Sopenharmony_ci	struct ocrdma_dealloc_pd_range *cmd;
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	/* return normal PDs to firmware */
156562306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_PD_RANGE, sizeof(*cmd));
156662306a36Sopenharmony_ci	if (!cmd)
156762306a36Sopenharmony_ci		goto mbx_err;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (dev->pd_mgr->max_normal_pd) {
157062306a36Sopenharmony_ci		cmd->start_pd_id = dev->pd_mgr->pd_norm_start;
157162306a36Sopenharmony_ci		cmd->pd_count = dev->pd_mgr->max_normal_pd;
157262306a36Sopenharmony_ci		ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
157362306a36Sopenharmony_ci	}
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	if (dev->pd_mgr->max_dpp_pd) {
157662306a36Sopenharmony_ci		kfree(cmd);
157762306a36Sopenharmony_ci		/* return DPP PDs to firmware */
157862306a36Sopenharmony_ci		cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_PD_RANGE,
157962306a36Sopenharmony_ci					  sizeof(*cmd));
158062306a36Sopenharmony_ci		if (!cmd)
158162306a36Sopenharmony_ci			goto mbx_err;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		cmd->start_pd_id = dev->pd_mgr->pd_dpp_start;
158462306a36Sopenharmony_ci		cmd->pd_count = dev->pd_mgr->max_dpp_pd;
158562306a36Sopenharmony_ci		ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
158662306a36Sopenharmony_ci	}
158762306a36Sopenharmony_cimbx_err:
158862306a36Sopenharmony_ci	kfree(cmd);
158962306a36Sopenharmony_ci}
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_civoid ocrdma_alloc_pd_pool(struct ocrdma_dev *dev)
159262306a36Sopenharmony_ci{
159362306a36Sopenharmony_ci	int status;
159462306a36Sopenharmony_ci
159562306a36Sopenharmony_ci	dev->pd_mgr = kzalloc(sizeof(struct ocrdma_pd_resource_mgr),
159662306a36Sopenharmony_ci			      GFP_KERNEL);
159762306a36Sopenharmony_ci	if (!dev->pd_mgr)
159862306a36Sopenharmony_ci		return;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	status = ocrdma_mbx_alloc_pd_range(dev);
160162306a36Sopenharmony_ci	if (status) {
160262306a36Sopenharmony_ci		pr_err("%s(%d) Unable to initialize PD pool, using default.\n",
160362306a36Sopenharmony_ci			 __func__, dev->id);
160462306a36Sopenharmony_ci	}
160562306a36Sopenharmony_ci}
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_cistatic void ocrdma_free_pd_pool(struct ocrdma_dev *dev)
160862306a36Sopenharmony_ci{
160962306a36Sopenharmony_ci	ocrdma_mbx_dealloc_pd_range(dev);
161062306a36Sopenharmony_ci	bitmap_free(dev->pd_mgr->pd_norm_bitmap);
161162306a36Sopenharmony_ci	bitmap_free(dev->pd_mgr->pd_dpp_bitmap);
161262306a36Sopenharmony_ci	kfree(dev->pd_mgr);
161362306a36Sopenharmony_ci}
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_cistatic int ocrdma_build_q_conf(u32 *num_entries, int entry_size,
161662306a36Sopenharmony_ci			       int *num_pages, int *page_size)
161762306a36Sopenharmony_ci{
161862306a36Sopenharmony_ci	int i;
161962306a36Sopenharmony_ci	int mem_size;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	*num_entries = roundup_pow_of_two(*num_entries);
162262306a36Sopenharmony_ci	mem_size = *num_entries * entry_size;
162362306a36Sopenharmony_ci	/* find the possible lowest possible multiplier */
162462306a36Sopenharmony_ci	for (i = 0; i < OCRDMA_MAX_Q_PAGE_SIZE_CNT; i++) {
162562306a36Sopenharmony_ci		if (mem_size <= (OCRDMA_Q_PAGE_BASE_SIZE << i))
162662306a36Sopenharmony_ci			break;
162762306a36Sopenharmony_ci	}
162862306a36Sopenharmony_ci	if (i >= OCRDMA_MAX_Q_PAGE_SIZE_CNT)
162962306a36Sopenharmony_ci		return -EINVAL;
163062306a36Sopenharmony_ci	mem_size = roundup(mem_size,
163162306a36Sopenharmony_ci		       ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES));
163262306a36Sopenharmony_ci	*num_pages =
163362306a36Sopenharmony_ci	    mem_size / ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES);
163462306a36Sopenharmony_ci	*page_size = ((OCRDMA_Q_PAGE_BASE_SIZE << i) / OCRDMA_MAX_Q_PAGES);
163562306a36Sopenharmony_ci	*num_entries = mem_size / entry_size;
163662306a36Sopenharmony_ci	return 0;
163762306a36Sopenharmony_ci}
163862306a36Sopenharmony_ci
163962306a36Sopenharmony_cistatic int ocrdma_mbx_create_ah_tbl(struct ocrdma_dev *dev)
164062306a36Sopenharmony_ci{
164162306a36Sopenharmony_ci	int i;
164262306a36Sopenharmony_ci	int status = -ENOMEM;
164362306a36Sopenharmony_ci	int max_ah;
164462306a36Sopenharmony_ci	struct ocrdma_create_ah_tbl *cmd;
164562306a36Sopenharmony_ci	struct ocrdma_create_ah_tbl_rsp *rsp;
164662306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
164762306a36Sopenharmony_ci	dma_addr_t pa;
164862306a36Sopenharmony_ci	struct ocrdma_pbe *pbes;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_AH_TBL, sizeof(*cmd));
165162306a36Sopenharmony_ci	if (!cmd)
165262306a36Sopenharmony_ci		return status;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	max_ah = OCRDMA_MAX_AH;
165562306a36Sopenharmony_ci	dev->av_tbl.size = sizeof(struct ocrdma_av) * max_ah;
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	/* number of PBEs in PBL */
165862306a36Sopenharmony_ci	cmd->ah_conf = (OCRDMA_AH_TBL_PAGES <<
165962306a36Sopenharmony_ci				OCRDMA_CREATE_AH_NUM_PAGES_SHIFT) &
166062306a36Sopenharmony_ci				OCRDMA_CREATE_AH_NUM_PAGES_MASK;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	/* page size */
166362306a36Sopenharmony_ci	for (i = 0; i < OCRDMA_MAX_Q_PAGE_SIZE_CNT; i++) {
166462306a36Sopenharmony_ci		if (PAGE_SIZE == (OCRDMA_MIN_Q_PAGE_SIZE << i))
166562306a36Sopenharmony_ci			break;
166662306a36Sopenharmony_ci	}
166762306a36Sopenharmony_ci	cmd->ah_conf |= (i << OCRDMA_CREATE_AH_PAGE_SIZE_SHIFT) &
166862306a36Sopenharmony_ci				OCRDMA_CREATE_AH_PAGE_SIZE_MASK;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/* ah_entry size */
167162306a36Sopenharmony_ci	cmd->ah_conf |= (sizeof(struct ocrdma_av) <<
167262306a36Sopenharmony_ci				OCRDMA_CREATE_AH_ENTRY_SIZE_SHIFT) &
167362306a36Sopenharmony_ci				OCRDMA_CREATE_AH_ENTRY_SIZE_MASK;
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	dev->av_tbl.pbl.va = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
167662306a36Sopenharmony_ci						&dev->av_tbl.pbl.pa,
167762306a36Sopenharmony_ci						GFP_KERNEL);
167862306a36Sopenharmony_ci	if (dev->av_tbl.pbl.va == NULL)
167962306a36Sopenharmony_ci		goto mem_err;
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	dev->av_tbl.va = dma_alloc_coherent(&pdev->dev, dev->av_tbl.size,
168262306a36Sopenharmony_ci					    &pa, GFP_KERNEL);
168362306a36Sopenharmony_ci	if (dev->av_tbl.va == NULL)
168462306a36Sopenharmony_ci		goto mem_err_ah;
168562306a36Sopenharmony_ci	dev->av_tbl.pa = pa;
168662306a36Sopenharmony_ci	dev->av_tbl.num_ah = max_ah;
168762306a36Sopenharmony_ci
168862306a36Sopenharmony_ci	pbes = (struct ocrdma_pbe *)dev->av_tbl.pbl.va;
168962306a36Sopenharmony_ci	for (i = 0; i < dev->av_tbl.size / OCRDMA_MIN_Q_PAGE_SIZE; i++) {
169062306a36Sopenharmony_ci		pbes[i].pa_lo = (u32)cpu_to_le32(pa & 0xffffffff);
169162306a36Sopenharmony_ci		pbes[i].pa_hi = (u32)cpu_to_le32(upper_32_bits(pa));
169262306a36Sopenharmony_ci		pa += PAGE_SIZE;
169362306a36Sopenharmony_ci	}
169462306a36Sopenharmony_ci	cmd->tbl_addr[0].lo = (u32)(dev->av_tbl.pbl.pa & 0xFFFFFFFF);
169562306a36Sopenharmony_ci	cmd->tbl_addr[0].hi = (u32)upper_32_bits(dev->av_tbl.pbl.pa);
169662306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
169762306a36Sopenharmony_ci	if (status)
169862306a36Sopenharmony_ci		goto mbx_err;
169962306a36Sopenharmony_ci	rsp = (struct ocrdma_create_ah_tbl_rsp *)cmd;
170062306a36Sopenharmony_ci	dev->av_tbl.ahid = rsp->ahid & 0xFFFF;
170162306a36Sopenharmony_ci	kfree(cmd);
170262306a36Sopenharmony_ci	return 0;
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_cimbx_err:
170562306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
170662306a36Sopenharmony_ci			  dev->av_tbl.pa);
170762306a36Sopenharmony_ci	dev->av_tbl.va = NULL;
170862306a36Sopenharmony_cimem_err_ah:
170962306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
171062306a36Sopenharmony_ci			  dev->av_tbl.pbl.pa);
171162306a36Sopenharmony_ci	dev->av_tbl.pbl.va = NULL;
171262306a36Sopenharmony_ci	dev->av_tbl.size = 0;
171362306a36Sopenharmony_cimem_err:
171462306a36Sopenharmony_ci	kfree(cmd);
171562306a36Sopenharmony_ci	return status;
171662306a36Sopenharmony_ci}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_cistatic void ocrdma_mbx_delete_ah_tbl(struct ocrdma_dev *dev)
171962306a36Sopenharmony_ci{
172062306a36Sopenharmony_ci	struct ocrdma_delete_ah_tbl *cmd;
172162306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	if (dev->av_tbl.va == NULL)
172462306a36Sopenharmony_ci		return;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_AH_TBL, sizeof(*cmd));
172762306a36Sopenharmony_ci	if (!cmd)
172862306a36Sopenharmony_ci		return;
172962306a36Sopenharmony_ci	cmd->ahid = dev->av_tbl.ahid;
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
173262306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, dev->av_tbl.size, dev->av_tbl.va,
173362306a36Sopenharmony_ci			  dev->av_tbl.pa);
173462306a36Sopenharmony_ci	dev->av_tbl.va = NULL;
173562306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->av_tbl.pbl.va,
173662306a36Sopenharmony_ci			  dev->av_tbl.pbl.pa);
173762306a36Sopenharmony_ci	kfree(cmd);
173862306a36Sopenharmony_ci}
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci/* Multiple CQs uses the EQ. This routine returns least used
174162306a36Sopenharmony_ci * EQ to associate with CQ. This will distributes the interrupt
174262306a36Sopenharmony_ci * processing and CPU load to associated EQ, vector and so to that CPU.
174362306a36Sopenharmony_ci */
174462306a36Sopenharmony_cistatic u16 ocrdma_bind_eq(struct ocrdma_dev *dev)
174562306a36Sopenharmony_ci{
174662306a36Sopenharmony_ci	int i, selected_eq = 0, cq_cnt = 0;
174762306a36Sopenharmony_ci	u16 eq_id;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	mutex_lock(&dev->dev_lock);
175062306a36Sopenharmony_ci	cq_cnt = dev->eq_tbl[0].cq_cnt;
175162306a36Sopenharmony_ci	eq_id = dev->eq_tbl[0].q.id;
175262306a36Sopenharmony_ci	/* find the EQ which is has the least number of
175362306a36Sopenharmony_ci	 * CQs associated with it.
175462306a36Sopenharmony_ci	 */
175562306a36Sopenharmony_ci	for (i = 0; i < dev->eq_cnt; i++) {
175662306a36Sopenharmony_ci		if (dev->eq_tbl[i].cq_cnt < cq_cnt) {
175762306a36Sopenharmony_ci			cq_cnt = dev->eq_tbl[i].cq_cnt;
175862306a36Sopenharmony_ci			eq_id = dev->eq_tbl[i].q.id;
175962306a36Sopenharmony_ci			selected_eq = i;
176062306a36Sopenharmony_ci		}
176162306a36Sopenharmony_ci	}
176262306a36Sopenharmony_ci	dev->eq_tbl[selected_eq].cq_cnt += 1;
176362306a36Sopenharmony_ci	mutex_unlock(&dev->dev_lock);
176462306a36Sopenharmony_ci	return eq_id;
176562306a36Sopenharmony_ci}
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_cistatic void ocrdma_unbind_eq(struct ocrdma_dev *dev, u16 eq_id)
176862306a36Sopenharmony_ci{
176962306a36Sopenharmony_ci	int i;
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	mutex_lock(&dev->dev_lock);
177262306a36Sopenharmony_ci	i = ocrdma_get_eq_table_index(dev, eq_id);
177362306a36Sopenharmony_ci	if (i == -EINVAL)
177462306a36Sopenharmony_ci		BUG();
177562306a36Sopenharmony_ci	dev->eq_tbl[i].cq_cnt -= 1;
177662306a36Sopenharmony_ci	mutex_unlock(&dev->dev_lock);
177762306a36Sopenharmony_ci}
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ciint ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
178062306a36Sopenharmony_ci			 int entries, int dpp_cq, u16 pd_id)
178162306a36Sopenharmony_ci{
178262306a36Sopenharmony_ci	int status = -ENOMEM; int max_hw_cqe;
178362306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
178462306a36Sopenharmony_ci	struct ocrdma_create_cq *cmd;
178562306a36Sopenharmony_ci	struct ocrdma_create_cq_rsp *rsp;
178662306a36Sopenharmony_ci	u32 hw_pages, cqe_size, page_size, cqe_count;
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	if (entries > dev->attr.max_cqe) {
178962306a36Sopenharmony_ci		pr_err("%s(%d) max_cqe=0x%x, requester_cqe=0x%x\n",
179062306a36Sopenharmony_ci		       __func__, dev->id, dev->attr.max_cqe, entries);
179162306a36Sopenharmony_ci		return -EINVAL;
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ci	if (dpp_cq && (ocrdma_get_asic_type(dev) != OCRDMA_ASIC_GEN_SKH_R))
179462306a36Sopenharmony_ci		return -EINVAL;
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	if (dpp_cq) {
179762306a36Sopenharmony_ci		cq->max_hw_cqe = 1;
179862306a36Sopenharmony_ci		max_hw_cqe = 1;
179962306a36Sopenharmony_ci		cqe_size = OCRDMA_DPP_CQE_SIZE;
180062306a36Sopenharmony_ci		hw_pages = 1;
180162306a36Sopenharmony_ci	} else {
180262306a36Sopenharmony_ci		cq->max_hw_cqe = dev->attr.max_cqe;
180362306a36Sopenharmony_ci		max_hw_cqe = dev->attr.max_cqe;
180462306a36Sopenharmony_ci		cqe_size = sizeof(struct ocrdma_cqe);
180562306a36Sopenharmony_ci		hw_pages = OCRDMA_CREATE_CQ_MAX_PAGES;
180662306a36Sopenharmony_ci	}
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	cq->len = roundup(max_hw_cqe * cqe_size, OCRDMA_MIN_Q_PAGE_SIZE);
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_CQ, sizeof(*cmd));
181162306a36Sopenharmony_ci	if (!cmd)
181262306a36Sopenharmony_ci		return -ENOMEM;
181362306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ,
181462306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
181562306a36Sopenharmony_ci	cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
181662306a36Sopenharmony_ci	if (!cq->va) {
181762306a36Sopenharmony_ci		status = -ENOMEM;
181862306a36Sopenharmony_ci		goto mem_err;
181962306a36Sopenharmony_ci	}
182062306a36Sopenharmony_ci	page_size = cq->len / hw_pages;
182162306a36Sopenharmony_ci	cmd->cmd.pgsz_pgcnt = (page_size / OCRDMA_MIN_Q_PAGE_SIZE) <<
182262306a36Sopenharmony_ci					OCRDMA_CREATE_CQ_PAGE_SIZE_SHIFT;
182362306a36Sopenharmony_ci	cmd->cmd.pgsz_pgcnt |= hw_pages;
182462306a36Sopenharmony_ci	cmd->cmd.ev_cnt_flags = OCRDMA_CREATE_CQ_DEF_FLAGS;
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	cq->eqn = ocrdma_bind_eq(dev);
182762306a36Sopenharmony_ci	cmd->cmd.req.rsvd_version = OCRDMA_CREATE_CQ_VER3;
182862306a36Sopenharmony_ci	cqe_count = cq->len / cqe_size;
182962306a36Sopenharmony_ci	cq->cqe_cnt = cqe_count;
183062306a36Sopenharmony_ci	if (cqe_count > 1024) {
183162306a36Sopenharmony_ci		/* Set cnt to 3 to indicate more than 1024 cq entries */
183262306a36Sopenharmony_ci		cmd->cmd.ev_cnt_flags |= (0x3 << OCRDMA_CREATE_CQ_CNT_SHIFT);
183362306a36Sopenharmony_ci	} else {
183462306a36Sopenharmony_ci		u8 count = 0;
183562306a36Sopenharmony_ci		switch (cqe_count) {
183662306a36Sopenharmony_ci		case 256:
183762306a36Sopenharmony_ci			count = 0;
183862306a36Sopenharmony_ci			break;
183962306a36Sopenharmony_ci		case 512:
184062306a36Sopenharmony_ci			count = 1;
184162306a36Sopenharmony_ci			break;
184262306a36Sopenharmony_ci		case 1024:
184362306a36Sopenharmony_ci			count = 2;
184462306a36Sopenharmony_ci			break;
184562306a36Sopenharmony_ci		default:
184662306a36Sopenharmony_ci			goto mbx_err;
184762306a36Sopenharmony_ci		}
184862306a36Sopenharmony_ci		cmd->cmd.ev_cnt_flags |= (count << OCRDMA_CREATE_CQ_CNT_SHIFT);
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci	/* shared eq between all the consumer cqs. */
185162306a36Sopenharmony_ci	cmd->cmd.eqn = cq->eqn;
185262306a36Sopenharmony_ci	if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) {
185362306a36Sopenharmony_ci		if (dpp_cq)
185462306a36Sopenharmony_ci			cmd->cmd.pgsz_pgcnt |= OCRDMA_CREATE_CQ_DPP <<
185562306a36Sopenharmony_ci				OCRDMA_CREATE_CQ_TYPE_SHIFT;
185662306a36Sopenharmony_ci		cq->phase_change = false;
185762306a36Sopenharmony_ci		cmd->cmd.pdid_cqecnt = (cq->len / cqe_size);
185862306a36Sopenharmony_ci	} else {
185962306a36Sopenharmony_ci		cmd->cmd.pdid_cqecnt = (cq->len / cqe_size) - 1;
186062306a36Sopenharmony_ci		cmd->cmd.ev_cnt_flags |= OCRDMA_CREATE_CQ_FLAGS_AUTO_VALID;
186162306a36Sopenharmony_ci		cq->phase_change = true;
186262306a36Sopenharmony_ci	}
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci	/* pd_id valid only for v3 */
186562306a36Sopenharmony_ci	cmd->cmd.pdid_cqecnt |= (pd_id <<
186662306a36Sopenharmony_ci		OCRDMA_CREATE_CQ_CMD_PDID_SHIFT);
186762306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->cmd.pa[0], hw_pages, cq->pa, page_size);
186862306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
186962306a36Sopenharmony_ci	if (status)
187062306a36Sopenharmony_ci		goto mbx_err;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	rsp = (struct ocrdma_create_cq_rsp *)cmd;
187362306a36Sopenharmony_ci	cq->id = (u16) (rsp->rsp.cq_id & OCRDMA_CREATE_CQ_RSP_CQ_ID_MASK);
187462306a36Sopenharmony_ci	kfree(cmd);
187562306a36Sopenharmony_ci	return 0;
187662306a36Sopenharmony_cimbx_err:
187762306a36Sopenharmony_ci	ocrdma_unbind_eq(dev, cq->eqn);
187862306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, cq->len, cq->va, cq->pa);
187962306a36Sopenharmony_cimem_err:
188062306a36Sopenharmony_ci	kfree(cmd);
188162306a36Sopenharmony_ci	return status;
188262306a36Sopenharmony_ci}
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_civoid ocrdma_mbx_destroy_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq)
188562306a36Sopenharmony_ci{
188662306a36Sopenharmony_ci	struct ocrdma_destroy_cq *cmd;
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_CQ, sizeof(*cmd));
188962306a36Sopenharmony_ci	if (!cmd)
189062306a36Sopenharmony_ci		return;
189162306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->req, OCRDMA_CMD_DELETE_CQ,
189262306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	cmd->bypass_flush_qid |=
189562306a36Sopenharmony_ci	    (cq->id << OCRDMA_DESTROY_CQ_QID_SHIFT) &
189662306a36Sopenharmony_ci	    OCRDMA_DESTROY_CQ_QID_MASK;
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
189962306a36Sopenharmony_ci	ocrdma_unbind_eq(dev, cq->eqn);
190062306a36Sopenharmony_ci	dma_free_coherent(&dev->nic_info.pdev->dev, cq->len, cq->va, cq->pa);
190162306a36Sopenharmony_ci	kfree(cmd);
190262306a36Sopenharmony_ci}
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ciint ocrdma_mbx_alloc_lkey(struct ocrdma_dev *dev, struct ocrdma_hw_mr *hwmr,
190562306a36Sopenharmony_ci			  u32 pdid, int addr_check)
190662306a36Sopenharmony_ci{
190762306a36Sopenharmony_ci	int status = -ENOMEM;
190862306a36Sopenharmony_ci	struct ocrdma_alloc_lkey *cmd;
190962306a36Sopenharmony_ci	struct ocrdma_alloc_lkey_rsp *rsp;
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_ALLOC_LKEY, sizeof(*cmd));
191262306a36Sopenharmony_ci	if (!cmd)
191362306a36Sopenharmony_ci		return status;
191462306a36Sopenharmony_ci	cmd->pdid = pdid;
191562306a36Sopenharmony_ci	cmd->pbl_sz_flags |= addr_check;
191662306a36Sopenharmony_ci	cmd->pbl_sz_flags |= (hwmr->fr_mr << OCRDMA_ALLOC_LKEY_FMR_SHIFT);
191762306a36Sopenharmony_ci	cmd->pbl_sz_flags |=
191862306a36Sopenharmony_ci	    (hwmr->remote_wr << OCRDMA_ALLOC_LKEY_REMOTE_WR_SHIFT);
191962306a36Sopenharmony_ci	cmd->pbl_sz_flags |=
192062306a36Sopenharmony_ci	    (hwmr->remote_rd << OCRDMA_ALLOC_LKEY_REMOTE_RD_SHIFT);
192162306a36Sopenharmony_ci	cmd->pbl_sz_flags |=
192262306a36Sopenharmony_ci	    (hwmr->local_wr << OCRDMA_ALLOC_LKEY_LOCAL_WR_SHIFT);
192362306a36Sopenharmony_ci	cmd->pbl_sz_flags |=
192462306a36Sopenharmony_ci	    (hwmr->remote_atomic << OCRDMA_ALLOC_LKEY_REMOTE_ATOMIC_SHIFT);
192562306a36Sopenharmony_ci	cmd->pbl_sz_flags |=
192662306a36Sopenharmony_ci	    (hwmr->num_pbls << OCRDMA_ALLOC_LKEY_PBL_SIZE_SHIFT);
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
192962306a36Sopenharmony_ci	if (status)
193062306a36Sopenharmony_ci		goto mbx_err;
193162306a36Sopenharmony_ci	rsp = (struct ocrdma_alloc_lkey_rsp *)cmd;
193262306a36Sopenharmony_ci	hwmr->lkey = rsp->lrkey;
193362306a36Sopenharmony_cimbx_err:
193462306a36Sopenharmony_ci	kfree(cmd);
193562306a36Sopenharmony_ci	return status;
193662306a36Sopenharmony_ci}
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ciint ocrdma_mbx_dealloc_lkey(struct ocrdma_dev *dev, int fr_mr, u32 lkey)
193962306a36Sopenharmony_ci{
194062306a36Sopenharmony_ci	int status;
194162306a36Sopenharmony_ci	struct ocrdma_dealloc_lkey *cmd;
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DEALLOC_LKEY, sizeof(*cmd));
194462306a36Sopenharmony_ci	if (!cmd)
194562306a36Sopenharmony_ci		return -ENOMEM;
194662306a36Sopenharmony_ci	cmd->lkey = lkey;
194762306a36Sopenharmony_ci	cmd->rsvd_frmr = fr_mr ? 1 : 0;
194862306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	kfree(cmd);
195162306a36Sopenharmony_ci	return status;
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cistatic int ocrdma_mbx_reg_mr(struct ocrdma_dev *dev, struct ocrdma_hw_mr *hwmr,
195562306a36Sopenharmony_ci			     u32 pdid, u32 pbl_cnt, u32 pbe_size, u32 last)
195662306a36Sopenharmony_ci{
195762306a36Sopenharmony_ci	int status = -ENOMEM;
195862306a36Sopenharmony_ci	int i;
195962306a36Sopenharmony_ci	struct ocrdma_reg_nsmr *cmd;
196062306a36Sopenharmony_ci	struct ocrdma_reg_nsmr_rsp *rsp;
196162306a36Sopenharmony_ci	u64 fbo = hwmr->va & (hwmr->pbe_size - 1);
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_REGISTER_NSMR, sizeof(*cmd));
196462306a36Sopenharmony_ci	if (!cmd)
196562306a36Sopenharmony_ci		return -ENOMEM;
196662306a36Sopenharmony_ci	cmd->num_pbl_pdid =
196762306a36Sopenharmony_ci	    pdid | (hwmr->num_pbls << OCRDMA_REG_NSMR_NUM_PBL_SHIFT);
196862306a36Sopenharmony_ci	cmd->fr_mr = hwmr->fr_mr;
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->remote_wr <<
197162306a36Sopenharmony_ci				    OCRDMA_REG_NSMR_REMOTE_WR_SHIFT);
197262306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->remote_rd <<
197362306a36Sopenharmony_ci				    OCRDMA_REG_NSMR_REMOTE_RD_SHIFT);
197462306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->local_wr <<
197562306a36Sopenharmony_ci				    OCRDMA_REG_NSMR_LOCAL_WR_SHIFT);
197662306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->remote_atomic <<
197762306a36Sopenharmony_ci				    OCRDMA_REG_NSMR_REMOTE_ATOMIC_SHIFT);
197862306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->mw_bind <<
197962306a36Sopenharmony_ci				    OCRDMA_REG_NSMR_BIND_MEMWIN_SHIFT);
198062306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (last << OCRDMA_REG_NSMR_LAST_SHIFT);
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->pbe_size / OCRDMA_MIN_HPAGE_SIZE);
198362306a36Sopenharmony_ci	cmd->flags_hpage_pbe_sz |= (hwmr->pbl_size / OCRDMA_MIN_HPAGE_SIZE) <<
198462306a36Sopenharmony_ci					OCRDMA_REG_NSMR_HPAGE_SIZE_SHIFT;
198562306a36Sopenharmony_ci	cmd->totlen_low = hwmr->len;
198662306a36Sopenharmony_ci	cmd->totlen_high = upper_32_bits(hwmr->len);
198762306a36Sopenharmony_ci	cmd->fbo_low = lower_32_bits(fbo);
198862306a36Sopenharmony_ci	cmd->fbo_high = upper_32_bits(fbo);
198962306a36Sopenharmony_ci	cmd->va_loaddr = (u32) hwmr->va;
199062306a36Sopenharmony_ci	cmd->va_hiaddr = (u32) upper_32_bits(hwmr->va);
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_ci	for (i = 0; i < pbl_cnt; i++) {
199362306a36Sopenharmony_ci		cmd->pbl[i].lo = (u32) (hwmr->pbl_table[i].pa & 0xffffffff);
199462306a36Sopenharmony_ci		cmd->pbl[i].hi = upper_32_bits(hwmr->pbl_table[i].pa);
199562306a36Sopenharmony_ci	}
199662306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
199762306a36Sopenharmony_ci	if (status)
199862306a36Sopenharmony_ci		goto mbx_err;
199962306a36Sopenharmony_ci	rsp = (struct ocrdma_reg_nsmr_rsp *)cmd;
200062306a36Sopenharmony_ci	hwmr->lkey = rsp->lrkey;
200162306a36Sopenharmony_cimbx_err:
200262306a36Sopenharmony_ci	kfree(cmd);
200362306a36Sopenharmony_ci	return status;
200462306a36Sopenharmony_ci}
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_cistatic int ocrdma_mbx_reg_mr_cont(struct ocrdma_dev *dev,
200762306a36Sopenharmony_ci				  struct ocrdma_hw_mr *hwmr, u32 pbl_cnt,
200862306a36Sopenharmony_ci				  u32 pbl_offset, u32 last)
200962306a36Sopenharmony_ci{
201062306a36Sopenharmony_ci	int status;
201162306a36Sopenharmony_ci	int i;
201262306a36Sopenharmony_ci	struct ocrdma_reg_nsmr_cont *cmd;
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_REGISTER_NSMR_CONT, sizeof(*cmd));
201562306a36Sopenharmony_ci	if (!cmd)
201662306a36Sopenharmony_ci		return -ENOMEM;
201762306a36Sopenharmony_ci	cmd->lrkey = hwmr->lkey;
201862306a36Sopenharmony_ci	cmd->num_pbl_offset = (pbl_cnt << OCRDMA_REG_NSMR_CONT_NUM_PBL_SHIFT) |
201962306a36Sopenharmony_ci	    (pbl_offset & OCRDMA_REG_NSMR_CONT_PBL_SHIFT_MASK);
202062306a36Sopenharmony_ci	cmd->last = last << OCRDMA_REG_NSMR_CONT_LAST_SHIFT;
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	for (i = 0; i < pbl_cnt; i++) {
202362306a36Sopenharmony_ci		cmd->pbl[i].lo =
202462306a36Sopenharmony_ci		    (u32) (hwmr->pbl_table[i + pbl_offset].pa & 0xffffffff);
202562306a36Sopenharmony_ci		cmd->pbl[i].hi =
202662306a36Sopenharmony_ci		    upper_32_bits(hwmr->pbl_table[i + pbl_offset].pa);
202762306a36Sopenharmony_ci	}
202862306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	kfree(cmd);
203162306a36Sopenharmony_ci	return status;
203262306a36Sopenharmony_ci}
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ciint ocrdma_reg_mr(struct ocrdma_dev *dev,
203562306a36Sopenharmony_ci		  struct ocrdma_hw_mr *hwmr, u32 pdid, int acc)
203662306a36Sopenharmony_ci{
203762306a36Sopenharmony_ci	int status;
203862306a36Sopenharmony_ci	u32 last = 0;
203962306a36Sopenharmony_ci	u32 cur_pbl_cnt, pbl_offset;
204062306a36Sopenharmony_ci	u32 pending_pbl_cnt = hwmr->num_pbls;
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	pbl_offset = 0;
204362306a36Sopenharmony_ci	cur_pbl_cnt = min(pending_pbl_cnt, MAX_OCRDMA_NSMR_PBL);
204462306a36Sopenharmony_ci	if (cur_pbl_cnt == pending_pbl_cnt)
204562306a36Sopenharmony_ci		last = 1;
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	status = ocrdma_mbx_reg_mr(dev, hwmr, pdid,
204862306a36Sopenharmony_ci				   cur_pbl_cnt, hwmr->pbe_size, last);
204962306a36Sopenharmony_ci	if (status) {
205062306a36Sopenharmony_ci		pr_err("%s() status=%d\n", __func__, status);
205162306a36Sopenharmony_ci		return status;
205262306a36Sopenharmony_ci	}
205362306a36Sopenharmony_ci	/* if there is no more pbls to register then exit. */
205462306a36Sopenharmony_ci	if (last)
205562306a36Sopenharmony_ci		return 0;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	while (!last) {
205862306a36Sopenharmony_ci		pbl_offset += cur_pbl_cnt;
205962306a36Sopenharmony_ci		pending_pbl_cnt -= cur_pbl_cnt;
206062306a36Sopenharmony_ci		cur_pbl_cnt = min(pending_pbl_cnt, MAX_OCRDMA_NSMR_PBL);
206162306a36Sopenharmony_ci		/* if we reach the end of the pbls, then need to set the last
206262306a36Sopenharmony_ci		 * bit, indicating no more pbls to register for this memory key.
206362306a36Sopenharmony_ci		 */
206462306a36Sopenharmony_ci		if (cur_pbl_cnt == pending_pbl_cnt)
206562306a36Sopenharmony_ci			last = 1;
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci		status = ocrdma_mbx_reg_mr_cont(dev, hwmr, cur_pbl_cnt,
206862306a36Sopenharmony_ci						pbl_offset, last);
206962306a36Sopenharmony_ci		if (status)
207062306a36Sopenharmony_ci			break;
207162306a36Sopenharmony_ci	}
207262306a36Sopenharmony_ci	if (status)
207362306a36Sopenharmony_ci		pr_err("%s() err. status=%d\n", __func__, status);
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	return status;
207662306a36Sopenharmony_ci}
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_cibool ocrdma_is_qp_in_sq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp)
207962306a36Sopenharmony_ci{
208062306a36Sopenharmony_ci	struct ocrdma_qp *tmp;
208162306a36Sopenharmony_ci	bool found = false;
208262306a36Sopenharmony_ci	list_for_each_entry(tmp, &cq->sq_head, sq_entry) {
208362306a36Sopenharmony_ci		if (qp == tmp) {
208462306a36Sopenharmony_ci			found = true;
208562306a36Sopenharmony_ci			break;
208662306a36Sopenharmony_ci		}
208762306a36Sopenharmony_ci	}
208862306a36Sopenharmony_ci	return found;
208962306a36Sopenharmony_ci}
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_cibool ocrdma_is_qp_in_rq_flushlist(struct ocrdma_cq *cq, struct ocrdma_qp *qp)
209262306a36Sopenharmony_ci{
209362306a36Sopenharmony_ci	struct ocrdma_qp *tmp;
209462306a36Sopenharmony_ci	bool found = false;
209562306a36Sopenharmony_ci	list_for_each_entry(tmp, &cq->rq_head, rq_entry) {
209662306a36Sopenharmony_ci		if (qp == tmp) {
209762306a36Sopenharmony_ci			found = true;
209862306a36Sopenharmony_ci			break;
209962306a36Sopenharmony_ci		}
210062306a36Sopenharmony_ci	}
210162306a36Sopenharmony_ci	return found;
210262306a36Sopenharmony_ci}
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_civoid ocrdma_flush_qp(struct ocrdma_qp *qp)
210562306a36Sopenharmony_ci{
210662306a36Sopenharmony_ci	bool found;
210762306a36Sopenharmony_ci	unsigned long flags;
210862306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
210962306a36Sopenharmony_ci
211062306a36Sopenharmony_ci	spin_lock_irqsave(&dev->flush_q_lock, flags);
211162306a36Sopenharmony_ci	found = ocrdma_is_qp_in_sq_flushlist(qp->sq_cq, qp);
211262306a36Sopenharmony_ci	if (!found)
211362306a36Sopenharmony_ci		list_add_tail(&qp->sq_entry, &qp->sq_cq->sq_head);
211462306a36Sopenharmony_ci	if (!qp->srq) {
211562306a36Sopenharmony_ci		found = ocrdma_is_qp_in_rq_flushlist(qp->rq_cq, qp);
211662306a36Sopenharmony_ci		if (!found)
211762306a36Sopenharmony_ci			list_add_tail(&qp->rq_entry, &qp->rq_cq->rq_head);
211862306a36Sopenharmony_ci	}
211962306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->flush_q_lock, flags);
212062306a36Sopenharmony_ci}
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_cistatic void ocrdma_init_hwq_ptr(struct ocrdma_qp *qp)
212362306a36Sopenharmony_ci{
212462306a36Sopenharmony_ci	qp->sq.head = 0;
212562306a36Sopenharmony_ci	qp->sq.tail = 0;
212662306a36Sopenharmony_ci	qp->rq.head = 0;
212762306a36Sopenharmony_ci	qp->rq.tail = 0;
212862306a36Sopenharmony_ci}
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ciint ocrdma_qp_state_change(struct ocrdma_qp *qp, enum ib_qp_state new_ib_state,
213162306a36Sopenharmony_ci			   enum ib_qp_state *old_ib_state)
213262306a36Sopenharmony_ci{
213362306a36Sopenharmony_ci	unsigned long flags;
213462306a36Sopenharmony_ci	enum ocrdma_qp_state new_state;
213562306a36Sopenharmony_ci	new_state = get_ocrdma_qp_state(new_ib_state);
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	/* sync with wqe and rqe posting */
213862306a36Sopenharmony_ci	spin_lock_irqsave(&qp->q_lock, flags);
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	if (old_ib_state)
214162306a36Sopenharmony_ci		*old_ib_state = get_ibqp_state(qp->state);
214262306a36Sopenharmony_ci	if (new_state == qp->state) {
214362306a36Sopenharmony_ci		spin_unlock_irqrestore(&qp->q_lock, flags);
214462306a36Sopenharmony_ci		return 1;
214562306a36Sopenharmony_ci	}
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci	if (new_state == OCRDMA_QPS_INIT) {
214962306a36Sopenharmony_ci		ocrdma_init_hwq_ptr(qp);
215062306a36Sopenharmony_ci		ocrdma_del_flush_qp(qp);
215162306a36Sopenharmony_ci	} else if (new_state == OCRDMA_QPS_ERR) {
215262306a36Sopenharmony_ci		ocrdma_flush_qp(qp);
215362306a36Sopenharmony_ci	}
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	qp->state = new_state;
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	spin_unlock_irqrestore(&qp->q_lock, flags);
215862306a36Sopenharmony_ci	return 0;
215962306a36Sopenharmony_ci}
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_cistatic u32 ocrdma_set_create_qp_mbx_access_flags(struct ocrdma_qp *qp)
216262306a36Sopenharmony_ci{
216362306a36Sopenharmony_ci	u32 flags = 0;
216462306a36Sopenharmony_ci	if (qp->cap_flags & OCRDMA_QP_INB_RD)
216562306a36Sopenharmony_ci		flags |= OCRDMA_CREATE_QP_REQ_INB_RDEN_MASK;
216662306a36Sopenharmony_ci	if (qp->cap_flags & OCRDMA_QP_INB_WR)
216762306a36Sopenharmony_ci		flags |= OCRDMA_CREATE_QP_REQ_INB_WREN_MASK;
216862306a36Sopenharmony_ci	if (qp->cap_flags & OCRDMA_QP_MW_BIND)
216962306a36Sopenharmony_ci		flags |= OCRDMA_CREATE_QP_REQ_BIND_MEMWIN_MASK;
217062306a36Sopenharmony_ci	if (qp->cap_flags & OCRDMA_QP_LKEY0)
217162306a36Sopenharmony_ci		flags |= OCRDMA_CREATE_QP_REQ_ZERO_LKEYEN_MASK;
217262306a36Sopenharmony_ci	if (qp->cap_flags & OCRDMA_QP_FAST_REG)
217362306a36Sopenharmony_ci		flags |= OCRDMA_CREATE_QP_REQ_FMR_EN_MASK;
217462306a36Sopenharmony_ci	return flags;
217562306a36Sopenharmony_ci}
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_cistatic int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd,
217862306a36Sopenharmony_ci					struct ib_qp_init_attr *attrs,
217962306a36Sopenharmony_ci					struct ocrdma_qp *qp)
218062306a36Sopenharmony_ci{
218162306a36Sopenharmony_ci	int status;
218262306a36Sopenharmony_ci	u32 len, hw_pages, hw_page_size;
218362306a36Sopenharmony_ci	dma_addr_t pa;
218462306a36Sopenharmony_ci	struct ocrdma_pd *pd = qp->pd;
218562306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
218662306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
218762306a36Sopenharmony_ci	u32 max_wqe_allocated;
218862306a36Sopenharmony_ci	u32 max_sges = attrs->cap.max_send_sge;
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	/* QP1 may exceed 127 */
219162306a36Sopenharmony_ci	max_wqe_allocated = min_t(u32, attrs->cap.max_send_wr + 1,
219262306a36Sopenharmony_ci				dev->attr.max_wqe);
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	status = ocrdma_build_q_conf(&max_wqe_allocated,
219562306a36Sopenharmony_ci		dev->attr.wqe_size, &hw_pages, &hw_page_size);
219662306a36Sopenharmony_ci	if (status) {
219762306a36Sopenharmony_ci		pr_err("%s() req. max_send_wr=0x%x\n", __func__,
219862306a36Sopenharmony_ci		       max_wqe_allocated);
219962306a36Sopenharmony_ci		return -EINVAL;
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci	qp->sq.max_cnt = max_wqe_allocated;
220262306a36Sopenharmony_ci	len = (hw_pages * hw_page_size);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
220562306a36Sopenharmony_ci	if (!qp->sq.va)
220662306a36Sopenharmony_ci		return -EINVAL;
220762306a36Sopenharmony_ci	qp->sq.len = len;
220862306a36Sopenharmony_ci	qp->sq.pa = pa;
220962306a36Sopenharmony_ci	qp->sq.entry_size = dev->attr.wqe_size;
221062306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->wq_addr[0], hw_pages, pa, hw_page_size);
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	cmd->type_pgsz_pdn |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE)
221362306a36Sopenharmony_ci				<< OCRDMA_CREATE_QP_REQ_SQ_PAGE_SIZE_SHIFT);
221462306a36Sopenharmony_ci	cmd->num_wq_rq_pages |= (hw_pages <<
221562306a36Sopenharmony_ci				 OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_SHIFT) &
221662306a36Sopenharmony_ci	    OCRDMA_CREATE_QP_REQ_NUM_WQ_PAGES_MASK;
221762306a36Sopenharmony_ci	cmd->max_sge_send_write |= (max_sges <<
221862306a36Sopenharmony_ci				    OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_SHIFT) &
221962306a36Sopenharmony_ci	    OCRDMA_CREATE_QP_REQ_MAX_SGE_SEND_MASK;
222062306a36Sopenharmony_ci	cmd->max_sge_send_write |= (max_sges <<
222162306a36Sopenharmony_ci				    OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_SHIFT) &
222262306a36Sopenharmony_ci					OCRDMA_CREATE_QP_REQ_MAX_SGE_WRITE_MASK;
222362306a36Sopenharmony_ci	cmd->max_wqe_rqe |= (ilog2(qp->sq.max_cnt) <<
222462306a36Sopenharmony_ci			     OCRDMA_CREATE_QP_REQ_MAX_WQE_SHIFT) &
222562306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_WQE_MASK;
222662306a36Sopenharmony_ci	cmd->wqe_rqe_size |= (dev->attr.wqe_size <<
222762306a36Sopenharmony_ci			      OCRDMA_CREATE_QP_REQ_WQE_SIZE_SHIFT) &
222862306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_WQE_SIZE_MASK;
222962306a36Sopenharmony_ci	return 0;
223062306a36Sopenharmony_ci}
223162306a36Sopenharmony_ci
223262306a36Sopenharmony_cistatic int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd,
223362306a36Sopenharmony_ci					struct ib_qp_init_attr *attrs,
223462306a36Sopenharmony_ci					struct ocrdma_qp *qp)
223562306a36Sopenharmony_ci{
223662306a36Sopenharmony_ci	int status;
223762306a36Sopenharmony_ci	u32 len, hw_pages, hw_page_size;
223862306a36Sopenharmony_ci	dma_addr_t pa = 0;
223962306a36Sopenharmony_ci	struct ocrdma_pd *pd = qp->pd;
224062306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
224162306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
224262306a36Sopenharmony_ci	u32 max_rqe_allocated = attrs->cap.max_recv_wr + 1;
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci	status = ocrdma_build_q_conf(&max_rqe_allocated, dev->attr.rqe_size,
224562306a36Sopenharmony_ci				     &hw_pages, &hw_page_size);
224662306a36Sopenharmony_ci	if (status) {
224762306a36Sopenharmony_ci		pr_err("%s() req. max_recv_wr=0x%x\n", __func__,
224862306a36Sopenharmony_ci		       attrs->cap.max_recv_wr + 1);
224962306a36Sopenharmony_ci		return status;
225062306a36Sopenharmony_ci	}
225162306a36Sopenharmony_ci	qp->rq.max_cnt = max_rqe_allocated;
225262306a36Sopenharmony_ci	len = (hw_pages * hw_page_size);
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci	qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
225562306a36Sopenharmony_ci	if (!qp->rq.va)
225662306a36Sopenharmony_ci		return -ENOMEM;
225762306a36Sopenharmony_ci	qp->rq.pa = pa;
225862306a36Sopenharmony_ci	qp->rq.len = len;
225962306a36Sopenharmony_ci	qp->rq.entry_size = dev->attr.rqe_size;
226062306a36Sopenharmony_ci
226162306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->rq_addr[0], hw_pages, pa, hw_page_size);
226262306a36Sopenharmony_ci	cmd->type_pgsz_pdn |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE) <<
226362306a36Sopenharmony_ci		OCRDMA_CREATE_QP_REQ_RQ_PAGE_SIZE_SHIFT);
226462306a36Sopenharmony_ci	cmd->num_wq_rq_pages |=
226562306a36Sopenharmony_ci	    (hw_pages << OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_SHIFT) &
226662306a36Sopenharmony_ci	    OCRDMA_CREATE_QP_REQ_NUM_RQ_PAGES_MASK;
226762306a36Sopenharmony_ci	cmd->max_sge_recv_flags |= (attrs->cap.max_recv_sge <<
226862306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_SHIFT) &
226962306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_SGE_RECV_MASK;
227062306a36Sopenharmony_ci	cmd->max_wqe_rqe |= (ilog2(qp->rq.max_cnt) <<
227162306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_RQE_SHIFT) &
227262306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_RQE_MASK;
227362306a36Sopenharmony_ci	cmd->wqe_rqe_size |= (dev->attr.rqe_size <<
227462306a36Sopenharmony_ci			OCRDMA_CREATE_QP_REQ_RQE_SIZE_SHIFT) &
227562306a36Sopenharmony_ci			OCRDMA_CREATE_QP_REQ_RQE_SIZE_MASK;
227662306a36Sopenharmony_ci	return 0;
227762306a36Sopenharmony_ci}
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_cistatic void ocrdma_set_create_qp_dpp_cmd(struct ocrdma_create_qp_req *cmd,
228062306a36Sopenharmony_ci					 struct ocrdma_pd *pd,
228162306a36Sopenharmony_ci					 struct ocrdma_qp *qp,
228262306a36Sopenharmony_ci					 u8 enable_dpp_cq, u16 dpp_cq_id)
228362306a36Sopenharmony_ci{
228462306a36Sopenharmony_ci	pd->num_dpp_qp--;
228562306a36Sopenharmony_ci	qp->dpp_enabled = true;
228662306a36Sopenharmony_ci	cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_ENABLE_DPP_MASK;
228762306a36Sopenharmony_ci	if (!enable_dpp_cq)
228862306a36Sopenharmony_ci		return;
228962306a36Sopenharmony_ci	cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_ENABLE_DPP_MASK;
229062306a36Sopenharmony_ci	cmd->dpp_credits_cqid = dpp_cq_id;
229162306a36Sopenharmony_ci	cmd->dpp_credits_cqid |= OCRDMA_CREATE_QP_REQ_DPP_CREDIT_LIMIT <<
229262306a36Sopenharmony_ci					OCRDMA_CREATE_QP_REQ_DPP_CREDIT_SHIFT;
229362306a36Sopenharmony_ci}
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_cistatic int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd,
229662306a36Sopenharmony_ci					struct ocrdma_qp *qp)
229762306a36Sopenharmony_ci{
229862306a36Sopenharmony_ci	struct ocrdma_pd *pd = qp->pd;
229962306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
230062306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
230162306a36Sopenharmony_ci	dma_addr_t pa = 0;
230262306a36Sopenharmony_ci	int ird_page_size = dev->attr.ird_page_size;
230362306a36Sopenharmony_ci	int ird_q_len = dev->attr.num_ird_pages * ird_page_size;
230462306a36Sopenharmony_ci	struct ocrdma_hdr_wqe *rqe;
230562306a36Sopenharmony_ci	int i  = 0;
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	if (dev->attr.ird == 0)
230862306a36Sopenharmony_ci		return 0;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len, &pa,
231162306a36Sopenharmony_ci					  GFP_KERNEL);
231262306a36Sopenharmony_ci	if (!qp->ird_q_va)
231362306a36Sopenharmony_ci		return -ENOMEM;
231462306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages,
231562306a36Sopenharmony_ci			     pa, ird_page_size);
231662306a36Sopenharmony_ci	for (; i < ird_q_len / dev->attr.rqe_size; i++) {
231762306a36Sopenharmony_ci		rqe = (struct ocrdma_hdr_wqe *)(qp->ird_q_va +
231862306a36Sopenharmony_ci			(i * dev->attr.rqe_size));
231962306a36Sopenharmony_ci		rqe->cw = 0;
232062306a36Sopenharmony_ci		rqe->cw |= 2;
232162306a36Sopenharmony_ci		rqe->cw |= (OCRDMA_TYPE_LKEY << OCRDMA_WQE_TYPE_SHIFT);
232262306a36Sopenharmony_ci		rqe->cw |= (8 << OCRDMA_WQE_SIZE_SHIFT);
232362306a36Sopenharmony_ci		rqe->cw |= (8 << OCRDMA_WQE_NXT_WQE_SIZE_SHIFT);
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci	return 0;
232662306a36Sopenharmony_ci}
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_cistatic void ocrdma_get_create_qp_rsp(struct ocrdma_create_qp_rsp *rsp,
232962306a36Sopenharmony_ci				     struct ocrdma_qp *qp,
233062306a36Sopenharmony_ci				     struct ib_qp_init_attr *attrs,
233162306a36Sopenharmony_ci				     u16 *dpp_offset, u16 *dpp_credit_lmt)
233262306a36Sopenharmony_ci{
233362306a36Sopenharmony_ci	u32 max_wqe_allocated, max_rqe_allocated;
233462306a36Sopenharmony_ci	qp->id = rsp->qp_id & OCRDMA_CREATE_QP_RSP_QP_ID_MASK;
233562306a36Sopenharmony_ci	qp->rq.dbid = rsp->sq_rq_id & OCRDMA_CREATE_QP_RSP_RQ_ID_MASK;
233662306a36Sopenharmony_ci	qp->sq.dbid = rsp->sq_rq_id >> OCRDMA_CREATE_QP_RSP_SQ_ID_SHIFT;
233762306a36Sopenharmony_ci	qp->max_ird = rsp->max_ord_ird & OCRDMA_CREATE_QP_RSP_MAX_IRD_MASK;
233862306a36Sopenharmony_ci	qp->max_ord = (rsp->max_ord_ird >> OCRDMA_CREATE_QP_RSP_MAX_ORD_SHIFT);
233962306a36Sopenharmony_ci	qp->dpp_enabled = false;
234062306a36Sopenharmony_ci	if (rsp->dpp_response & OCRDMA_CREATE_QP_RSP_DPP_ENABLED_MASK) {
234162306a36Sopenharmony_ci		qp->dpp_enabled = true;
234262306a36Sopenharmony_ci		*dpp_credit_lmt = (rsp->dpp_response &
234362306a36Sopenharmony_ci				OCRDMA_CREATE_QP_RSP_DPP_CREDITS_MASK) >>
234462306a36Sopenharmony_ci				OCRDMA_CREATE_QP_RSP_DPP_CREDITS_SHIFT;
234562306a36Sopenharmony_ci		*dpp_offset = (rsp->dpp_response &
234662306a36Sopenharmony_ci				OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_MASK) >>
234762306a36Sopenharmony_ci				OCRDMA_CREATE_QP_RSP_DPP_PAGE_OFFSET_SHIFT;
234862306a36Sopenharmony_ci	}
234962306a36Sopenharmony_ci	max_wqe_allocated =
235062306a36Sopenharmony_ci		rsp->max_wqe_rqe >> OCRDMA_CREATE_QP_RSP_MAX_WQE_SHIFT;
235162306a36Sopenharmony_ci	max_wqe_allocated = 1 << max_wqe_allocated;
235262306a36Sopenharmony_ci	max_rqe_allocated = 1 << ((u16)rsp->max_wqe_rqe);
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	qp->sq.max_cnt = max_wqe_allocated;
235562306a36Sopenharmony_ci	qp->sq.max_wqe_idx = max_wqe_allocated - 1;
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci	if (!attrs->srq) {
235862306a36Sopenharmony_ci		qp->rq.max_cnt = max_rqe_allocated;
235962306a36Sopenharmony_ci		qp->rq.max_wqe_idx = max_rqe_allocated - 1;
236062306a36Sopenharmony_ci	}
236162306a36Sopenharmony_ci}
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ciint ocrdma_mbx_create_qp(struct ocrdma_qp *qp, struct ib_qp_init_attr *attrs,
236462306a36Sopenharmony_ci			 u8 enable_dpp_cq, u16 dpp_cq_id, u16 *dpp_offset,
236562306a36Sopenharmony_ci			 u16 *dpp_credit_lmt)
236662306a36Sopenharmony_ci{
236762306a36Sopenharmony_ci	int status = -ENOMEM;
236862306a36Sopenharmony_ci	u32 flags = 0;
236962306a36Sopenharmony_ci	struct ocrdma_pd *pd = qp->pd;
237062306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
237162306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
237262306a36Sopenharmony_ci	struct ocrdma_cq *cq;
237362306a36Sopenharmony_ci	struct ocrdma_create_qp_req *cmd;
237462306a36Sopenharmony_ci	struct ocrdma_create_qp_rsp *rsp;
237562306a36Sopenharmony_ci	int qptype;
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci	switch (attrs->qp_type) {
237862306a36Sopenharmony_ci	case IB_QPT_GSI:
237962306a36Sopenharmony_ci		qptype = OCRDMA_QPT_GSI;
238062306a36Sopenharmony_ci		break;
238162306a36Sopenharmony_ci	case IB_QPT_RC:
238262306a36Sopenharmony_ci		qptype = OCRDMA_QPT_RC;
238362306a36Sopenharmony_ci		break;
238462306a36Sopenharmony_ci	case IB_QPT_UD:
238562306a36Sopenharmony_ci		qptype = OCRDMA_QPT_UD;
238662306a36Sopenharmony_ci		break;
238762306a36Sopenharmony_ci	default:
238862306a36Sopenharmony_ci		return -EINVAL;
238962306a36Sopenharmony_ci	}
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_QP, sizeof(*cmd));
239262306a36Sopenharmony_ci	if (!cmd)
239362306a36Sopenharmony_ci		return status;
239462306a36Sopenharmony_ci	cmd->type_pgsz_pdn |= (qptype << OCRDMA_CREATE_QP_REQ_QPT_SHIFT) &
239562306a36Sopenharmony_ci						OCRDMA_CREATE_QP_REQ_QPT_MASK;
239662306a36Sopenharmony_ci	status = ocrdma_set_create_qp_sq_cmd(cmd, attrs, qp);
239762306a36Sopenharmony_ci	if (status)
239862306a36Sopenharmony_ci		goto sq_err;
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	if (attrs->srq) {
240162306a36Sopenharmony_ci		struct ocrdma_srq *srq = get_ocrdma_srq(attrs->srq);
240262306a36Sopenharmony_ci		cmd->max_sge_recv_flags |= OCRDMA_CREATE_QP_REQ_USE_SRQ_MASK;
240362306a36Sopenharmony_ci		cmd->rq_addr[0].lo = srq->id;
240462306a36Sopenharmony_ci		qp->srq = srq;
240562306a36Sopenharmony_ci	} else {
240662306a36Sopenharmony_ci		status = ocrdma_set_create_qp_rq_cmd(cmd, attrs, qp);
240762306a36Sopenharmony_ci		if (status)
240862306a36Sopenharmony_ci			goto rq_err;
240962306a36Sopenharmony_ci	}
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	status = ocrdma_set_create_qp_ird_cmd(cmd, qp);
241262306a36Sopenharmony_ci	if (status)
241362306a36Sopenharmony_ci		goto mbx_err;
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci	cmd->type_pgsz_pdn |= (pd->id << OCRDMA_CREATE_QP_REQ_PD_ID_SHIFT) &
241662306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_PD_ID_MASK;
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci	flags = ocrdma_set_create_qp_mbx_access_flags(qp);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	cmd->max_sge_recv_flags |= flags;
242162306a36Sopenharmony_ci	cmd->max_ord_ird |= (dev->attr.max_ord_per_qp <<
242262306a36Sopenharmony_ci			     OCRDMA_CREATE_QP_REQ_MAX_ORD_SHIFT) &
242362306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_ORD_MASK;
242462306a36Sopenharmony_ci	cmd->max_ord_ird |= (dev->attr.max_ird_per_qp <<
242562306a36Sopenharmony_ci			     OCRDMA_CREATE_QP_REQ_MAX_IRD_SHIFT) &
242662306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_MAX_IRD_MASK;
242762306a36Sopenharmony_ci	cq = get_ocrdma_cq(attrs->send_cq);
242862306a36Sopenharmony_ci	cmd->wq_rq_cqid |= (cq->id << OCRDMA_CREATE_QP_REQ_WQ_CQID_SHIFT) &
242962306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_WQ_CQID_MASK;
243062306a36Sopenharmony_ci	qp->sq_cq = cq;
243162306a36Sopenharmony_ci	cq = get_ocrdma_cq(attrs->recv_cq);
243262306a36Sopenharmony_ci	cmd->wq_rq_cqid |= (cq->id << OCRDMA_CREATE_QP_REQ_RQ_CQID_SHIFT) &
243362306a36Sopenharmony_ci				OCRDMA_CREATE_QP_REQ_RQ_CQID_MASK;
243462306a36Sopenharmony_ci	qp->rq_cq = cq;
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	if (pd->dpp_enabled && attrs->cap.max_inline_data && pd->num_dpp_qp &&
243762306a36Sopenharmony_ci	    (attrs->cap.max_inline_data <= dev->attr.max_inline_data)) {
243862306a36Sopenharmony_ci		ocrdma_set_create_qp_dpp_cmd(cmd, pd, qp, enable_dpp_cq,
243962306a36Sopenharmony_ci					     dpp_cq_id);
244062306a36Sopenharmony_ci	}
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
244362306a36Sopenharmony_ci	if (status)
244462306a36Sopenharmony_ci		goto mbx_err;
244562306a36Sopenharmony_ci	rsp = (struct ocrdma_create_qp_rsp *)cmd;
244662306a36Sopenharmony_ci	ocrdma_get_create_qp_rsp(rsp, qp, attrs, dpp_offset, dpp_credit_lmt);
244762306a36Sopenharmony_ci	qp->state = OCRDMA_QPS_RST;
244862306a36Sopenharmony_ci	kfree(cmd);
244962306a36Sopenharmony_ci	return 0;
245062306a36Sopenharmony_cimbx_err:
245162306a36Sopenharmony_ci	if (qp->rq.va)
245262306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev, qp->rq.len, qp->rq.va, qp->rq.pa);
245362306a36Sopenharmony_cirq_err:
245462306a36Sopenharmony_ci	pr_err("%s(%d) rq_err\n", __func__, dev->id);
245562306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, qp->sq.len, qp->sq.va, qp->sq.pa);
245662306a36Sopenharmony_cisq_err:
245762306a36Sopenharmony_ci	pr_err("%s(%d) sq_err\n", __func__, dev->id);
245862306a36Sopenharmony_ci	kfree(cmd);
245962306a36Sopenharmony_ci	return status;
246062306a36Sopenharmony_ci}
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ciint ocrdma_mbx_query_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
246362306a36Sopenharmony_ci			struct ocrdma_qp_params *param)
246462306a36Sopenharmony_ci{
246562306a36Sopenharmony_ci	int status = -ENOMEM;
246662306a36Sopenharmony_ci	struct ocrdma_query_qp *cmd;
246762306a36Sopenharmony_ci	struct ocrdma_query_qp_rsp *rsp;
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_QP, sizeof(*rsp));
247062306a36Sopenharmony_ci	if (!cmd)
247162306a36Sopenharmony_ci		return status;
247262306a36Sopenharmony_ci	cmd->qp_id = qp->id;
247362306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
247462306a36Sopenharmony_ci	if (status)
247562306a36Sopenharmony_ci		goto mbx_err;
247662306a36Sopenharmony_ci	rsp = (struct ocrdma_query_qp_rsp *)cmd;
247762306a36Sopenharmony_ci	memcpy(param, &rsp->params, sizeof(struct ocrdma_qp_params));
247862306a36Sopenharmony_cimbx_err:
247962306a36Sopenharmony_ci	kfree(cmd);
248062306a36Sopenharmony_ci	return status;
248162306a36Sopenharmony_ci}
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_cistatic int ocrdma_set_av_params(struct ocrdma_qp *qp,
248462306a36Sopenharmony_ci				struct ocrdma_modify_qp *cmd,
248562306a36Sopenharmony_ci				struct ib_qp_attr *attrs,
248662306a36Sopenharmony_ci				int attr_mask)
248762306a36Sopenharmony_ci{
248862306a36Sopenharmony_ci	int status;
248962306a36Sopenharmony_ci	struct rdma_ah_attr *ah_attr = &attrs->ah_attr;
249062306a36Sopenharmony_ci	const struct ib_gid_attr *sgid_attr;
249162306a36Sopenharmony_ci	u16 vlan_id = 0xFFFF;
249262306a36Sopenharmony_ci	u8 mac_addr[6], hdr_type;
249362306a36Sopenharmony_ci	union {
249462306a36Sopenharmony_ci		struct sockaddr_in  _sockaddr_in;
249562306a36Sopenharmony_ci		struct sockaddr_in6 _sockaddr_in6;
249662306a36Sopenharmony_ci	} sgid_addr, dgid_addr;
249762306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
249862306a36Sopenharmony_ci	const struct ib_global_route *grh;
249962306a36Sopenharmony_ci
250062306a36Sopenharmony_ci	if ((rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) == 0)
250162306a36Sopenharmony_ci		return -EINVAL;
250262306a36Sopenharmony_ci	grh = rdma_ah_read_grh(ah_attr);
250362306a36Sopenharmony_ci	if (atomic_cmpxchg(&dev->update_sl, 1, 0))
250462306a36Sopenharmony_ci		ocrdma_init_service_level(dev);
250562306a36Sopenharmony_ci	cmd->params.tclass_sq_psn |=
250662306a36Sopenharmony_ci	    (grh->traffic_class << OCRDMA_QP_PARAMS_TCLASS_SHIFT);
250762306a36Sopenharmony_ci	cmd->params.rnt_rc_sl_fl |=
250862306a36Sopenharmony_ci	    (grh->flow_label & OCRDMA_QP_PARAMS_FLOW_LABEL_MASK);
250962306a36Sopenharmony_ci	cmd->params.rnt_rc_sl_fl |= (rdma_ah_get_sl(ah_attr) <<
251062306a36Sopenharmony_ci				     OCRDMA_QP_PARAMS_SL_SHIFT);
251162306a36Sopenharmony_ci	cmd->params.hop_lmt_rq_psn |=
251262306a36Sopenharmony_ci	    (grh->hop_limit << OCRDMA_QP_PARAMS_HOP_LMT_SHIFT);
251362306a36Sopenharmony_ci	cmd->flags |= OCRDMA_QP_PARA_FLOW_LBL_VALID;
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	/* GIDs */
251662306a36Sopenharmony_ci	memcpy(&cmd->params.dgid[0], &grh->dgid.raw[0],
251762306a36Sopenharmony_ci	       sizeof(cmd->params.dgid));
251862306a36Sopenharmony_ci
251962306a36Sopenharmony_ci	sgid_attr = ah_attr->grh.sgid_attr;
252062306a36Sopenharmony_ci	status = rdma_read_gid_l2_fields(sgid_attr, &vlan_id, &mac_addr[0]);
252162306a36Sopenharmony_ci	if (status)
252262306a36Sopenharmony_ci		return status;
252362306a36Sopenharmony_ci
252462306a36Sopenharmony_ci	qp->sgid_idx = grh->sgid_index;
252562306a36Sopenharmony_ci	memcpy(&cmd->params.sgid[0], &sgid_attr->gid.raw[0],
252662306a36Sopenharmony_ci	       sizeof(cmd->params.sgid));
252762306a36Sopenharmony_ci	status = ocrdma_resolve_dmac(dev, ah_attr, &mac_addr[0]);
252862306a36Sopenharmony_ci	if (status)
252962306a36Sopenharmony_ci		return status;
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci	cmd->params.dmac_b0_to_b3 = mac_addr[0] | (mac_addr[1] << 8) |
253262306a36Sopenharmony_ci				(mac_addr[2] << 16) | (mac_addr[3] << 24);
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci	hdr_type = rdma_gid_attr_network_type(sgid_attr);
253562306a36Sopenharmony_ci	if (hdr_type == RDMA_NETWORK_IPV4) {
253662306a36Sopenharmony_ci		rdma_gid2ip((struct sockaddr *)&sgid_addr, &sgid_attr->gid);
253762306a36Sopenharmony_ci		rdma_gid2ip((struct sockaddr *)&dgid_addr, &grh->dgid);
253862306a36Sopenharmony_ci		memcpy(&cmd->params.dgid[0],
253962306a36Sopenharmony_ci		       &dgid_addr._sockaddr_in.sin_addr.s_addr, 4);
254062306a36Sopenharmony_ci		memcpy(&cmd->params.sgid[0],
254162306a36Sopenharmony_ci		       &sgid_addr._sockaddr_in.sin_addr.s_addr, 4);
254262306a36Sopenharmony_ci	}
254362306a36Sopenharmony_ci	/* convert them to LE format. */
254462306a36Sopenharmony_ci	ocrdma_cpu_to_le32(&cmd->params.dgid[0], sizeof(cmd->params.dgid));
254562306a36Sopenharmony_ci	ocrdma_cpu_to_le32(&cmd->params.sgid[0], sizeof(cmd->params.sgid));
254662306a36Sopenharmony_ci	cmd->params.vlan_dmac_b4_to_b5 = mac_addr[4] | (mac_addr[5] << 8);
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	if (vlan_id == 0xFFFF)
254962306a36Sopenharmony_ci		vlan_id = 0;
255062306a36Sopenharmony_ci	if (vlan_id || dev->pfc_state) {
255162306a36Sopenharmony_ci		if (!vlan_id) {
255262306a36Sopenharmony_ci			pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
255362306a36Sopenharmony_ci			       dev->id);
255462306a36Sopenharmony_ci			pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
255562306a36Sopenharmony_ci			       dev->id);
255662306a36Sopenharmony_ci		}
255762306a36Sopenharmony_ci		cmd->params.vlan_dmac_b4_to_b5 |=
255862306a36Sopenharmony_ci		    vlan_id << OCRDMA_QP_PARAMS_VLAN_SHIFT;
255962306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_VLAN_EN_VALID;
256062306a36Sopenharmony_ci		cmd->params.rnt_rc_sl_fl |=
256162306a36Sopenharmony_ci			(dev->sl & 0x07) << OCRDMA_QP_PARAMS_SL_SHIFT;
256262306a36Sopenharmony_ci	}
256362306a36Sopenharmony_ci	cmd->params.max_sge_recv_flags |= ((hdr_type <<
256462306a36Sopenharmony_ci					OCRDMA_QP_PARAMS_FLAGS_L3_TYPE_SHIFT) &
256562306a36Sopenharmony_ci					OCRDMA_QP_PARAMS_FLAGS_L3_TYPE_MASK);
256662306a36Sopenharmony_ci	return 0;
256762306a36Sopenharmony_ci}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_cistatic int ocrdma_set_qp_params(struct ocrdma_qp *qp,
257062306a36Sopenharmony_ci				struct ocrdma_modify_qp *cmd,
257162306a36Sopenharmony_ci				struct ib_qp_attr *attrs, int attr_mask)
257262306a36Sopenharmony_ci{
257362306a36Sopenharmony_ci	int status = 0;
257462306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(qp->ibqp.device);
257562306a36Sopenharmony_ci
257662306a36Sopenharmony_ci	if (attr_mask & IB_QP_PKEY_INDEX) {
257762306a36Sopenharmony_ci		cmd->params.path_mtu_pkey_indx |= (attrs->pkey_index &
257862306a36Sopenharmony_ci					    OCRDMA_QP_PARAMS_PKEY_INDEX_MASK);
257962306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_PKEY_VALID;
258062306a36Sopenharmony_ci	}
258162306a36Sopenharmony_ci	if (attr_mask & IB_QP_QKEY) {
258262306a36Sopenharmony_ci		qp->qkey = attrs->qkey;
258362306a36Sopenharmony_ci		cmd->params.qkey = attrs->qkey;
258462306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_QKEY_VALID;
258562306a36Sopenharmony_ci	}
258662306a36Sopenharmony_ci	if (attr_mask & IB_QP_AV) {
258762306a36Sopenharmony_ci		status = ocrdma_set_av_params(qp, cmd, attrs, attr_mask);
258862306a36Sopenharmony_ci		if (status)
258962306a36Sopenharmony_ci			return status;
259062306a36Sopenharmony_ci	} else if (qp->qp_type == IB_QPT_GSI || qp->qp_type == IB_QPT_UD) {
259162306a36Sopenharmony_ci		/* set the default mac address for UD, GSI QPs */
259262306a36Sopenharmony_ci		cmd->params.dmac_b0_to_b3 = dev->nic_info.mac_addr[0] |
259362306a36Sopenharmony_ci			(dev->nic_info.mac_addr[1] << 8) |
259462306a36Sopenharmony_ci			(dev->nic_info.mac_addr[2] << 16) |
259562306a36Sopenharmony_ci			(dev->nic_info.mac_addr[3] << 24);
259662306a36Sopenharmony_ci		cmd->params.vlan_dmac_b4_to_b5 = dev->nic_info.mac_addr[4] |
259762306a36Sopenharmony_ci					(dev->nic_info.mac_addr[5] << 8);
259862306a36Sopenharmony_ci	}
259962306a36Sopenharmony_ci	if ((attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY) &&
260062306a36Sopenharmony_ci	    attrs->en_sqd_async_notify) {
260162306a36Sopenharmony_ci		cmd->params.max_sge_recv_flags |=
260262306a36Sopenharmony_ci			OCRDMA_QP_PARAMS_FLAGS_SQD_ASYNC;
260362306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_DST_QPN_VALID;
260462306a36Sopenharmony_ci	}
260562306a36Sopenharmony_ci	if (attr_mask & IB_QP_DEST_QPN) {
260662306a36Sopenharmony_ci		cmd->params.ack_to_rnr_rtc_dest_qpn |= (attrs->dest_qp_num &
260762306a36Sopenharmony_ci				OCRDMA_QP_PARAMS_DEST_QPN_MASK);
260862306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_DST_QPN_VALID;
260962306a36Sopenharmony_ci	}
261062306a36Sopenharmony_ci	if (attr_mask & IB_QP_PATH_MTU) {
261162306a36Sopenharmony_ci		if (attrs->path_mtu < IB_MTU_512 ||
261262306a36Sopenharmony_ci		    attrs->path_mtu > IB_MTU_4096) {
261362306a36Sopenharmony_ci			pr_err("ocrdma%d: IB MTU %d is not supported\n",
261462306a36Sopenharmony_ci			       dev->id, ib_mtu_enum_to_int(attrs->path_mtu));
261562306a36Sopenharmony_ci			status = -EINVAL;
261662306a36Sopenharmony_ci			goto pmtu_err;
261762306a36Sopenharmony_ci		}
261862306a36Sopenharmony_ci		cmd->params.path_mtu_pkey_indx |=
261962306a36Sopenharmony_ci		    (ib_mtu_enum_to_int(attrs->path_mtu) <<
262062306a36Sopenharmony_ci		     OCRDMA_QP_PARAMS_PATH_MTU_SHIFT) &
262162306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_PATH_MTU_MASK;
262262306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_PMTU_VALID;
262362306a36Sopenharmony_ci	}
262462306a36Sopenharmony_ci	if (attr_mask & IB_QP_TIMEOUT) {
262562306a36Sopenharmony_ci		cmd->params.ack_to_rnr_rtc_dest_qpn |= attrs->timeout <<
262662306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_ACK_TIMEOUT_SHIFT;
262762306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_ACK_TO_VALID;
262862306a36Sopenharmony_ci	}
262962306a36Sopenharmony_ci	if (attr_mask & IB_QP_RETRY_CNT) {
263062306a36Sopenharmony_ci		cmd->params.rnt_rc_sl_fl |= (attrs->retry_cnt <<
263162306a36Sopenharmony_ci				      OCRDMA_QP_PARAMS_RETRY_CNT_SHIFT) &
263262306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_RETRY_CNT_MASK;
263362306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_RETRY_CNT_VALID;
263462306a36Sopenharmony_ci	}
263562306a36Sopenharmony_ci	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
263662306a36Sopenharmony_ci		cmd->params.rnt_rc_sl_fl |= (attrs->min_rnr_timer <<
263762306a36Sopenharmony_ci				      OCRDMA_QP_PARAMS_RNR_NAK_TIMER_SHIFT) &
263862306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_RNR_NAK_TIMER_MASK;
263962306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_RNT_VALID;
264062306a36Sopenharmony_ci	}
264162306a36Sopenharmony_ci	if (attr_mask & IB_QP_RNR_RETRY) {
264262306a36Sopenharmony_ci		cmd->params.ack_to_rnr_rtc_dest_qpn |= (attrs->rnr_retry <<
264362306a36Sopenharmony_ci			OCRDMA_QP_PARAMS_RNR_RETRY_CNT_SHIFT)
264462306a36Sopenharmony_ci			& OCRDMA_QP_PARAMS_RNR_RETRY_CNT_MASK;
264562306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_RRC_VALID;
264662306a36Sopenharmony_ci	}
264762306a36Sopenharmony_ci	if (attr_mask & IB_QP_SQ_PSN) {
264862306a36Sopenharmony_ci		cmd->params.tclass_sq_psn |= (attrs->sq_psn & 0x00ffffff);
264962306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_SQPSN_VALID;
265062306a36Sopenharmony_ci	}
265162306a36Sopenharmony_ci	if (attr_mask & IB_QP_RQ_PSN) {
265262306a36Sopenharmony_ci		cmd->params.hop_lmt_rq_psn |= (attrs->rq_psn & 0x00ffffff);
265362306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_RQPSN_VALID;
265462306a36Sopenharmony_ci	}
265562306a36Sopenharmony_ci	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
265662306a36Sopenharmony_ci		if (attrs->max_rd_atomic > dev->attr.max_ord_per_qp) {
265762306a36Sopenharmony_ci			status = -EINVAL;
265862306a36Sopenharmony_ci			goto pmtu_err;
265962306a36Sopenharmony_ci		}
266062306a36Sopenharmony_ci		qp->max_ord = attrs->max_rd_atomic;
266162306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_MAX_ORD_VALID;
266262306a36Sopenharmony_ci	}
266362306a36Sopenharmony_ci	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
266462306a36Sopenharmony_ci		if (attrs->max_dest_rd_atomic > dev->attr.max_ird_per_qp) {
266562306a36Sopenharmony_ci			status = -EINVAL;
266662306a36Sopenharmony_ci			goto pmtu_err;
266762306a36Sopenharmony_ci		}
266862306a36Sopenharmony_ci		qp->max_ird = attrs->max_dest_rd_atomic;
266962306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_MAX_IRD_VALID;
267062306a36Sopenharmony_ci	}
267162306a36Sopenharmony_ci	cmd->params.max_ord_ird = (qp->max_ord <<
267262306a36Sopenharmony_ci				OCRDMA_QP_PARAMS_MAX_ORD_SHIFT) |
267362306a36Sopenharmony_ci				(qp->max_ird & OCRDMA_QP_PARAMS_MAX_IRD_MASK);
267462306a36Sopenharmony_cipmtu_err:
267562306a36Sopenharmony_ci	return status;
267662306a36Sopenharmony_ci}
267762306a36Sopenharmony_ci
267862306a36Sopenharmony_ciint ocrdma_mbx_modify_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
267962306a36Sopenharmony_ci			 struct ib_qp_attr *attrs, int attr_mask)
268062306a36Sopenharmony_ci{
268162306a36Sopenharmony_ci	int status = -ENOMEM;
268262306a36Sopenharmony_ci	struct ocrdma_modify_qp *cmd;
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_MODIFY_QP, sizeof(*cmd));
268562306a36Sopenharmony_ci	if (!cmd)
268662306a36Sopenharmony_ci		return status;
268762306a36Sopenharmony_ci
268862306a36Sopenharmony_ci	cmd->params.id = qp->id;
268962306a36Sopenharmony_ci	cmd->flags = 0;
269062306a36Sopenharmony_ci	if (attr_mask & IB_QP_STATE) {
269162306a36Sopenharmony_ci		cmd->params.max_sge_recv_flags |=
269262306a36Sopenharmony_ci		    (get_ocrdma_qp_state(attrs->qp_state) <<
269362306a36Sopenharmony_ci		     OCRDMA_QP_PARAMS_STATE_SHIFT) &
269462306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_STATE_MASK;
269562306a36Sopenharmony_ci		cmd->flags |= OCRDMA_QP_PARA_QPS_VALID;
269662306a36Sopenharmony_ci	} else {
269762306a36Sopenharmony_ci		cmd->params.max_sge_recv_flags |=
269862306a36Sopenharmony_ci		    (qp->state << OCRDMA_QP_PARAMS_STATE_SHIFT) &
269962306a36Sopenharmony_ci		    OCRDMA_QP_PARAMS_STATE_MASK;
270062306a36Sopenharmony_ci	}
270162306a36Sopenharmony_ci
270262306a36Sopenharmony_ci	status = ocrdma_set_qp_params(qp, cmd, attrs, attr_mask);
270362306a36Sopenharmony_ci	if (status)
270462306a36Sopenharmony_ci		goto mbx_err;
270562306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
270662306a36Sopenharmony_ci	if (status)
270762306a36Sopenharmony_ci		goto mbx_err;
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_cimbx_err:
271062306a36Sopenharmony_ci	kfree(cmd);
271162306a36Sopenharmony_ci	return status;
271262306a36Sopenharmony_ci}
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_ciint ocrdma_mbx_destroy_qp(struct ocrdma_dev *dev, struct ocrdma_qp *qp)
271562306a36Sopenharmony_ci{
271662306a36Sopenharmony_ci	int status = -ENOMEM;
271762306a36Sopenharmony_ci	struct ocrdma_destroy_qp *cmd;
271862306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_QP, sizeof(*cmd));
272162306a36Sopenharmony_ci	if (!cmd)
272262306a36Sopenharmony_ci		return status;
272362306a36Sopenharmony_ci	cmd->qp_id = qp->id;
272462306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
272562306a36Sopenharmony_ci	if (status)
272662306a36Sopenharmony_ci		goto mbx_err;
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_cimbx_err:
272962306a36Sopenharmony_ci	kfree(cmd);
273062306a36Sopenharmony_ci	if (qp->sq.va)
273162306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev, qp->sq.len, qp->sq.va, qp->sq.pa);
273262306a36Sopenharmony_ci	if (!qp->srq && qp->rq.va)
273362306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev, qp->rq.len, qp->rq.va, qp->rq.pa);
273462306a36Sopenharmony_ci	if (qp->dpp_enabled)
273562306a36Sopenharmony_ci		qp->pd->num_dpp_qp++;
273662306a36Sopenharmony_ci	return status;
273762306a36Sopenharmony_ci}
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ciint ocrdma_mbx_create_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq,
274062306a36Sopenharmony_ci			  struct ib_srq_init_attr *srq_attr,
274162306a36Sopenharmony_ci			  struct ocrdma_pd *pd)
274262306a36Sopenharmony_ci{
274362306a36Sopenharmony_ci	int status = -ENOMEM;
274462306a36Sopenharmony_ci	int hw_pages, hw_page_size;
274562306a36Sopenharmony_ci	int len;
274662306a36Sopenharmony_ci	struct ocrdma_create_srq_rsp *rsp;
274762306a36Sopenharmony_ci	struct ocrdma_create_srq *cmd;
274862306a36Sopenharmony_ci	dma_addr_t pa;
274962306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
275062306a36Sopenharmony_ci	u32 max_rqe_allocated;
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_SRQ, sizeof(*cmd));
275362306a36Sopenharmony_ci	if (!cmd)
275462306a36Sopenharmony_ci		return status;
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci	cmd->pgsz_pdid = pd->id & OCRDMA_CREATE_SRQ_PD_ID_MASK;
275762306a36Sopenharmony_ci	max_rqe_allocated = srq_attr->attr.max_wr + 1;
275862306a36Sopenharmony_ci	status = ocrdma_build_q_conf(&max_rqe_allocated,
275962306a36Sopenharmony_ci				dev->attr.rqe_size,
276062306a36Sopenharmony_ci				&hw_pages, &hw_page_size);
276162306a36Sopenharmony_ci	if (status) {
276262306a36Sopenharmony_ci		pr_err("%s() req. max_wr=0x%x\n", __func__,
276362306a36Sopenharmony_ci		       srq_attr->attr.max_wr);
276462306a36Sopenharmony_ci		status = -EINVAL;
276562306a36Sopenharmony_ci		goto ret;
276662306a36Sopenharmony_ci	}
276762306a36Sopenharmony_ci	len = hw_pages * hw_page_size;
276862306a36Sopenharmony_ci	srq->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
276962306a36Sopenharmony_ci	if (!srq->rq.va) {
277062306a36Sopenharmony_ci		status = -ENOMEM;
277162306a36Sopenharmony_ci		goto ret;
277262306a36Sopenharmony_ci	}
277362306a36Sopenharmony_ci	ocrdma_build_q_pages(&cmd->rq_addr[0], hw_pages, pa, hw_page_size);
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	srq->rq.entry_size = dev->attr.rqe_size;
277662306a36Sopenharmony_ci	srq->rq.pa = pa;
277762306a36Sopenharmony_ci	srq->rq.len = len;
277862306a36Sopenharmony_ci	srq->rq.max_cnt = max_rqe_allocated;
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	cmd->max_sge_rqe = ilog2(max_rqe_allocated);
278162306a36Sopenharmony_ci	cmd->max_sge_rqe |= srq_attr->attr.max_sge <<
278262306a36Sopenharmony_ci				OCRDMA_CREATE_SRQ_MAX_SGE_RECV_SHIFT;
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci	cmd->pgsz_pdid |= (ilog2(hw_page_size / OCRDMA_MIN_Q_PAGE_SIZE)
278562306a36Sopenharmony_ci		<< OCRDMA_CREATE_SRQ_PG_SZ_SHIFT);
278662306a36Sopenharmony_ci	cmd->pages_rqe_sz |= (dev->attr.rqe_size
278762306a36Sopenharmony_ci		<< OCRDMA_CREATE_SRQ_RQE_SIZE_SHIFT)
278862306a36Sopenharmony_ci		& OCRDMA_CREATE_SRQ_RQE_SIZE_MASK;
278962306a36Sopenharmony_ci	cmd->pages_rqe_sz |= hw_pages << OCRDMA_CREATE_SRQ_NUM_RQ_PAGES_SHIFT;
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
279262306a36Sopenharmony_ci	if (status)
279362306a36Sopenharmony_ci		goto mbx_err;
279462306a36Sopenharmony_ci	rsp = (struct ocrdma_create_srq_rsp *)cmd;
279562306a36Sopenharmony_ci	srq->id = rsp->id;
279662306a36Sopenharmony_ci	srq->rq.dbid = rsp->id;
279762306a36Sopenharmony_ci	max_rqe_allocated = ((rsp->max_sge_rqe_allocated &
279862306a36Sopenharmony_ci		OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_MASK) >>
279962306a36Sopenharmony_ci		OCRDMA_CREATE_SRQ_RSP_MAX_RQE_ALLOCATED_SHIFT);
280062306a36Sopenharmony_ci	max_rqe_allocated = (1 << max_rqe_allocated);
280162306a36Sopenharmony_ci	srq->rq.max_cnt = max_rqe_allocated;
280262306a36Sopenharmony_ci	srq->rq.max_wqe_idx = max_rqe_allocated - 1;
280362306a36Sopenharmony_ci	srq->rq.max_sges = (rsp->max_sge_rqe_allocated &
280462306a36Sopenharmony_ci		OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_MASK) >>
280562306a36Sopenharmony_ci		OCRDMA_CREATE_SRQ_RSP_MAX_SGE_RECV_ALLOCATED_SHIFT;
280662306a36Sopenharmony_ci	goto ret;
280762306a36Sopenharmony_cimbx_err:
280862306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, srq->rq.len, srq->rq.va, pa);
280962306a36Sopenharmony_ciret:
281062306a36Sopenharmony_ci	kfree(cmd);
281162306a36Sopenharmony_ci	return status;
281262306a36Sopenharmony_ci}
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ciint ocrdma_mbx_modify_srq(struct ocrdma_srq *srq, struct ib_srq_attr *srq_attr)
281562306a36Sopenharmony_ci{
281662306a36Sopenharmony_ci	int status = -ENOMEM;
281762306a36Sopenharmony_ci	struct ocrdma_modify_srq *cmd;
281862306a36Sopenharmony_ci	struct ocrdma_pd *pd = srq->pd;
281962306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(pd->ibpd.device);
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_MODIFY_SRQ, sizeof(*cmd));
282262306a36Sopenharmony_ci	if (!cmd)
282362306a36Sopenharmony_ci		return status;
282462306a36Sopenharmony_ci	cmd->id = srq->id;
282562306a36Sopenharmony_ci	cmd->limit_max_rqe |= srq_attr->srq_limit <<
282662306a36Sopenharmony_ci	    OCRDMA_MODIFY_SRQ_LIMIT_SHIFT;
282762306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
282862306a36Sopenharmony_ci	kfree(cmd);
282962306a36Sopenharmony_ci	return status;
283062306a36Sopenharmony_ci}
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ciint ocrdma_mbx_query_srq(struct ocrdma_srq *srq, struct ib_srq_attr *srq_attr)
283362306a36Sopenharmony_ci{
283462306a36Sopenharmony_ci	int status = -ENOMEM;
283562306a36Sopenharmony_ci	struct ocrdma_query_srq *cmd;
283662306a36Sopenharmony_ci	struct ocrdma_dev *dev = get_ocrdma_dev(srq->ibsrq.device);
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_QUERY_SRQ, sizeof(*cmd));
283962306a36Sopenharmony_ci	if (!cmd)
284062306a36Sopenharmony_ci		return status;
284162306a36Sopenharmony_ci	cmd->id = srq->rq.dbid;
284262306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
284362306a36Sopenharmony_ci	if (status == 0) {
284462306a36Sopenharmony_ci		struct ocrdma_query_srq_rsp *rsp =
284562306a36Sopenharmony_ci		    (struct ocrdma_query_srq_rsp *)cmd;
284662306a36Sopenharmony_ci		srq_attr->max_sge =
284762306a36Sopenharmony_ci		    rsp->srq_lmt_max_sge &
284862306a36Sopenharmony_ci		    OCRDMA_QUERY_SRQ_RSP_MAX_SGE_RECV_MASK;
284962306a36Sopenharmony_ci		srq_attr->max_wr =
285062306a36Sopenharmony_ci		    rsp->max_rqe_pdid >> OCRDMA_QUERY_SRQ_RSP_MAX_RQE_SHIFT;
285162306a36Sopenharmony_ci		srq_attr->srq_limit = rsp->srq_lmt_max_sge >>
285262306a36Sopenharmony_ci		    OCRDMA_QUERY_SRQ_RSP_SRQ_LIMIT_SHIFT;
285362306a36Sopenharmony_ci	}
285462306a36Sopenharmony_ci	kfree(cmd);
285562306a36Sopenharmony_ci	return status;
285662306a36Sopenharmony_ci}
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_civoid ocrdma_mbx_destroy_srq(struct ocrdma_dev *dev, struct ocrdma_srq *srq)
285962306a36Sopenharmony_ci{
286062306a36Sopenharmony_ci	struct ocrdma_destroy_srq *cmd;
286162306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
286262306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_DELETE_SRQ, sizeof(*cmd));
286362306a36Sopenharmony_ci	if (!cmd)
286462306a36Sopenharmony_ci		return;
286562306a36Sopenharmony_ci	cmd->id = srq->id;
286662306a36Sopenharmony_ci	ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
286762306a36Sopenharmony_ci	if (srq->rq.va)
286862306a36Sopenharmony_ci		dma_free_coherent(&pdev->dev, srq->rq.len,
286962306a36Sopenharmony_ci				  srq->rq.va, srq->rq.pa);
287062306a36Sopenharmony_ci	kfree(cmd);
287162306a36Sopenharmony_ci}
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_cistatic int ocrdma_mbx_get_dcbx_config(struct ocrdma_dev *dev, u32 ptype,
287462306a36Sopenharmony_ci				      struct ocrdma_dcbx_cfg *dcbxcfg)
287562306a36Sopenharmony_ci{
287662306a36Sopenharmony_ci	int status;
287762306a36Sopenharmony_ci	dma_addr_t pa;
287862306a36Sopenharmony_ci	struct ocrdma_mqe cmd;
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	struct ocrdma_get_dcbx_cfg_req *req = NULL;
288162306a36Sopenharmony_ci	struct ocrdma_get_dcbx_cfg_rsp *rsp = NULL;
288262306a36Sopenharmony_ci	struct pci_dev *pdev = dev->nic_info.pdev;
288362306a36Sopenharmony_ci	struct ocrdma_mqe_sge *mqe_sge = cmd.u.nonemb_req.sge;
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	memset(&cmd, 0, sizeof(struct ocrdma_mqe));
288662306a36Sopenharmony_ci	cmd.hdr.pyld_len = max_t (u32, sizeof(struct ocrdma_get_dcbx_cfg_rsp),
288762306a36Sopenharmony_ci					sizeof(struct ocrdma_get_dcbx_cfg_req));
288862306a36Sopenharmony_ci	req = dma_alloc_coherent(&pdev->dev, cmd.hdr.pyld_len, &pa, GFP_KERNEL);
288962306a36Sopenharmony_ci	if (!req) {
289062306a36Sopenharmony_ci		status = -ENOMEM;
289162306a36Sopenharmony_ci		goto mem_err;
289262306a36Sopenharmony_ci	}
289362306a36Sopenharmony_ci
289462306a36Sopenharmony_ci	cmd.hdr.spcl_sge_cnt_emb |= (1 << OCRDMA_MQE_HDR_SGE_CNT_SHIFT) &
289562306a36Sopenharmony_ci					OCRDMA_MQE_HDR_SGE_CNT_MASK;
289662306a36Sopenharmony_ci	mqe_sge->pa_lo = (u32) (pa & 0xFFFFFFFFUL);
289762306a36Sopenharmony_ci	mqe_sge->pa_hi = (u32) upper_32_bits(pa);
289862306a36Sopenharmony_ci	mqe_sge->len = cmd.hdr.pyld_len;
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	ocrdma_init_mch(&req->hdr, OCRDMA_CMD_GET_DCBX_CONFIG,
290162306a36Sopenharmony_ci			OCRDMA_SUBSYS_DCBX, cmd.hdr.pyld_len);
290262306a36Sopenharmony_ci	req->param_type = ptype;
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, &cmd);
290562306a36Sopenharmony_ci	if (status)
290662306a36Sopenharmony_ci		goto mbx_err;
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	rsp = (struct ocrdma_get_dcbx_cfg_rsp *)req;
290962306a36Sopenharmony_ci	ocrdma_le32_to_cpu(rsp, sizeof(struct ocrdma_get_dcbx_cfg_rsp));
291062306a36Sopenharmony_ci	memcpy(dcbxcfg, &rsp->cfg, sizeof(struct ocrdma_dcbx_cfg));
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_cimbx_err:
291362306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, cmd.hdr.pyld_len, req, pa);
291462306a36Sopenharmony_cimem_err:
291562306a36Sopenharmony_ci	return status;
291662306a36Sopenharmony_ci}
291762306a36Sopenharmony_ci
291862306a36Sopenharmony_ci#define OCRDMA_MAX_SERVICE_LEVEL_INDEX	0x08
291962306a36Sopenharmony_ci#define OCRDMA_DEFAULT_SERVICE_LEVEL	0x05
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_cistatic int ocrdma_parse_dcbxcfg_rsp(struct ocrdma_dev *dev, int ptype,
292262306a36Sopenharmony_ci				    struct ocrdma_dcbx_cfg *dcbxcfg,
292362306a36Sopenharmony_ci				    u8 *srvc_lvl)
292462306a36Sopenharmony_ci{
292562306a36Sopenharmony_ci	int status = -EINVAL, indx, slindx;
292662306a36Sopenharmony_ci	int ventry_cnt;
292762306a36Sopenharmony_ci	struct ocrdma_app_parameter *app_param;
292862306a36Sopenharmony_ci	u8 valid, proto_sel;
292962306a36Sopenharmony_ci	u8 app_prio, pfc_prio;
293062306a36Sopenharmony_ci	u16 proto;
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	if (!(dcbxcfg->tcv_aev_opv_st & OCRDMA_DCBX_STATE_MASK)) {
293362306a36Sopenharmony_ci		pr_info("%s ocrdma%d DCBX is disabled\n",
293462306a36Sopenharmony_ci			dev_name(&dev->nic_info.pdev->dev), dev->id);
293562306a36Sopenharmony_ci		goto out;
293662306a36Sopenharmony_ci	}
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	if (!ocrdma_is_enabled_and_synced(dcbxcfg->pfc_state)) {
293962306a36Sopenharmony_ci		pr_info("%s ocrdma%d priority flow control(%s) is %s%s\n",
294062306a36Sopenharmony_ci			dev_name(&dev->nic_info.pdev->dev), dev->id,
294162306a36Sopenharmony_ci			(ptype > 0 ? "operational" : "admin"),
294262306a36Sopenharmony_ci			(dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_ENABLED) ?
294362306a36Sopenharmony_ci			"enabled" : "disabled",
294462306a36Sopenharmony_ci			(dcbxcfg->pfc_state & OCRDMA_STATE_FLAG_SYNC) ?
294562306a36Sopenharmony_ci			"" : ", not sync'ed");
294662306a36Sopenharmony_ci		goto out;
294762306a36Sopenharmony_ci	} else {
294862306a36Sopenharmony_ci		pr_info("%s ocrdma%d priority flow control is enabled and sync'ed\n",
294962306a36Sopenharmony_ci			dev_name(&dev->nic_info.pdev->dev), dev->id);
295062306a36Sopenharmony_ci	}
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	ventry_cnt = (dcbxcfg->tcv_aev_opv_st >>
295362306a36Sopenharmony_ci				OCRDMA_DCBX_APP_ENTRY_SHIFT)
295462306a36Sopenharmony_ci				& OCRDMA_DCBX_STATE_MASK;
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	for (indx = 0; indx < ventry_cnt; indx++) {
295762306a36Sopenharmony_ci		app_param = &dcbxcfg->app_param[indx];
295862306a36Sopenharmony_ci		valid = (app_param->valid_proto_app >>
295962306a36Sopenharmony_ci				OCRDMA_APP_PARAM_VALID_SHIFT)
296062306a36Sopenharmony_ci				& OCRDMA_APP_PARAM_VALID_MASK;
296162306a36Sopenharmony_ci		proto_sel = (app_param->valid_proto_app
296262306a36Sopenharmony_ci				>>  OCRDMA_APP_PARAM_PROTO_SEL_SHIFT)
296362306a36Sopenharmony_ci				& OCRDMA_APP_PARAM_PROTO_SEL_MASK;
296462306a36Sopenharmony_ci		proto = app_param->valid_proto_app &
296562306a36Sopenharmony_ci				OCRDMA_APP_PARAM_APP_PROTO_MASK;
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci		if (
296862306a36Sopenharmony_ci			valid && proto == ETH_P_IBOE &&
296962306a36Sopenharmony_ci			proto_sel == OCRDMA_PROTO_SELECT_L2) {
297062306a36Sopenharmony_ci			for (slindx = 0; slindx <
297162306a36Sopenharmony_ci				OCRDMA_MAX_SERVICE_LEVEL_INDEX; slindx++) {
297262306a36Sopenharmony_ci				app_prio = ocrdma_get_app_prio(
297362306a36Sopenharmony_ci						(u8 *)app_param->app_prio,
297462306a36Sopenharmony_ci						slindx);
297562306a36Sopenharmony_ci				pfc_prio = ocrdma_get_pfc_prio(
297662306a36Sopenharmony_ci						(u8 *)dcbxcfg->pfc_prio,
297762306a36Sopenharmony_ci						slindx);
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci				if (app_prio && pfc_prio) {
298062306a36Sopenharmony_ci					*srvc_lvl = slindx;
298162306a36Sopenharmony_ci					status = 0;
298262306a36Sopenharmony_ci					goto out;
298362306a36Sopenharmony_ci				}
298462306a36Sopenharmony_ci			}
298562306a36Sopenharmony_ci			if (slindx == OCRDMA_MAX_SERVICE_LEVEL_INDEX) {
298662306a36Sopenharmony_ci				pr_info("%s ocrdma%d application priority not set for 0x%x protocol\n",
298762306a36Sopenharmony_ci					dev_name(&dev->nic_info.pdev->dev),
298862306a36Sopenharmony_ci					dev->id, proto);
298962306a36Sopenharmony_ci			}
299062306a36Sopenharmony_ci		}
299162306a36Sopenharmony_ci	}
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ciout:
299462306a36Sopenharmony_ci	return status;
299562306a36Sopenharmony_ci}
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_civoid ocrdma_init_service_level(struct ocrdma_dev *dev)
299862306a36Sopenharmony_ci{
299962306a36Sopenharmony_ci	int status = 0, indx;
300062306a36Sopenharmony_ci	struct ocrdma_dcbx_cfg dcbxcfg;
300162306a36Sopenharmony_ci	u8 srvc_lvl = OCRDMA_DEFAULT_SERVICE_LEVEL;
300262306a36Sopenharmony_ci	int ptype = OCRDMA_PARAMETER_TYPE_OPER;
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	for (indx = 0; indx < 2; indx++) {
300562306a36Sopenharmony_ci		status = ocrdma_mbx_get_dcbx_config(dev, ptype, &dcbxcfg);
300662306a36Sopenharmony_ci		if (status) {
300762306a36Sopenharmony_ci			pr_err("%s(): status=%d\n", __func__, status);
300862306a36Sopenharmony_ci			ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
300962306a36Sopenharmony_ci			continue;
301062306a36Sopenharmony_ci		}
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci		status = ocrdma_parse_dcbxcfg_rsp(dev, ptype,
301362306a36Sopenharmony_ci						  &dcbxcfg, &srvc_lvl);
301462306a36Sopenharmony_ci		if (status) {
301562306a36Sopenharmony_ci			ptype = OCRDMA_PARAMETER_TYPE_ADMIN;
301662306a36Sopenharmony_ci			continue;
301762306a36Sopenharmony_ci		}
301862306a36Sopenharmony_ci
301962306a36Sopenharmony_ci		break;
302062306a36Sopenharmony_ci	}
302162306a36Sopenharmony_ci
302262306a36Sopenharmony_ci	if (status)
302362306a36Sopenharmony_ci		pr_info("%s ocrdma%d service level default\n",
302462306a36Sopenharmony_ci			dev_name(&dev->nic_info.pdev->dev), dev->id);
302562306a36Sopenharmony_ci	else
302662306a36Sopenharmony_ci		pr_info("%s ocrdma%d service level %d\n",
302762306a36Sopenharmony_ci			dev_name(&dev->nic_info.pdev->dev), dev->id,
302862306a36Sopenharmony_ci			srvc_lvl);
302962306a36Sopenharmony_ci
303062306a36Sopenharmony_ci	dev->pfc_state = ocrdma_is_enabled_and_synced(dcbxcfg.pfc_state);
303162306a36Sopenharmony_ci	dev->sl = srvc_lvl;
303262306a36Sopenharmony_ci}
303362306a36Sopenharmony_ci
303462306a36Sopenharmony_ciint ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
303562306a36Sopenharmony_ci{
303662306a36Sopenharmony_ci	int i;
303762306a36Sopenharmony_ci	int status = -EINVAL;
303862306a36Sopenharmony_ci	struct ocrdma_av *av;
303962306a36Sopenharmony_ci	unsigned long flags;
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci	av = dev->av_tbl.va;
304262306a36Sopenharmony_ci	spin_lock_irqsave(&dev->av_tbl.lock, flags);
304362306a36Sopenharmony_ci	for (i = 0; i < dev->av_tbl.num_ah; i++) {
304462306a36Sopenharmony_ci		if (av->valid == 0) {
304562306a36Sopenharmony_ci			av->valid = OCRDMA_AV_VALID;
304662306a36Sopenharmony_ci			ah->av = av;
304762306a36Sopenharmony_ci			ah->id = i;
304862306a36Sopenharmony_ci			status = 0;
304962306a36Sopenharmony_ci			break;
305062306a36Sopenharmony_ci		}
305162306a36Sopenharmony_ci		av++;
305262306a36Sopenharmony_ci	}
305362306a36Sopenharmony_ci	if (i == dev->av_tbl.num_ah)
305462306a36Sopenharmony_ci		status = -EAGAIN;
305562306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->av_tbl.lock, flags);
305662306a36Sopenharmony_ci	return status;
305762306a36Sopenharmony_ci}
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_civoid ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
306062306a36Sopenharmony_ci{
306162306a36Sopenharmony_ci	unsigned long flags;
306262306a36Sopenharmony_ci	spin_lock_irqsave(&dev->av_tbl.lock, flags);
306362306a36Sopenharmony_ci	ah->av->valid = 0;
306462306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->av_tbl.lock, flags);
306562306a36Sopenharmony_ci}
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_cistatic int ocrdma_create_eqs(struct ocrdma_dev *dev)
306862306a36Sopenharmony_ci{
306962306a36Sopenharmony_ci	int num_eq, i, status = 0;
307062306a36Sopenharmony_ci	int irq;
307162306a36Sopenharmony_ci	unsigned long flags = 0;
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci	num_eq = dev->nic_info.msix.num_vectors -
307462306a36Sopenharmony_ci			dev->nic_info.msix.start_vector;
307562306a36Sopenharmony_ci	if (dev->nic_info.intr_mode == BE_INTERRUPT_MODE_INTX) {
307662306a36Sopenharmony_ci		num_eq = 1;
307762306a36Sopenharmony_ci		flags = IRQF_SHARED;
307862306a36Sopenharmony_ci	} else {
307962306a36Sopenharmony_ci		num_eq = min_t(u32, num_eq, num_online_cpus());
308062306a36Sopenharmony_ci	}
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci	if (!num_eq)
308362306a36Sopenharmony_ci		return -EINVAL;
308462306a36Sopenharmony_ci
308562306a36Sopenharmony_ci	dev->eq_tbl = kcalloc(num_eq, sizeof(struct ocrdma_eq), GFP_KERNEL);
308662306a36Sopenharmony_ci	if (!dev->eq_tbl)
308762306a36Sopenharmony_ci		return -ENOMEM;
308862306a36Sopenharmony_ci
308962306a36Sopenharmony_ci	for (i = 0; i < num_eq; i++) {
309062306a36Sopenharmony_ci		status = ocrdma_create_eq(dev, &dev->eq_tbl[i],
309162306a36Sopenharmony_ci					OCRDMA_EQ_LEN);
309262306a36Sopenharmony_ci		if (status) {
309362306a36Sopenharmony_ci			status = -EINVAL;
309462306a36Sopenharmony_ci			break;
309562306a36Sopenharmony_ci		}
309662306a36Sopenharmony_ci		sprintf(dev->eq_tbl[i].irq_name, "ocrdma%d-%d",
309762306a36Sopenharmony_ci			dev->id, i);
309862306a36Sopenharmony_ci		irq = ocrdma_get_irq(dev, &dev->eq_tbl[i]);
309962306a36Sopenharmony_ci		status = request_irq(irq, ocrdma_irq_handler, flags,
310062306a36Sopenharmony_ci				     dev->eq_tbl[i].irq_name,
310162306a36Sopenharmony_ci				     &dev->eq_tbl[i]);
310262306a36Sopenharmony_ci		if (status)
310362306a36Sopenharmony_ci			goto done;
310462306a36Sopenharmony_ci		dev->eq_cnt += 1;
310562306a36Sopenharmony_ci	}
310662306a36Sopenharmony_ci	/* one eq is sufficient for data path to work */
310762306a36Sopenharmony_ci	return 0;
310862306a36Sopenharmony_cidone:
310962306a36Sopenharmony_ci	ocrdma_destroy_eqs(dev);
311062306a36Sopenharmony_ci	return status;
311162306a36Sopenharmony_ci}
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_cistatic int ocrdma_mbx_modify_eqd(struct ocrdma_dev *dev, struct ocrdma_eq *eq,
311462306a36Sopenharmony_ci				 int num)
311562306a36Sopenharmony_ci{
311662306a36Sopenharmony_ci	int i, status;
311762306a36Sopenharmony_ci	struct ocrdma_modify_eqd_req *cmd;
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_MODIFY_EQ_DELAY, sizeof(*cmd));
312062306a36Sopenharmony_ci	if (!cmd)
312162306a36Sopenharmony_ci		return -ENOMEM;
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_MODIFY_EQ_DELAY,
312462306a36Sopenharmony_ci			OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci	cmd->cmd.num_eq = num;
312762306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
312862306a36Sopenharmony_ci		cmd->cmd.set_eqd[i].eq_id = eq[i].q.id;
312962306a36Sopenharmony_ci		cmd->cmd.set_eqd[i].phase = 0;
313062306a36Sopenharmony_ci		cmd->cmd.set_eqd[i].delay_multiplier =
313162306a36Sopenharmony_ci				(eq[i].aic_obj.prev_eqd * 65)/100;
313262306a36Sopenharmony_ci	}
313362306a36Sopenharmony_ci	status = ocrdma_mbx_cmd(dev, (struct ocrdma_mqe *)cmd);
313462306a36Sopenharmony_ci
313562306a36Sopenharmony_ci	kfree(cmd);
313662306a36Sopenharmony_ci	return status;
313762306a36Sopenharmony_ci}
313862306a36Sopenharmony_ci
313962306a36Sopenharmony_cistatic int ocrdma_modify_eqd(struct ocrdma_dev *dev, struct ocrdma_eq *eq,
314062306a36Sopenharmony_ci			     int num)
314162306a36Sopenharmony_ci{
314262306a36Sopenharmony_ci	int num_eqs, i = 0;
314362306a36Sopenharmony_ci	if (num > 8) {
314462306a36Sopenharmony_ci		while (num) {
314562306a36Sopenharmony_ci			num_eqs = min(num, 8);
314662306a36Sopenharmony_ci			ocrdma_mbx_modify_eqd(dev, &eq[i], num_eqs);
314762306a36Sopenharmony_ci			i += num_eqs;
314862306a36Sopenharmony_ci			num -= num_eqs;
314962306a36Sopenharmony_ci		}
315062306a36Sopenharmony_ci	} else {
315162306a36Sopenharmony_ci		ocrdma_mbx_modify_eqd(dev, eq, num);
315262306a36Sopenharmony_ci	}
315362306a36Sopenharmony_ci	return 0;
315462306a36Sopenharmony_ci}
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_civoid ocrdma_eqd_set_task(struct work_struct *work)
315762306a36Sopenharmony_ci{
315862306a36Sopenharmony_ci	struct ocrdma_dev *dev =
315962306a36Sopenharmony_ci		container_of(work, struct ocrdma_dev, eqd_work.work);
316062306a36Sopenharmony_ci	struct ocrdma_eq *eq = NULL;
316162306a36Sopenharmony_ci	int i, num = 0;
316262306a36Sopenharmony_ci	u64 eq_intr;
316362306a36Sopenharmony_ci
316462306a36Sopenharmony_ci	for (i = 0; i < dev->eq_cnt; i++) {
316562306a36Sopenharmony_ci		eq = &dev->eq_tbl[i];
316662306a36Sopenharmony_ci		if (eq->aic_obj.eq_intr_cnt > eq->aic_obj.prev_eq_intr_cnt) {
316762306a36Sopenharmony_ci			eq_intr = eq->aic_obj.eq_intr_cnt -
316862306a36Sopenharmony_ci				  eq->aic_obj.prev_eq_intr_cnt;
316962306a36Sopenharmony_ci			if ((eq_intr > EQ_INTR_PER_SEC_THRSH_HI) &&
317062306a36Sopenharmony_ci			    (eq->aic_obj.prev_eqd == EQ_AIC_MIN_EQD)) {
317162306a36Sopenharmony_ci				eq->aic_obj.prev_eqd = EQ_AIC_MAX_EQD;
317262306a36Sopenharmony_ci				num++;
317362306a36Sopenharmony_ci			} else if ((eq_intr < EQ_INTR_PER_SEC_THRSH_LOW) &&
317462306a36Sopenharmony_ci				   (eq->aic_obj.prev_eqd == EQ_AIC_MAX_EQD)) {
317562306a36Sopenharmony_ci				eq->aic_obj.prev_eqd = EQ_AIC_MIN_EQD;
317662306a36Sopenharmony_ci				num++;
317762306a36Sopenharmony_ci			}
317862306a36Sopenharmony_ci		}
317962306a36Sopenharmony_ci		eq->aic_obj.prev_eq_intr_cnt = eq->aic_obj.eq_intr_cnt;
318062306a36Sopenharmony_ci	}
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_ci	if (num)
318362306a36Sopenharmony_ci		ocrdma_modify_eqd(dev, &dev->eq_tbl[0], num);
318462306a36Sopenharmony_ci	schedule_delayed_work(&dev->eqd_work, msecs_to_jiffies(1000));
318562306a36Sopenharmony_ci}
318662306a36Sopenharmony_ci
318762306a36Sopenharmony_ciint ocrdma_init_hw(struct ocrdma_dev *dev)
318862306a36Sopenharmony_ci{
318962306a36Sopenharmony_ci	int status;
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ci	/* create the eqs  */
319262306a36Sopenharmony_ci	status = ocrdma_create_eqs(dev);
319362306a36Sopenharmony_ci	if (status)
319462306a36Sopenharmony_ci		goto qpeq_err;
319562306a36Sopenharmony_ci	status = ocrdma_create_mq(dev);
319662306a36Sopenharmony_ci	if (status)
319762306a36Sopenharmony_ci		goto mq_err;
319862306a36Sopenharmony_ci	status = ocrdma_mbx_query_fw_config(dev);
319962306a36Sopenharmony_ci	if (status)
320062306a36Sopenharmony_ci		goto conf_err;
320162306a36Sopenharmony_ci	status = ocrdma_mbx_query_dev(dev);
320262306a36Sopenharmony_ci	if (status)
320362306a36Sopenharmony_ci		goto conf_err;
320462306a36Sopenharmony_ci	status = ocrdma_mbx_query_fw_ver(dev);
320562306a36Sopenharmony_ci	if (status)
320662306a36Sopenharmony_ci		goto conf_err;
320762306a36Sopenharmony_ci	status = ocrdma_mbx_create_ah_tbl(dev);
320862306a36Sopenharmony_ci	if (status)
320962306a36Sopenharmony_ci		goto conf_err;
321062306a36Sopenharmony_ci	status = ocrdma_mbx_get_phy_info(dev);
321162306a36Sopenharmony_ci	if (status)
321262306a36Sopenharmony_ci		goto info_attrb_err;
321362306a36Sopenharmony_ci	status = ocrdma_mbx_get_ctrl_attribs(dev);
321462306a36Sopenharmony_ci	if (status)
321562306a36Sopenharmony_ci		goto info_attrb_err;
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci	return 0;
321862306a36Sopenharmony_ci
321962306a36Sopenharmony_ciinfo_attrb_err:
322062306a36Sopenharmony_ci	ocrdma_mbx_delete_ah_tbl(dev);
322162306a36Sopenharmony_ciconf_err:
322262306a36Sopenharmony_ci	ocrdma_destroy_mq(dev);
322362306a36Sopenharmony_cimq_err:
322462306a36Sopenharmony_ci	ocrdma_destroy_eqs(dev);
322562306a36Sopenharmony_ciqpeq_err:
322662306a36Sopenharmony_ci	pr_err("%s() status=%d\n", __func__, status);
322762306a36Sopenharmony_ci	return status;
322862306a36Sopenharmony_ci}
322962306a36Sopenharmony_ci
323062306a36Sopenharmony_civoid ocrdma_cleanup_hw(struct ocrdma_dev *dev)
323162306a36Sopenharmony_ci{
323262306a36Sopenharmony_ci	ocrdma_free_pd_pool(dev);
323362306a36Sopenharmony_ci	ocrdma_mbx_delete_ah_tbl(dev);
323462306a36Sopenharmony_ci
323562306a36Sopenharmony_ci	/* cleanup the control path */
323662306a36Sopenharmony_ci	ocrdma_destroy_mq(dev);
323762306a36Sopenharmony_ci
323862306a36Sopenharmony_ci	/* cleanup the eqs */
323962306a36Sopenharmony_ci	ocrdma_destroy_eqs(dev);
324062306a36Sopenharmony_ci}
3241