drivers/net/usb/qmi_wwan.c
Source file repositories/reference/linux-study-clean/drivers/net/usb/qmi_wwan.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/usb/qmi_wwan.c- Extension
.c- Size
- 58399 bytes
- Lines
- 1623
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/sched/signal.hlinux/netdevice.hlinux/ethtool.hlinux/etherdevice.hlinux/if_arp.hlinux/kstrtox.hlinux/mii.hlinux/rtnetlink.hlinux/usb.hlinux/usb/cdc.hlinux/usb/usbnet.hlinux/usb/cdc-wdm.hlinux/u64_stats_sync.h
Detected Declarations
struct qmi_wwan_statestruct qmimux_hdrstruct qmimux_privenum qmi_wwan_flagsenum qmi_wwan_quirksfunction qmimux_openfunction qmimux_stopfunction qmimux_start_xmitfunction qmimux_setupfunction qmimux_has_slavesfunction qmimux_rx_fixupfunction mux_id_showfunction qmimux_register_devicefunction qmimux_unregister_devicefunction qmi_wwan_netdev_setupfunction raw_ip_showfunction raw_ip_storefunction add_mux_showfunction add_mux_storefunction del_mux_showfunction del_mux_storefunction pass_through_showfunction pass_through_storefunction qmi_wwan_rx_fixupfunction possibly_iphdrfunction qmi_wwan_mac_addrfunction qmi_wwan_manage_powerfunction qmi_wwan_cdc_wdm_manage_powerfunction qmi_wwan_register_subdriverfunction qmi_wwan_change_dtrfunction qmi_wwan_bindfunction le16_to_cpufunction qmi_wwan_unbindfunction qmi_wwan_suspendfunction qmi_wwan_resumefunction quectel_ec20_detectedfunction qmi_wwan_probefunction qmi_wwan_disconnect
Annotated Snippet
static const struct net_device_ops qmimux_netdev_ops = {
.ndo_open = qmimux_open,
.ndo_stop = qmimux_stop,
.ndo_start_xmit = qmimux_start_xmit,
};
static void qmimux_setup(struct net_device *dev)
{
dev->header_ops = NULL; /* No header */
dev->type = ARPHRD_NONE;
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->netdev_ops = &qmimux_netdev_ops;
dev->mtu = 1500;
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
dev->needs_free_netdev = true;
}
static struct net_device *qmimux_find_dev(struct usbnet *dev, u8 mux_id)
{
struct qmimux_priv *priv;
struct list_head *iter;
struct net_device *ldev;
rcu_read_lock();
netdev_for_each_upper_dev_rcu(dev->net, ldev, iter) {
priv = netdev_priv(ldev);
if (priv->mux_id == mux_id) {
rcu_read_unlock();
return ldev;
}
}
rcu_read_unlock();
return NULL;
}
static bool qmimux_has_slaves(struct usbnet *dev)
{
return !list_empty(&dev->net->adj_list.upper);
}
static int qmimux_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
unsigned int len, offset = 0, pad_len, pkt_len;
struct qmimux_hdr *hdr;
struct net_device *net;
struct sk_buff *skbn;
u8 qmimux_hdr_sz = sizeof(*hdr);
while (offset + qmimux_hdr_sz < skb->len) {
hdr = (struct qmimux_hdr *)(skb->data + offset);
len = be16_to_cpu(hdr->pkt_len);
/* drop the packet, bogus length */
if (offset + len + qmimux_hdr_sz > skb->len)
return 0;
/* control packet, we do not know what to do */
if (hdr->pad & 0x80)
goto skip;
/* extract padding length and check for valid length info */
pad_len = hdr->pad & 0x3f;
if (len == 0 || pad_len >= len)
goto skip;
pkt_len = len - pad_len;
net = qmimux_find_dev(dev, hdr->mux_id);
if (!net)
goto skip;
skbn = netdev_alloc_skb(net, pkt_len + LL_MAX_HEADER);
if (!skbn)
return 0;
/* Raw IP packets don't have a MAC header, but other subsystems
* (like xfrm) may still access MAC header offsets, so they must
* be initialized.
*/
skb_reset_mac_header(skbn);
switch (skb->data[offset + qmimux_hdr_sz] & 0xf0) {
case 0x40:
skbn->protocol = htons(ETH_P_IP);
break;
case 0x60:
skbn->protocol = htons(ETH_P_IPV6);
break;
default:
/* not ip - do not know what to do */
Annotation
- Immediate include surface: `linux/module.h`, `linux/sched/signal.h`, `linux/netdevice.h`, `linux/ethtool.h`, `linux/etherdevice.h`, `linux/if_arp.h`, `linux/kstrtox.h`, `linux/mii.h`.
- Detected declarations: `struct qmi_wwan_state`, `struct qmimux_hdr`, `struct qmimux_priv`, `enum qmi_wwan_flags`, `enum qmi_wwan_quirks`, `function qmimux_open`, `function qmimux_stop`, `function qmimux_start_xmit`, `function qmimux_setup`, `function qmimux_has_slaves`.
- 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.
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.