// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause

/* Authors: Cheng Xu <chengyou@linux.alibaba.com> */
/*          Kai Shen <kaishen@linux.alibaba.com> */
/* Copyright (c) 2020-2022, Alibaba Group. */

#include "erdma_verbs.h"

#define MAX_POLL_CHUNK_SIZE 16

void notify_eq(struct erdma_eq *eq)
{
	u64 db_data = FIELD_PREP(ERDMA_EQDB_CI_MASK, eq->ci) |
		      FIELD_PREP(ERDMA_EQDB_ARM_MASK, 1);

	*eq->dbrec = db_data;
	writeq(db_data, eq->db);

	atomic64_inc(&eq->notify_num);
}

void *get_next_valid_eqe(struct erdma_eq *eq)
{
	u64 *eqe = get_queue_entry(eq->qbuf, eq->ci, eq->depth, EQE_SHIFT);
	u32 owner = FIELD_GET(ERDMA_CEQE_HDR_O_MASK, READ_ONCE(*eqe));

	return owner ^ !!(eq->ci & eq->depth) ? eqe : NULL;
}

void erdma_aeq_event_handler(struct erdma_dev *dev)
{
	struct erdma_aeqe *aeqe;
	u32 cqn, qpn;
	struct erdma_qp *qp;
	struct erdma_cq *cq;
	struct ib_event event;
	u32 poll_cnt = 0;

	memset(&event, 0, sizeof(event));

	while (poll_cnt < MAX_POLL_CHUNK_SIZE) {
		aeqe = get_next_valid_eqe(&dev->aeq);
		if (!aeqe)
			break;

		dma_rmb();

		dev->aeq.ci++;
		atomic64_inc(&dev->aeq.event_num);
		poll_cnt++;

		if (FIELD_GET(ERDMA_AEQE_HDR_TYPE_MASK,
			      le32_to_cpu(aeqe->hdr)) == ERDMA_AE_TYPE_CQ_ERR) {
			cqn = le32_to_cpu(aeqe->event_data0);
			cq = find_cq_by_cqn(dev, cqn);
			if (!cq)
				continue;

			event.device = cq->ibcq.device;
			event.element.cq = &cq->ibcq;
			event.event = IB_EVENT_CQ_ERR;
			if (cq->ibcq.event_handler)
				cq->ibcq.event_handler(&event,
						       cq->ibcq.cq_context);
		} else {
			qpn = le32_to_cpu(aeqe->event_data0);
			qp = find_qp_by_qpn(dev, qpn);
			if (!qp)
				continue;

			event.device = qp->ibqp.device;
			event.element.qp = &qp->ibqp;
			event.event = IB_EVENT_QP_FATAL;
			if (qp->ibqp.event_handler)
				qp->ibqp.event_handler(&event,
						       qp->ibqp.qp_context);
		}
	}

	notify_eq(&dev->aeq);
}

int erdma_eq_common_init(struct erdma_dev *dev, struct erdma_eq *eq, u32 depth)
{
	u32 buf_size = depth << EQE_SHIFT;

	eq->qbuf = dma_alloc_coherent(&dev->pdev->dev, buf_size,
				      &eq->qbuf_dma_addr, GFP_KERNEL);
	if (!eq->qbuf)
		return -ENOMEM;

	eq->dbrec = dma_pool_zalloc(dev->db_pool, GFP_KERNEL, &eq->dbrec_dma);
	if (!eq->dbrec)
		goto err_free_qbuf;

	spin_lock_init(&eq->lock);
	atomic64_set(&eq->event_num, 0);
	atomic64_set(&eq->notify_num, 0);
	eq->ci = 0;
	eq->depth = depth;

	return 0;

err_free_qbuf:
	dma_free_coherent(&dev->pdev->dev, buf_size, eq->qbuf,
			  eq->qbuf_dma_addr);

	return -ENOMEM;
}

void erdma_eq_destroy(struct erdma_dev *dev, struct erdma_eq *eq)
{
	dma_pool_free(dev->db_pool, eq->dbrec, eq->dbrec_dma);
	dma_free_coherent(&dev->pdev->dev, eq->depth << EQE_SHIFT, eq->qbuf,
			  eq->qbuf_dma_addr);
}

int erdma_aeq_init(struct erdma_dev *dev)
{
	struct erdma_eq *eq = &dev->aeq;
	int ret;

	ret = erdma_eq_common_init(dev, &dev->aeq, ERDMA_DEFAULT_EQ_DEPTH);
	if (ret)
		return ret;

	eq->db = dev->func_bar + ERDMA_REGS_AEQ_DB_REG;

	erdma_reg_write32(dev, ERDMA_REGS_AEQ_ADDR_H_REG,
			  upper_32_bits(eq->qbuf_dma_addr));
	erdma_reg_write32(dev, ERDMA_REGS_AEQ_ADDR_L_REG,
			  lower_32_bits(eq->qbuf_dma_addr));
	erdma_reg_write32(dev, ERDMA_REGS_AEQ_DEPTH_REG, eq->depth);
	erdma_reg_write64(dev, ERDMA_AEQ_DB_HOST_ADDR_REG, eq->dbrec_dma);

	return 0;
}

void erdma_ceq_completion_handler(struct erdma_eq_cb *ceq_cb)
{
	struct erdma_dev *dev = ceq_cb->dev;
	struct erdma_cq *cq;
	u32 poll_cnt = 0;
	u64 *ceqe;
	int cqn;

	if (!ceq_cb->ready)
		return;

	while (poll_cnt < MAX_POLL_CHUNK_SIZE) {
		ceqe = get_next_valid_eqe(&ceq_cb->eq);
		if (!ceqe)
			break;

		dma_rmb();
		ceq_cb->eq.ci++;
		poll_cnt++;
		cqn = FIELD_GET(ERDMA_CEQE_HDR_CQN_MASK, READ_ONCE(*ceqe));

		cq = find_cq_by_cqn(dev, cqn);
		if (!cq)
			continue;

		if (rdma_is_kernel_res(&cq->ibcq.res))
			cq->kern_cq.cmdsn++;

		if (cq->ibcq.comp_handler)
			cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
	}

	notify_eq(&ceq_cb->eq);
}

static irqreturn_t erdma_intr_ceq_handler(int irq, void *data)
{
	struct erdma_eq_cb *ceq_cb = data;

	tasklet_schedule(&ceq_cb->tasklet);

	return IRQ_HANDLED;
}

static void erdma_intr_ceq_task(unsigned long data)
{
	erdma_ceq_completion_handler((struct erdma_eq_cb *)data);
}

static int erdma_set_ceq_irq(struct erdma_dev *dev, u16 ceqn)
{
	struct erdma_eq_cb *eqc = &dev->ceqs[ceqn];
	int err;

	snprintf(eqc->irq.name, ERDMA_IRQNAME_SIZE, "erdma-ceq%u@pci:%s", ceqn,
		 pci_name(dev->pdev));
	eqc->irq.msix_vector = pci_irq_vector(dev->pdev, ceqn + 1);

	tasklet_init(&dev->ceqs[ceqn].tasklet, erdma_intr_ceq_task,
		     (unsigned long)&dev->ceqs[ceqn]);

	cpumask_set_cpu(cpumask_local_spread(ceqn + 1, dev->attrs.numa_node),
			&eqc->irq.affinity_hint_mask);

	err = request_irq(eqc->irq.msix_vector, erdma_intr_ceq_handler, 0,
			  eqc->irq.name, eqc);
	if (err) {
		dev_err(&dev->pdev->dev, "failed to request_irq(%d)\n", err);
		return err;
	}

	irq_set_affinity_hint(eqc->irq.msix_vector,
			      &eqc->irq.affinity_hint_mask);

	return 0;
}

static void erdma_free_ceq_irq(struct erdma_dev *dev, u16 ceqn)
{
	struct erdma_eq_cb *eqc = &dev->ceqs[ceqn];

	irq_set_affinity_hint(eqc->irq.msix_vector, NULL);
	free_irq(eqc->irq.msix_vector, eqc);
}

static int create_eq_cmd(struct erdma_dev *dev, u32 eqn, struct erdma_eq *eq)
{
	struct erdma_cmdq_create_eq_req req;

	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON,
				CMDQ_OPCODE_CREATE_EQ);
	req.eqn = eqn;
	req.depth = ilog2(eq->depth);
	req.qbuf_addr = eq->qbuf_dma_addr;
	req.qtype = ERDMA_EQ_TYPE_CEQ;
	/* Vector index is the same as EQN. */
	req.vector_idx = eqn;
	req.db_dma_addr_l = lower_32_bits(eq->dbrec_dma);
	req.db_dma_addr_h = upper_32_bits(eq->dbrec_dma);

	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
}

static int erdma_ceq_init_one(struct erdma_dev *dev, u16 ceqn)
{
	struct erdma_eq *eq = &dev->ceqs[ceqn].eq;
	int ret;

	ret = erdma_eq_common_init(dev, eq, ERDMA_DEFAULT_EQ_DEPTH);
	if (ret)
		return ret;

	eq->db = dev->func_bar + ERDMA_REGS_CEQ_DB_BASE_REG +
		 (ceqn + 1) * ERDMA_DB_SIZE;
	dev->ceqs[ceqn].dev = dev;
	dev->ceqs[ceqn].ready = true;

	/* CEQ indexed from 1, 0 rsvd for CMDQ-EQ. */
	ret = create_eq_cmd(dev, ceqn + 1, eq);
	if (ret) {
		erdma_eq_destroy(dev, eq);
		dev->ceqs[ceqn].ready = false;
	}

	return ret;
}

static void erdma_ceq_uninit_one(struct erdma_dev *dev, u16 ceqn)
{
	struct erdma_eq *eq = &dev->ceqs[ceqn].eq;
	struct erdma_cmdq_destroy_eq_req req;
	int err;

	dev->ceqs[ceqn].ready = 0;

	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_COMMON,
				CMDQ_OPCODE_DESTROY_EQ);
	/* CEQ indexed from 1, 0 rsvd for CMDQ-EQ. */
	req.eqn = ceqn + 1;
	req.qtype = ERDMA_EQ_TYPE_CEQ;
	req.vector_idx = ceqn + 1;

	err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
	if (err)
		return;

	erdma_eq_destroy(dev, eq);
}

int erdma_ceqs_init(struct erdma_dev *dev)
{
	u32 i, j;
	int err;

	for (i = 0; i < dev->attrs.irq_num - 1; i++) {
		err = erdma_ceq_init_one(dev, i);
		if (err)
			goto out_err;

		err = erdma_set_ceq_irq(dev, i);
		if (err) {
			erdma_ceq_uninit_one(dev, i);
			goto out_err;
		}
	}

	return 0;

out_err:
	for (j = 0; j < i; j++) {
		erdma_free_ceq_irq(dev, j);
		erdma_ceq_uninit_one(dev, j);
	}

	return err;
}

void erdma_ceqs_uninit(struct erdma_dev *dev)
{
	u32 i;

	for (i = 0; i < dev->attrs.irq_num - 1; i++) {
		erdma_free_ceq_irq(dev, i);
		erdma_ceq_uninit_one(dev, i);
	}
}
