arch/powerpc/platforms/powernv/pci-ioda-tce.c
Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powernv/pci-ioda-tce.c
File Facts
- System
- Linux kernel
- Corpus path
arch/powerpc/platforms/powernv/pci-ioda-tce.c- Extension
.c- Size
- 10524 bytes
- Lines
- 431
- Domain
- Architecture Layer
- Bucket
- arch/powerpc
- Inferred role
- Architecture Layer: implementation source
- Status
- source implementation candidate
Why This File Exists
CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/kernel.hlinux/iommu.hasm/iommu.hasm/tce.hpci.h
Detected Declarations
function pnv_ioda_parse_tce_sizesfunction pnv_pci_setup_iommu_tablefunction pnv_tce_buildfunction pnv_tce_xchgfunction pnv_tce_freefunction pnv_tce_getfunction pnv_pci_ioda2_table_do_free_pagesfunction pnv_pci_ioda2_table_free_pagesfunction pnv_pci_ioda2_table_alloc_pagesfunction pnv_pci_unlink_table_and_groupfunction pnv_pci_link_table_and_group
Annotated Snippet
if (!tce) {
__be64 *tmp2;
if (!alloc)
return NULL;
tmp2 = pnv_alloc_tce_level(tbl->it_nid,
ilog2(tbl->it_level_size) + 3);
if (!tmp2)
return NULL;
tce = __pa(tmp2) | TCE_PCI_READ | TCE_PCI_WRITE;
oldtce = be64_to_cpu(cmpxchg(&tmp[n], 0,
cpu_to_be64(tce)));
if (oldtce) {
pnv_pci_ioda2_table_do_free_pages(tmp2,
ilog2(tbl->it_level_size) + 3, 1);
tce = oldtce;
}
}
tmp = __va(tce & ~(TCE_PCI_READ | TCE_PCI_WRITE));
idx &= ~mask;
mask >>= shift;
--level;
}
return tmp + idx;
}
int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction,
unsigned long attrs)
{
u64 proto_tce = iommu_direction_to_tce_perm(direction);
u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
long i;
if (proto_tce & TCE_PCI_WRITE)
proto_tce |= TCE_PCI_READ;
for (i = 0; i < npages; i++) {
unsigned long newtce = proto_tce |
((rpn + i) << tbl->it_page_shift);
unsigned long idx = index - tbl->it_offset + i;
*(pnv_tce(tbl, false, idx, true)) = cpu_to_be64(newtce);
}
return 0;
}
#ifdef CONFIG_IOMMU_API
int pnv_tce_xchg(struct iommu_table *tbl, long index,
unsigned long *hpa, enum dma_data_direction *direction)
{
u64 proto_tce = iommu_direction_to_tce_perm(*direction);
unsigned long newtce = *hpa | proto_tce, oldtce;
unsigned long idx = index - tbl->it_offset;
__be64 *ptce = NULL;
BUG_ON(*hpa & ~IOMMU_PAGE_MASK(tbl));
if (*direction == DMA_NONE) {
ptce = pnv_tce(tbl, false, idx, false);
if (!ptce) {
*hpa = 0;
return 0;
}
}
if (!ptce) {
ptce = pnv_tce(tbl, false, idx, true);
if (!ptce)
return -ENOMEM;
}
if (newtce & TCE_PCI_WRITE)
newtce |= TCE_PCI_READ;
oldtce = be64_to_cpu(xchg(ptce, cpu_to_be64(newtce)));
*hpa = oldtce & ~(TCE_PCI_READ | TCE_PCI_WRITE);
*direction = iommu_tce_direction(oldtce);
return 0;
}
__be64 *pnv_tce_useraddrptr(struct iommu_table *tbl, long index, bool alloc)
{
if (WARN_ON_ONCE(!tbl->it_userspace))
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/iommu.h`, `asm/iommu.h`, `asm/tce.h`, `pci.h`.
- Detected declarations: `function pnv_ioda_parse_tce_sizes`, `function pnv_pci_setup_iommu_table`, `function pnv_tce_build`, `function pnv_tce_xchg`, `function pnv_tce_free`, `function pnv_tce_get`, `function pnv_pci_ioda2_table_do_free_pages`, `function pnv_pci_ioda2_table_free_pages`, `function pnv_pci_ioda2_table_alloc_pages`, `function pnv_pci_unlink_table_and_group`.
- Atlas domain: Architecture Layer / arch/powerpc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.