^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2003 Evgeniy Polyakov <zbr@ioremap.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/connector.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "w1_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "w1_netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Bundle together everything required to process a request in one memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * allocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct w1_cb_block {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) atomic_t refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u32 portid; /* Sending process port ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* maximum value for first_cn->len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) u16 maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* pointers to building up the reply message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct cn_msg *first_cn; /* fixed once the structure is populated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct cn_msg *cn; /* advances as cn_msg is appeneded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct w1_netlink_msg *msg; /* advances as w1_netlink_msg is appened */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct w1_netlink_cmd *cmd; /* advances as cmds are appened */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct w1_netlink_msg *cur_msg; /* currently message being processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* copy of the original request follows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct cn_msg request_cn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* followed by variable length:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * cn_msg, data (w1_netlink_msg and w1_netlink_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * one or more struct w1_cb_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * reply first_cn, data (w1_netlink_msg and w1_netlink_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct w1_cb_node {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct w1_async_cmd async;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* pointers within w1_cb_block and cn data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct w1_cb_block *block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct w1_netlink_msg *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct w1_slave *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct w1_master *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * w1_reply_len() - calculate current reply length, compare to maxlen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * @block: block to calculate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Calculates the current message length including possible multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * cn_msg and data, excludes the first sizeof(struct cn_msg). Direclty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * compariable to maxlen and usable to send the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static u16 w1_reply_len(struct w1_cb_block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!block->cn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return (u8 *)block->cn - (u8 *)block->first_cn + block->cn->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void w1_unref_block(struct w1_cb_block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (atomic_sub_return(1, &block->refcnt) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u16 len = w1_reply_len(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) cn_netlink_send_mult(block->first_cn, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) block->portid, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) kfree(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * w1_reply_make_space() - send message if needed to make space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @block: block to make space on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @space: how many bytes requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Verify there is enough room left for the caller to add "space" bytes to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * message, if there isn't send the message and reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void w1_reply_make_space(struct w1_cb_block *block, u16 space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u16 len = w1_reply_len(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (len + space >= block->maxlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) cn_netlink_send_mult(block->first_cn, len, block->portid, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) block->first_cn->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) block->cn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) block->msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) block->cmd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Early send when replies aren't bundled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void w1_netlink_check_send(struct w1_cb_block *block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!(block->request_cn.flags & W1_CN_BUNDLE) && block->cn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) w1_reply_make_space(block, block->maxlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * w1_netlink_setup_msg() - prepare to write block->msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * @block: block to operate on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @ack: determines if cn can be reused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * block->cn will be setup with the correct ack, advancing if needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * block->cn->len does not include space for block->msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * block->msg advances but remains uninitialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static void w1_netlink_setup_msg(struct w1_cb_block *block, u32 ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (block->cn && block->cn->ack == ack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) block->msg = (struct w1_netlink_msg *)(block->cn->data + block->cn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* advance or set to data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (block->cn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) block->cn = (struct cn_msg *)(block->cn->data +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) block->cn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) block->cn = block->first_cn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) memcpy(block->cn, &block->request_cn, sizeof(*block->cn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) block->cn->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) block->cn->ack = ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) block->msg = (struct w1_netlink_msg *)block->cn->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Append cmd to msg, include cmd->data as well. This is because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * any following data goes with the command and in the case of a read is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * the results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void w1_netlink_queue_cmd(struct w1_cb_block *block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct w1_netlink_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u32 space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) w1_reply_make_space(block, sizeof(struct cn_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) sizeof(struct w1_netlink_msg) + sizeof(*cmd) + cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* There's a status message sent after each command, so no point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * in trying to bundle this cmd after an existing one, because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * there won't be one. Allocate and copy over a new cn_msg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) w1_netlink_setup_msg(block, block->request_cn.seq + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) memcpy(block->msg, block->cur_msg, sizeof(*block->msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) block->cn->len += sizeof(*block->msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) block->msg->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) block->cmd = (struct w1_netlink_cmd *)(block->msg->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) space = sizeof(*cmd) + cmd->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (block->cmd != cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) memcpy(block->cmd, cmd, space);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) block->cn->len += space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) block->msg->len += space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Append req_msg and req_cmd, no other commands and no data from req_cmd are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * copied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void w1_netlink_queue_status(struct w1_cb_block *block,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct w1_netlink_msg *req_msg, struct w1_netlink_cmd *req_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) u16 space = sizeof(struct cn_msg) + sizeof(*req_msg) + sizeof(*req_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) w1_reply_make_space(block, space);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) w1_netlink_setup_msg(block, block->request_cn.ack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) memcpy(block->msg, req_msg, sizeof(*req_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) block->cn->len += sizeof(*req_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) block->msg->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) block->msg->status = (u8)-error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (req_cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)block->msg->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) memcpy(cmd, req_cmd, sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) block->cn->len += sizeof(*cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) block->msg->len += sizeof(*cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) cmd->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) w1_netlink_check_send(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * w1_netlink_send_error() - sends the error message now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @cn: original cn_msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @msg: original w1_netlink_msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * @portid: where to send it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * @error: error status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * Use when a block isn't available to queue the message to and cn, msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * might not be contiguous.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int portid, int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct cn_msg cn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct w1_netlink_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) } packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) memcpy(&packet.cn, cn, sizeof(packet.cn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) memcpy(&packet.msg, msg, sizeof(packet.msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) packet.cn.len = sizeof(packet.msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) packet.msg.len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) packet.msg.status = (u8)-error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) cn_netlink_send(&packet.cn, portid, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * w1_netlink_send() - sends w1 netlink notifications
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @dev: w1_master the even is associated with or for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @msg: w1_netlink_msg message to be sent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * This are notifications generated from the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct cn_msg cn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct w1_netlink_msg msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) } packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) memset(&packet, 0, sizeof(packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) packet.cn.id.idx = CN_W1_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) packet.cn.id.val = CN_W1_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) packet.cn.seq = dev->seq++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) packet.cn.len = sizeof(*msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) memcpy(&packet.msg, msg, sizeof(*msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) packet.msg.len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) cn_netlink_send(&packet.cn, 0, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void w1_send_slave(struct w1_master *dev, u64 rn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct w1_cb_block *block = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct w1_netlink_cmd *cache_cmd = block->cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) u64 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) w1_reply_make_space(block, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* Add cmd back if the packet was sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!block->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) cache_cmd->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) w1_netlink_queue_cmd(block, cache_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) data = (u64 *)(block->cmd->data + block->cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *data = rn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) block->cn->len += sizeof(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) block->msg->len += sizeof(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) block->cmd->len += sizeof(*data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void w1_found_send_slave(struct w1_master *dev, u64 rn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* update kernel slave list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) w1_slave_found(dev, rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) w1_send_slave(dev, rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* Get the current slave list, or search (with or without alarm) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int w1_get_slaves(struct w1_master *dev, struct w1_netlink_cmd *req_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct w1_slave *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) req_cmd->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) w1_netlink_queue_cmd(dev->priv, req_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (req_cmd->cmd == W1_CMD_LIST_SLAVES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) u64 rn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) mutex_lock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) memcpy(&rn, &sl->reg_num, sizeof(rn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) w1_send_slave(dev, rn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) mutex_unlock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) w1_search_process_cb(dev, req_cmd->cmd == W1_CMD_ALARM_SEARCH ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) W1_ALARM_SEARCH : W1_SEARCH, w1_found_send_slave);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int w1_process_command_io(struct w1_master *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct w1_netlink_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) switch (cmd->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case W1_CMD_TOUCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) w1_touch_block(dev, cmd->data, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) w1_netlink_queue_cmd(dev->priv, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case W1_CMD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) w1_read_block(dev, cmd->data, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) w1_netlink_queue_cmd(dev->priv, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case W1_CMD_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) w1_write_block(dev, cmd->data, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int w1_process_command_addremove(struct w1_master *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct w1_netlink_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct w1_slave *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct w1_reg_num *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (cmd->len != sizeof(*id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) id = (struct w1_reg_num *)cmd->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) sl = w1_slave_search_device(dev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) switch (cmd->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case W1_CMD_SLAVE_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) err = w1_attach_slave_device(dev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case W1_CMD_SLAVE_REMOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) w1_slave_detach(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int w1_process_command_master(struct w1_master *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct w1_netlink_cmd *req_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* drop bus_mutex for search (does it's own locking), and add/remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * which doesn't use the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) switch (req_cmd->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) case W1_CMD_SEARCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) case W1_CMD_ALARM_SEARCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) case W1_CMD_LIST_SLAVES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) mutex_unlock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) err = w1_get_slaves(dev, req_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mutex_lock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) case W1_CMD_READ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) case W1_CMD_WRITE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case W1_CMD_TOUCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) err = w1_process_command_io(dev, req_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case W1_CMD_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) err = w1_reset_bus(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case W1_CMD_SLAVE_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case W1_CMD_SLAVE_REMOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) mutex_unlock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) mutex_lock(&dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) err = w1_process_command_addremove(dev, req_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) mutex_unlock(&dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) mutex_lock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static int w1_process_command_slave(struct w1_slave *sl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct w1_netlink_cmd *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) sl->reg_num.crc, cmd->cmd, cmd->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return w1_process_command_io(sl->master, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int w1_process_command_root(struct cn_msg *req_cn, u32 portid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct w1_master *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct cn_msg *cn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct w1_netlink_msg *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u32 *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!cn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) cn->id.idx = CN_W1_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) cn->id.val = CN_W1_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) cn->seq = req_cn->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) cn->ack = req_cn->seq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) cn->len = sizeof(struct w1_netlink_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) msg = (struct w1_netlink_msg *)cn->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) msg->type = W1_LIST_MASTERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) msg->status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) msg->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) id = (u32 *)msg->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) mutex_lock(&w1_mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) list_for_each_entry(dev, &w1_masters, w1_master_entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) cn_netlink_send(cn, portid, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cn->len = sizeof(struct w1_netlink_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) msg->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) id = (u32 *)msg->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) *id = dev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) msg->len += sizeof(*id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) cn->len += sizeof(*id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) cn_netlink_send(cn, portid, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mutex_unlock(&w1_mlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) kfree(cn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct w1_cb_node *node = container_of(async_cmd, struct w1_cb_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) async);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u16 mlen = node->msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct w1_slave *sl = node->sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)node->msg->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) mutex_lock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dev->priv = node->block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (sl && w1_reset_select_slave(sl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) node->block->cur_msg = node->msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) while (mlen && !err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) err = w1_process_command_slave(sl, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) err = w1_process_command_master(dev, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) w1_netlink_check_send(node->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) w1_netlink_queue_status(node->block, node->msg, cmd, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) len = sizeof(*cmd) + cmd->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) mlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!cmd || err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) w1_netlink_queue_status(node->block, node->msg, cmd, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* ref taken in w1_search_slave or w1_search_master_id when building
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) w1_unref_slave(sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) atomic_dec(&dev->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) dev->priv = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mutex_unlock(&dev->bus_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) mutex_lock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) list_del(&async_cmd->async_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) mutex_unlock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) w1_unref_block(node->block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) static void w1_list_count_cmds(struct w1_netlink_msg *msg, int *cmd_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) u16 *slave_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)msg->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) u16 mlen = msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int slave_list = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) while (mlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) switch (cmd->cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case W1_CMD_SEARCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case W1_CMD_ALARM_SEARCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case W1_CMD_LIST_SLAVES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) ++slave_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ++*cmd_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) len = sizeof(*cmd) + cmd->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) mlen -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (slave_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct w1_master *dev = w1_search_master_id(msg->id.mst.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* Bytes, and likely an overstimate, and if it isn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * the results can still be split between packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *slave_len += sizeof(struct w1_reg_num) * slave_list *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) (dev->slave_count + dev->max_slave_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* search incremented it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) atomic_dec(&dev->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) static void w1_cn_callback(struct cn_msg *cn, struct netlink_skb_parms *nsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct w1_netlink_msg *msg = (struct w1_netlink_msg *)(cn + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct w1_slave *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct w1_master *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) u16 msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) u16 slave_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct w1_cb_block *block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct w1_cb_node *node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int node_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int cmd_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) /* If any unknown flag is set let the application know, that way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * applications can detect the absence of features in kernels that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * don't know about them. http://lwn.net/Articles/587527/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (cn->flags & ~(W1_CN_BUNDLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) w1_netlink_send_error(cn, msg, nsp->portid, -EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Count the number of master or slave commands there are to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * space for one cb_node each.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) msg_len = cn->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) while (msg_len && !err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) /* count messages for nodes and allocate any additional space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * required for slave lists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (msg->type == W1_MASTER_CMD || msg->type == W1_SLAVE_CMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ++node_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) w1_list_count_cmds(msg, &cmd_count, &slave_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) msg_len -= sizeof(struct w1_netlink_msg) + msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) msg = (struct w1_netlink_msg *)(((u8 *)msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) sizeof(struct w1_netlink_msg) + msg->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) msg = (struct w1_netlink_msg *)(cn + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (node_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) int reply_size = sizeof(*cn) + cn->len + slave_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (cn->flags & W1_CN_BUNDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* bundling duplicats some of the messages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) reply_size += 2 * cmd_count * (sizeof(struct cn_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) sizeof(struct w1_netlink_msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) sizeof(struct w1_netlink_cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) reply_size = min(CONNECTOR_MAX_MSG_SIZE, reply_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* allocate space for the block, a copy of the original message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * one node per cmd to point into the original message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * space for replies which is the original message size plus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * space for any list slave data and status messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * cn->len doesn't include itself which is part of the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) size = /* block + original message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) sizeof(struct w1_cb_block) + sizeof(*cn) + cn->len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* space for nodes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) node_count * sizeof(struct w1_cb_node) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* replies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sizeof(struct cn_msg) + reply_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) block = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (!block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* if the system is already out of memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * (A) will this work, and (B) would it be better
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * to not try?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) w1_netlink_send_error(cn, msg, nsp->portid, -ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) atomic_set(&block->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) block->portid = nsp->portid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) memcpy(&block->request_cn, cn, sizeof(*cn) + cn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) node = (struct w1_cb_node *)(block->request_cn.data + cn->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* Sneeky, when not bundling, reply_size is the allocated space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * required for the reply, cn_msg isn't part of maxlen so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * it should be reply_size - sizeof(struct cn_msg), however
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * when checking if there is enough space, w1_reply_make_space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) * is called with the full message size including cn_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * because it isn't known at that time if an additional cn_msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * will need to be allocated. So an extra cn_msg is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * above in "size".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) block->maxlen = reply_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) block->first_cn = (struct cn_msg *)(node + node_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) memset(block->first_cn, 0, sizeof(*block->first_cn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) msg_len = cn->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) while (msg_len && !err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) sl = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) err = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* execute on this thread, no need to process later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (msg->type == W1_LIST_MASTERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) err = w1_process_command_root(cn, nsp->portid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) goto out_cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) /* All following message types require additional data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) * check here before references are taken.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (!msg->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) err = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) goto out_cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* both search calls take references */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (msg->type == W1_MASTER_CMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dev = w1_search_master_id(msg->id.mst.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else if (msg->type == W1_SLAVE_CMD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) sl = w1_search_slave((struct w1_reg_num *)msg->id.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dev = sl->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) pr_notice("%s: cn: %x.%x, wrong type: %u, len: %u.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) __func__, cn->id.idx, cn->id.val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) msg->type, msg->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) err = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto out_cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) goto out_cont;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) atomic_inc(&block->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) node->async.cb = w1_process_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) node->block = block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) node->msg = (struct w1_netlink_msg *)((u8 *)&block->request_cn +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) (size_t)((u8 *)msg - (u8 *)cn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) node->sl = sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) node->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) mutex_lock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) list_add_tail(&node->async.async_entry, &dev->async_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) wake_up_process(dev->thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) mutex_unlock(&dev->list_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ++node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) out_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /* Can't queue because that modifies block and another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * thread could be processing the messages by now and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * there isn't a lock, send directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) w1_netlink_send_error(cn, msg, nsp->portid, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) msg_len -= sizeof(struct w1_netlink_msg) + msg->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) msg = (struct w1_netlink_msg *)(((u8 *)msg) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) sizeof(struct w1_netlink_msg) + msg->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * Let's allow requests for nonexisting devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (err == -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) w1_unref_block(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int w1_init_netlink(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return cn_add_callback(&w1_id, "w1", &w1_cn_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) void w1_fini_netlink(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) cn_del_callback(&w1_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *cn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int w1_init_netlink(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) void w1_fini_netlink(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) #endif