aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/w1/w1.netlink29
-rw-r--r--drivers/w1/w1_netlink.c53
-rw-r--r--drivers/w1/w1_netlink.h2
3 files changed, 76 insertions, 8 deletions
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
index 2756681b6ef5..804445f745ed 100644
--- a/Documentation/w1/w1.netlink
+++ b/Documentation/w1/w1.netlink
@@ -118,6 +118,35 @@ W1 reset command.
118 id is equal to the bus master id to use for searching] 118 id is equal to the bus master id to use for searching]
119 [w1_netlink_cmd cmd = W1_CMD_RESET] 119 [w1_netlink_cmd cmd = W1_CMD_RESET]
120 120
121
122Command status replies.
123======================
124
125Each command (either root, master or slave with or without w1_netlink_cmd
126structure) will be 'acked' by the w1 core. Format of the reply is the same
127as request message except that length parameters do not account for data
128requested by the user, i.e. read/write/touch IO requests will not contain
129data, so w1_netlink_cmd.len will be 0, w1_netlink_msg.len will be size
130of the w1_netlink_cmd structure and cn_msg.len will be equal to the sum
131of the sizeof(struct w1_netlink_msg) and sizeof(struct w1_netlink_cmd).
132If reply is generated for master or root command (which do not have
133w1_netlink_cmd attached), reply will contain only cn_msg and w1_netlink_msg
134structires.
135
136w1_netlink_msg.status field will carry positive error value
137(EINVAL for example) or zero in case of success.
138
139All other fields in every structure will mirror the same parameters in the
140request message (except lengths as described above).
141
142Status reply is generated for every w1_netlink_cmd embedded in the
143w1_netlink_msg, if there are no w1_netlink_cmd structures,
144reply will be generated for the w1_netlink_msg.
145
146All w1_netlink_cmd command structures are handled in every w1_netlink_msg,
147even if there were errors, only length mismatch interrupts message processing.
148
149
121Operation steps in w1 core when new command is received. 150Operation steps in w1 core when new command is received.
122======================================================= 151=======================================================
123 152
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
275static 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
276static void w1_cn_callback(void *data) 309static 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);
351out_cont: 388out_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
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 68a4ff46cb96..27e950f935b1 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -40,7 +40,7 @@ enum w1_netlink_message_types {
40struct w1_netlink_msg 40struct w1_netlink_msg
41{ 41{
42 __u8 type; 42 __u8 type;
43 __u8 reserved; 43 __u8 status;
44 __u16 len; 44 __u16 len;
45 union { 45 union {
46 __u8 id[8]; 46 __u8 id[8];