// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright IBM Corp. 2000, 2009
 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
 *	      Cornelia Huck <cornelia.huck@de.ibm.com>
 *	      Jan Glauber <jang@linux.vnet.ibm.com>
 */
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/kernel_stat.h>
#include <linux/atomic.h>
#include <linux/rculist.h>

#include <asm/debug.h>
#include <asm/qdio.h>
#include <asm/airq.h>
#include <asm/isc.h>
#include <asm/tpi.h>

#include "cio.h"
#include "ioasm.h"
#include "qdio.h"
#include "qdio_debug.h"

/*
 * Restriction: only 63 iqdio subchannels would have its own indicator,
 * after that, subsequent subchannels share one indicator
 */
#define TIQDIO_NR_NONSHARED_IND		63
#define TIQDIO_NR_INDICATORS		(TIQDIO_NR_NONSHARED_IND + 1)
#define TIQDIO_SHARED_IND		63

/* device state change indicators */
struct indicator_t {
	u32 ind;	/* u32 because of compare-and-swap performance */
	atomic_t count; /* use count, 0 or 1 for non-shared indicators */
};

/* list of thin interrupt input queues */
static LIST_HEAD(tiq_list);
static DEFINE_MUTEX(tiq_list_lock);

static struct indicator_t *q_indicators;

u64 last_ai_time;

/* returns addr for the device state change indicator */
static u32 *get_indicator(void)
{
	int i;

	for (i = 0; i < TIQDIO_NR_NONSHARED_IND; i++)
		if (!atomic_cmpxchg(&q_indicators[i].count, 0, 1))
			return &q_indicators[i].ind;

	/* use the shared indicator */
	atomic_inc(&q_indicators[TIQDIO_SHARED_IND].count);
	return &q_indicators[TIQDIO_SHARED_IND].ind;
}

static void put_indicator(u32 *addr)
{
	struct indicator_t *ind = container_of(addr, struct indicator_t, ind);

	if (!addr)
		return;
	atomic_dec(&ind->count);
}

static inline int references_shared_dsci(struct qdio_irq *irq_ptr)
{
	return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
}

int test_nonshared_ind(struct qdio_irq *irq_ptr)
{
	if (!is_thinint_irq(irq_ptr))
		return 0;
	if (references_shared_dsci(irq_ptr))
		return 0;
	if (*irq_ptr->dsci)
		return 1;
	else
		return 0;
}

static inline u32 clear_shared_ind(void)
{
	if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
		return 0;
	return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
}

/**
 * tiqdio_thinint_handler - thin interrupt handler for qdio
 * @airq: pointer to adapter interrupt descriptor
 * @tpi_info: interrupt information (e.g. floating vs directed -- unused)
 */
static void tiqdio_thinint_handler(struct airq_struct *airq,
				   struct tpi_info *tpi_info)
{
	u64 irq_time = S390_lowcore.int_clock;
	u32 si_used = clear_shared_ind();
	struct qdio_irq *irq;

	last_ai_time = irq_time;
	inc_irq_stat(IRQIO_QAI);

	/* protect tiq_list entries, only changed in activate or shutdown */
	rcu_read_lock();

	list_for_each_entry_rcu(irq, &tiq_list, entry) {
		/* only process queues from changed sets */
		if (unlikely(references_shared_dsci(irq))) {
			if (!si_used)
				continue;
		} else {
			if (!*irq->dsci)
				continue;

			xchg(irq->dsci, 0);
		}

		qdio_deliver_irq(irq);
		irq->last_data_irq_time = irq_time;

		QDIO_PERF_STAT_INC(irq, adapter_int);
	}
	rcu_read_unlock();
}

static struct airq_struct tiqdio_airq = {
	.handler = tiqdio_thinint_handler,
	.isc = QDIO_AIRQ_ISC,
};

static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
{
	struct chsc_scssc_area *scssc = (void *)irq_ptr->chsc_page;
	dma64_t summary_indicator_addr, subchannel_indicator_addr;
	int rc;

	if (reset) {
		summary_indicator_addr = 0;
		subchannel_indicator_addr = 0;
	} else {
		summary_indicator_addr = virt_to_dma64(tiqdio_airq.lsi_ptr);
		subchannel_indicator_addr = virt_to_dma64(irq_ptr->dsci);
	}

	rc = chsc_sadc(irq_ptr->schid, scssc, summary_indicator_addr,
		       subchannel_indicator_addr, tiqdio_airq.isc);
	if (rc) {
		DBF_ERROR("%4x SSI r:%4x", irq_ptr->schid.sch_no,
			  scssc->response.code);
		goto out;
	}

	DBF_EVENT("setscind");
	DBF_HEX(&summary_indicator_addr, sizeof(summary_indicator_addr));
	DBF_HEX(&subchannel_indicator_addr, sizeof(subchannel_indicator_addr));
out:
	return rc;
}

int qdio_establish_thinint(struct qdio_irq *irq_ptr)
{
	int rc;

	if (!is_thinint_irq(irq_ptr))
		return 0;

	irq_ptr->dsci = get_indicator();
	DBF_HEX(&irq_ptr->dsci, sizeof(void *));

	rc = set_subchannel_ind(irq_ptr, 0);
	if (rc) {
		put_indicator(irq_ptr->dsci);
		return rc;
	}

	mutex_lock(&tiq_list_lock);
	list_add_rcu(&irq_ptr->entry, &tiq_list);
	mutex_unlock(&tiq_list_lock);
	return 0;
}

void qdio_shutdown_thinint(struct qdio_irq *irq_ptr)
{
	if (!is_thinint_irq(irq_ptr))
		return;

	mutex_lock(&tiq_list_lock);
	list_del_rcu(&irq_ptr->entry);
	mutex_unlock(&tiq_list_lock);
	synchronize_rcu();

	/* reset adapter interrupt indicators */
	set_subchannel_ind(irq_ptr, 1);
	put_indicator(irq_ptr->dsci);
}

int __init qdio_thinint_init(void)
{
	int rc;

	q_indicators = kcalloc(TIQDIO_NR_INDICATORS, sizeof(struct indicator_t),
			       GFP_KERNEL);
	if (!q_indicators)
		return -ENOMEM;

	rc = register_adapter_interrupt(&tiqdio_airq);
	if (rc) {
		DBF_EVENT("RTI:%x", rc);
		kfree(q_indicators);
		return rc;
	}
	return 0;
}

void __exit qdio_thinint_exit(void)
{
	WARN_ON(!list_empty(&tiq_list));
	unregister_adapter_interrupt(&tiqdio_airq);
	kfree(q_indicators);
}
