drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
Source file repositories/reference/linux-study-clean/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c- Extension
.c- Size
- 19040 bytes
- Lines
- 683
- Domain
- Driver Families
- Bucket
- drivers/net
- 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/atomic.hlinux/bitfield.hlinux/delay.hlinux/device.hlinux/dma-direction.hlinux/dma-mapping.hlinux/err.hlinux/gfp.hlinux/kernel.hlinux/kthread.hlinux/list.hlinux/minmax.hlinux/netdevice.hlinux/pm_runtime.hlinux/sched.hlinux/spinlock.hlinux/skbuff.hlinux/types.hlinux/wait.hlinux/workqueue.ht7xx_dpmaif.ht7xx_hif_dpmaif.ht7xx_hif_dpmaif_tx.ht7xx_pci.h
Detected Declarations
function Copyrightfunction t7xx_dpmaif_release_tx_bufferfunction t7xx_dpmaif_tx_releasefunction t7xx_dpmaif_drb_ring_not_emptyfunction t7xx_dpmaif_tx_donefunction t7xx_setup_msg_drbfunction t7xx_setup_payload_drbfunction t7xx_record_drb_skbfunction t7xx_dpmaif_add_skb_to_ringfunction t7xx_tx_lists_are_all_emptyfunction t7xx_txq_drb_wr_availablefunction t7xx_skb_drb_cntfunction t7xx_txq_burst_send_skbfunction t7xx_do_tx_hw_pushfunction t7xx_dpmaif_tx_hw_push_threadfunction t7xx_dpmaif_tx_thread_initfunction t7xx_dpmaif_tx_thread_relfunction t7xx_dpmaif_tx_send_skbfunction t7xx_dpmaif_irq_tx_donefunction t7xx_dpmaif_tx_drb_buf_initfunction t7xx_dpmaif_tx_free_drb_skbfunction t7xx_dpmaif_tx_drb_buf_relfunction t7xx_dpmaif_txq_initfunction t7xx_dpmaif_txq_freefunction t7xx_dpmaif_tx_stopfunction t7xx_dpmaif_txq_flush_relfunction t7xx_dpmaif_tx_clear
Annotated Snippet
if (FIELD_GET(DRB_HDR_DTYP, le32_to_cpu(cur_drb->header)) == DES_DTYP_PD) {
cur_drb_skb = drb_skb_base + cur_idx;
if (!cur_drb_skb->is_msg)
dma_unmap_single(dpmaif_ctrl->dev, cur_drb_skb->bus_addr,
cur_drb_skb->data_len, DMA_TO_DEVICE);
if (!FIELD_GET(DRB_HDR_CONT, le32_to_cpu(cur_drb->header))) {
if (!cur_drb_skb->skb) {
dev_err(dpmaif_ctrl->dev,
"txq%u: DRB check fail, invalid skb\n", q_num);
continue;
}
dev_kfree_skb_any(cur_drb_skb->skb);
}
cur_drb_skb->skb = NULL;
}
spin_lock_irqsave(&txq->tx_lock, flags);
cur_idx = t7xx_ring_buf_get_next_wr_idx(drb_cnt, cur_idx);
txq->drb_release_rd_idx = cur_idx;
spin_unlock_irqrestore(&txq->tx_lock, flags);
if (atomic_inc_return(&txq->tx_budget) > txq->drb_size_cnt / 8)
cb->state_notify(dpmaif_ctrl->t7xx_dev, DMPAIF_TXQ_STATE_IRQ, txq->index);
}
if (FIELD_GET(DRB_HDR_CONT, le32_to_cpu(cur_drb->header)))
dev_err(dpmaif_ctrl->dev, "txq%u: DRB not marked as the last one\n", q_num);
return i;
}
static int t7xx_dpmaif_tx_release(struct dpmaif_ctrl *dpmaif_ctrl,
unsigned int q_num, unsigned int budget)
{
struct dpmaif_tx_queue *txq = &dpmaif_ctrl->txq[q_num];
unsigned int rel_cnt, real_rel_cnt;
/* Update read index from HW */
t7xx_dpmaif_update_drb_rd_idx(dpmaif_ctrl, q_num);
rel_cnt = t7xx_ring_buf_rd_wr_count(txq->drb_size_cnt, txq->drb_release_rd_idx,
txq->drb_rd_idx, DPMAIF_READ);
real_rel_cnt = min_not_zero(budget, rel_cnt);
if (real_rel_cnt)
real_rel_cnt = t7xx_dpmaif_release_tx_buffer(dpmaif_ctrl, q_num, real_rel_cnt);
return real_rel_cnt < rel_cnt ? -EAGAIN : 0;
}
static bool t7xx_dpmaif_drb_ring_not_empty(struct dpmaif_tx_queue *txq)
{
return !!t7xx_dpmaif_update_drb_rd_idx(txq->dpmaif_ctrl, txq->index);
}
static void t7xx_dpmaif_tx_done(struct work_struct *work)
{
struct dpmaif_tx_queue *txq = container_of(work, struct dpmaif_tx_queue, dpmaif_tx_work);
struct dpmaif_ctrl *dpmaif_ctrl = txq->dpmaif_ctrl;
struct dpmaif_hw_info *hw_info;
int ret;
ret = pm_runtime_resume_and_get(dpmaif_ctrl->dev);
if (ret < 0 && ret != -EACCES)
return;
/* The device may be in low power state. Disable sleep if needed */
t7xx_pci_disable_sleep(dpmaif_ctrl->t7xx_dev);
if (t7xx_pci_sleep_disable_complete(dpmaif_ctrl->t7xx_dev)) {
hw_info = &dpmaif_ctrl->hw_info;
ret = t7xx_dpmaif_tx_release(dpmaif_ctrl, txq->index, txq->drb_size_cnt);
if (ret == -EAGAIN ||
(t7xx_dpmaif_ul_clr_done(hw_info, txq->index) &&
t7xx_dpmaif_drb_ring_not_empty(txq))) {
queue_work(dpmaif_ctrl->txq[txq->index].worker,
&dpmaif_ctrl->txq[txq->index].dpmaif_tx_work);
/* Give the device time to enter the low power state */
t7xx_dpmaif_clr_ip_busy_sts(hw_info);
} else {
t7xx_dpmaif_clr_ip_busy_sts(hw_info);
t7xx_dpmaif_unmask_ulq_intr(hw_info, txq->index);
}
}
t7xx_pci_enable_sleep(dpmaif_ctrl->t7xx_dev);
pm_runtime_put_autosuspend(dpmaif_ctrl->dev);
}
Annotation
- Immediate include surface: `linux/atomic.h`, `linux/bitfield.h`, `linux/delay.h`, `linux/device.h`, `linux/dma-direction.h`, `linux/dma-mapping.h`, `linux/err.h`, `linux/gfp.h`.
- Detected declarations: `function Copyright`, `function t7xx_dpmaif_release_tx_buffer`, `function t7xx_dpmaif_tx_release`, `function t7xx_dpmaif_drb_ring_not_empty`, `function t7xx_dpmaif_tx_done`, `function t7xx_setup_msg_drb`, `function t7xx_setup_payload_drb`, `function t7xx_record_drb_skb`, `function t7xx_dpmaif_add_skb_to_ring`, `function t7xx_tx_lists_are_all_empty`.
- Atlas domain: Driver Families / drivers/net.
- 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.