drivers/net/wwan/qcom_bam_dmux.c
Source file repositories/reference/linux-study-clean/drivers/net/wwan/qcom_bam_dmux.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/wwan/qcom_bam_dmux.c- Extension
.c- Size
- 21765 bytes
- Lines
- 909
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- 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/bitops.hlinux/completion.hlinux/dma-mapping.hlinux/dmaengine.hlinux/if_arp.hlinux/interrupt.hlinux/mod_devicetable.hlinux/module.hlinux/netdevice.hlinux/platform_device.hlinux/pm_runtime.hlinux/soc/qcom/smem_state.hlinux/spinlock.hlinux/wait.hlinux/workqueue.hnet/pkt_sched.h
Detected Declarations
struct bam_dmux_hdrstruct bam_dmux_skb_dmastruct bam_dmuxstruct bam_dmux_netdevfunction bam_dmux_pc_votefunction bam_dmux_pc_ackfunction bam_dmux_skb_dma_mapfunction bam_dmux_skb_dma_unmapfunction bam_dmux_tx_wake_queuesfunction bam_dmux_tx_stop_queuesfunction bam_dmux_tx_donefunction bam_dmux_tx_callbackfunction bam_dmux_skb_dma_submit_txfunction bam_dmux_tx_queuefunction bam_dmux_send_cmdfunction bam_dmux_netdev_openfunction bam_dmux_netdev_stopfunction needed_roomfunction bam_dmux_tx_prepare_skbfunction bam_dmux_netdev_start_xmitfunction bam_dmux_tx_wakeup_workfunction bam_dmux_netdev_setupfunction bam_dmux_register_netdev_workfunction for_each_set_bitfunction bam_dmux_skb_dma_submit_rxfunction bam_dmux_skb_dma_queue_rxfunction bam_dmux_cmd_datafunction bam_dmux_cmd_openfunction bam_dmux_cmd_closefunction bam_dmux_rx_callbackfunction bam_dmux_power_onfunction bam_dmux_free_skbsfunction bam_dmux_power_offfunction bam_dmux_pc_irqfunction bam_dmux_pc_ack_irqfunction bam_dmux_runtime_suspendfunction bam_dmux_runtime_resumefunction bam_dmux_probefunction bam_dmux_remove
Annotated Snippet
static const struct net_device_ops bam_dmux_ops = {
.ndo_open = bam_dmux_netdev_open,
.ndo_stop = bam_dmux_netdev_stop,
.ndo_start_xmit = bam_dmux_netdev_start_xmit,
};
static const struct device_type wwan_type = {
.name = "wwan",
};
static void bam_dmux_netdev_setup(struct net_device *dev)
{
dev->netdev_ops = &bam_dmux_ops;
dev->type = ARPHRD_RAWIP;
SET_NETDEV_DEVTYPE(dev, &wwan_type);
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = ETH_DATA_LEN;
dev->max_mtu = BAM_DMUX_MAX_DATA_SIZE;
dev->needed_headroom = sizeof(struct bam_dmux_hdr);
dev->needed_tailroom = sizeof(u32); /* word-aligned */
dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
/* This perm addr will be used as interface identifier by IPv6 */
dev->addr_assign_type = NET_ADDR_RANDOM;
eth_random_addr(dev->perm_addr);
}
static void bam_dmux_register_netdev_work(struct work_struct *work)
{
struct bam_dmux *dmux = container_of(work, struct bam_dmux, register_netdev_work);
struct bam_dmux_netdev *bndev;
struct net_device *netdev;
int ch, ret;
for_each_set_bit(ch, dmux->remote_channels, BAM_DMUX_NUM_CH) {
if (dmux->netdevs[ch])
continue;
netdev = alloc_netdev(sizeof(*bndev), "wwan%d", NET_NAME_ENUM,
bam_dmux_netdev_setup);
if (!netdev)
return;
SET_NETDEV_DEV(netdev, dmux->dev);
netdev->dev_port = ch;
bndev = netdev_priv(netdev);
bndev->dmux = dmux;
bndev->ch = ch;
ret = register_netdev(netdev);
if (ret) {
dev_err(dmux->dev, "Failed to register netdev for channel %u: %d\n",
ch, ret);
free_netdev(netdev);
return;
}
dmux->netdevs[ch] = netdev;
}
}
static void bam_dmux_rx_callback(void *data);
static bool bam_dmux_skb_dma_submit_rx(struct bam_dmux_skb_dma *skb_dma)
{
struct bam_dmux *dmux = skb_dma->dmux;
struct dma_async_tx_descriptor *desc;
desc = dmaengine_prep_slave_single(dmux->rx, skb_dma->addr,
skb_dma->skb->len, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(dmux->dev, "Failed to prepare RX DMA buffer\n");
return false;
}
desc->callback = bam_dmux_rx_callback;
desc->callback_param = skb_dma;
desc->cookie = dmaengine_submit(desc);
return true;
}
static bool bam_dmux_skb_dma_queue_rx(struct bam_dmux_skb_dma *skb_dma, gfp_t gfp)
{
if (!skb_dma->skb) {
skb_dma->skb = __netdev_alloc_skb(NULL, BAM_DMUX_BUFFER_SIZE, gfp);
if (!skb_dma->skb)
Annotation
- Immediate include surface: `linux/atomic.h`, `linux/bitops.h`, `linux/completion.h`, `linux/dma-mapping.h`, `linux/dmaengine.h`, `linux/if_arp.h`, `linux/interrupt.h`, `linux/mod_devicetable.h`.
- Detected declarations: `struct bam_dmux_hdr`, `struct bam_dmux_skb_dma`, `struct bam_dmux`, `struct bam_dmux_netdev`, `function bam_dmux_pc_vote`, `function bam_dmux_pc_ack`, `function bam_dmux_skb_dma_map`, `function bam_dmux_skb_dma_unmap`, `function bam_dmux_tx_wake_queues`, `function bam_dmux_tx_stop_queues`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: pattern 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.