drivers/net/can/dev/skb.c
Source file repositories/reference/linux-study-clean/drivers/net/can/dev/skb.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/can/dev/skb.c- Extension
.c- Size
- 9432 bytes
- Lines
- 406
- Domain
- Driver Families
- Bucket
- drivers/net
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/can/dev.hlinux/module.hnet/can.h
Detected Declarations
function can_flush_echo_skbfunction can_put_echo_skbfunction __can_get_echo_skbfunction can_get_echo_skbfunction can_free_echo_skbfunction init_can_skbfunction can_skb_init_validfunction can_dropped_invalid_skbexport can_put_echo_skbexport can_get_echo_skbexport can_free_echo_skbexport alloc_can_skbexport alloc_canfd_skbexport alloc_canxl_skbexport alloc_can_err_skbexport can_dropped_invalid_skb
Annotated Snippet
if (priv->echo_skb[i]) {
kfree_skb(priv->echo_skb[i]);
priv->echo_skb[i] = NULL;
stats->tx_dropped++;
stats->tx_aborted_errors++;
}
}
}
/* Put the skb on the stack to be looped backed locally lateron
*
* The function is typically called in the start_xmit function
* of the device driver. The driver must protect access to
* priv->echo_skb, if necessary.
*/
int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
unsigned int idx, unsigned int frame_len)
{
struct can_priv *priv = netdev_priv(dev);
struct can_skb_ext *csx;
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
__func__, idx, priv->echo_skb_max);
return -EINVAL;
}
/* check flag whether this packet has to be looped back */
if (!(dev->flags & IFF_ECHO) ||
(skb->protocol != htons(ETH_P_CAN) &&
skb->protocol != htons(ETH_P_CANFD) &&
skb->protocol != htons(ETH_P_CANXL))) {
kfree_skb(skb);
return 0;
}
if (!priv->echo_skb[idx]) {
skb = can_create_echo_skb(skb);
if (!skb)
return -ENOMEM;
/* make settings for echo to reduce code in irq context */
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->dev = dev;
/* save frame_len to reuse it when transmission is completed */
csx = can_skb_ext_find(skb);
if (csx)
csx->can_framelen = frame_len;
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
skb_tx_timestamp(skb);
/* save this skb for tx interrupt echo handling */
priv->echo_skb[idx] = skb;
} else {
/* locking problem with netif_stop_queue() ?? */
netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
kfree_skb(skb);
return -EBUSY;
}
return 0;
}
EXPORT_SYMBOL_GPL(can_put_echo_skb);
struct sk_buff *
__can_get_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *len_ptr, unsigned int *frame_len_ptr)
{
struct can_priv *priv = netdev_priv(dev);
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
__func__, idx, priv->echo_skb_max);
return NULL;
}
if (priv->echo_skb[idx]) {
/* Using "struct canfd_frame::len" for the frame
* length is supported on both CAN and CANFD frames.
*/
struct sk_buff *skb = priv->echo_skb[idx];
struct can_skb_ext *csx;
if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)
skb_tstamp_tx(skb, skb_hwtstamps(skb));
Annotation
- Immediate include surface: `linux/can/dev.h`, `linux/module.h`, `net/can.h`.
- Detected declarations: `function can_flush_echo_skb`, `function can_put_echo_skb`, `function __can_get_echo_skb`, `function can_get_echo_skb`, `function can_free_echo_skb`, `function init_can_skb`, `function can_skb_init_valid`, `function can_dropped_invalid_skb`, `export can_put_echo_skb`, `export can_get_echo_skb`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: integration implementation candidate.
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.