drivers/dma/qcom/hidma.c
Source file repositories/reference/linux-study-clean/drivers/dma/qcom/hidma.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/dma/qcom/hidma.c- Extension
.c- Size
- 25414 bytes
- Lines
- 962
- Domain
- Driver Families
- Bucket
- drivers/dma
- 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/dmaengine.hlinux/dma-mapping.hlinux/list.hlinux/mod_devicetable.hlinux/module.hlinux/platform_device.hlinux/slab.hlinux/spinlock.hlinux/property.hlinux/delay.hlinux/acpi.hlinux/irq.hlinux/atomic.hlinux/pm_runtime.hlinux/msi.h../dmaengine.hhidma.h
Detected Declarations
enum hidma_capfunction hidma_freefunction hidma_process_completedfunction hidma_callbackfunction hidma_chan_initfunction hidma_issue_taskfunction hidma_issue_pendingfunction hidma_txn_is_successfunction hidma_tx_statusfunction hidma_tx_submitfunction hidma_alloc_chan_resourcesfunction hidma_prep_dma_memcpyfunction hidma_prep_dma_memsetfunction hidma_terminate_channelfunction hidma_terminate_allfunction hidma_free_chan_resourcesfunction hidma_pausefunction hidma_resumefunction hidma_chirq_handlerfunction hidma_chirq_handler_msifunction hidma_show_valuesfunction hidma_sysfs_uninitfunction hidma_create_sysfs_entryfunction hidma_sysfs_initfunction hidma_write_msi_msgfunction hidma_free_msisfunction hidma_request_msifunction hidma_test_capabilityfunction hidma_probefunction hidma_shutdownfunction hidma_remove
Annotated Snippet
if (llstat == DMA_COMPLETE) {
mchan->last_success = last_cookie;
result.result = DMA_TRANS_NOERROR;
} else {
result.result = DMA_TRANS_ABORTED;
}
dma_cookie_complete(desc);
spin_unlock_irqrestore(&mchan->lock, irqflags);
dmaengine_desc_get_callback(desc, &cb);
dma_run_dependencies(desc);
spin_lock_irqsave(&mchan->lock, irqflags);
list_move(&mdesc->node, &mchan->free);
spin_unlock_irqrestore(&mchan->lock, irqflags);
dmaengine_desc_callback_invoke(&cb, &result);
}
}
/*
* Called once for each submitted descriptor.
* PM is locked once for each descriptor that is currently
* in execution.
*/
static void hidma_callback(void *data)
{
struct hidma_desc *mdesc = data;
struct hidma_chan *mchan = to_hidma_chan(mdesc->desc.chan);
struct dma_device *ddev = mchan->chan.device;
struct hidma_dev *dmadev = to_hidma_dev(ddev);
unsigned long irqflags;
bool queued = false;
spin_lock_irqsave(&mchan->lock, irqflags);
if (mdesc->node.next) {
/* Delete from the active list, add to completed list */
list_move_tail(&mdesc->node, &mchan->completed);
queued = true;
/* calculate the next running descriptor */
mchan->running = list_first_entry(&mchan->active,
struct hidma_desc, node);
}
spin_unlock_irqrestore(&mchan->lock, irqflags);
hidma_process_completed(mchan);
if (queued) {
pm_runtime_mark_last_busy(dmadev->ddev.dev);
pm_runtime_put_autosuspend(dmadev->ddev.dev);
}
}
static int hidma_chan_init(struct hidma_dev *dmadev, u32 dma_sig)
{
struct hidma_chan *mchan;
struct dma_device *ddev;
mchan = devm_kzalloc(dmadev->ddev.dev, sizeof(*mchan), GFP_KERNEL);
if (!mchan)
return -ENOMEM;
ddev = &dmadev->ddev;
mchan->dma_sig = dma_sig;
mchan->dmadev = dmadev;
mchan->chan.device = ddev;
dma_cookie_init(&mchan->chan);
INIT_LIST_HEAD(&mchan->free);
INIT_LIST_HEAD(&mchan->prepared);
INIT_LIST_HEAD(&mchan->active);
INIT_LIST_HEAD(&mchan->completed);
INIT_LIST_HEAD(&mchan->queued);
spin_lock_init(&mchan->lock);
list_add_tail(&mchan->chan.device_node, &ddev->channels);
return 0;
}
static void hidma_issue_task(struct tasklet_struct *t)
{
struct hidma_dev *dmadev = from_tasklet(dmadev, t, task);
pm_runtime_get_sync(dmadev->ddev.dev);
hidma_ll_start(dmadev->lldev);
}
Annotation
- Immediate include surface: `linux/dmaengine.h`, `linux/dma-mapping.h`, `linux/list.h`, `linux/mod_devicetable.h`, `linux/module.h`, `linux/platform_device.h`, `linux/slab.h`, `linux/spinlock.h`.
- Detected declarations: `enum hidma_cap`, `function hidma_free`, `function hidma_process_completed`, `function hidma_callback`, `function hidma_chan_init`, `function hidma_issue_task`, `function hidma_issue_pending`, `function hidma_txn_is_success`, `function hidma_tx_status`, `function hidma_tx_submit`.
- Atlas domain: Driver Families / drivers/dma.
- 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.