drivers/misc/ocxl/link.c

Source file repositories/reference/linux-study-clean/drivers/misc/ocxl/link.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/ocxl/link.c
Extension
.c
Size
19834 bytes
Lines
780
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 pe_data {
	struct mm_struct *mm;
	/* callback to trigger when a translation fault occurs */
	void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr);
	/* opaque pointer to be passed to the above callback */
	void *xsl_err_data;
	struct rcu_head rcu;
	struct ocxl_link *link;
	struct mmu_notifier mmu_notifier;
};

struct spa {
	struct ocxl_process_element *spa_mem;
	int spa_order;
	struct mutex spa_lock;
	struct radix_tree_root pe_tree; /* Maps PE handles to pe_data */
	char *irq_name;
	int virq;
	void __iomem *reg_dsisr;
	void __iomem *reg_dar;
	void __iomem *reg_tfc;
	void __iomem *reg_pe_handle;
	/*
	 * The following field are used by the memory fault
	 * interrupt handler. We can only have one interrupt at a
	 * time. The NPU won't raise another interrupt until the
	 * previous one has been ack'd by writing to the TFC register
	 */
	struct xsl_fault {
		struct work_struct fault_work;
		u64 pe;
		u64 dsisr;
		u64 dar;
		struct pe_data pe_data;
	} xsl_fault;
};

/*
 * A opencapi link can be used be by several PCI functions. We have
 * one link per device slot.
 *
 * A linked list of opencapi links should suffice, as there's a
 * limited number of opencapi slots on a system and lookup is only
 * done when the device is probed
 */
struct ocxl_link {
	struct list_head list;
	struct kref ref;
	int domain;
	int bus;
	int dev;
	void __iomem *arva;     /* ATSD register virtual address */
	spinlock_t atsd_lock;   /* to serialize shootdowns */
	atomic_t irq_available;
	struct spa *spa;
	void *platform_data;
};
static LIST_HEAD(links_list);
static DEFINE_MUTEX(links_list_lock);

enum xsl_response {
	CONTINUE,
	ADDRESS_ERROR,
	RESTART,
};


static void read_irq(struct spa *spa, u64 *dsisr, u64 *dar, u64 *pe)
{
	u64 reg;

	*dsisr = in_be64(spa->reg_dsisr);
	*dar = in_be64(spa->reg_dar);
	reg = in_be64(spa->reg_pe_handle);
	*pe = reg & SPA_PE_MASK;
}

static void ack_irq(struct spa *spa, enum xsl_response r)
{
	u64 reg = 0;

	/* continue is not supported */
	if (r == RESTART)
		reg = PPC_BIT(31);
	else if (r == ADDRESS_ERROR)
		reg = PPC_BIT(30);
	else
		WARN(1, "Invalid irq response %d\n", r);

	if (reg) {

Annotation

Implementation Notes