// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2023 Advanced Micro Devices, Inc */

#include <linux/dynamic_debug.h>

#include "core.h"

struct pdsc_wait_context {
	struct pdsc_qcq *qcq;
	struct completion wait_completion;
};

static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
{
	union pds_core_notifyq_comp *comp;
	struct pdsc *pdsc = qcq->pdsc;
	struct pdsc_cq *cq = &qcq->cq;
	struct pdsc_cq_info *cq_info;
	int nq_work = 0;
	u64 eid;

	cq_info = &cq->info[cq->tail_idx];
	comp = cq_info->comp;
	eid = le64_to_cpu(comp->event.eid);
	while (eid > pdsc->last_eid) {
		u16 ecode = le16_to_cpu(comp->event.ecode);

		switch (ecode) {
		case PDS_EVENT_LINK_CHANGE:
			dev_info(pdsc->dev, "NotifyQ LINK_CHANGE ecode %d eid %lld\n",
				 ecode, eid);
			pdsc_notify(PDS_EVENT_LINK_CHANGE, comp);
			break;

		case PDS_EVENT_RESET:
			dev_info(pdsc->dev, "NotifyQ RESET ecode %d eid %lld\n",
				 ecode, eid);
			pdsc_notify(PDS_EVENT_RESET, comp);
			break;

		case PDS_EVENT_XCVR:
			dev_info(pdsc->dev, "NotifyQ XCVR ecode %d eid %lld\n",
				 ecode, eid);
			break;

		default:
			dev_info(pdsc->dev, "NotifyQ ecode %d eid %lld\n",
				 ecode, eid);
			break;
		}

		pdsc->last_eid = eid;
		cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
		cq_info = &cq->info[cq->tail_idx];
		comp = cq_info->comp;
		eid = le64_to_cpu(comp->event.eid);

		nq_work++;
	}

	qcq->accum_work += nq_work;

	return nq_work;
}

static bool pdsc_adminq_inc_if_up(struct pdsc *pdsc)
{
	if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER) ||
	    pdsc->state & BIT_ULL(PDSC_S_FW_DEAD))
		return false;

	return refcount_inc_not_zero(&pdsc->adminq_refcnt);
}

void pdsc_process_adminq(struct pdsc_qcq *qcq)
{
	union pds_core_adminq_comp *comp;
	struct pdsc_queue *q = &qcq->q;
	struct pdsc *pdsc = qcq->pdsc;
	struct pdsc_cq *cq = &qcq->cq;
	struct pdsc_q_info *q_info;
	unsigned long irqflags;
	int nq_work = 0;
	int aq_work = 0;

	/* Don't process AdminQ when it's not up */
	if (!pdsc_adminq_inc_if_up(pdsc)) {
		dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
			__func__);
		return;
	}

	/* Check for NotifyQ event */
	nq_work = pdsc_process_notifyq(&pdsc->notifyqcq);

	/* Check for empty queue, which can happen if the interrupt was
	 * for a NotifyQ event and there are no new AdminQ completions.
	 */
	if (q->tail_idx == q->head_idx)
		goto credits;

	/* Find the first completion to clean,
	 * run the callback in the related q_info,
	 * and continue while we still match done color
	 */
	spin_lock_irqsave(&pdsc->adminq_lock, irqflags);
	comp = cq->info[cq->tail_idx].comp;
	while (pdsc_color_match(comp->color, cq->done_color)) {
		q_info = &q->info[q->tail_idx];
		q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);

		/* Copy out the completion data */
		memcpy(q_info->dest, comp, sizeof(*comp));

		complete_all(&q_info->wc->wait_completion);

		if (cq->tail_idx == cq->num_descs - 1)
			cq->done_color = !cq->done_color;
		cq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);
		comp = cq->info[cq->tail_idx].comp;

		aq_work++;
	}
	spin_unlock_irqrestore(&pdsc->adminq_lock, irqflags);

	qcq->accum_work += aq_work;

credits:
	/* Return the interrupt credits, one for each completion */
	pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx],
			      nq_work + aq_work,
			      PDS_CORE_INTR_CRED_REARM);
	refcount_dec(&pdsc->adminq_refcnt);
}

void pdsc_work_thread(struct work_struct *work)
{
	struct pdsc_qcq *qcq = container_of(work, struct pdsc_qcq, work);

	pdsc_process_adminq(qcq);
}

irqreturn_t pdsc_adminq_isr(int irq, void *data)
{
	struct pdsc *pdsc = data;
	struct pdsc_qcq *qcq;

	/* Don't process AdminQ when it's not up */
	if (!pdsc_adminq_inc_if_up(pdsc)) {
		dev_err(pdsc->dev, "%s: called while adminq is unavailable\n",
			__func__);
		return IRQ_HANDLED;
	}

	qcq = &pdsc->adminqcq;
	queue_work(pdsc->wq, &qcq->work);
	refcount_dec(&pdsc->adminq_refcnt);

	return IRQ_HANDLED;
}

static int __pdsc_adminq_post(struct pdsc *pdsc,
			      struct pdsc_qcq *qcq,
			      union pds_core_adminq_cmd *cmd,
			      union pds_core_adminq_comp *comp,
			      struct pdsc_wait_context *wc)
{
	struct pdsc_queue *q = &qcq->q;
	struct pdsc_q_info *q_info;
	unsigned long irqflags;
	unsigned int avail;
	int index;
	int ret;

	spin_lock_irqsave(&pdsc->adminq_lock, irqflags);

	/* Check for space in the queue */
	avail = q->tail_idx;
	if (q->head_idx >= avail)
		avail += q->num_descs - q->head_idx - 1;
	else
		avail -= q->head_idx + 1;
	if (!avail) {
		ret = -ENOSPC;
		goto err_out_unlock;
	}

	/* Check that the FW is running */
	if (!pdsc_is_fw_running(pdsc)) {
		if (pdsc->info_regs) {
			u8 fw_status =
				ioread8(&pdsc->info_regs->fw_status);

			dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n",
				 __func__, fw_status);
		} else {
			dev_info(pdsc->dev, "%s: post failed - BARs not setup\n",
				 __func__);
		}
		ret = -ENXIO;

		goto err_out_unlock;
	}

	/* Post the request */
	index = q->head_idx;
	q_info = &q->info[index];
	q_info->wc = wc;
	q_info->dest = comp;
	memcpy(q_info->desc, cmd, sizeof(*cmd));

	dev_dbg(pdsc->dev, "head_idx %d tail_idx %d\n",
		q->head_idx, q->tail_idx);
	dev_dbg(pdsc->dev, "post admin queue command:\n");
	dynamic_hex_dump("cmd ", DUMP_PREFIX_OFFSET, 16, 1,
			 cmd, sizeof(*cmd), true);

	q->head_idx = (q->head_idx + 1) & (q->num_descs - 1);

	pds_core_dbell_ring(pdsc->kern_dbpage,
			    q->hw_type, q->dbval | q->head_idx);
	ret = index;

err_out_unlock:
	spin_unlock_irqrestore(&pdsc->adminq_lock, irqflags);
	return ret;
}

int pdsc_adminq_post(struct pdsc *pdsc,
		     union pds_core_adminq_cmd *cmd,
		     union pds_core_adminq_comp *comp,
		     bool fast_poll)
{
	struct pdsc_wait_context wc = {
		.wait_completion =
			COMPLETION_INITIALIZER_ONSTACK(wc.wait_completion),
	};
	unsigned long poll_interval = 1;
	unsigned long poll_jiffies;
	unsigned long time_limit;
	unsigned long time_start;
	unsigned long time_done;
	unsigned long remaining;
	int err = 0;
	int index;

	if (!pdsc_adminq_inc_if_up(pdsc)) {
		dev_dbg(pdsc->dev, "%s: preventing adminq cmd %u\n",
			__func__, cmd->opcode);
		return -ENXIO;
	}

	wc.qcq = &pdsc->adminqcq;
	index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc);
	if (index < 0) {
		err = index;
		goto err_out;
	}

	time_start = jiffies;
	time_limit = time_start + HZ * pdsc->devcmd_timeout;
	do {
		/* Timeslice the actual wait to catch IO errors etc early */
		poll_jiffies = msecs_to_jiffies(poll_interval);
		remaining = wait_for_completion_timeout(&wc.wait_completion,
							poll_jiffies);
		if (remaining)
			break;

		if (!pdsc_is_fw_running(pdsc)) {
			if (pdsc->info_regs) {
				u8 fw_status =
					ioread8(&pdsc->info_regs->fw_status);

				dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n",
					__func__, fw_status);
			} else {
				dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n",
					__func__);
			}
			err = -ENXIO;
			break;
		}

		/* When fast_poll is not requested, prevent aggressive polling
		 * on failures due to timeouts by doing exponential back off.
		 */
		if (!fast_poll && poll_interval < PDSC_ADMINQ_MAX_POLL_INTERVAL)
			poll_interval <<= 1;
	} while (time_before(jiffies, time_limit));
	time_done = jiffies;
	dev_dbg(pdsc->dev, "%s: elapsed %d msecs\n",
		__func__, jiffies_to_msecs(time_done - time_start));

	/* Check the results */
	if (time_after_eq(time_done, time_limit))
		err = -ETIMEDOUT;

	dev_dbg(pdsc->dev, "read admin queue completion idx %d:\n", index);
	dynamic_hex_dump("comp ", DUMP_PREFIX_OFFSET, 16, 1,
			 comp, sizeof(*comp), true);

	if (remaining && comp->status)
		err = pdsc_err_to_errno(comp->status);

err_out:
	if (err) {
		dev_dbg(pdsc->dev, "%s: opcode %d status %d err %pe\n",
			__func__, cmd->opcode, comp->status, ERR_PTR(err));
		if (err == -ENXIO || err == -ETIMEDOUT)
			queue_work(pdsc->wq, &pdsc->health_work);
	}

	refcount_dec(&pdsc->adminq_refcnt);

	return err;
}
EXPORT_SYMBOL_GPL(pdsc_adminq_post);
