drivers/pci/hotplug/cpqphp_pci.c

Source file repositories/reference/linux-study-clean/drivers/pci/hotplug/cpqphp_pci.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/hotplug/cpqphp_pci.c
Extension
.c
Size
38706 bytes
Lines
1548
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: implementation source
Status
source 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

if (func->pci_dev == NULL) {
			dbg("ERROR: pci_dev still null\n");
			goto out;
		}
	}

	if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
		pci_hp_add_bridge(func->pci_dev);
		child = func->pci_dev->subordinate;
		if (child)
			pci_bus_add_devices(child);
	}

	pci_dev_put(func->pci_dev);

 out:
	pci_unlock_rescan_remove();
	return 0;
}


int cpqhp_unconfigure_device(struct pci_func *func)
{
	int j;

	dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function);

	pci_lock_rescan_remove();
	for (j = 0; j < 8 ; j++) {
		struct pci_dev *temp = pci_get_domain_bus_and_slot(0,
							func->bus,
							PCI_DEVFN(func->device,
							j));
		if (temp) {
			pci_dev_put(temp);
			pci_stop_and_remove_bus_device(temp);
		}
	}
	pci_unlock_rescan_remove();
	return 0;
}

/*
 * cpqhp_set_irq
 *
 * @bus_num: bus number of PCI device
 * @dev_num: device number of PCI device
 * @slot: pointer to u8 where slot number will be returned
 */
int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
{
	int rc = 0;

	if (cpqhp_legacy_mode) {
		struct pci_dev *fakedev;
		struct pci_bus *fakebus;
		u16 temp_word;

		fakedev = kmalloc_obj(*fakedev);
		fakebus = kmalloc_obj(*fakebus);
		if (!fakedev || !fakebus) {
			kfree(fakedev);
			kfree(fakebus);
			return -ENOMEM;
		}

		fakedev->devfn = dev_num << 3;
		fakedev->bus = fakebus;
		fakebus->number = bus_num;
		dbg("%s: dev %d, bus %d, pin %d, num %d\n",
		    __func__, dev_num, bus_num, int_pin, irq_num);
		rc = pcibios_set_irq_routing(fakedev, int_pin - 1, irq_num);
		kfree(fakedev);
		kfree(fakebus);
		dbg("%s: rc %d\n", __func__, rc);
		if (!rc)
			return !rc;

		/* set the Edge Level Control Register (ELCR) */
		temp_word = inb(0x4d0);
		temp_word |= inb(0x4d1) << 8;

		temp_word |= 0x01 << irq_num;

		/* This should only be for x86 as it sets the Edge Level
		 * Control Register
		 */
		outb((u8)(temp_word & 0xFF), 0x4d0);
		outb((u8)((temp_word & 0xFF00) >> 8), 0x4d1);
		rc = 0;

Annotation

Implementation Notes