drivers/pci/controller/dwc/pcie-designware-host.c
Source file repositories/reference/linux-study-clean/drivers/pci/controller/dwc/pcie-designware-host.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/controller/dwc/pcie-designware-host.c- Extension
.c- Size
- 34839 bytes
- Lines
- 1328
- 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.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/align.hlinux/iopoll.hlinux/irqchip/chained_irq.hlinux/irqchip/irq-msi-lib.hlinux/irqdomain.hlinux/msi.hlinux/of_address.hlinux/of_pci.hlinux/pci_regs.hlinux/platform_device.h../../pci.hpcie-designware.h
Detected Declarations
function dw_irq_noopfunction dw_handle_msi_irqfunction dw_chained_msi_isrfunction dw_pci_setup_msi_msgfunction dw_pci_bottom_maskfunction dw_pci_bottom_unmaskfunction dw_pci_bottom_ackfunction dw_pcie_irq_domain_allocfunction scoped_guardfunction dw_pcie_irq_domain_freefunction dw_pcie_allocate_domainsfunction dw_pcie_free_msifunction dw_pcie_msi_initfunction dw_pcie_parse_split_msi_irqfunction dw_pcie_msi_host_initfunction dw_pcie_host_request_msg_tlp_resfunction dw_pcie_config_ecam_iatufunction dw_pcie_create_ecam_windowfunction dw_pcie_ecam_enabledfunction dw_pcie_host_get_resourcesfunction dw_pcie_host_initfunction dw_pcie_msi_host_initfunction dw_pcie_host_deinitfunction dw_pcie_rd_other_conffunction dw_pcie_wr_other_conffunction dw_pcie_iatu_setupfunction IOsfunction resource_list_for_each_entryfunction dw_pcie_other_conf_map_busfunction dw_pcie_program_presetsfunction dw_pcie_config_presetsfunction dw_pcie_setup_rcfunction dw_pcie_pme_turn_offfunction dw_pcie_suspend_noirqfunction dw_pcie_resume_noirqexport dw_pcie_allocate_domainsexport dw_pcie_free_msiexport dw_pcie_msi_initexport dw_pcie_msi_host_initexport dw_pcie_host_initexport dw_pcie_host_deinitexport dw_pcie_own_conf_map_busexport dw_pcie_setup_rcexport dw_pcie_suspend_noirqexport dw_pcie_resume_noirq
Annotated Snippet
static void dw_irq_noop(struct irq_data *d) { }
#endif
static bool dw_pcie_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
struct irq_domain *real_parent, struct msi_domain_info *info)
{
if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
return false;
#ifdef CONFIG_SMP
info->chip->irq_ack = dw_irq_noop;
info->chip->irq_pre_redirect = irq_chip_pre_redirect_parent;
#else
info->chip->irq_ack = irq_chip_ack_parent;
#endif
return true;
}
#define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
MSI_FLAG_USE_DEF_CHIP_OPS | \
MSI_FLAG_PCI_MSI_MASK_PARENT)
#define DW_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \
MSI_FLAG_PCI_MSIX | \
MSI_GENERIC_FLAGS_MASK)
#define IS_256MB_ALIGNED(x) IS_ALIGNED(x, SZ_256M)
static const struct msi_parent_ops dw_pcie_msi_parent_ops = {
.required_flags = DW_PCIE_MSI_FLAGS_REQUIRED,
.supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED,
.bus_select_token = DOMAIN_BUS_PCI_MSI,
.prefix = "DW-",
.init_dev_msi_info = dw_pcie_init_dev_msi_info,
};
/* MSI int handler */
void dw_handle_msi_irq(struct dw_pcie_rp *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
unsigned int i, num_ctrls;
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
for (i = 0; i < num_ctrls; i++) {
unsigned int reg_off = i * MSI_REG_CTRL_BLOCK_SIZE;
unsigned int irq_off = i * MAX_MSI_IRQS_PER_CTRL;
unsigned long status, pos;
status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS + reg_off);
if (!status)
continue;
for_each_set_bit(pos, &status, MAX_MSI_IRQS_PER_CTRL)
generic_handle_demux_domain_irq(pp->irq_domain, irq_off + pos);
}
}
/* Chained MSI interrupt service routine */
static void dw_chained_msi_isr(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct dw_pcie_rp *pp;
chained_irq_enter(chip, desc);
pp = irq_desc_get_handler_data(desc);
dw_handle_msi_irq(pp);
chained_irq_exit(chip, desc);
}
static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
{
struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
u64 msi_target = (u64)pp->msi_data;
msg->address_lo = lower_32_bits(msi_target);
msg->address_hi = upper_32_bits(msi_target);
msg->data = d->hwirq;
dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
(int)d->hwirq, msg->address_hi, msg->address_lo);
}
static void dw_pci_bottom_mask(struct irq_data *d)
{
struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
unsigned int res, bit, ctrl;
Annotation
- Immediate include surface: `linux/align.h`, `linux/iopoll.h`, `linux/irqchip/chained_irq.h`, `linux/irqchip/irq-msi-lib.h`, `linux/irqdomain.h`, `linux/msi.h`, `linux/of_address.h`, `linux/of_pci.h`.
- Detected declarations: `function dw_irq_noop`, `function dw_handle_msi_irq`, `function dw_chained_msi_isr`, `function dw_pci_setup_msi_msg`, `function dw_pci_bottom_mask`, `function dw_pci_bottom_unmask`, `function dw_pci_bottom_ack`, `function dw_pcie_irq_domain_alloc`, `function scoped_guard`, `function dw_pcie_irq_domain_free`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- 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.