drivers/pci/pcie/dpc.c
Source file repositories/reference/linux-study-clean/drivers/pci/pcie/dpc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/pcie/dpc.c- Extension
.c- Size
- 14784 bytes
- Lines
- 537
- 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.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/aer.hlinux/bitfield.hlinux/delay.hlinux/interrupt.hlinux/init.hlinux/pci.hportdrv.h../pci.h
Detected Declarations
function pci_save_dpc_statefunction pci_restore_dpc_statefunction dpc_completedfunction pci_dpc_recoveredfunction dpc_wait_rp_inactivefunction dpc_reset_linkfunction dpc_process_rp_pio_errorfunction dpc_get_aer_uncorrect_severityfunction dpc_process_errorfunction pci_clear_surpdn_errorsfunction dpc_handle_surprise_removalfunction dpc_is_surprise_removalfunction dpc_handlerfunction dpc_irqfunction pci_dpc_initfunction dpc_enablefunction dpc_disablefunction dpc_probefunction dpc_suspendfunction dpc_resumefunction dpc_removefunction pcie_dpc_init
Annotated Snippet
aer_get_device_error_info(&info, 0)) {
aer_print_error(&info, 0);
pci_aer_clear_nonfatal_status(pdev);
pci_aer_clear_fatal_status(pdev);
}
break;
case PCI_EXP_DPC_STATUS_TRIGGER_RSN_NFE:
case PCI_EXP_DPC_STATUS_TRIGGER_RSN_FE:
pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID,
&source);
pci_warn(pdev, "containment event, status:%#06x, %s received from %04x:%02x:%02x.%d\n",
status,
(reason == PCI_EXP_DPC_STATUS_TRIGGER_RSN_FE) ?
"ERR_FATAL" : "ERR_NONFATAL",
pci_domain_nr(pdev->bus), PCI_BUS_NUM(source),
PCI_SLOT(source), PCI_FUNC(source));
break;
case PCI_EXP_DPC_STATUS_TRIGGER_RSN_IN_EXT:
ext_reason = status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT;
pci_warn(pdev, "containment event, status:%#06x: %s detected\n",
status,
(ext_reason == PCI_EXP_DPC_STATUS_TRIGGER_RSN_RP_PIO) ?
"RP PIO error" :
(ext_reason == PCI_EXP_DPC_STATUS_TRIGGER_RSN_SW_TRIGGER) ?
"software trigger" :
"reserved error");
/* show RP PIO error detail information */
if (ext_reason == PCI_EXP_DPC_STATUS_TRIGGER_RSN_RP_PIO &&
pdev->dpc_rp_extensions)
dpc_process_rp_pio_error(pdev);
break;
}
}
static void pci_clear_surpdn_errors(struct pci_dev *pdev)
{
if (pdev->dpc_rp_extensions)
pci_write_config_dword(pdev, pdev->dpc_cap +
PCI_EXP_DPC_RP_PIO_STATUS, ~0);
/*
* In practice, Surprise Down errors have been observed to also set
* error bits in the Status Register as well as the Fatal Error
* Detected bit in the Device Status Register.
*/
pci_write_config_word(pdev, PCI_STATUS, 0xffff);
pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_FED);
}
static void dpc_handle_surprise_removal(struct pci_dev *pdev)
{
if (!pcie_wait_for_link(pdev, false)) {
pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n");
goto out;
}
if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev))
goto out;
pci_aer_raw_clear_status(pdev);
pci_clear_surpdn_errors(pdev);
pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_TRIGGER);
out:
clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags);
wake_up_all(&dpc_completed_waitqueue);
}
static bool dpc_is_surprise_removal(struct pci_dev *pdev)
{
u16 status;
if (!pdev->is_hotplug_bridge)
return false;
if (pci_read_config_word(pdev, pdev->aer_cap + PCI_ERR_UNCOR_STATUS,
&status))
return false;
return status & PCI_ERR_UNC_SURPDN;
}
static irqreturn_t dpc_handler(int irq, void *context)
{
struct pci_dev *pdev = context;
/*
Annotation
- Immediate include surface: `linux/aer.h`, `linux/bitfield.h`, `linux/delay.h`, `linux/interrupt.h`, `linux/init.h`, `linux/pci.h`, `portdrv.h`, `../pci.h`.
- Detected declarations: `function pci_save_dpc_state`, `function pci_restore_dpc_state`, `function dpc_completed`, `function pci_dpc_recovered`, `function dpc_wait_rp_inactive`, `function dpc_reset_link`, `function dpc_process_rp_pio_error`, `function dpc_get_aer_uncorrect_severity`, `function dpc_process_error`, `function pci_clear_surpdn_errors`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.