drivers/dma/hsu/hsu.c
Source file repositories/reference/linux-study-clean/drivers/dma/hsu/hsu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/dma/hsu/hsu.c- Extension
.c- Size
- 13173 bytes
- Lines
- 513
- Domain
- Driver Families
- Bucket
- drivers/dma
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- 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/bits.hlinux/delay.hlinux/device.hlinux/dmaengine.hlinux/dma-mapping.hlinux/init.hlinux/interrupt.hlinux/list.hlinux/module.hlinux/percpu-defs.hlinux/scatterlist.hlinux/slab.hlinux/string.hlinux/spinlock.hhsu.h
Detected Declarations
function Copyrightfunction hsu_chan_enablefunction hsu_dma_chan_startfunction hsu_dma_stop_channelfunction hsu_dma_start_channelfunction hsu_dma_start_transferfunction hsu_dma_get_statusfunction hsu_dma_do_irqfunction hsu_dma_desc_freefunction for_each_sgfunction hsu_dma_issue_pendingfunction hsu_dma_active_desc_sizefunction hsu_dma_tx_statusfunction hsu_dma_slave_configfunction hsu_dma_pausefunction hsu_dma_resumefunction hsu_dma_terminate_allfunction hsu_dma_free_chan_resourcesfunction hsu_dma_synchronizefunction hsu_dma_probefunction hsu_dma_removeexport hsu_dma_get_statusexport hsu_dma_do_irqexport hsu_dma_probeexport hsu_dma_remove
Annotated Snippet
if (status & HSU_CH_SR_CHE) {
desc->status = DMA_ERROR;
} else if (desc->active < desc->nents) {
hsu_dma_start_channel(hsuc);
} else {
vchan_cookie_complete(&desc->vdesc);
desc->status = DMA_COMPLETE;
stat->bytes_transferred += desc->length;
hsu_dma_start_transfer(hsuc);
}
}
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
return 1;
}
EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
{
struct hsu_dma_desc *desc;
desc = kzalloc_obj(*desc, GFP_NOWAIT);
if (!desc)
return NULL;
desc->sg = kzalloc_objs(*desc->sg, nents, GFP_NOWAIT);
if (!desc->sg) {
kfree(desc);
return NULL;
}
return desc;
}
static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
{
struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
kfree(desc->sg);
kfree(desc);
}
static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
struct hsu_dma_desc *desc;
struct scatterlist *sg;
unsigned int i;
desc = hsu_dma_alloc_desc(sg_len);
if (!desc)
return NULL;
for_each_sg(sgl, sg, sg_len, i) {
desc->sg[i].addr = sg_dma_address(sg);
desc->sg[i].len = sg_dma_len(sg);
desc->length += sg_dma_len(sg);
}
desc->nents = sg_len;
desc->direction = direction;
/* desc->active = 0 by kzalloc */
desc->status = DMA_IN_PROGRESS;
return vchan_tx_prep(&hsuc->vchan, &desc->vdesc, flags);
}
static void hsu_dma_issue_pending(struct dma_chan *chan)
{
struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
unsigned long flags;
spin_lock_irqsave(&hsuc->vchan.lock, flags);
if (vchan_issue_pending(&hsuc->vchan) && !hsuc->desc)
hsu_dma_start_transfer(hsuc);
spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
}
static size_t hsu_dma_active_desc_size(struct hsu_dma_chan *hsuc)
{
struct hsu_dma_desc *desc = hsuc->desc;
size_t bytes = 0;
int i;
for (i = desc->active; i < desc->nents; i++)
bytes += desc->sg[i].len;
Annotation
- Immediate include surface: `linux/bits.h`, `linux/delay.h`, `linux/device.h`, `linux/dmaengine.h`, `linux/dma-mapping.h`, `linux/init.h`, `linux/interrupt.h`, `linux/list.h`.
- Detected declarations: `function Copyright`, `function hsu_chan_enable`, `function hsu_dma_chan_start`, `function hsu_dma_stop_channel`, `function hsu_dma_start_channel`, `function hsu_dma_start_transfer`, `function hsu_dma_get_status`, `function hsu_dma_do_irq`, `function hsu_dma_desc_free`, `function for_each_sg`.
- Atlas domain: Driver Families / drivers/dma.
- 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.