drivers/ntb/msi.c

Source file repositories/reference/linux-study-clean/drivers/ntb/msi.c

File Facts

System
Linux kernel
Corpus path
drivers/ntb/msi.c
Extension
.c
Size
8444 bytes
Lines
345
Domain
Driver Families
Bucket
drivers/ntb
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 ntb_msi {
	u64 base_addr;
	u64 end_addr;

	void (*desc_changed)(void *ctx);

	u32 __iomem *peer_mws[];
};

/**
 * ntb_msi_init() - Initialize the MSI context
 * @ntb:	NTB device context
 *
 * This function must be called before any other ntb_msi function.
 * It initializes the context for MSI operations and maps
 * the peer memory windows.
 *
 * This function reserves the last N outbound memory windows (where N
 * is the number of peers).
 *
 * Return: Zero on success, otherwise a negative error number.
 */
int ntb_msi_init(struct ntb_dev *ntb,
		 void (*desc_changed)(void *ctx))
{
	phys_addr_t mw_phys_addr;
	resource_size_t mw_size;
	int peer_widx;
	int peers;
	int ret;
	int i;

	peers = ntb_peer_port_count(ntb);
	if (peers <= 0)
		return -EINVAL;

	ntb->msi = devm_kzalloc(&ntb->dev, struct_size(ntb->msi, peer_mws, peers),
				GFP_KERNEL);
	if (!ntb->msi)
		return -ENOMEM;

	ntb->msi->desc_changed = desc_changed;

	for (i = 0; i < peers; i++) {
		peer_widx = ntb_peer_mw_count(ntb) - 1 - i;

		ret = ntb_peer_mw_get_addr(ntb, peer_widx, &mw_phys_addr,
					   &mw_size);
		if (ret)
			goto unroll;

		ntb->msi->peer_mws[i] = devm_ioremap(&ntb->dev, mw_phys_addr,
						     mw_size);
		if (!ntb->msi->peer_mws[i]) {
			ret = -EFAULT;
			goto unroll;
		}
	}

	return 0;

unroll:
	for (i = 0; i < peers; i++)
		if (ntb->msi->peer_mws[i])
			devm_iounmap(&ntb->dev, ntb->msi->peer_mws[i]);

	devm_kfree(&ntb->dev, ntb->msi);
	ntb->msi = NULL;
	return ret;
}
EXPORT_SYMBOL(ntb_msi_init);

/**
 * ntb_msi_setup_mws() - Initialize the MSI inbound memory windows
 * @ntb:	NTB device context
 *
 * This function sets up the required inbound memory windows. It should be
 * called from a work function after a link up event.
 *
 * Over the entire network, this function will reserves the last N
 * inbound memory windows for each peer (where N is the number of peers).
 *
 * ntb_msi_init() must be called before this function.
 *
 * Return: Zero on success, otherwise a negative error number.
 */
int ntb_msi_setup_mws(struct ntb_dev *ntb)
{
	struct msi_desc *desc;
	u64 addr;

Annotation

Implementation Notes