drivers/irqchip/irq-loongarch-avec.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-loongarch-avec.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-loongarch-avec.c
Extension
.c
Size
10234 bytes
Lines
431
Domain
Driver Families
Bucket
drivers/irqchip
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pending_list {
	struct list_head	head;
};

static struct cpumask intersect_mask;
static DEFINE_PER_CPU(struct pending_list, pending_list);
#endif

static DEFINE_PER_CPU(struct irq_desc * [NR_VECTORS], irq_map);

struct avecintc_chip {
	raw_spinlock_t		lock;
	struct fwnode_handle	*fwnode;
	struct irq_domain	*domain;
	struct irq_matrix	*vector_matrix;
	phys_addr_t		msi_base_addr;
};

static struct avecintc_chip loongarch_avec;

static inline void avecintc_enable(void)
{
#ifdef CONFIG_MACH_LOONGSON64
	u64 value;

	value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
	value |= IOCSR_MISC_FUNC_AVEC_EN;
	iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC);
#endif
}

static inline void avecintc_ack_irq(struct irq_data *d)
{
}

static inline void avecintc_mask_irq(struct irq_data *d)
{
}

static inline void avecintc_unmask_irq(struct irq_data *d)
{
}

#ifdef CONFIG_SMP
static inline void pending_list_init(int cpu)
{
	struct pending_list *plist = per_cpu_ptr(&pending_list, cpu);

	INIT_LIST_HEAD(&plist->head);
}

void avecintc_sync(struct avecintc_data *adata)
{
	struct pending_list *plist;

	if (cpu_online(adata->prev_cpu)) {
		plist = per_cpu_ptr(&pending_list, adata->prev_cpu);
		list_add_tail(&adata->entry, &plist->head);
		adata->moving = 1;
		mp_ops.send_ipi_single(adata->prev_cpu, ACTION_CLEAR_VECTOR);
	}
}

static int avecintc_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force)
{
	int cpu, ret, vector;
	struct avecintc_data *adata;

	scoped_guard(raw_spinlock, &loongarch_avec.lock) {
		adata = irq_data_get_irq_chip_data(data);

		if (adata->moving)
			return -EBUSY;

		if (cpu_online(adata->cpu) && cpumask_test_cpu(adata->cpu, dest))
			return IRQ_SET_MASK_OK_DONE;

		cpumask_and(&intersect_mask, dest, cpu_online_mask);

		ret = irq_matrix_alloc(loongarch_avec.vector_matrix, &intersect_mask, false, &cpu);
		if (ret < 0)
			return ret;

		vector = ret;
		adata->cpu = cpu;
		adata->vec = vector;
		per_cpu_ptr(irq_map, adata->cpu)[adata->vec] = irq_data_to_desc(data);
		if (!cpu_has_redirectint)
			avecintc_sync(adata);
	}

Annotation

Implementation Notes