drivers/pci/xen-pcifront.c

Source file repositories/reference/linux-study-clean/drivers/pci/xen-pcifront.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/xen-pcifront.c
Extension
.c
Size
26183 bytes
Lines
1095
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pci_driver *pdrv;
	int bus = pdev->sh_info->aer_op.bus;
	int devfn = pdev->sh_info->aer_op.devfn;
	int domain = pdev->sh_info->aer_op.domain;
	struct pci_dev *pcidev;

	dev_dbg(&pdev->xdev->dev,
		"pcifront AER process: cmd %x (bus:%x, devfn%x)",
		cmd, bus, devfn);

	pcidev = pci_get_domain_bus_and_slot(domain, bus, devfn);
	if (!pcidev || !pcidev->dev.driver) {
		dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n");
		pci_dev_put(pcidev);
		return PCI_ERS_RESULT_NONE;
	}
	pdrv = to_pci_driver(pcidev->dev.driver);

	if (pdrv->err_handler && pdrv->err_handler->error_detected) {
		pci_dbg(pcidev, "trying to call AER service\n");
		switch (cmd) {
		case XEN_PCI_OP_aer_detected:
			return pdrv->err_handler->error_detected(pcidev, state);
		case XEN_PCI_OP_aer_mmio:
			return pdrv->err_handler->mmio_enabled(pcidev);
		case XEN_PCI_OP_aer_slotreset:
			return pdrv->err_handler->slot_reset(pcidev);
		case XEN_PCI_OP_aer_resume:
			pdrv->err_handler->resume(pcidev);
			return PCI_ERS_RESULT_NONE;
		default:
			dev_err(&pdev->xdev->dev,
				"bad request in aer recovery operation!\n");
		}
	}

	return PCI_ERS_RESULT_NONE;
}


static void pcifront_do_aer(struct work_struct *data)
{
	struct pcifront_device *pdev =
		container_of(data, struct pcifront_device, op_work);
	int cmd = pdev->sh_info->aer_op.cmd;
	pci_channel_state_t state =
		(pci_channel_state_t)pdev->sh_info->aer_op.err;

	/*
	 * If a pci_conf op is in progress, we have to wait until it is done
	 * before service aer op
	 */
	dev_dbg(&pdev->xdev->dev,
		"pcifront service aer bus %x devfn %x\n",
		pdev->sh_info->aer_op.bus, pdev->sh_info->aer_op.devfn);

	pdev->sh_info->aer_op.err = pcifront_common_process(cmd, pdev, state);

	/* Post the operation to the guest. */
	wmb();
	clear_bit(_XEN_PCIB_active, (unsigned long *)&pdev->sh_info->flags);
	notify_remote_via_evtchn(pdev->evtchn);

	/*in case of we lost an aer request in four lines time_window*/
	smp_mb__before_atomic();
	clear_bit(_PDEVB_op_active, &pdev->flags);
	smp_mb__after_atomic();

	schedule_pcifront_aer_op(pdev);

}

static irqreturn_t pcifront_handler_aer(int irq, void *dev)
{
	struct pcifront_device *pdev = dev;

	schedule_pcifront_aer_op(pdev);
	return IRQ_HANDLED;
}
static int pcifront_connect_and_init_dma(struct pcifront_device *pdev)
{
	int err = 0;

	spin_lock(&pcifront_dev_lock);

	if (!pcifront_dev) {
		dev_info(&pdev->xdev->dev, "Installing PCI frontend\n");
		pcifront_dev = pdev;
	} else
		err = -EEXIST;

Annotation

Implementation Notes