diff options
-rw-r--r-- | drivers/w1/w1.h | 5 | ||||
-rw-r--r-- | drivers/w1/w1_netlink.c | 42 |
2 files changed, 30 insertions, 17 deletions
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index a096ef40119e..390a7307fb41 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h | |||
@@ -210,6 +210,11 @@ struct w1_master | |||
210 | struct w1_bus_master *bus_master; | 210 | struct w1_bus_master *bus_master; |
211 | 211 | ||
212 | u32 seq; | 212 | u32 seq; |
213 | /* port id to send netlink responses to. The value is temporarily | ||
214 | * stored here while processing a message, set after locking the | ||
215 | * mutex, zero before unlocking the mutex. | ||
216 | */ | ||
217 | u32 portid; | ||
213 | }; | 218 | }; |
214 | 219 | ||
215 | /** | 220 | /** |
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index b63109ada5a7..a5dc21934cf2 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c | |||
@@ -45,7 +45,7 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) | |||
45 | 45 | ||
46 | memcpy(w, msg, sizeof(struct w1_netlink_msg)); | 46 | memcpy(w, msg, sizeof(struct w1_netlink_msg)); |
47 | 47 | ||
48 | cn_netlink_send(m, 0, 0, GFP_KERNEL); | 48 | cn_netlink_send(m, dev->portid, 0, GFP_KERNEL); |
49 | } | 49 | } |
50 | 50 | ||
51 | static void w1_send_slave(struct w1_master *dev, u64 rn) | 51 | static void w1_send_slave(struct w1_master *dev, u64 rn) |
@@ -60,7 +60,7 @@ static void w1_send_slave(struct w1_master *dev, u64 rn) | |||
60 | 60 | ||
61 | if (avail < 8) { | 61 | if (avail < 8) { |
62 | msg->ack++; | 62 | msg->ack++; |
63 | cn_netlink_send(msg, 0, 0, GFP_KERNEL); | 63 | cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL); |
64 | 64 | ||
65 | msg->len = sizeof(struct w1_netlink_msg) + | 65 | msg->len = sizeof(struct w1_netlink_msg) + |
66 | sizeof(struct w1_netlink_cmd); | 66 | sizeof(struct w1_netlink_cmd); |
@@ -131,7 +131,7 @@ static int w1_get_slaves(struct w1_master *dev, | |||
131 | } | 131 | } |
132 | 132 | ||
133 | msg->ack = 0; | 133 | msg->ack = 0; |
134 | cn_netlink_send(msg, 0, 0, GFP_KERNEL); | 134 | cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL); |
135 | 135 | ||
136 | dev->priv = NULL; | 136 | dev->priv = NULL; |
137 | dev->priv_size = 0; | 137 | dev->priv_size = 0; |
@@ -142,7 +142,7 @@ static int w1_get_slaves(struct w1_master *dev, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, | 144 | static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, |
145 | struct w1_netlink_cmd *cmd) | 145 | struct w1_netlink_cmd *cmd, u32 portid) |
146 | { | 146 | { |
147 | void *data; | 147 | void *data; |
148 | struct w1_netlink_msg *h; | 148 | struct w1_netlink_msg *h; |
@@ -173,7 +173,7 @@ static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, | |||
173 | 173 | ||
174 | memcpy(c->data, cmd->data, c->len); | 174 | memcpy(c->data, cmd->data, c->len); |
175 | 175 | ||
176 | err = cn_netlink_send(cm, 0, 0, GFP_KERNEL); | 176 | err = cn_netlink_send(cm, portid, 0, GFP_KERNEL); |
177 | 177 | ||
178 | kfree(data); | 178 | kfree(data); |
179 | 179 | ||
@@ -188,11 +188,11 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg, | |||
188 | switch (cmd->cmd) { | 188 | switch (cmd->cmd) { |
189 | case W1_CMD_TOUCH: | 189 | case W1_CMD_TOUCH: |
190 | w1_touch_block(dev, cmd->data, cmd->len); | 190 | w1_touch_block(dev, cmd->data, cmd->len); |
191 | w1_send_read_reply(msg, hdr, cmd); | 191 | w1_send_read_reply(msg, hdr, cmd, dev->portid); |
192 | break; | 192 | break; |
193 | case W1_CMD_READ: | 193 | case W1_CMD_READ: |
194 | w1_read_block(dev, cmd->data, cmd->len); | 194 | w1_read_block(dev, cmd->data, cmd->len); |
195 | w1_send_read_reply(msg, hdr, cmd); | 195 | w1_send_read_reply(msg, hdr, cmd, dev->portid); |
196 | break; | 196 | break; |
197 | case W1_CMD_WRITE: | 197 | case W1_CMD_WRITE: |
198 | w1_write_block(dev, cmd->data, cmd->len); | 198 | w1_write_block(dev, cmd->data, cmd->len); |
@@ -283,7 +283,8 @@ static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, | |||
283 | return w1_process_command_io(sl->master, msg, hdr, cmd); | 283 | return w1_process_command_io(sl->master, msg, hdr, cmd); |
284 | } | 284 | } |
285 | 285 | ||
286 | static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) | 286 | static int w1_process_command_root(struct cn_msg *msg, |
287 | struct w1_netlink_msg *mcmd, u32 portid) | ||
287 | { | 288 | { |
288 | struct w1_master *m; | 289 | struct w1_master *m; |
289 | struct cn_msg *cn; | 290 | struct cn_msg *cn; |
@@ -316,7 +317,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc | |||
316 | mutex_lock(&w1_mlock); | 317 | mutex_lock(&w1_mlock); |
317 | list_for_each_entry(m, &w1_masters, w1_master_entry) { | 318 | list_for_each_entry(m, &w1_masters, w1_master_entry) { |
318 | if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { | 319 | if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { |
319 | cn_netlink_send(cn, 0, 0, GFP_KERNEL); | 320 | cn_netlink_send(cn, portid, 0, GFP_KERNEL); |
320 | cn->ack++; | 321 | cn->ack++; |
321 | cn->len = sizeof(struct w1_netlink_msg); | 322 | cn->len = sizeof(struct w1_netlink_msg); |
322 | w->len = 0; | 323 | w->len = 0; |
@@ -329,7 +330,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc | |||
329 | id++; | 330 | id++; |
330 | } | 331 | } |
331 | cn->ack = 0; | 332 | cn->ack = 0; |
332 | cn_netlink_send(cn, 0, 0, GFP_KERNEL); | 333 | cn_netlink_send(cn, portid, 0, GFP_KERNEL); |
333 | mutex_unlock(&w1_mlock); | 334 | mutex_unlock(&w1_mlock); |
334 | 335 | ||
335 | kfree(cn); | 336 | kfree(cn); |
@@ -337,7 +338,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc | |||
337 | } | 338 | } |
338 | 339 | ||
339 | static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, | 340 | static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, |
340 | struct w1_netlink_cmd *rcmd, int error) | 341 | struct w1_netlink_cmd *rcmd, int portid, int error) |
341 | { | 342 | { |
342 | struct cn_msg *cmsg; | 343 | struct cn_msg *cmsg; |
343 | struct w1_netlink_msg *msg; | 344 | struct w1_netlink_msg *msg; |
@@ -364,7 +365,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm | |||
364 | cmsg->len += sizeof(*cmd); | 365 | cmsg->len += sizeof(*cmd); |
365 | } | 366 | } |
366 | 367 | ||
367 | error = cn_netlink_send(cmsg, 0, 0, GFP_KERNEL); | 368 | error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL); |
368 | kfree(cmsg); | 369 | kfree(cmsg); |
369 | 370 | ||
370 | return error; | 371 | return error; |
@@ -375,6 +376,7 @@ static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rm | |||
375 | */ | 376 | */ |
376 | struct w1_cb_block { | 377 | struct w1_cb_block { |
377 | atomic_t refcnt; | 378 | atomic_t refcnt; |
379 | u32 portid; /* Sending process port ID */ | ||
378 | struct cn_msg msg; | 380 | struct cn_msg msg; |
379 | /* cn_msg data */ | 381 | /* cn_msg data */ |
380 | /* one or more variable length struct w1_cb_node */ | 382 | /* one or more variable length struct w1_cb_node */ |
@@ -399,6 +401,7 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) | |||
399 | struct w1_netlink_cmd *cmd = NULL; | 401 | struct w1_netlink_cmd *cmd = NULL; |
400 | 402 | ||
401 | mutex_lock(&dev->mutex); | 403 | mutex_lock(&dev->mutex); |
404 | dev->portid = node->block->portid; | ||
402 | if (sl && w1_reset_select_slave(sl)) | 405 | if (sl && w1_reset_select_slave(sl)) |
403 | err = -ENODEV; | 406 | err = -ENODEV; |
404 | 407 | ||
@@ -417,7 +420,8 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) | |||
417 | err = w1_process_command_master(dev, &node->block->msg, | 420 | err = w1_process_command_master(dev, &node->block->msg, |
418 | node->m, cmd); | 421 | node->m, cmd); |
419 | 422 | ||
420 | w1_netlink_send_error(&node->block->msg, node->m, cmd, err); | 423 | w1_netlink_send_error(&node->block->msg, node->m, cmd, |
424 | node->block->portid, err); | ||
421 | err = 0; | 425 | err = 0; |
422 | 426 | ||
423 | cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); | 427 | cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); |
@@ -425,12 +429,14 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) | |||
425 | } | 429 | } |
426 | 430 | ||
427 | if (!cmd || err) | 431 | if (!cmd || err) |
428 | w1_netlink_send_error(&node->block->msg, node->m, cmd, err); | 432 | w1_netlink_send_error(&node->block->msg, node->m, cmd, |
433 | node->block->portid, err); | ||
429 | 434 | ||
430 | if (sl) | 435 | if (sl) |
431 | w1_unref_slave(sl); | 436 | w1_unref_slave(sl); |
432 | else | 437 | else |
433 | atomic_dec(&dev->refcnt); | 438 | atomic_dec(&dev->refcnt); |
439 | dev->portid = 0; | ||
434 | mutex_unlock(&dev->mutex); | 440 | mutex_unlock(&dev->mutex); |
435 | 441 | ||
436 | mutex_lock(&dev->list_mutex); | 442 | mutex_lock(&dev->list_mutex); |
@@ -476,10 +482,12 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
476 | node_count*sizeof(struct w1_cb_node); | 482 | node_count*sizeof(struct w1_cb_node); |
477 | block = kmalloc(size, GFP_KERNEL); | 483 | block = kmalloc(size, GFP_KERNEL); |
478 | if (!block) { | 484 | if (!block) { |
479 | w1_netlink_send_error(msg, m, NULL, -ENOMEM); | 485 | w1_netlink_send_error(msg, m, NULL, nsp->portid, |
486 | -ENOMEM); | ||
480 | return; | 487 | return; |
481 | } | 488 | } |
482 | atomic_set(&block->refcnt, 1); | 489 | atomic_set(&block->refcnt, 1); |
490 | block->portid = nsp->portid; | ||
483 | memcpy(&block->msg, msg, sizeof(*msg) + msg->len); | 491 | memcpy(&block->msg, msg, sizeof(*msg) + msg->len); |
484 | node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len); | 492 | node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len); |
485 | } | 493 | } |
@@ -509,7 +517,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
509 | if (sl) | 517 | if (sl) |
510 | dev = sl->master; | 518 | dev = sl->master; |
511 | } else { | 519 | } else { |
512 | err = w1_process_command_root(msg, m); | 520 | err = w1_process_command_root(msg, m, nsp->portid); |
513 | goto out_cont; | 521 | goto out_cont; |
514 | } | 522 | } |
515 | 523 | ||
@@ -538,7 +546,7 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | |||
538 | 546 | ||
539 | out_cont: | 547 | out_cont: |
540 | if (err) | 548 | if (err) |
541 | w1_netlink_send_error(msg, m, NULL, err); | 549 | w1_netlink_send_error(msg, m, NULL, nsp->portid, err); |
542 | msg_len -= sizeof(struct w1_netlink_msg) + m->len; | 550 | msg_len -= sizeof(struct w1_netlink_msg) + m->len; |
543 | m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); | 551 | m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); |
544 | 552 | ||