drivers/acpi/pci_slot.c

Source file repositories/reference/linux-study-clean/drivers/acpi/pci_slot.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/pci_slot.c
Extension
.c
Size
4705 bytes
Lines
188
Domain
Driver Families
Bucket
drivers/acpi
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

struct acpi_pci_slot {
	struct pci_slot *pci_slot;	/* corresponding pci_slot */
	struct list_head list;		/* node in the list of slots */
};

static LIST_HEAD(slot_list);
static DEFINE_MUTEX(slot_list_lock);

static int
check_slot(acpi_handle handle, unsigned long long *sun)
{
	int device = -1;
	unsigned long long sta;
	acpi_status status;
	u64 adr;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };

	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
	pr_debug("Checking slot on path: %s\n", (char *)buffer.pointer);

	if (check_sta_before_sun) {
		/* If SxFy doesn't have _STA, we just assume it's there */
		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
		if (ACPI_SUCCESS(status) && !(sta & ACPI_STA_DEVICE_PRESENT))
			goto out;
	}

	if (acpi_get_local_u64_address(handle, &adr)) {
		pr_debug("_ADR returned with failure on %s\n",
			 (char *)buffer.pointer);
		goto out;
	}

	/* No _SUN == not a slot == bail */
	status = acpi_evaluate_integer(handle, "_SUN", NULL, sun);
	if (ACPI_FAILURE(status)) {
		pr_debug("_SUN returned %d on %s\n",
			 status, (char *)buffer.pointer);
		goto out;
	}

	device = (adr >> 16) & 0xffff;
out:
	kfree(buffer.pointer);
	return device;
}

/*
 * Check whether handle has an associated slot and create PCI slot if it has.
 */
static acpi_status
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
{
	int device;
	unsigned long long sun;
	char name[SLOT_NAME_SIZE];
	struct acpi_pci_slot *slot;
	struct pci_slot *pci_slot;
	struct pci_bus *pci_bus = context;

	device = check_slot(handle, &sun);
	if (device < 0)
		return AE_OK;

	/*
	 * There may be multiple PCI functions associated with the same slot.
	 * Check whether PCI slot has already been created for this PCI device.
	 */
	list_for_each_entry(slot, &slot_list, list) {
		pci_slot = slot->pci_slot;
		if (pci_slot->bus == pci_bus && pci_slot->number == device)
			return AE_OK;
	}

	slot = kmalloc_obj(*slot);
	if (!slot)
		return AE_OK;

	snprintf(name, sizeof(name), "%llu", sun);
	pci_slot = pci_create_slot(pci_bus, device, name, NULL);
	if (IS_ERR(pci_slot)) {
		pr_err("pci_create_slot returned %pe\n", pci_slot);
		kfree(slot);
		return AE_OK;
	}

	slot->pci_slot = pci_slot;
	list_add(&slot->list, &slot_list);

	get_device(&pci_bus->dev);

Annotation

Implementation Notes