drivers/pci/quirks.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pci/quirks.c
Extension
.c
Size
236620 bytes
Lines
6426
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: exported/initcall integration point
Status
integration 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 (ret) {
			pci_info(dev, "retraining failed\n");
			pcie_set_target_speed(dev, PCIE_LNKCTL2_TLS2SPEED(oldlnkctl2),
					      true);
			return ret;
		}

		pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
	}

	pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2);

	if ((lnksta & PCI_EXP_LNKSTA_DLLLA) &&
	    (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT &&
	    pci_match_id(ids, dev)) {
		u32 lnkcap;

		pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n");
		pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
		ret = pcie_set_target_speed(dev, PCIE_LNKCAP_SLS2SPEED(lnkcap), false);
		if (ret) {
			pci_info(dev, "retraining failed\n");
			return ret;
		}
	}

	return ret;
}

static ktime_t fixup_debug_start(struct pci_dev *dev,
				 void (*fn)(struct pci_dev *dev))
{
	if (initcall_debug)
		pci_info(dev, "calling  %pS @ %i\n", fn, task_pid_nr(current));

	return ktime_get();
}

static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
			       void (*fn)(struct pci_dev *dev))
{
	ktime_t delta, rettime;
	unsigned long long duration;

	rettime = ktime_get();
	delta = ktime_sub(rettime, calltime);
	duration = (unsigned long long) ktime_to_ns(delta) >> 10;
	if (initcall_debug || duration > 10000)
		pci_info(dev, "%pS took %lld usecs\n", fn, duration);
}

static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
			  struct pci_fixup *end)
{
	ktime_t calltime;

	for (; f < end; f++)
		if ((f->class == (u32) (dev->class >> f->class_shift) ||
		     f->class == (u32) PCI_ANY_ID) &&
		    (f->vendor == dev->vendor ||
		     f->vendor == (u16) PCI_ANY_ID) &&
		    (f->device == dev->device ||
		     f->device == (u16) PCI_ANY_ID)) {
			void (*hook)(struct pci_dev *dev);
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
			hook = offset_to_ptr(&f->hook_offset);
#else
			hook = f->hook;
#endif
			calltime = fixup_debug_start(dev, hook);
			hook(dev);
			fixup_debug_report(dev, calltime, hook);
		}
}

extern struct pci_fixup __start_pci_fixups_early[];
extern struct pci_fixup __end_pci_fixups_early[];
extern struct pci_fixup __start_pci_fixups_header[];
extern struct pci_fixup __end_pci_fixups_header[];
extern struct pci_fixup __start_pci_fixups_final[];
extern struct pci_fixup __end_pci_fixups_final[];
extern struct pci_fixup __start_pci_fixups_enable[];
extern struct pci_fixup __end_pci_fixups_enable[];
extern struct pci_fixup __start_pci_fixups_resume[];
extern struct pci_fixup __end_pci_fixups_resume[];
extern struct pci_fixup __start_pci_fixups_resume_early[];
extern struct pci_fixup __end_pci_fixups_resume_early[];
extern struct pci_fixup __start_pci_fixups_suspend[];
extern struct pci_fixup __end_pci_fixups_suspend[];
extern struct pci_fixup __start_pci_fixups_suspend_late[];

Annotation

Implementation Notes