drivers/vdpa/ifcvf/ifcvf_base.c

Source file repositories/reference/linux-study-clean/drivers/vdpa/ifcvf/ifcvf_base.c

File Facts

System
Linux kernel
Corpus path
drivers/vdpa/ifcvf/ifcvf_base.c
Extension
.c
Size
10423 bytes
Lines
432
Domain
Driver Families
Bucket
drivers/vdpa
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

if (ret < 0) {
			IFCVF_ERR(pdev,
				  "Failed to get PCI capability at %x\n", pos);
			break;
		}

		if (cap.cap_vndr != PCI_CAP_ID_VNDR)
			goto next;

		switch (cap.cfg_type) {
		case VIRTIO_PCI_CAP_COMMON_CFG:
			hw->common_cfg = get_cap_addr(hw, &cap);
			IFCVF_DBG(pdev, "hw->common_cfg = %p\n",
				  hw->common_cfg);
			break;
		case VIRTIO_PCI_CAP_NOTIFY_CFG:
			pci_read_config_dword(pdev, pos + sizeof(cap),
					      &hw->notify_off_multiplier);
			hw->notify_bar = cap.bar;
			hw->notify_base = get_cap_addr(hw, &cap);
			hw->notify_base_pa = pci_resource_start(pdev, cap.bar) +
					le32_to_cpu(cap.offset);
			IFCVF_DBG(pdev, "hw->notify_base = %p\n",
				  hw->notify_base);
			break;
		case VIRTIO_PCI_CAP_ISR_CFG:
			hw->isr = get_cap_addr(hw, &cap);
			IFCVF_DBG(pdev, "hw->isr = %p\n", hw->isr);
			break;
		case VIRTIO_PCI_CAP_DEVICE_CFG:
			hw->dev_cfg = get_cap_addr(hw, &cap);
			hw->cap_dev_config_size = le32_to_cpu(cap.length);
			IFCVF_DBG(pdev, "hw->dev_cfg = %p\n", hw->dev_cfg);
			break;
		}

next:
		pos = cap.cap_next;
	}

	if (hw->common_cfg == NULL || hw->notify_base == NULL ||
	    hw->isr == NULL || hw->dev_cfg == NULL) {
		IFCVF_ERR(pdev, "Incomplete PCI capabilities\n");
		return -EIO;
	}

	hw->nr_vring = vp_ioread16(&hw->common_cfg->num_queues);
	hw->vring = kzalloc(sizeof(struct vring_info) * hw->nr_vring, GFP_KERNEL);
	if (!hw->vring)
		return -ENOMEM;

	for (i = 0; i < hw->nr_vring; i++) {
		vp_iowrite16(i, &hw->common_cfg->queue_select);
		notify_off = vp_ioread16(&hw->common_cfg->queue_notify_off);
		hw->vring[i].notify_addr = hw->notify_base +
			notify_off * hw->notify_off_multiplier;
		hw->vring[i].notify_pa = hw->notify_base_pa +
			notify_off * hw->notify_off_multiplier;
		hw->vring[i].irq = -EINVAL;
	}

	hw->lm_cfg = hw->base[IFCVF_LM_BAR];

	IFCVF_DBG(pdev,
		  "PCI capability mapping: common cfg: %p, notify base: %p\n, isr cfg: %p, device cfg: %p, multiplier: %u\n",
		  hw->common_cfg, hw->notify_base, hw->isr,
		  hw->dev_cfg, hw->notify_off_multiplier);

	hw->vqs_reused_irq = -EINVAL;
	hw->config_irq = -EINVAL;

	return 0;
}

u8 ifcvf_get_status(struct ifcvf_hw *hw)
{
	return vp_ioread8(&hw->common_cfg->device_status);
}

void ifcvf_set_status(struct ifcvf_hw *hw, u8 status)
{
	vp_iowrite8(status, &hw->common_cfg->device_status);
}

void ifcvf_reset(struct ifcvf_hw *hw)
{
	ifcvf_set_status(hw, 0);
	while (ifcvf_get_status(hw))
		msleep(1);
}

Annotation

Implementation Notes