drivers/irqchip/irq-ls-scfg-msi.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-ls-scfg-msi.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-ls-scfg-msi.c
Extension
.c
Size
10730 bytes
Lines
421
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 ls_scfg_msi_cfg {
	u32 ibs_shift; /* Shift of interrupt bit select */
	u32 msir_irqs; /* The irq number per MSIR */
	u32 msir_base; /* The base address of MSIR */
};

struct ls_scfg_msir {
	struct ls_scfg_msi *msi_data;
	unsigned int index;
	unsigned int gic_irq;
	unsigned int bit_start;
	unsigned int bit_end;
	unsigned int srs; /* Shared interrupt register select */
	void __iomem *reg;
};

struct ls_scfg_msi {
	spinlock_t		lock;
	struct platform_device	*pdev;
	struct irq_domain	*parent;
	void __iomem		*regs;
	phys_addr_t		msiir_addr;
	struct ls_scfg_msi_cfg	*cfg;
	u32			msir_num;
	struct ls_scfg_msir	*msir;
	u32			irqs_num;
	unsigned long		*used;
};

#define MPIC_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
				 MSI_FLAG_USE_DEF_CHIP_OPS)
#define MPIC_MSI_FLAGS_SUPPORTED (MSI_FLAG_PCI_MSIX       | \
				  MSI_GENERIC_FLAGS_MASK)

static const struct msi_parent_ops ls_scfg_msi_parent_ops = {
	.required_flags		= MPIC_MSI_FLAGS_REQUIRED,
	.supported_flags	= MPIC_MSI_FLAGS_SUPPORTED,
	.bus_select_token	= DOMAIN_BUS_NEXUS,
	.bus_select_mask	= MATCH_PCI_MSI,
	.prefix			= "MSI-",
	.init_dev_msi_info	= msi_lib_init_dev_msi_info,
};

static int msi_affinity_flag = 1;

static int __init early_parse_ls_scfg_msi(char *p)
{
	if (p && strncmp(p, "no-affinity", 11) == 0)
		msi_affinity_flag = 0;
	else
		msi_affinity_flag = 1;

	return 0;
}
early_param("lsmsi", early_parse_ls_scfg_msi);

static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
{
	struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(data);

	msg->data = data->hwirq;

	if (msi_affinity_flag) {
		const struct cpumask *mask;

		mask = irq_data_get_effective_affinity_mask(data);
		msg->data |= cpumask_first(mask);
	}

	msi_msg_set_addr(irq_data_get_msi_desc(data), msg,
			 msi_data->msiir_addr);
}

static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
				    const struct cpumask *mask, bool force)
{
	struct ls_scfg_msi *msi_data = irq_data_get_irq_chip_data(irq_data);
	u32 cpu;

	if (!msi_affinity_flag)
		return -EINVAL;

	if (!force)
		cpu = cpumask_any_and(mask, cpu_online_mask);
	else
		cpu = cpumask_first(mask);

	if (cpu >= msi_data->msir_num)
		return -EINVAL;

Annotation

Implementation Notes