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