drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
Source file repositories/reference/linux-study-clean/drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/iommu/arm/arm-smmu/arm-smmu-qcom-debug.c- Extension
.c- Size
- 14885 bytes
- Lines
- 518
- Domain
- Driver Families
- Bucket
- drivers/iommu
- 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.
- 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.
- 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/cleanup.hlinux/device.hlinux/interconnect.hlinux/firmware/qcom/qcom_scm.hlinux/iopoll.hlinux/list.hlinux/mod_devicetable.hlinux/mutex.hlinux/platform_device.hlinux/ratelimit.hlinux/spinlock.harm-smmu.harm-smmu-qcom.h
Detected Declarations
struct qcom_tbufunction qcom_smmu_tlb_sync_debugfunction list_for_each_entryfunction qcom_tbu_haltfunction qcom_tbu_resumefunction qcom_tbu_trigger_atosfunction qcom_iova_to_physfunction qcom_smmu_iova_to_phys_hardfunction qcom_smmu_verify_faultfunction qcom_smmu_context_faultfunction qcom_tbu_probe
Annotated Snippet
struct qcom_tbu {
struct device *dev;
struct device_node *smmu_np;
u32 sid_range[2];
struct list_head list;
struct clk *clk;
struct icc_path *path;
void __iomem *base;
spinlock_t halt_lock; /* multiple halt or resume can't execute concurrently */
int halt_count;
};
static struct qcom_smmu *to_qcom_smmu(struct arm_smmu_device *smmu)
{
return container_of(smmu, struct qcom_smmu, smmu);
}
void qcom_smmu_tlb_sync_debug(struct arm_smmu_device *smmu)
{
int ret;
u32 tbu_pwr_status, sync_inv_ack, sync_inv_progress;
struct qcom_smmu *qsmmu = container_of(smmu, struct qcom_smmu, smmu);
const struct qcom_smmu_config *cfg;
static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
if (__ratelimit(&rs)) {
dev_err(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked\n");
cfg = qsmmu->data->cfg;
if (!cfg)
return;
ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_TBU_PWR_STATUS],
&tbu_pwr_status);
if (ret)
dev_err(smmu->dev,
"Failed to read TBU power status: %d\n", ret);
ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_STATS_SYNC_INV_TBU_ACK],
&sync_inv_ack);
if (ret)
dev_err(smmu->dev,
"Failed to read TBU sync/inv ack status: %d\n", ret);
ret = qcom_scm_io_readl(smmu->ioaddr + cfg->reg_offset[QCOM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR],
&sync_inv_progress);
if (ret)
dev_err(smmu->dev,
"Failed to read TCU syn/inv progress: %d\n", ret);
dev_err(smmu->dev,
"TBU: power_status %#x sync_inv_ack %#x sync_inv_progress %#x\n",
tbu_pwr_status, sync_inv_ack, sync_inv_progress);
}
}
static struct qcom_tbu *qcom_find_tbu(struct qcom_smmu *qsmmu, u32 sid)
{
struct qcom_tbu *tbu;
u32 start, end;
guard(mutex)(&tbu_list_lock);
if (list_empty(&tbu_list))
return NULL;
list_for_each_entry(tbu, &tbu_list, list) {
start = tbu->sid_range[0];
end = start + tbu->sid_range[1];
if (qsmmu->smmu.dev->of_node == tbu->smmu_np &&
start <= sid && sid < end)
return tbu;
}
dev_err(qsmmu->smmu.dev, "Unable to find TBU for sid 0x%x\n", sid);
return NULL;
}
static int qcom_tbu_halt(struct qcom_tbu *tbu, struct arm_smmu_domain *smmu_domain)
{
struct arm_smmu_device *smmu = smmu_domain->smmu;
int ret = 0, idx = smmu_domain->cfg.cbndx;
u32 val, fsr, status;
guard(spinlock_irqsave)(&tbu->halt_lock);
if (tbu->halt_count) {
tbu->halt_count++;
return ret;
Annotation
- Immediate include surface: `linux/cleanup.h`, `linux/device.h`, `linux/interconnect.h`, `linux/firmware/qcom/qcom_scm.h`, `linux/iopoll.h`, `linux/list.h`, `linux/mod_devicetable.h`, `linux/mutex.h`.
- Detected declarations: `struct qcom_tbu`, `function qcom_smmu_tlb_sync_debug`, `function list_for_each_entry`, `function qcom_tbu_halt`, `function qcom_tbu_resume`, `function qcom_tbu_trigger_atos`, `function qcom_iova_to_phys`, `function qcom_smmu_iova_to_phys_hard`, `function qcom_smmu_verify_fault`, `function qcom_smmu_context_fault`.
- Atlas domain: Driver Families / drivers/iommu.
- Implementation status: source 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.