drivers/ntb/hw/idt/ntb_hw_idt.c

Source file repositories/reference/linux-study-clean/drivers/ntb/hw/idt/ntb_hw_idt.c

File Facts

System
Linux kernel
Corpus path
drivers/ntb/hw/idt/ntb_hw_idt.c
Extension
.c
Size
91926 bytes
Lines
2914
Domain
Driver Families
Bucket
drivers/ntb
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations idt_dbgfs_info_ops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = idt_dbgfs_info_read
};

/*
 * idt_dbgfs_info_read() - DebugFS read info node callback
 * @file:	File node descriptor.
 * @ubuf:	User-space buffer to put data to
 * @count:	Size of the buffer
 * @offp:	Offset within the buffer
 */
static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf,
				   size_t count, loff_t *offp)
{
	struct idt_ntb_dev *ndev = filp->private_data;
	unsigned char idx, pidx, cnt;
	unsigned long irqflags, mdeg;
	ssize_t ret = 0, off = 0;
	enum ntb_speed speed;
	enum ntb_width width;
	char *strbuf;
	size_t size;
	u32 data;

	/* Lets limit the buffer size the way the Intel/AMD drivers do */
	size = min_t(size_t, count, 0x1000U);

	/* Allocate the memory for the buffer */
	strbuf = kmalloc(size, GFP_KERNEL);
	if (strbuf == NULL)
		return -ENOMEM;

	/* Put the data into the string buffer */
	off += scnprintf(strbuf + off, size - off,
		"\n\t\tIDT NTB device Information:\n\n");

	/* General local device configurations */
	off += scnprintf(strbuf + off, size - off,
		"Local Port %hhu, Partition %hhu\n", ndev->port, ndev->part);

	/* Peer ports information */
	off += scnprintf(strbuf + off, size - off, "Peers:\n");
	for (idx = 0; idx < ndev->peer_cnt; idx++) {
		off += scnprintf(strbuf + off, size - off,
			"\t%hhu. Port %hhu, Partition %hhu\n",
			idx, ndev->peers[idx].port, ndev->peers[idx].part);
	}

	/* Links status */
	data = idt_ntb_link_is_up(&ndev->ntb, &speed, &width);
	off += scnprintf(strbuf + off, size - off,
		"NTB link status\t- 0x%08x, ", data);
	off += scnprintf(strbuf + off, size - off, "PCIe Gen %d x%d lanes\n",
		speed, width);

	/* Mapping table entries */
	off += scnprintf(strbuf + off, size - off, "NTB Mapping Table:\n");
	for (idx = 0; idx < IDT_MTBL_ENTRY_CNT; idx++) {
		spin_lock_irqsave(&ndev->mtbl_lock, irqflags);
		idt_nt_write(ndev, IDT_NT_NTMTBLADDR, idx);
		data = idt_nt_read(ndev, IDT_NT_NTMTBLDATA);
		spin_unlock_irqrestore(&ndev->mtbl_lock, irqflags);

		/* Print valid entries only */
		if (data & IDT_NTMTBLDATA_VALID) {
			off += scnprintf(strbuf + off, size - off,
				"\t%hhu. Partition %d, Requester ID 0x%04x\n",
				idx, GET_FIELD(NTMTBLDATA_PART, data),
				GET_FIELD(NTMTBLDATA_REQID, data));
		}
	}
	off += scnprintf(strbuf + off, size - off, "\n");

	/* Outbound memory windows information */
	off += scnprintf(strbuf + off, size - off,
		"Outbound Memory Windows:\n");
	for (idx = 0; idx < ndev->mw_cnt; idx += cnt) {
		data = ndev->mws[idx].type;
		cnt = idt_get_mw_count(data);

		/* Print Memory Window information */
		if (data == IDT_MW_DIR)
			off += scnprintf(strbuf + off, size - off,
				"\t%hhu.\t", idx);
		else
			off += scnprintf(strbuf + off, size - off,
				"\t%hhu-%d.\t", idx, idx + cnt - 1);

Annotation

Implementation Notes