summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/w1/w1.h5
-rw-r--r--drivers/w1/w1_netlink.c42
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
51static void w1_send_slave(struct w1_master *dev, u64 rn) 51static 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
144static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, 144static 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
286static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mcmd) 286static 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
339static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, 340static 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 */
376struct w1_cb_block { 377struct 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
539out_cont: 547out_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