aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Fries <David@Fries.net>2014-04-08 23:37:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 16:56:21 -0400
commit8a0427d192e6043834414210dd14cc1289daff18 (patch)
tree1e76812e3744b6946a815fb94f877cc31d11b302
parent34470e0bfae223e3f22bd2bd6e0e1dac366c9290 (diff)
w1: optional bundling of netlink kernel replies
Applications can submit a set of commands in one packet to the kernel, and in some cases it is required such as reading the temperature sensor results. This adds an option W1_CN_BUNDLE to the flags of cn_msg to request the kernel to reply in one packet for efficiency. The cn_msg flags now check for unknown flag values and return an error if one is seen. See "Proper handling of unknown flags in system calls" http://lwn.net/Articles/588444/ This corrects the ack values returned as per the protocol standard, namely the original ack for status messages and seq + 1 for all others such as the data returned from a read. Some of the common variable names have been standardized as follows. struct cn_msg *cn struct w1_netlink_msg *msg struct w1_netlink_cmd *cmd struct w1_master *dev When an argument and a function scope variable would collide, add req_ to the argument. Signed-off-by: David Fries <David@Fries.net> Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/connector/connector.txt2
-rw-r--r--Documentation/w1/w1.generic2
-rw-r--r--Documentation/w1/w1.netlink13
-rw-r--r--drivers/w1/w1.h8
-rw-r--r--drivers/w1/w1_netlink.c649
-rw-r--r--drivers/w1/w1_netlink.h36
6 files changed, 447 insertions, 263 deletions
diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt
index e56abdb21975..f6215f95149b 100644
--- a/Documentation/connector/connector.txt
+++ b/Documentation/connector/connector.txt
@@ -118,7 +118,7 @@ acknowledge number MUST be the same + 1.
118If we receive a message and its sequence number is not equal to one we 118If we receive a message and its sequence number is not equal to one we
119are expecting, then it is a new message. If we receive a message and 119are expecting, then it is a new message. If we receive a message and
120its sequence number is the same as one we are expecting, but its 120its sequence number is the same as one we are expecting, but its
121acknowledge is not equal to the acknowledge number in the original 121acknowledge is not equal to the sequence number in the original
122message + 1, then it is a new message. 122message + 1, then it is a new message.
123 123
124Obviously, the protocol header contains the above id. 124Obviously, the protocol header contains the above id.
diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic
index a31c5a242973..b2033c64c7da 100644
--- a/Documentation/w1/w1.generic
+++ b/Documentation/w1/w1.generic
@@ -82,7 +82,7 @@ driver - (standard) symlink to the w1 driver
82w1_master_add - Manually register a slave device 82w1_master_add - Manually register a slave device
83w1_master_attempts - the number of times a search was attempted 83w1_master_attempts - the number of times a search was attempted
84w1_master_max_slave_count 84w1_master_max_slave_count
85 - the maximum slaves that may be attached to a master 85 - maximum number of slaves to search for at a time
86w1_master_name - the name of the device (w1_bus_masterX) 86w1_master_name - the name of the device (w1_bus_masterX)
87w1_master_pullup - 5V strong pullup 0 enabled, 1 disabled 87w1_master_pullup - 5V strong pullup 0 enabled, 1 disabled
88w1_master_remove - Manually remove a slave device 88w1_master_remove - Manually remove a slave device
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
index 927a52cc0519..ef2727192d69 100644
--- a/Documentation/w1/w1.netlink
+++ b/Documentation/w1/w1.netlink
@@ -30,7 +30,7 @@ Protocol.
30 W1_SLAVE_CMD 30 W1_SLAVE_CMD
31 userspace command for slave device 31 userspace command for slave device
32 (read/write/touch) 32 (read/write/touch)
33 __u8 res - reserved 33 __u8 status - error indication from kernel
34 __u16 len - size of data attached to this header data 34 __u16 len - size of data attached to this header data
35 union { 35 union {
36 __u8 id[8]; - slave unique device id 36 __u8 id[8]; - slave unique device id
@@ -44,10 +44,14 @@ Protocol.
44 __u8 cmd - command opcode. 44 __u8 cmd - command opcode.
45 W1_CMD_READ - read command 45 W1_CMD_READ - read command
46 W1_CMD_WRITE - write command 46 W1_CMD_WRITE - write command
47 W1_CMD_TOUCH - touch command
48 (write and sample data back to userspace)
49 W1_CMD_SEARCH - search command 47 W1_CMD_SEARCH - search command
50 W1_CMD_ALARM_SEARCH - alarm search command 48 W1_CMD_ALARM_SEARCH - alarm search command
49 W1_CMD_TOUCH - touch command
50 (write and sample data back to userspace)
51 W1_CMD_RESET - send bus reset
52 W1_CMD_SLAVE_ADD - add slave to kernel list
53 W1_CMD_SLAVE_REMOVE - remove slave from kernel list
54 W1_CMD_LIST_SLAVES - get slaves list from kernel
51 __u8 res - reserved 55 __u8 res - reserved
52 __u16 len - length of data for this command 56 __u16 len - length of data for this command
53 For read command data must be allocated like for write command 57 For read command data must be allocated like for write command
@@ -87,8 +91,7 @@ format:
87 id0 ... idN 91 id0 ... idN
88 92
89 Each message is at most 4k in size, so if number of master devices 93 Each message is at most 4k in size, so if number of master devices
90 exceeds this, it will be split into several messages, 94 exceeds this, it will be split into several messages.
91 cn.seq will be increased for each one.
92 95
93W1 search and alarm search commands. 96W1 search and alarm search commands.
94request: 97request:
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 734dab7fc687..56a49ba41d83 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -203,7 +203,6 @@ enum w1_master_flags {
203 * @search_id: allows continuing a search 203 * @search_id: allows continuing a search
204 * @refcnt: reference count 204 * @refcnt: reference count
205 * @priv: private data storage 205 * @priv: private data storage
206 * @priv_size: size allocated
207 * @enable_pullup: allows a strong pullup 206 * @enable_pullup: allows a strong pullup
208 * @pullup_duration: time for the next strong pullup 207 * @pullup_duration: time for the next strong pullup
209 * @flags: one of w1_master_flags 208 * @flags: one of w1_master_flags
@@ -214,7 +213,6 @@ enum w1_master_flags {
214 * @dev: sysfs device 213 * @dev: sysfs device
215 * @bus_master: io operations available 214 * @bus_master: io operations available
216 * @seq: sequence number used for netlink broadcasts 215 * @seq: sequence number used for netlink broadcasts
217 * @portid: destination for the current netlink command
218 */ 216 */
219struct w1_master 217struct w1_master
220{ 218{
@@ -241,7 +239,6 @@ struct w1_master
241 atomic_t refcnt; 239 atomic_t refcnt;
242 240
243 void *priv; 241 void *priv;
244 int priv_size;
245 242
246 /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */ 243 /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */
247 int enable_pullup; 244 int enable_pullup;
@@ -260,11 +257,6 @@ struct w1_master
260 struct w1_bus_master *bus_master; 257 struct w1_bus_master *bus_master;
261 258
262 u32 seq; 259 u32 seq;
263 /* port id to send netlink responses to. The value is temporarily
264 * stored here while processing a message, set after locking the
265 * mutex, zero before unlocking the mutex.
266 */
267 u32 portid;
268}; 260};
269 261
270/** 262/**
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index a02704a59321..351a2978ba72 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -29,51 +29,247 @@
29#include "w1_netlink.h" 29#include "w1_netlink.h"
30 30
31#if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE))) 31#if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE)))
32void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 32
33#define MIN(a, b) (((a) < (b)) ? (a) : (b))
34
35/* Bundle together everything required to process a request in one memory
36 * allocation.
37 */
38struct w1_cb_block {
39 atomic_t refcnt;
40 u32 portid; /* Sending process port ID */
41 /* maximum value for first_cn->len */
42 u16 maxlen;
43 /* pointers to building up the reply message */
44 struct cn_msg *first_cn; /* fixed once the structure is populated */
45 struct cn_msg *cn; /* advances as cn_msg is appeneded */
46 struct w1_netlink_msg *msg; /* advances as w1_netlink_msg is appened */
47 struct w1_netlink_cmd *cmd; /* advances as cmds are appened */
48 struct w1_netlink_msg *cur_msg; /* currently message being processed */
49 /* copy of the original request follows */
50 struct cn_msg request_cn;
51 /* followed by variable length:
52 * cn_msg, data (w1_netlink_msg and w1_netlink_cmd)
53 * one or more struct w1_cb_node
54 * reply first_cn, data (w1_netlink_msg and w1_netlink_cmd)
55 */
56};
57struct w1_cb_node {
58 struct w1_async_cmd async;
59 /* pointers within w1_cb_block and cn data */
60 struct w1_cb_block *block;
61 struct w1_netlink_msg *msg;
62 struct w1_slave *sl;
63 struct w1_master *dev;
64};
65
66/**
67 * w1_reply_len() - calculate current reply length, compare to maxlen
68 * @block: block to calculate
69 *
70 * Calculates the current message length including possible multiple
71 * cn_msg and data, excludes the first sizeof(struct cn_msg). Direclty
72 * compariable to maxlen and usable to send the message.
73 */
74static u16 w1_reply_len(struct w1_cb_block *block)
75{
76 if (!block->cn)
77 return 0;
78 return (u8 *)block->cn - (u8 *)block->first_cn + block->cn->len;
79}
80
81static void w1_unref_block(struct w1_cb_block *block)
82{
83 if (atomic_sub_return(1, &block->refcnt) == 0) {
84 u16 len = w1_reply_len(block);
85 if (len) {
86 cn_netlink_send_mult(block->first_cn, len,
87 block->portid, 0, GFP_KERNEL);
88 }
89 kfree(block);
90 }
91}
92
93/**
94 * w1_reply_make_space() - send message if needed to make space
95 * @block: block to make space on
96 * @space: how many bytes requested
97 *
98 * Verify there is enough room left for the caller to add "space" bytes to the
99 * message, if there isn't send the message and reset.
100 */
101static void w1_reply_make_space(struct w1_cb_block *block, u16 space)
102{
103 u16 len = w1_reply_len(block);
104 if (len + space >= block->maxlen) {
105 cn_netlink_send_mult(block->first_cn, len, block->portid, 0, GFP_KERNEL);
106 block->first_cn->len = 0;
107 block->cn = NULL;
108 block->msg = NULL;
109 block->cmd = NULL;
110 }
111}
112
113/* Early send when replies aren't bundled. */
114static void w1_netlink_check_send(struct w1_cb_block *block)
115{
116 if (!(block->request_cn.flags & W1_CN_BUNDLE) && block->cn)
117 w1_reply_make_space(block, block->maxlen);
118}
119
120/**
121 * w1_netlink_setup_msg() - prepare to write block->msg
122 * @block: block to operate on
123 * @ack: determines if cn can be reused
124 *
125 * block->cn will be setup with the correct ack, advancing if needed
126 * block->cn->len does not include space for block->msg
127 * block->msg advances but remains uninitialized
128 */
129static void w1_netlink_setup_msg(struct w1_cb_block *block, u32 ack)
130{
131 if (block->cn && block->cn->ack == ack) {
132 block->msg = (struct w1_netlink_msg *)(block->cn->data + block->cn->len);
133 } else {
134 /* advance or set to data */
135 if (block->cn)
136 block->cn = (struct cn_msg *)(block->cn->data +
137 block->cn->len);
138 else
139 block->cn = block->first_cn;
140
141 memcpy(block->cn, &block->request_cn, sizeof(*block->cn));
142 block->cn->len = 0;
143 block->cn->ack = ack;
144 block->msg = (struct w1_netlink_msg *)block->cn->data;
145 }
146}
147
148/* Append cmd to msg, include cmd->data as well. This is because
149 * any following data goes with the command and in the case of a read is
150 * the results.
151 */
152static void w1_netlink_queue_cmd(struct w1_cb_block *block,
153 struct w1_netlink_cmd *cmd)
154{
155 u32 space;
156 w1_reply_make_space(block, sizeof(struct cn_msg) +
157 sizeof(struct w1_netlink_msg) + sizeof(*cmd) + cmd->len);
158
159 /* There's a status message sent after each command, so no point
160 * in trying to bundle this cmd after an existing one, because
161 * there won't be one. Allocate and copy over a new cn_msg.
162 */
163 w1_netlink_setup_msg(block, block->request_cn.seq + 1);
164 memcpy(block->msg, block->cur_msg, sizeof(*block->msg));
165 block->cn->len += sizeof(*block->msg);
166 block->msg->len = 0;
167 block->cmd = (struct w1_netlink_cmd *)(block->msg->data);
168
169 space = sizeof(*cmd) + cmd->len;
170 if (block->cmd != cmd)
171 memcpy(block->cmd, cmd, space);
172 block->cn->len += space;
173 block->msg->len += space;
174}
175
176/* Append req_msg and req_cmd, no other commands and no data from req_cmd are
177 * copied.
178 */
179static void w1_netlink_queue_status(struct w1_cb_block *block,
180 struct w1_netlink_msg *req_msg, struct w1_netlink_cmd *req_cmd,
181 int error)
33{ 182{
34 char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)]; 183 u16 space = sizeof(struct cn_msg) + sizeof(*req_msg) + sizeof(*req_cmd);
35 struct cn_msg *m = (struct cn_msg *)buf; 184 w1_reply_make_space(block, space);
36 struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1); 185 w1_netlink_setup_msg(block, block->request_cn.ack);
186
187 memcpy(block->msg, req_msg, sizeof(*req_msg));
188 block->cn->len += sizeof(*req_msg);
189 block->msg->len = 0;
190 block->msg->status = (u8)-error;
191 if (req_cmd) {
192 struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)block->msg->data;
193 memcpy(cmd, req_cmd, sizeof(*cmd));
194 block->cn->len += sizeof(*cmd);
195 block->msg->len += sizeof(*cmd);
196 cmd->len = 0;
197 }
198 w1_netlink_check_send(block);
199}
37 200
38 memset(buf, 0, sizeof(buf)); 201/**
202 * w1_netlink_send_error() - sends the error message now
203 * @cn: original cn_msg
204 * @msg: original w1_netlink_msg
205 * @portid: where to send it
206 * @error: error status
207 *
208 * Use when a block isn't available to queue the message to and cn, msg
209 * might not be contiguous.
210 */
211static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg,
212 int portid, int error)
213{
214 struct {
215 struct cn_msg cn;
216 struct w1_netlink_msg msg;
217 } packet;
218 memcpy(&packet.cn, cn, sizeof(packet.cn));
219 memcpy(&packet.msg, msg, sizeof(packet.msg));
220 packet.cn.len = sizeof(packet.msg);
221 packet.msg.len = 0;
222 packet.msg.status = (u8)-error;
223 cn_netlink_send(&packet.cn, portid, 0, GFP_KERNEL);
224}
225
226/**
227 * w1_netlink_send() - sends w1 netlink notifications
228 * @dev: w1_master the even is associated with or for
229 * @msg: w1_netlink_msg message to be sent
230 *
231 * This are notifications generated from the kernel.
232 */
233void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
234{
235 struct {
236 struct cn_msg cn;
237 struct w1_netlink_msg msg;
238 } packet;
239 memset(&packet, 0, sizeof(packet));
39 240
40 m->id.idx = CN_W1_IDX; 241 packet.cn.id.idx = CN_W1_IDX;
41 m->id.val = CN_W1_VAL; 242 packet.cn.id.val = CN_W1_VAL;
42 243
43 m->seq = dev->seq++; 244 packet.cn.seq = dev->seq++;
44 m->len = sizeof(struct w1_netlink_msg); 245 packet.cn.len = sizeof(*msg);
45 246
46 memcpy(w, msg, sizeof(struct w1_netlink_msg)); 247 memcpy(&packet.msg, msg, sizeof(*msg));
248 packet.msg.len = 0;
47 249
48 cn_netlink_send(m, dev->portid, 0, GFP_KERNEL); 250 cn_netlink_send(&packet.cn, 0, 0, GFP_KERNEL);
49} 251}
50 252
51static void w1_send_slave(struct w1_master *dev, u64 rn) 253static void w1_send_slave(struct w1_master *dev, u64 rn)
52{ 254{
53 struct cn_msg *msg = dev->priv; 255 struct w1_cb_block *block = dev->priv;
54 struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1); 256 struct w1_netlink_cmd *cache_cmd = block->cmd;
55 struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1);
56 int avail;
57 u64 *data; 257 u64 *data;
58 258
59 avail = dev->priv_size - cmd->len; 259 w1_reply_make_space(block, sizeof(*data));
60 260
61 if (avail < 8) { 261 /* Add cmd back if the packet was sent */
62 msg->ack++; 262 if (!block->cmd) {
63 cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL); 263 cache_cmd->len = 0;
64 264 w1_netlink_queue_cmd(block, cache_cmd);
65 msg->len = sizeof(struct w1_netlink_msg) +
66 sizeof(struct w1_netlink_cmd);
67 hdr->len = sizeof(struct w1_netlink_cmd);
68 cmd->len = 0;
69 } 265 }
70 266
71 data = (void *)(cmd + 1) + cmd->len; 267 data = (u64 *)(block->cmd->data + block->cmd->len);
72 268
73 *data = rn; 269 *data = rn;
74 cmd->len += 8; 270 block->cn->len += sizeof(*data);
75 hdr->len += 8; 271 block->msg->len += sizeof(*data);
76 msg->len += 8; 272 block->cmd->len += sizeof(*data);
77} 273}
78 274
79static void w1_found_send_slave(struct w1_master *dev, u64 rn) 275static void w1_found_send_slave(struct w1_master *dev, u64 rn)
@@ -85,40 +281,15 @@ static void w1_found_send_slave(struct w1_master *dev, u64 rn)
85} 281}
86 282
87/* Get the current slave list, or search (with or without alarm) */ 283/* Get the current slave list, or search (with or without alarm) */
88static int w1_get_slaves(struct w1_master *dev, 284static int w1_get_slaves(struct w1_master *dev, struct w1_netlink_cmd *req_cmd)
89 struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr,
90 struct w1_netlink_cmd *req_cmd)
91{ 285{
92 struct cn_msg *msg;
93 struct w1_netlink_msg *hdr;
94 struct w1_netlink_cmd *cmd;
95 struct w1_slave *sl; 286 struct w1_slave *sl;
96 287
97 msg = kzalloc(PAGE_SIZE, GFP_KERNEL); 288 req_cmd->len = 0;
98 if (!msg) 289 w1_netlink_queue_cmd(dev->priv, req_cmd);
99 return -ENOMEM;
100
101 msg->id = req_msg->id;
102 msg->seq = req_msg->seq;
103 msg->ack = 0;
104 msg->len = sizeof(struct w1_netlink_msg) +
105 sizeof(struct w1_netlink_cmd);
106
107 hdr = (struct w1_netlink_msg *)(msg + 1);
108 cmd = (struct w1_netlink_cmd *)(hdr + 1);
109
110 hdr->type = W1_MASTER_CMD;
111 hdr->id = req_hdr->id;
112 hdr->len = sizeof(struct w1_netlink_cmd);
113
114 cmd->cmd = req_cmd->cmd;
115 cmd->len = 0;
116
117 dev->priv = msg;
118 dev->priv_size = PAGE_SIZE - msg->len - sizeof(struct cn_msg);
119 290
120 if (req_cmd->cmd == W1_CMD_LIST_SLAVES) { 291 if (req_cmd->cmd == W1_CMD_LIST_SLAVES) {
121 __u64 rn; 292 u64 rn;
122 mutex_lock(&dev->list_mutex); 293 mutex_lock(&dev->list_mutex);
123 list_for_each_entry(sl, &dev->slist, w1_slave_entry) { 294 list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
124 memcpy(&rn, &sl->reg_num, sizeof(rn)); 295 memcpy(&rn, &sl->reg_num, sizeof(rn));
@@ -126,73 +297,26 @@ static int w1_get_slaves(struct w1_master *dev,
126 } 297 }
127 mutex_unlock(&dev->list_mutex); 298 mutex_unlock(&dev->list_mutex);
128 } else { 299 } else {
129 w1_search_process_cb(dev, cmd->cmd == W1_CMD_ALARM_SEARCH ? 300 w1_search_process_cb(dev, req_cmd->cmd == W1_CMD_ALARM_SEARCH ?
130 W1_ALARM_SEARCH : W1_SEARCH, w1_found_send_slave); 301 W1_ALARM_SEARCH : W1_SEARCH, w1_found_send_slave);
131 } 302 }
132 303
133 msg->ack = 0;
134 cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL);
135
136 dev->priv = NULL;
137 dev->priv_size = 0;
138
139 kfree(msg);
140
141 return 0; 304 return 0;
142} 305}
143 306
144static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, 307static int w1_process_command_io(struct w1_master *dev,
145 struct w1_netlink_cmd *cmd, u32 portid) 308 struct w1_netlink_cmd *cmd)
146{
147 void *data;
148 struct w1_netlink_msg *h;
149 struct w1_netlink_cmd *c;
150 struct cn_msg *cm;
151 int err;
152
153 data = kzalloc(sizeof(struct cn_msg) +
154 sizeof(struct w1_netlink_msg) +
155 sizeof(struct w1_netlink_cmd) +
156 cmd->len, GFP_KERNEL);
157 if (!data)
158 return -ENOMEM;
159
160 cm = (struct cn_msg *)(data);
161 h = (struct w1_netlink_msg *)(cm + 1);
162 c = (struct w1_netlink_cmd *)(h + 1);
163
164 memcpy(cm, msg, sizeof(struct cn_msg));
165 memcpy(h, hdr, sizeof(struct w1_netlink_msg));
166 memcpy(c, cmd, sizeof(struct w1_netlink_cmd));
167
168 cm->ack = msg->seq+1;
169 cm->len = sizeof(struct w1_netlink_msg) +
170 sizeof(struct w1_netlink_cmd) + cmd->len;
171
172 h->len = sizeof(struct w1_netlink_cmd) + cmd->len;
173
174 memcpy(c->data, cmd->data, c->len);
175
176 err = cn_netlink_send(cm, portid, 0, GFP_KERNEL);
177
178 kfree(data);
179
180 return err;
181}
182
183static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
184 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
185{ 309{
186 int err = 0; 310 int err = 0;
187 311
188 switch (cmd->cmd) { 312 switch (cmd->cmd) {
189 case W1_CMD_TOUCH: 313 case W1_CMD_TOUCH:
190 w1_touch_block(dev, cmd->data, cmd->len); 314 w1_touch_block(dev, cmd->data, cmd->len);
191 w1_send_read_reply(msg, hdr, cmd, dev->portid); 315 w1_netlink_queue_cmd(dev->priv, cmd);
192 break; 316 break;
193 case W1_CMD_READ: 317 case W1_CMD_READ:
194 w1_read_block(dev, cmd->data, cmd->len); 318 w1_read_block(dev, cmd->data, cmd->len);
195 w1_send_read_reply(msg, hdr, cmd, dev->portid); 319 w1_netlink_queue_cmd(dev->priv, cmd);
196 break; 320 break;
197 case W1_CMD_WRITE: 321 case W1_CMD_WRITE:
198 w1_write_block(dev, cmd->data, cmd->len); 322 w1_write_block(dev, cmd->data, cmd->len);
@@ -206,14 +330,13 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg,
206} 330}
207 331
208static int w1_process_command_addremove(struct w1_master *dev, 332static int w1_process_command_addremove(struct w1_master *dev,
209 struct cn_msg *msg, struct w1_netlink_msg *hdr,
210 struct w1_netlink_cmd *cmd) 333 struct w1_netlink_cmd *cmd)
211{ 334{
212 struct w1_slave *sl; 335 struct w1_slave *sl;
213 int err = 0; 336 int err = 0;
214 struct w1_reg_num *id; 337 struct w1_reg_num *id;
215 338
216 if (cmd->len != 8) 339 if (cmd->len != sizeof(*id))
217 return -EINVAL; 340 return -EINVAL;
218 341
219 id = (struct w1_reg_num *)cmd->data; 342 id = (struct w1_reg_num *)cmd->data;
@@ -241,7 +364,6 @@ static int w1_process_command_addremove(struct w1_master *dev,
241} 364}
242 365
243static int w1_process_command_master(struct w1_master *dev, 366static int w1_process_command_master(struct w1_master *dev,
244 struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr,
245 struct w1_netlink_cmd *req_cmd) 367 struct w1_netlink_cmd *req_cmd)
246{ 368{
247 int err = -EINVAL; 369 int err = -EINVAL;
@@ -254,13 +376,13 @@ static int w1_process_command_master(struct w1_master *dev,
254 case W1_CMD_ALARM_SEARCH: 376 case W1_CMD_ALARM_SEARCH:
255 case W1_CMD_LIST_SLAVES: 377 case W1_CMD_LIST_SLAVES:
256 mutex_unlock(&dev->bus_mutex); 378 mutex_unlock(&dev->bus_mutex);
257 err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd); 379 err = w1_get_slaves(dev, req_cmd);
258 mutex_lock(&dev->bus_mutex); 380 mutex_lock(&dev->bus_mutex);
259 break; 381 break;
260 case W1_CMD_READ: 382 case W1_CMD_READ:
261 case W1_CMD_WRITE: 383 case W1_CMD_WRITE:
262 case W1_CMD_TOUCH: 384 case W1_CMD_TOUCH:
263 err = w1_process_command_io(dev, req_msg, req_hdr, req_cmd); 385 err = w1_process_command_io(dev, req_cmd);
264 break; 386 break;
265 case W1_CMD_RESET: 387 case W1_CMD_RESET:
266 err = w1_reset_bus(dev); 388 err = w1_reset_bus(dev);
@@ -269,8 +391,7 @@ static int w1_process_command_master(struct w1_master *dev,
269 case W1_CMD_SLAVE_REMOVE: 391 case W1_CMD_SLAVE_REMOVE:
270 mutex_unlock(&dev->bus_mutex); 392 mutex_unlock(&dev->bus_mutex);
271 mutex_lock(&dev->mutex); 393 mutex_lock(&dev->mutex);
272 err = w1_process_command_addremove(dev, req_msg, req_hdr, 394 err = w1_process_command_addremove(dev, req_cmd);
273 req_cmd);
274 mutex_unlock(&dev->mutex); 395 mutex_unlock(&dev->mutex);
275 mutex_lock(&dev->bus_mutex); 396 mutex_lock(&dev->bus_mutex);
276 break; 397 break;
@@ -282,22 +403,21 @@ static int w1_process_command_master(struct w1_master *dev,
282 return err; 403 return err;
283} 404}
284 405
285static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, 406static int w1_process_command_slave(struct w1_slave *sl,
286 struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) 407 struct w1_netlink_cmd *cmd)
287{ 408{
288 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n", 409 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
289 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, 410 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id,
290 sl->reg_num.crc, cmd->cmd, cmd->len); 411 sl->reg_num.crc, cmd->cmd, cmd->len);
291 412
292 return w1_process_command_io(sl->master, msg, hdr, cmd); 413 return w1_process_command_io(sl->master, cmd);
293} 414}
294 415
295static int w1_process_command_root(struct cn_msg *msg, 416static int w1_process_command_root(struct cn_msg *req_cn, u32 portid)
296 struct w1_netlink_msg *mcmd, u32 portid)
297{ 417{
298 struct w1_master *m; 418 struct w1_master *dev;
299 struct cn_msg *cn; 419 struct cn_msg *cn;
300 struct w1_netlink_msg *w; 420 struct w1_netlink_msg *msg;
301 u32 *id; 421 u32 *id;
302 422
303 cn = kmalloc(PAGE_SIZE, GFP_KERNEL); 423 cn = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -307,32 +427,30 @@ static int w1_process_command_root(struct cn_msg *msg,
307 cn->id.idx = CN_W1_IDX; 427 cn->id.idx = CN_W1_IDX;
308 cn->id.val = CN_W1_VAL; 428 cn->id.val = CN_W1_VAL;
309 429
310 cn->seq = msg->seq; 430 cn->seq = req_cn->seq;
311 cn->ack = 1; 431 cn->ack = req_cn->seq + 1;
312 cn->len = sizeof(struct w1_netlink_msg); 432 cn->len = sizeof(struct w1_netlink_msg);
313 w = (struct w1_netlink_msg *)(cn + 1); 433 msg = (struct w1_netlink_msg *)cn->data;
314 434
315 w->type = W1_LIST_MASTERS; 435 msg->type = W1_LIST_MASTERS;
316 w->status = 0; 436 msg->status = 0;
317 w->len = 0; 437 msg->len = 0;
318 id = (u32 *)(w + 1); 438 id = (u32 *)msg->data;
319 439
320 mutex_lock(&w1_mlock); 440 mutex_lock(&w1_mlock);
321 list_for_each_entry(m, &w1_masters, w1_master_entry) { 441 list_for_each_entry(dev, &w1_masters, w1_master_entry) {
322 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { 442 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) {
323 cn_netlink_send(cn, portid, 0, GFP_KERNEL); 443 cn_netlink_send(cn, portid, 0, GFP_KERNEL);
324 cn->ack++;
325 cn->len = sizeof(struct w1_netlink_msg); 444 cn->len = sizeof(struct w1_netlink_msg);
326 w->len = 0; 445 msg->len = 0;
327 id = (u32 *)(w + 1); 446 id = (u32 *)msg->data;
328 } 447 }
329 448
330 *id = m->id; 449 *id = dev->id;
331 w->len += sizeof(*id); 450 msg->len += sizeof(*id);
332 cn->len += sizeof(*id); 451 cn->len += sizeof(*id);
333 id++; 452 id++;
334 } 453 }
335 cn->ack = 0;
336 cn_netlink_send(cn, portid, 0, GFP_KERNEL); 454 cn_netlink_send(cn, portid, 0, GFP_KERNEL);
337 mutex_unlock(&w1_mlock); 455 mutex_unlock(&w1_mlock);
338 456
@@ -340,100 +458,44 @@ static int w1_process_command_root(struct cn_msg *msg,
340 return 0; 458 return 0;
341} 459}
342 460
343static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg,
344 struct w1_netlink_cmd *rcmd, int portid, int error)
345{
346 struct cn_msg *cmsg;
347 struct w1_netlink_msg *msg;
348 struct w1_netlink_cmd *cmd;
349
350 cmsg = kzalloc(sizeof(*msg) + sizeof(*cmd) + sizeof(*cmsg), GFP_KERNEL);
351 if (!cmsg)
352 return -ENOMEM;
353
354 msg = (struct w1_netlink_msg *)(cmsg + 1);
355 cmd = (struct w1_netlink_cmd *)(msg + 1);
356
357 memcpy(cmsg, rcmsg, sizeof(*cmsg));
358 cmsg->len = sizeof(*msg);
359
360 memcpy(msg, rmsg, sizeof(*msg));
361 msg->len = 0;
362 msg->status = (short)-error;
363
364 if (rcmd) {
365 memcpy(cmd, rcmd, sizeof(*cmd));
366 cmd->len = 0;
367 msg->len += sizeof(*cmd);
368 cmsg->len += sizeof(*cmd);
369 }
370
371 error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL);
372 kfree(cmsg);
373
374 return error;
375}
376
377/* Bundle together a reference count, the full message, and broken out
378 * commands to be executed on each w1 master kthread in one memory allocation.
379 */
380struct w1_cb_block {
381 atomic_t refcnt;
382 u32 portid; /* Sending process port ID */
383 struct cn_msg msg;
384 /* cn_msg data */
385 /* one or more variable length struct w1_cb_node */
386};
387struct w1_cb_node {
388 struct w1_async_cmd async;
389 /* pointers within w1_cb_block and msg data */
390 struct w1_cb_block *block;
391 struct w1_netlink_msg *m;
392 struct w1_slave *sl;
393 struct w1_master *dev;
394};
395
396static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) 461static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
397{ 462{
398 struct w1_cb_node *node = container_of(async_cmd, struct w1_cb_node, 463 struct w1_cb_node *node = container_of(async_cmd, struct w1_cb_node,
399 async); 464 async);
400 u16 mlen = node->m->len; 465 u16 mlen = node->msg->len;
401 u8 *cmd_data = node->m->data; 466 u16 len;
402 int err = 0; 467 int err = 0;
403 struct w1_slave *sl = node->sl; 468 struct w1_slave *sl = node->sl;
404 struct w1_netlink_cmd *cmd = NULL; 469 struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)node->msg->data;
405 470
406 mutex_lock(&dev->bus_mutex); 471 mutex_lock(&dev->bus_mutex);
407 dev->portid = node->block->portid; 472 dev->priv = node->block;
408 if (sl && w1_reset_select_slave(sl)) 473 if (sl && w1_reset_select_slave(sl))
409 err = -ENODEV; 474 err = -ENODEV;
475 node->block->cur_msg = node->msg;
410 476
411 while (mlen && !err) { 477 while (mlen && !err) {
412 cmd = (struct w1_netlink_cmd *)cmd_data;
413
414 if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) { 478 if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
415 err = -E2BIG; 479 err = -E2BIG;
416 break; 480 break;
417 } 481 }
418 482
419 if (sl) 483 if (sl)
420 err = w1_process_command_slave(sl, &node->block->msg, 484 err = w1_process_command_slave(sl, cmd);
421 node->m, cmd);
422 else 485 else
423 err = w1_process_command_master(dev, &node->block->msg, 486 err = w1_process_command_master(dev, cmd);
424 node->m, cmd); 487 w1_netlink_check_send(node->block);
425 488
426 w1_netlink_send_error(&node->block->msg, node->m, cmd, 489 w1_netlink_queue_status(node->block, node->msg, cmd, err);
427 node->block->portid, err);
428 err = 0; 490 err = 0;
429 491
430 cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); 492 len = sizeof(*cmd) + cmd->len;
431 mlen -= cmd->len + sizeof(struct w1_netlink_cmd); 493 cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len);
494 mlen -= len;
432 } 495 }
433 496
434 if (!cmd || err) 497 if (!cmd || err)
435 w1_netlink_send_error(&node->block->msg, node->m, cmd, 498 w1_netlink_queue_status(node->block, node->msg, cmd, err);
436 node->block->portid, err);
437 499
438 /* ref taken in w1_search_slave or w1_search_master_id when building 500 /* ref taken in w1_search_slave or w1_search_master_id when building
439 * the block 501 * the block
@@ -442,99 +504,186 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd)
442 w1_unref_slave(sl); 504 w1_unref_slave(sl);
443 else 505 else
444 atomic_dec(&dev->refcnt); 506 atomic_dec(&dev->refcnt);
445 dev->portid = 0; 507 dev->priv = NULL;
446 mutex_unlock(&dev->bus_mutex); 508 mutex_unlock(&dev->bus_mutex);
447 509
448 mutex_lock(&dev->list_mutex); 510 mutex_lock(&dev->list_mutex);
449 list_del(&async_cmd->async_entry); 511 list_del(&async_cmd->async_entry);
450 mutex_unlock(&dev->list_mutex); 512 mutex_unlock(&dev->list_mutex);
451 513
452 if (atomic_sub_return(1, &node->block->refcnt) == 0) 514 w1_unref_block(node->block);
453 kfree(node->block); 515}
516
517static void w1_list_count_cmds(struct w1_netlink_msg *msg, int *cmd_count,
518 u16 *slave_len)
519{
520 struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)msg->data;
521 u16 mlen = msg->len;
522 u16 len;
523 int slave_list = 0;
524 while (mlen) {
525 if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen)
526 break;
527
528 switch (cmd->cmd) {
529 case W1_CMD_SEARCH:
530 case W1_CMD_ALARM_SEARCH:
531 case W1_CMD_LIST_SLAVES:
532 ++slave_list;
533 }
534 ++*cmd_count;
535 len = sizeof(*cmd) + cmd->len;
536 cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len);
537 mlen -= len;
538 }
539
540 if (slave_list) {
541 struct w1_master *dev = w1_search_master_id(msg->id.mst.id);
542 if (dev) {
543 /* Bytes, and likely an overstimate, and if it isn't
544 * the results can still be split between packets.
545 */
546 *slave_len += sizeof(struct w1_reg_num) * slave_list *
547 (dev->slave_count + dev->max_slave_count);
548 /* search incremented it */
549 atomic_dec(&dev->refcnt);
550 }
551 }
454} 552}
455 553
456static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 554static void w1_cn_callback(struct cn_msg *cn, struct netlink_skb_parms *nsp)
457{ 555{
458 struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1); 556 struct w1_netlink_msg *msg = (struct w1_netlink_msg *)(cn + 1);
459 struct w1_slave *sl; 557 struct w1_slave *sl;
460 struct w1_master *dev; 558 struct w1_master *dev;
461 u16 msg_len; 559 u16 msg_len;
560 u16 slave_len = 0;
462 int err = 0; 561 int err = 0;
463 struct w1_cb_block *block = NULL; 562 struct w1_cb_block *block = NULL;
464 struct w1_cb_node *node = NULL; 563 struct w1_cb_node *node = NULL;
465 int node_count = 0; 564 int node_count = 0;
565 int cmd_count = 0;
566
567 /* If any unknown flag is set let the application know, that way
568 * applications can detect the absence of features in kernels that
569 * don't know about them. http://lwn.net/Articles/587527/
570 */
571 if (cn->flags & ~(W1_CN_BUNDLE)) {
572 w1_netlink_send_error(cn, msg, nsp->portid, -EINVAL);
573 return;
574 }
466 575
467 /* Count the number of master or slave commands there are to allocate 576 /* Count the number of master or slave commands there are to allocate
468 * space for one cb_node each. 577 * space for one cb_node each.
469 */ 578 */
470 msg_len = msg->len; 579 msg_len = cn->len;
471 while (msg_len && !err) { 580 while (msg_len && !err) {
472 if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { 581 if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) {
473 err = -E2BIG; 582 err = -E2BIG;
474 break; 583 break;
475 } 584 }
476 585
477 if (m->type == W1_MASTER_CMD || m->type == W1_SLAVE_CMD) 586 /* count messages for nodes and allocate any additional space
587 * required for slave lists
588 */
589 if (msg->type == W1_MASTER_CMD || msg->type == W1_SLAVE_CMD) {
478 ++node_count; 590 ++node_count;
591 w1_list_count_cmds(msg, &cmd_count, &slave_len);
592 }
479 593
480 msg_len -= sizeof(struct w1_netlink_msg) + m->len; 594 msg_len -= sizeof(struct w1_netlink_msg) + msg->len;
481 m = (struct w1_netlink_msg *)(((u8 *)m) + 595 msg = (struct w1_netlink_msg *)(((u8 *)msg) +
482 sizeof(struct w1_netlink_msg) + m->len); 596 sizeof(struct w1_netlink_msg) + msg->len);
483 } 597 }
484 m = (struct w1_netlink_msg *)(msg + 1); 598 msg = (struct w1_netlink_msg *)(cn + 1);
485 if (node_count) { 599 if (node_count) {
486 /* msg->len doesn't include itself */ 600 int size;
487 long size = sizeof(struct w1_cb_block) + msg->len + 601 u16 reply_size = sizeof(*cn) + cn->len + slave_len;
488 node_count*sizeof(struct w1_cb_node); 602 if (cn->flags & W1_CN_BUNDLE) {
489 block = kmalloc(size, GFP_KERNEL); 603 /* bundling duplicats some of the messages */
604 reply_size += 2 * cmd_count * (sizeof(struct cn_msg) +
605 sizeof(struct w1_netlink_msg) +
606 sizeof(struct w1_netlink_cmd));
607 }
608 reply_size = MIN(CONNECTOR_MAX_MSG_SIZE, reply_size);
609
610 /* allocate space for the block, a copy of the original message,
611 * one node per cmd to point into the original message,
612 * space for replies which is the original message size plus
613 * space for any list slave data and status messages
614 * cn->len doesn't include itself which is part of the block
615 * */
616 size = /* block + original message */
617 sizeof(struct w1_cb_block) + sizeof(*cn) + cn->len +
618 /* space for nodes */
619 node_count * sizeof(struct w1_cb_node) +
620 /* replies */
621 sizeof(struct cn_msg) + reply_size;
622 block = kzalloc(size, GFP_KERNEL);
490 if (!block) { 623 if (!block) {
491 w1_netlink_send_error(msg, m, NULL, nsp->portid, 624 /* if the system is already out of memory,
492 -ENOMEM); 625 * (A) will this work, and (B) would it be better
626 * to not try?
627 */
628 w1_netlink_send_error(cn, msg, nsp->portid, -ENOMEM);
493 return; 629 return;
494 } 630 }
495 atomic_set(&block->refcnt, 1); 631 atomic_set(&block->refcnt, 1);
496 block->portid = nsp->portid; 632 block->portid = nsp->portid;
497 memcpy(&block->msg, msg, sizeof(*msg) + msg->len); 633 memcpy(&block->request_cn, cn, sizeof(*cn) + cn->len);
498 node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len); 634 node = (struct w1_cb_node *)(block->request_cn.data + cn->len);
635
636 /* Sneeky, when not bundling, reply_size is the allocated space
637 * required for the reply, cn_msg isn't part of maxlen so
638 * it should be reply_size - sizeof(struct cn_msg), however
639 * when checking if there is enough space, w1_reply_make_space
640 * is called with the full message size including cn_msg,
641 * because it isn't known at that time if an additional cn_msg
642 * will need to be allocated. So an extra cn_msg is added
643 * above in "size".
644 */
645 block->maxlen = reply_size;
646 block->first_cn = (struct cn_msg *)(node + node_count);
647 memset(block->first_cn, 0, sizeof(*block->first_cn));
499 } 648 }
500 649
501 msg_len = msg->len; 650 msg_len = cn->len;
502 while (msg_len && !err) { 651 while (msg_len && !err) {
503 652
504 dev = NULL; 653 dev = NULL;
505 sl = NULL; 654 sl = NULL;
506 655
507 if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { 656 if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) {
508 err = -E2BIG; 657 err = -E2BIG;
509 break; 658 break;
510 } 659 }
511 660
512 /* execute on this thread, no need to process later */ 661 /* execute on this thread, no need to process later */
513 if (m->type == W1_LIST_MASTERS) { 662 if (msg->type == W1_LIST_MASTERS) {
514 err = w1_process_command_root(msg, m, nsp->portid); 663 err = w1_process_command_root(cn, nsp->portid);
515 goto out_cont; 664 goto out_cont;
516 } 665 }
517 666
518 /* All following message types require additional data, 667 /* All following message types require additional data,
519 * check here before references are taken. 668 * check here before references are taken.
520 */ 669 */
521 if (!m->len) { 670 if (!msg->len) {
522 err = -EPROTO; 671 err = -EPROTO;
523 goto out_cont; 672 goto out_cont;
524 } 673 }
525 674
526 /* both search calls take reference counts */ 675 /* both search calls take references */
527 if (m->type == W1_MASTER_CMD) { 676 if (msg->type == W1_MASTER_CMD) {
528 dev = w1_search_master_id(m->id.mst.id); 677 dev = w1_search_master_id(msg->id.mst.id);
529 } else if (m->type == W1_SLAVE_CMD) { 678 } else if (msg->type == W1_SLAVE_CMD) {
530 sl = w1_search_slave((struct w1_reg_num *)m->id.id); 679 sl = w1_search_slave((struct w1_reg_num *)msg->id.id);
531 if (sl) 680 if (sl)
532 dev = sl->master; 681 dev = sl->master;
533 } else { 682 } else {
534 printk(KERN_NOTICE 683 printk(KERN_NOTICE
535 "%s: msg: %x.%x, wrong type: %u, len: %u.\n", 684 "%s: cn: %x.%x, wrong type: %u, len: %u.\n",
536 __func__, msg->id.idx, msg->id.val, 685 __func__, cn->id.idx, cn->id.val,
537 m->type, m->len); 686 msg->type, msg->len);
538 err = -EPROTO; 687 err = -EPROTO;
539 goto out_cont; 688 goto out_cont;
540 } 689 }
@@ -549,8 +698,8 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
549 atomic_inc(&block->refcnt); 698 atomic_inc(&block->refcnt);
550 node->async.cb = w1_process_cb; 699 node->async.cb = w1_process_cb;
551 node->block = block; 700 node->block = block;
552 node->m = (struct w1_netlink_msg *)((u8 *)&block->msg + 701 node->msg = (struct w1_netlink_msg *)((u8 *)&block->request_cn +
553 (size_t)((u8 *)m - (u8 *)msg)); 702 (size_t)((u8 *)msg - (u8 *)cn));
554 node->sl = sl; 703 node->sl = sl;
555 node->dev = dev; 704 node->dev = dev;
556 705
@@ -561,11 +710,15 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
561 ++node; 710 ++node;
562 711
563out_cont: 712out_cont:
713 /* Can't queue because that modifies block and another
714 * thread could be processing the messages by now and
715 * there isn't a lock, send directly.
716 */
564 if (err) 717 if (err)
565 w1_netlink_send_error(msg, m, NULL, nsp->portid, err); 718 w1_netlink_send_error(cn, msg, nsp->portid, err);
566 msg_len -= sizeof(struct w1_netlink_msg) + m->len; 719 msg_len -= sizeof(struct w1_netlink_msg) + msg->len;
567 m = (struct w1_netlink_msg *)(((u8 *)m) + 720 msg = (struct w1_netlink_msg *)(((u8 *)msg) +
568 sizeof(struct w1_netlink_msg) + m->len); 721 sizeof(struct w1_netlink_msg) + msg->len);
569 722
570 /* 723 /*
571 * Let's allow requests for nonexisting devices. 724 * Let's allow requests for nonexisting devices.
@@ -573,8 +726,8 @@ out_cont:
573 if (err == -ENODEV) 726 if (err == -ENODEV)
574 err = 0; 727 err = 0;
575 } 728 }
576 if (block && atomic_sub_return(1, &block->refcnt) == 0) 729 if (block)
577 kfree(block); 730 w1_unref_block(block);
578} 731}
579 732
580int w1_init_netlink(void) 733int w1_init_netlink(void)
@@ -591,7 +744,7 @@ void w1_fini_netlink(void)
591 cn_del_callback(&w1_id); 744 cn_del_callback(&w1_id);
592} 745}
593#else 746#else
594void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 747void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *cn)
595{ 748{
596} 749}
597 750
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 1e9504e67650..c99a9ce05e62 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -28,6 +28,17 @@
28#include "w1.h" 28#include "w1.h"
29 29
30/** 30/**
31 * enum w1_cn_msg_flags - bitfield flags for struct cn_msg.flags
32 *
33 * @W1_CN_BUNDLE: Request bundling replies into fewer messagse. Be prepared
34 * to handle multiple struct cn_msg, struct w1_netlink_msg, and
35 * struct w1_netlink_cmd in one packet.
36 */
37enum w1_cn_msg_flags {
38 W1_CN_BUNDLE = 1,
39};
40
41/**
31 * enum w1_netlink_message_types - message type 42 * enum w1_netlink_message_types - message type
32 * 43 *
33 * @W1_SLAVE_ADD: notification that a slave device was added 44 * @W1_SLAVE_ADD: notification that a slave device was added
@@ -49,6 +60,19 @@ enum w1_netlink_message_types {
49 W1_LIST_MASTERS, 60 W1_LIST_MASTERS,
50}; 61};
51 62
63/**
64 * struct w1_netlink_msg - holds w1 message type, id, and result
65 *
66 * @type: one of enum w1_netlink_message_types
67 * @status: kernel feedback for success 0 or errno failure value
68 * @len: length of data following w1_netlink_msg
69 * @id: union holding master bus id (msg.id) and slave device id (id[8]).
70 * @data: start address of any following data
71 *
72 * The base message structure for w1 messages over netlink.
73 * The netlink connector data sequence is, struct nlmsghdr, struct cn_msg,
74 * then one or more struct w1_netlink_msg (each with optional data).
75 */
52struct w1_netlink_msg 76struct w1_netlink_msg
53{ 77{
54 __u8 type; 78 __u8 type;
@@ -66,6 +90,7 @@ struct w1_netlink_msg
66 90
67/** 91/**
68 * enum w1_commands - commands available for master or slave operations 92 * enum w1_commands - commands available for master or slave operations
93 *
69 * @W1_CMD_READ: read len bytes 94 * @W1_CMD_READ: read len bytes
70 * @W1_CMD_WRITE: write len bytes 95 * @W1_CMD_WRITE: write len bytes
71 * @W1_CMD_SEARCH: initiate a standard search, returns only the slave 96 * @W1_CMD_SEARCH: initiate a standard search, returns only the slave
@@ -93,6 +118,17 @@ enum w1_commands {
93 W1_CMD_MAX 118 W1_CMD_MAX
94}; 119};
95 120
121/**
122 * struct w1_netlink_cmd - holds the command and data
123 *
124 * @cmd: one of enum w1_commands
125 * @res: reserved
126 * @len: length of data following w1_netlink_cmd
127 * @data: start address of any following data
128 *
129 * One or more struct w1_netlink_cmd is placed starting at w1_netlink_msg.data
130 * each with optional data.
131 */
96struct w1_netlink_cmd 132struct w1_netlink_cmd
97{ 133{
98 __u8 cmd; 134 __u8 cmd;