diff options
author | Evgeniy Polyakov <zbr@ioremap.net> | 2009-01-07 21:09:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 11:31:14 -0500 |
commit | 4037014e3fb71e998189374e19ca141c59d15323 (patch) | |
tree | c422a2c48bfa7b702a5e3927475cc3cb1bffc928 /drivers/w1/w1_netlink.c | |
parent | f89735c4e281e8642907b38640c076ae5048f3a6 (diff) |
w1: send status messages after command processing
Send completion status of the commands to the userspace. Message and
protocol are described in the documentation.
Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Paul Alfille <paul.alfille@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/w1/w1_netlink.c')
-rw-r--r-- | drivers/w1/w1_netlink.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index f978c7504004..fdf72851c574 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c | |||
@@ -152,7 +152,7 @@ static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg, | |||
152 | w1_write_block(dev, cmd->data, cmd->len); | 152 | w1_write_block(dev, cmd->data, cmd->len); |
153 | break; | 153 | break; |
154 | default: | 154 | default: |
155 | err = -1; | 155 | err = -EINVAL; |
156 | break; | 156 | break; |
157 | } | 157 | } |
158 | 158 | ||
@@ -195,14 +195,13 @@ static int w1_process_command_master(struct w1_master *dev, struct cn_msg *req_m | |||
195 | case W1_CMD_READ: | 195 | case W1_CMD_READ: |
196 | case W1_CMD_WRITE: | 196 | case W1_CMD_WRITE: |
197 | case W1_CMD_TOUCH: | 197 | case W1_CMD_TOUCH: |
198 | err = w1_process_command_io(dev, msg, hdr, cmd); | 198 | err = w1_process_command_io(dev, req_msg, req_hdr, req_cmd); |
199 | break; | 199 | break; |
200 | case W1_CMD_RESET: | 200 | case W1_CMD_RESET: |
201 | err = w1_reset_bus(dev); | 201 | err = w1_reset_bus(dev); |
202 | break; | 202 | break; |
203 | default: | 203 | default: |
204 | cmd->res = EINVAL; | 204 | err = -EINVAL; |
205 | cn_netlink_send(msg, 0, GFP_KERNEL); | ||
206 | break; | 205 | break; |
207 | } | 206 | } |
208 | 207 | ||
@@ -246,7 +245,7 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc | |||
246 | w = (struct w1_netlink_msg *)(cn + 1); | 245 | w = (struct w1_netlink_msg *)(cn + 1); |
247 | 246 | ||
248 | w->type = W1_LIST_MASTERS; | 247 | w->type = W1_LIST_MASTERS; |
249 | w->reserved = 0; | 248 | w->status = 0; |
250 | w->len = 0; | 249 | w->len = 0; |
251 | id = (u32 *)(w + 1); | 250 | id = (u32 *)(w + 1); |
252 | 251 | ||
@@ -273,6 +272,40 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *mc | |||
273 | return 0; | 272 | return 0; |
274 | } | 273 | } |
275 | 274 | ||
275 | static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, | ||
276 | struct w1_netlink_cmd *rcmd, int error) | ||
277 | { | ||
278 | struct cn_msg *cmsg; | ||
279 | struct w1_netlink_msg *msg; | ||
280 | struct w1_netlink_cmd *cmd; | ||
281 | |||
282 | cmsg = kzalloc(sizeof(*msg) + sizeof(*cmd) + sizeof(*cmsg), GFP_KERNEL); | ||
283 | if (!cmsg) | ||
284 | return -ENOMEM; | ||
285 | |||
286 | msg = (struct w1_netlink_msg *)(cmsg + 1); | ||
287 | cmd = (struct w1_netlink_cmd *)(msg + 1); | ||
288 | |||
289 | memcpy(cmsg, rcmsg, sizeof(*cmsg)); | ||
290 | cmsg->len = sizeof(*msg); | ||
291 | |||
292 | memcpy(msg, rmsg, sizeof(*msg)); | ||
293 | msg->len = 0; | ||
294 | msg->status = (short)-error; | ||
295 | |||
296 | if (rcmd) { | ||
297 | memcpy(cmd, rcmd, sizeof(*cmd)); | ||
298 | cmd->len = 0; | ||
299 | msg->len += sizeof(*cmd); | ||
300 | cmsg->len += sizeof(*cmd); | ||
301 | } | ||
302 | |||
303 | error = cn_netlink_send(cmsg, 0, GFP_KERNEL); | ||
304 | kfree(cmsg); | ||
305 | |||
306 | return error; | ||
307 | } | ||
308 | |||
276 | static void w1_cn_callback(void *data) | 309 | static void w1_cn_callback(void *data) |
277 | { | 310 | { |
278 | struct cn_msg *msg = data; | 311 | struct cn_msg *msg = data; |
@@ -289,6 +322,7 @@ static void w1_cn_callback(void *data) | |||
289 | 322 | ||
290 | dev = NULL; | 323 | dev = NULL; |
291 | sl = NULL; | 324 | sl = NULL; |
325 | cmd = NULL; | ||
292 | 326 | ||
293 | memcpy(&id, m->id.id, sizeof(id)); | 327 | memcpy(&id, m->id.id, sizeof(id)); |
294 | #if 0 | 328 | #if 0 |
@@ -336,9 +370,12 @@ static void w1_cn_callback(void *data) | |||
336 | } | 370 | } |
337 | 371 | ||
338 | if (sl) | 372 | if (sl) |
339 | w1_process_command_slave(sl, msg, m, cmd); | 373 | err = w1_process_command_slave(sl, msg, m, cmd); |
340 | else | 374 | else |
341 | w1_process_command_master(dev, msg, m, cmd); | 375 | err = w1_process_command_master(dev, msg, m, cmd); |
376 | |||
377 | w1_netlink_send_error(msg, m, cmd, err); | ||
378 | err = 0; | ||
342 | 379 | ||
343 | cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); | 380 | cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); |
344 | mlen -= cmd->len + sizeof(struct w1_netlink_cmd); | 381 | mlen -= cmd->len + sizeof(struct w1_netlink_cmd); |
@@ -349,6 +386,8 @@ out_up: | |||
349 | atomic_dec(&sl->refcnt); | 386 | atomic_dec(&sl->refcnt); |
350 | mutex_unlock(&dev->mutex); | 387 | mutex_unlock(&dev->mutex); |
351 | out_cont: | 388 | out_cont: |
389 | if (!cmd || err) | ||
390 | w1_netlink_send_error(msg, m, cmd, err); | ||
352 | msg->len -= sizeof(struct w1_netlink_msg) + m->len; | 391 | msg->len -= sizeof(struct w1_netlink_msg) + m->len; |
353 | m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); | 392 | m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); |
354 | 393 | ||