drivers/w1/w1_netlink.c
Source file repositories/reference/linux-study-clean/drivers/w1/w1_netlink.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/w1/w1_netlink.c- Extension
.c- Size
- 19400 bytes
- Lines
- 741
- Domain
- Driver Families
- Bucket
- drivers/w1
- 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.
- 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/slab.hlinux/skbuff.hlinux/netlink.hlinux/connector.hw1_internal.hw1_netlink.h
Detected Declarations
struct w1_cb_blockstruct w1_cb_nodefunction w1_reply_lenfunction w1_unref_blockfunction w1_reply_make_spacefunction w1_netlink_check_sendfunction w1_netlink_setup_msgfunction w1_netlink_queue_cmdfunction w1_netlink_queue_statusfunction w1_netlink_send_errorfunction w1_netlink_sendfunction w1_send_slavefunction w1_found_send_slavefunction w1_get_slavesfunction list_for_each_entryfunction w1_process_command_iofunction w1_process_command_addremovefunction w1_process_command_masterfunction w1_process_command_slavefunction w1_process_command_rootfunction w1_process_cbfunction w1_list_count_cmdsfunction w1_cn_callbackfunction w1_init_netlinkfunction w1_fini_netlinkfunction w1_netlink_sendfunction w1_fini_netlink
Annotated Snippet
struct w1_cb_block {
atomic_t refcnt;
u32 portid; /* Sending process port ID */
/* maximum value for first_cn->len */
u16 maxlen;
/* pointers to building up the reply message */
struct cn_msg *first_cn; /* fixed once the structure is populated */
struct cn_msg *cn; /* advances as cn_msg is appeneded */
struct w1_netlink_msg *msg; /* advances as w1_netlink_msg is appened */
struct w1_netlink_cmd *cmd; /* advances as cmds are appened */
struct w1_netlink_msg *cur_msg; /* currently message being processed */
/* copy of the original request follows */
struct cn_msg request_cn;
/* followed by variable length:
* cn_msg, data (w1_netlink_msg and w1_netlink_cmd)
* one or more struct w1_cb_node
* reply first_cn, data (w1_netlink_msg and w1_netlink_cmd)
*/
};
struct w1_cb_node {
struct w1_async_cmd async;
/* pointers within w1_cb_block and cn data */
struct w1_cb_block *block;
struct w1_netlink_msg *msg;
struct w1_slave *sl;
struct w1_master *dev;
};
/**
* w1_reply_len() - calculate current reply length, compare to maxlen
* @block: block to calculate
*
* Calculates the current message length including possible multiple
* cn_msg and data, excludes the first sizeof(struct cn_msg). Direclty
* compariable to maxlen and usable to send the message.
*/
static u16 w1_reply_len(struct w1_cb_block *block)
{
if (!block->cn)
return 0;
return (u8 *)block->cn - (u8 *)block->first_cn + block->cn->len;
}
static void w1_unref_block(struct w1_cb_block *block)
{
if (atomic_sub_return(1, &block->refcnt) == 0) {
u16 len = w1_reply_len(block);
if (len) {
cn_netlink_send_mult(block->first_cn, len,
block->portid, 0,
GFP_KERNEL, NULL, NULL);
}
kfree(block);
}
}
/**
* w1_reply_make_space() - send message if needed to make space
* @block: block to make space on
* @space: how many bytes requested
*
* Verify there is enough room left for the caller to add "space" bytes to the
* message, if there isn't send the message and reset.
*/
static void w1_reply_make_space(struct w1_cb_block *block, u16 space)
{
u16 len = w1_reply_len(block);
if (len + space >= block->maxlen) {
cn_netlink_send_mult(block->first_cn, len, block->portid,
0, GFP_KERNEL, NULL, NULL);
block->first_cn->len = 0;
block->cn = NULL;
block->msg = NULL;
block->cmd = NULL;
}
}
/* Early send when replies aren't bundled. */
static void w1_netlink_check_send(struct w1_cb_block *block)
{
if (!(block->request_cn.flags & W1_CN_BUNDLE) && block->cn)
w1_reply_make_space(block, block->maxlen);
}
/**
* w1_netlink_setup_msg() - prepare to write block->msg
* @block: block to operate on
* @ack: determines if cn can be reused
*
* block->cn will be setup with the correct ack, advancing if needed
Annotation
- Immediate include surface: `linux/slab.h`, `linux/skbuff.h`, `linux/netlink.h`, `linux/connector.h`, `w1_internal.h`, `w1_netlink.h`.
- Detected declarations: `struct w1_cb_block`, `struct w1_cb_node`, `function w1_reply_len`, `function w1_unref_block`, `function w1_reply_make_space`, `function w1_netlink_check_send`, `function w1_netlink_setup_msg`, `function w1_netlink_queue_cmd`, `function w1_netlink_queue_status`, `function w1_netlink_send_error`.
- Atlas domain: Driver Families / drivers/w1.
- Implementation status: source 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.