drivers/misc/ocxl/config.c

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

File Facts

System
Linux kernel
Corpus path
drivers/misc/ocxl/config.c
Extension
.c
Size
24639 bytes
Lines
938
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

if (time_after_eq(jiffies, timeout)) {
			dev_err(&dev->dev,
				"Timeout while reading AFU info DVSEC (offset=%d)\n",
				offset);
			return -EBUSY;
		}
		cpu_relax();
		pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_OFF, &val);
	}
	pci_read_config_dword(dev, pos + OCXL_DVSEC_AFU_INFO_DATA, data);
	return 0;
}

/**
 * read_template_version() - Read the template version from the AFU
 * @dev: the device for the AFU
 * @fn: the AFU offsets
 * @len: outputs the template length
 * @version: outputs the major<<8,minor version
 *
 * Returns 0 on success, negative on failure
 */
static int read_template_version(struct pci_dev *dev, struct ocxl_fn_config *fn,
				 u16 *len, u16 *version)
{
	u32 val32;
	u8 major, minor;
	int rc;

	rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val32);
	if (rc)
		return rc;

	*len = EXTRACT_BITS(val32, 16, 31);
	major = EXTRACT_BITS(val32, 8, 15);
	minor = EXTRACT_BITS(val32, 0, 7);
	*version = (major << 8) + minor;
	return 0;
}

int ocxl_config_check_afu_index(struct pci_dev *dev,
				struct ocxl_fn_config *fn, int afu_idx)
{
	int rc;
	u16 templ_version;
	u16 len, expected_len;

	pci_write_config_byte(dev,
			fn->dvsec_afu_info_pos + OCXL_DVSEC_AFU_INFO_AFU_IDX,
			afu_idx);

	rc = read_template_version(dev, fn, &len, &templ_version);
	if (rc)
		return rc;

	/* AFU index map can have holes, in which case we read all 0's */
	if (!templ_version && !len)
		return 0;

	dev_dbg(&dev->dev, "AFU descriptor template version %d.%d\n",
		templ_version >> 8, templ_version & 0xFF);

	switch (templ_version) {
	case 0x0005: // v0.5 was used prior to the spec approval
	case 0x0100:
		expected_len = OCXL_TEMPL_LEN_1_0;
		break;
	case 0x0101:
		expected_len = OCXL_TEMPL_LEN_1_1;
		break;
	default:
		dev_warn(&dev->dev, "Unknown AFU template version %#x\n",
			templ_version);
		expected_len = len;
	}
	if (len != expected_len)
		dev_warn(&dev->dev,
			"Unexpected template length %#x in AFU information, expected %#x for version %#x\n",
			len, expected_len, templ_version);
	return 1;
}

static int read_afu_name(struct pci_dev *dev, struct ocxl_fn_config *fn,
			struct ocxl_afu_config *afu)
{
	int i, rc;
	u32 val, *ptr;

	BUILD_BUG_ON(OCXL_AFU_NAME_SZ < OCXL_TEMPL_NAME_LEN);
	for (i = 0; i < OCXL_TEMPL_NAME_LEN; i += 4) {

Annotation

Implementation Notes