Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

w1: optional bundling of netlink kernel replies

Applications can submit a set of commands in one packet to the kernel,
and in some cases it is required such as reading the temperature
sensor results. This adds an option W1_CN_BUNDLE to the flags of
cn_msg to request the kernel to reply in one packet for efficiency.

The cn_msg flags now check for unknown flag values and return an error
if one is seen. See "Proper handling of unknown flags in system
calls" http://lwn.net/Articles/588444/

This corrects the ack values returned as per the protocol standard,
namely the original ack for status messages and seq + 1 for all others
such as the data returned from a read.

Some of the common variable names have been standardized as follows.
struct cn_msg *cn
struct w1_netlink_msg *msg
struct w1_netlink_cmd *cmd
struct w1_master *dev

When an argument and a function scope variable would collide, add req_
to the argument.

Signed-off-by: David Fries <David@Fries.net>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

David Fries and committed by
Greg Kroah-Hartman
8a0427d1 34470e0b

+447 -263
+1 -1
Documentation/connector/connector.txt
··· 118 118 If we receive a message and its sequence number is not equal to one we 119 119 are expecting, then it is a new message. If we receive a message and 120 120 its sequence number is the same as one we are expecting, but its 121 - acknowledge is not equal to the acknowledge number in the original 121 + acknowledge is not equal to the sequence number in the original 122 122 message + 1, then it is a new message. 123 123 124 124 Obviously, the protocol header contains the above id.
+1 -1
Documentation/w1/w1.generic
··· 82 82 w1_master_add - Manually register a slave device 83 83 w1_master_attempts - the number of times a search was attempted 84 84 w1_master_max_slave_count 85 - - the maximum slaves that may be attached to a master 85 + - maximum number of slaves to search for at a time 86 86 w1_master_name - the name of the device (w1_bus_masterX) 87 87 w1_master_pullup - 5V strong pullup 0 enabled, 1 disabled 88 88 w1_master_remove - Manually remove a slave device
-8
drivers/w1/w1.h
··· 203 203 * @search_id: allows continuing a search 204 204 * @refcnt: reference count 205 205 * @priv: private data storage 206 - * @priv_size: size allocated 207 206 * @enable_pullup: allows a strong pullup 208 207 * @pullup_duration: time for the next strong pullup 209 208 * @flags: one of w1_master_flags ··· 213 214 * @dev: sysfs device 214 215 * @bus_master: io operations available 215 216 * @seq: sequence number used for netlink broadcasts 216 - * @portid: destination for the current netlink command 217 217 */ 218 218 struct w1_master 219 219 { ··· 239 241 atomic_t refcnt; 240 242 241 243 void *priv; 242 - int priv_size; 243 244 244 245 /** 5V strong pullup enabled flag, 1 enabled, zero disabled. */ 245 246 int enable_pullup; ··· 257 260 struct w1_bus_master *bus_master; 258 261 259 262 u32 seq; 260 - /* port id to send netlink responses to. The value is temporarily 261 - * stored here while processing a message, set after locking the 262 - * mutex, zero before unlocking the mutex. 263 - */ 264 - u32 portid; 265 263 }; 266 264 267 265 /**
+401 -248
drivers/w1/w1_netlink.c
··· 29 29 #include "w1_netlink.h" 30 30 31 31 #if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE))) 32 + 33 + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 34 + 35 + /* Bundle together everything required to process a request in one memory 36 + * allocation. 37 + */ 38 + struct w1_cb_block { 39 + atomic_t refcnt; 40 + u32 portid; /* Sending process port ID */ 41 + /* maximum value for first_cn->len */ 42 + u16 maxlen; 43 + /* pointers to building up the reply message */ 44 + struct cn_msg *first_cn; /* fixed once the structure is populated */ 45 + struct cn_msg *cn; /* advances as cn_msg is appeneded */ 46 + struct w1_netlink_msg *msg; /* advances as w1_netlink_msg is appened */ 47 + struct w1_netlink_cmd *cmd; /* advances as cmds are appened */ 48 + struct w1_netlink_msg *cur_msg; /* currently message being processed */ 49 + /* copy of the original request follows */ 50 + struct cn_msg request_cn; 51 + /* followed by variable length: 52 + * cn_msg, data (w1_netlink_msg and w1_netlink_cmd) 53 + * one or more struct w1_cb_node 54 + * reply first_cn, data (w1_netlink_msg and w1_netlink_cmd) 55 + */ 56 + }; 57 + struct w1_cb_node { 58 + struct w1_async_cmd async; 59 + /* pointers within w1_cb_block and cn data */ 60 + struct w1_cb_block *block; 61 + struct w1_netlink_msg *msg; 62 + struct w1_slave *sl; 63 + struct w1_master *dev; 64 + }; 65 + 66 + /** 67 + * w1_reply_len() - calculate current reply length, compare to maxlen 68 + * @block: block to calculate 69 + * 70 + * Calculates the current message length including possible multiple 71 + * cn_msg and data, excludes the first sizeof(struct cn_msg). Direclty 72 + * compariable to maxlen and usable to send the message. 73 + */ 74 + static u16 w1_reply_len(struct w1_cb_block *block) 75 + { 76 + if (!block->cn) 77 + return 0; 78 + return (u8 *)block->cn - (u8 *)block->first_cn + block->cn->len; 79 + } 80 + 81 + static void w1_unref_block(struct w1_cb_block *block) 82 + { 83 + if (atomic_sub_return(1, &block->refcnt) == 0) { 84 + u16 len = w1_reply_len(block); 85 + if (len) { 86 + cn_netlink_send_mult(block->first_cn, len, 87 + block->portid, 0, GFP_KERNEL); 88 + } 89 + kfree(block); 90 + } 91 + } 92 + 93 + /** 94 + * w1_reply_make_space() - send message if needed to make space 95 + * @block: block to make space on 96 + * @space: how many bytes requested 97 + * 98 + * Verify there is enough room left for the caller to add "space" bytes to the 99 + * message, if there isn't send the message and reset. 100 + */ 101 + static void w1_reply_make_space(struct w1_cb_block *block, u16 space) 102 + { 103 + u16 len = w1_reply_len(block); 104 + if (len + space >= block->maxlen) { 105 + cn_netlink_send_mult(block->first_cn, len, block->portid, 0, GFP_KERNEL); 106 + block->first_cn->len = 0; 107 + block->cn = NULL; 108 + block->msg = NULL; 109 + block->cmd = NULL; 110 + } 111 + } 112 + 113 + /* Early send when replies aren't bundled. */ 114 + static void w1_netlink_check_send(struct w1_cb_block *block) 115 + { 116 + if (!(block->request_cn.flags & W1_CN_BUNDLE) && block->cn) 117 + w1_reply_make_space(block, block->maxlen); 118 + } 119 + 120 + /** 121 + * w1_netlink_setup_msg() - prepare to write block->msg 122 + * @block: block to operate on 123 + * @ack: determines if cn can be reused 124 + * 125 + * block->cn will be setup with the correct ack, advancing if needed 126 + * block->cn->len does not include space for block->msg 127 + * block->msg advances but remains uninitialized 128 + */ 129 + static void w1_netlink_setup_msg(struct w1_cb_block *block, u32 ack) 130 + { 131 + if (block->cn && block->cn->ack == ack) { 132 + block->msg = (struct w1_netlink_msg *)(block->cn->data + block->cn->len); 133 + } else { 134 + /* advance or set to data */ 135 + if (block->cn) 136 + block->cn = (struct cn_msg *)(block->cn->data + 137 + block->cn->len); 138 + else 139 + block->cn = block->first_cn; 140 + 141 + memcpy(block->cn, &block->request_cn, sizeof(*block->cn)); 142 + block->cn->len = 0; 143 + block->cn->ack = ack; 144 + block->msg = (struct w1_netlink_msg *)block->cn->data; 145 + } 146 + } 147 + 148 + /* Append cmd to msg, include cmd->data as well. This is because 149 + * any following data goes with the command and in the case of a read is 150 + * the results. 151 + */ 152 + static void w1_netlink_queue_cmd(struct w1_cb_block *block, 153 + struct w1_netlink_cmd *cmd) 154 + { 155 + u32 space; 156 + w1_reply_make_space(block, sizeof(struct cn_msg) + 157 + sizeof(struct w1_netlink_msg) + sizeof(*cmd) + cmd->len); 158 + 159 + /* There's a status message sent after each command, so no point 160 + * in trying to bundle this cmd after an existing one, because 161 + * there won't be one. Allocate and copy over a new cn_msg. 162 + */ 163 + w1_netlink_setup_msg(block, block->request_cn.seq + 1); 164 + memcpy(block->msg, block->cur_msg, sizeof(*block->msg)); 165 + block->cn->len += sizeof(*block->msg); 166 + block->msg->len = 0; 167 + block->cmd = (struct w1_netlink_cmd *)(block->msg->data); 168 + 169 + space = sizeof(*cmd) + cmd->len; 170 + if (block->cmd != cmd) 171 + memcpy(block->cmd, cmd, space); 172 + block->cn->len += space; 173 + block->msg->len += space; 174 + } 175 + 176 + /* Append req_msg and req_cmd, no other commands and no data from req_cmd are 177 + * copied. 178 + */ 179 + static void w1_netlink_queue_status(struct w1_cb_block *block, 180 + struct w1_netlink_msg *req_msg, struct w1_netlink_cmd *req_cmd, 181 + int error) 182 + { 183 + u16 space = sizeof(struct cn_msg) + sizeof(*req_msg) + sizeof(*req_cmd); 184 + w1_reply_make_space(block, space); 185 + w1_netlink_setup_msg(block, block->request_cn.ack); 186 + 187 + memcpy(block->msg, req_msg, sizeof(*req_msg)); 188 + block->cn->len += sizeof(*req_msg); 189 + block->msg->len = 0; 190 + block->msg->status = (u8)-error; 191 + if (req_cmd) { 192 + struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)block->msg->data; 193 + memcpy(cmd, req_cmd, sizeof(*cmd)); 194 + block->cn->len += sizeof(*cmd); 195 + block->msg->len += sizeof(*cmd); 196 + cmd->len = 0; 197 + } 198 + w1_netlink_check_send(block); 199 + } 200 + 201 + /** 202 + * w1_netlink_send_error() - sends the error message now 203 + * @cn: original cn_msg 204 + * @msg: original w1_netlink_msg 205 + * @portid: where to send it 206 + * @error: error status 207 + * 208 + * Use when a block isn't available to queue the message to and cn, msg 209 + * might not be contiguous. 210 + */ 211 + static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg, 212 + int portid, int error) 213 + { 214 + struct { 215 + struct cn_msg cn; 216 + struct w1_netlink_msg msg; 217 + } packet; 218 + memcpy(&packet.cn, cn, sizeof(packet.cn)); 219 + memcpy(&packet.msg, msg, sizeof(packet.msg)); 220 + packet.cn.len = sizeof(packet.msg); 221 + packet.msg.len = 0; 222 + packet.msg.status = (u8)-error; 223 + cn_netlink_send(&packet.cn, portid, 0, GFP_KERNEL); 224 + } 225 + 226 + /** 227 + * w1_netlink_send() - sends w1 netlink notifications 228 + * @dev: w1_master the even is associated with or for 229 + * @msg: w1_netlink_msg message to be sent 230 + * 231 + * This are notifications generated from the kernel. 232 + */ 32 233 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 33 234 { 34 - char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)]; 35 - struct cn_msg *m = (struct cn_msg *)buf; 36 - struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1); 235 + struct { 236 + struct cn_msg cn; 237 + struct w1_netlink_msg msg; 238 + } packet; 239 + memset(&packet, 0, sizeof(packet)); 37 240 38 - memset(buf, 0, sizeof(buf)); 241 + packet.cn.id.idx = CN_W1_IDX; 242 + packet.cn.id.val = CN_W1_VAL; 39 243 40 - m->id.idx = CN_W1_IDX; 41 - m->id.val = CN_W1_VAL; 244 + packet.cn.seq = dev->seq++; 245 + packet.cn.len = sizeof(*msg); 42 246 43 - m->seq = dev->seq++; 44 - m->len = sizeof(struct w1_netlink_msg); 247 + memcpy(&packet.msg, msg, sizeof(*msg)); 248 + packet.msg.len = 0; 45 249 46 - memcpy(w, msg, sizeof(struct w1_netlink_msg)); 47 - 48 - cn_netlink_send(m, dev->portid, 0, GFP_KERNEL); 250 + cn_netlink_send(&packet.cn, 0, 0, GFP_KERNEL); 49 251 } 50 252 51 253 static void w1_send_slave(struct w1_master *dev, u64 rn) 52 254 { 53 - struct cn_msg *msg = dev->priv; 54 - struct w1_netlink_msg *hdr = (struct w1_netlink_msg *)(msg + 1); 55 - struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)(hdr + 1); 56 - int avail; 255 + struct w1_cb_block *block = dev->priv; 256 + struct w1_netlink_cmd *cache_cmd = block->cmd; 57 257 u64 *data; 58 258 59 - avail = dev->priv_size - cmd->len; 259 + w1_reply_make_space(block, sizeof(*data)); 60 260 61 - if (avail < 8) { 62 - msg->ack++; 63 - cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL); 64 - 65 - msg->len = sizeof(struct w1_netlink_msg) + 66 - sizeof(struct w1_netlink_cmd); 67 - hdr->len = sizeof(struct w1_netlink_cmd); 68 - cmd->len = 0; 261 + /* Add cmd back if the packet was sent */ 262 + if (!block->cmd) { 263 + cache_cmd->len = 0; 264 + w1_netlink_queue_cmd(block, cache_cmd); 69 265 } 70 266 71 - data = (void *)(cmd + 1) + cmd->len; 267 + data = (u64 *)(block->cmd->data + block->cmd->len); 72 268 73 269 *data = rn; 74 - cmd->len += 8; 75 - hdr->len += 8; 76 - msg->len += 8; 270 + block->cn->len += sizeof(*data); 271 + block->msg->len += sizeof(*data); 272 + block->cmd->len += sizeof(*data); 77 273 } 78 274 79 275 static void w1_found_send_slave(struct w1_master *dev, u64 rn) ··· 281 85 } 282 86 283 87 /* Get the current slave list, or search (with or without alarm) */ 284 - static int w1_get_slaves(struct w1_master *dev, 285 - struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr, 286 - struct w1_netlink_cmd *req_cmd) 88 + static int w1_get_slaves(struct w1_master *dev, struct w1_netlink_cmd *req_cmd) 287 89 { 288 - struct cn_msg *msg; 289 - struct w1_netlink_msg *hdr; 290 - struct w1_netlink_cmd *cmd; 291 90 struct w1_slave *sl; 292 91 293 - msg = kzalloc(PAGE_SIZE, GFP_KERNEL); 294 - if (!msg) 295 - return -ENOMEM; 296 - 297 - msg->id = req_msg->id; 298 - msg->seq = req_msg->seq; 299 - msg->ack = 0; 300 - msg->len = sizeof(struct w1_netlink_msg) + 301 - sizeof(struct w1_netlink_cmd); 302 - 303 - hdr = (struct w1_netlink_msg *)(msg + 1); 304 - cmd = (struct w1_netlink_cmd *)(hdr + 1); 305 - 306 - hdr->type = W1_MASTER_CMD; 307 - hdr->id = req_hdr->id; 308 - hdr->len = sizeof(struct w1_netlink_cmd); 309 - 310 - cmd->cmd = req_cmd->cmd; 311 - cmd->len = 0; 312 - 313 - dev->priv = msg; 314 - dev->priv_size = PAGE_SIZE - msg->len - sizeof(struct cn_msg); 92 + req_cmd->len = 0; 93 + w1_netlink_queue_cmd(dev->priv, req_cmd); 315 94 316 95 if (req_cmd->cmd == W1_CMD_LIST_SLAVES) { 317 - __u64 rn; 96 + u64 rn; 318 97 mutex_lock(&dev->list_mutex); 319 98 list_for_each_entry(sl, &dev->slist, w1_slave_entry) { 320 99 memcpy(&rn, &sl->reg_num, sizeof(rn)); ··· 297 126 } 298 127 mutex_unlock(&dev->list_mutex); 299 128 } else { 300 - w1_search_process_cb(dev, cmd->cmd == W1_CMD_ALARM_SEARCH ? 129 + w1_search_process_cb(dev, req_cmd->cmd == W1_CMD_ALARM_SEARCH ? 301 130 W1_ALARM_SEARCH : W1_SEARCH, w1_found_send_slave); 302 131 } 303 - 304 - msg->ack = 0; 305 - cn_netlink_send(msg, dev->portid, 0, GFP_KERNEL); 306 - 307 - dev->priv = NULL; 308 - dev->priv_size = 0; 309 - 310 - kfree(msg); 311 132 312 133 return 0; 313 134 } 314 135 315 - static int w1_send_read_reply(struct cn_msg *msg, struct w1_netlink_msg *hdr, 316 - struct w1_netlink_cmd *cmd, u32 portid) 317 - { 318 - void *data; 319 - struct w1_netlink_msg *h; 320 - struct w1_netlink_cmd *c; 321 - struct cn_msg *cm; 322 - int err; 323 - 324 - data = kzalloc(sizeof(struct cn_msg) + 325 - sizeof(struct w1_netlink_msg) + 326 - sizeof(struct w1_netlink_cmd) + 327 - cmd->len, GFP_KERNEL); 328 - if (!data) 329 - return -ENOMEM; 330 - 331 - cm = (struct cn_msg *)(data); 332 - h = (struct w1_netlink_msg *)(cm + 1); 333 - c = (struct w1_netlink_cmd *)(h + 1); 334 - 335 - memcpy(cm, msg, sizeof(struct cn_msg)); 336 - memcpy(h, hdr, sizeof(struct w1_netlink_msg)); 337 - memcpy(c, cmd, sizeof(struct w1_netlink_cmd)); 338 - 339 - cm->ack = msg->seq+1; 340 - cm->len = sizeof(struct w1_netlink_msg) + 341 - sizeof(struct w1_netlink_cmd) + cmd->len; 342 - 343 - h->len = sizeof(struct w1_netlink_cmd) + cmd->len; 344 - 345 - memcpy(c->data, cmd->data, c->len); 346 - 347 - err = cn_netlink_send(cm, portid, 0, GFP_KERNEL); 348 - 349 - kfree(data); 350 - 351 - return err; 352 - } 353 - 354 - static int w1_process_command_io(struct w1_master *dev, struct cn_msg *msg, 355 - struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) 136 + static int w1_process_command_io(struct w1_master *dev, 137 + struct w1_netlink_cmd *cmd) 356 138 { 357 139 int err = 0; 358 140 359 141 switch (cmd->cmd) { 360 142 case W1_CMD_TOUCH: 361 143 w1_touch_block(dev, cmd->data, cmd->len); 362 - w1_send_read_reply(msg, hdr, cmd, dev->portid); 144 + w1_netlink_queue_cmd(dev->priv, cmd); 363 145 break; 364 146 case W1_CMD_READ: 365 147 w1_read_block(dev, cmd->data, cmd->len); 366 - w1_send_read_reply(msg, hdr, cmd, dev->portid); 148 + w1_netlink_queue_cmd(dev->priv, cmd); 367 149 break; 368 150 case W1_CMD_WRITE: 369 151 w1_write_block(dev, cmd->data, cmd->len); ··· 330 206 } 331 207 332 208 static int w1_process_command_addremove(struct w1_master *dev, 333 - struct cn_msg *msg, struct w1_netlink_msg *hdr, 334 209 struct w1_netlink_cmd *cmd) 335 210 { 336 211 struct w1_slave *sl; 337 212 int err = 0; 338 213 struct w1_reg_num *id; 339 214 340 - if (cmd->len != 8) 215 + if (cmd->len != sizeof(*id)) 341 216 return -EINVAL; 342 217 343 218 id = (struct w1_reg_num *)cmd->data; ··· 364 241 } 365 242 366 243 static int w1_process_command_master(struct w1_master *dev, 367 - struct cn_msg *req_msg, struct w1_netlink_msg *req_hdr, 368 244 struct w1_netlink_cmd *req_cmd) 369 245 { 370 246 int err = -EINVAL; ··· 376 254 case W1_CMD_ALARM_SEARCH: 377 255 case W1_CMD_LIST_SLAVES: 378 256 mutex_unlock(&dev->bus_mutex); 379 - err = w1_get_slaves(dev, req_msg, req_hdr, req_cmd); 257 + err = w1_get_slaves(dev, req_cmd); 380 258 mutex_lock(&dev->bus_mutex); 381 259 break; 382 260 case W1_CMD_READ: 383 261 case W1_CMD_WRITE: 384 262 case W1_CMD_TOUCH: 385 - err = w1_process_command_io(dev, req_msg, req_hdr, req_cmd); 263 + err = w1_process_command_io(dev, req_cmd); 386 264 break; 387 265 case W1_CMD_RESET: 388 266 err = w1_reset_bus(dev); ··· 391 269 case W1_CMD_SLAVE_REMOVE: 392 270 mutex_unlock(&dev->bus_mutex); 393 271 mutex_lock(&dev->mutex); 394 - err = w1_process_command_addremove(dev, req_msg, req_hdr, 395 - req_cmd); 272 + err = w1_process_command_addremove(dev, req_cmd); 396 273 mutex_unlock(&dev->mutex); 397 274 mutex_lock(&dev->bus_mutex); 398 275 break; ··· 403 282 return err; 404 283 } 405 284 406 - static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg, 407 - struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd) 285 + static int w1_process_command_slave(struct w1_slave *sl, 286 + struct w1_netlink_cmd *cmd) 408 287 { 409 288 dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n", 410 289 __func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, 411 290 sl->reg_num.crc, cmd->cmd, cmd->len); 412 291 413 - return w1_process_command_io(sl->master, msg, hdr, cmd); 292 + return w1_process_command_io(sl->master, cmd); 414 293 } 415 294 416 - static int w1_process_command_root(struct cn_msg *msg, 417 - struct w1_netlink_msg *mcmd, u32 portid) 295 + static int w1_process_command_root(struct cn_msg *req_cn, u32 portid) 418 296 { 419 - struct w1_master *m; 297 + struct w1_master *dev; 420 298 struct cn_msg *cn; 421 - struct w1_netlink_msg *w; 299 + struct w1_netlink_msg *msg; 422 300 u32 *id; 423 301 424 302 cn = kmalloc(PAGE_SIZE, GFP_KERNEL); ··· 427 307 cn->id.idx = CN_W1_IDX; 428 308 cn->id.val = CN_W1_VAL; 429 309 430 - cn->seq = msg->seq; 431 - cn->ack = 1; 310 + cn->seq = req_cn->seq; 311 + cn->ack = req_cn->seq + 1; 432 312 cn->len = sizeof(struct w1_netlink_msg); 433 - w = (struct w1_netlink_msg *)(cn + 1); 313 + msg = (struct w1_netlink_msg *)cn->data; 434 314 435 - w->type = W1_LIST_MASTERS; 436 - w->status = 0; 437 - w->len = 0; 438 - id = (u32 *)(w + 1); 315 + msg->type = W1_LIST_MASTERS; 316 + msg->status = 0; 317 + msg->len = 0; 318 + id = (u32 *)msg->data; 439 319 440 320 mutex_lock(&w1_mlock); 441 - list_for_each_entry(m, &w1_masters, w1_master_entry) { 321 + list_for_each_entry(dev, &w1_masters, w1_master_entry) { 442 322 if (cn->len + sizeof(*id) > PAGE_SIZE - sizeof(struct cn_msg)) { 443 323 cn_netlink_send(cn, portid, 0, GFP_KERNEL); 444 - cn->ack++; 445 324 cn->len = sizeof(struct w1_netlink_msg); 446 - w->len = 0; 447 - id = (u32 *)(w + 1); 325 + msg->len = 0; 326 + id = (u32 *)msg->data; 448 327 } 449 328 450 - *id = m->id; 451 - w->len += sizeof(*id); 329 + *id = dev->id; 330 + msg->len += sizeof(*id); 452 331 cn->len += sizeof(*id); 453 332 id++; 454 333 } 455 - cn->ack = 0; 456 334 cn_netlink_send(cn, portid, 0, GFP_KERNEL); 457 335 mutex_unlock(&w1_mlock); 458 336 ··· 458 340 return 0; 459 341 } 460 342 461 - static int w1_netlink_send_error(struct cn_msg *rcmsg, struct w1_netlink_msg *rmsg, 462 - struct w1_netlink_cmd *rcmd, int portid, int error) 463 - { 464 - struct cn_msg *cmsg; 465 - struct w1_netlink_msg *msg; 466 - struct w1_netlink_cmd *cmd; 467 - 468 - cmsg = kzalloc(sizeof(*msg) + sizeof(*cmd) + sizeof(*cmsg), GFP_KERNEL); 469 - if (!cmsg) 470 - return -ENOMEM; 471 - 472 - msg = (struct w1_netlink_msg *)(cmsg + 1); 473 - cmd = (struct w1_netlink_cmd *)(msg + 1); 474 - 475 - memcpy(cmsg, rcmsg, sizeof(*cmsg)); 476 - cmsg->len = sizeof(*msg); 477 - 478 - memcpy(msg, rmsg, sizeof(*msg)); 479 - msg->len = 0; 480 - msg->status = (short)-error; 481 - 482 - if (rcmd) { 483 - memcpy(cmd, rcmd, sizeof(*cmd)); 484 - cmd->len = 0; 485 - msg->len += sizeof(*cmd); 486 - cmsg->len += sizeof(*cmd); 487 - } 488 - 489 - error = cn_netlink_send(cmsg, portid, 0, GFP_KERNEL); 490 - kfree(cmsg); 491 - 492 - return error; 493 - } 494 - 495 - /* Bundle together a reference count, the full message, and broken out 496 - * commands to be executed on each w1 master kthread in one memory allocation. 497 - */ 498 - struct w1_cb_block { 499 - atomic_t refcnt; 500 - u32 portid; /* Sending process port ID */ 501 - struct cn_msg msg; 502 - /* cn_msg data */ 503 - /* one or more variable length struct w1_cb_node */ 504 - }; 505 - struct w1_cb_node { 506 - struct w1_async_cmd async; 507 - /* pointers within w1_cb_block and msg data */ 508 - struct w1_cb_block *block; 509 - struct w1_netlink_msg *m; 510 - struct w1_slave *sl; 511 - struct w1_master *dev; 512 - }; 513 - 514 343 static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) 515 344 { 516 345 struct w1_cb_node *node = container_of(async_cmd, struct w1_cb_node, 517 346 async); 518 - u16 mlen = node->m->len; 519 - u8 *cmd_data = node->m->data; 347 + u16 mlen = node->msg->len; 348 + u16 len; 520 349 int err = 0; 521 350 struct w1_slave *sl = node->sl; 522 - struct w1_netlink_cmd *cmd = NULL; 351 + struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)node->msg->data; 523 352 524 353 mutex_lock(&dev->bus_mutex); 525 - dev->portid = node->block->portid; 354 + dev->priv = node->block; 526 355 if (sl && w1_reset_select_slave(sl)) 527 356 err = -ENODEV; 357 + node->block->cur_msg = node->msg; 528 358 529 359 while (mlen && !err) { 530 - cmd = (struct w1_netlink_cmd *)cmd_data; 531 - 532 360 if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) { 533 361 err = -E2BIG; 534 362 break; 535 363 } 536 364 537 365 if (sl) 538 - err = w1_process_command_slave(sl, &node->block->msg, 539 - node->m, cmd); 366 + err = w1_process_command_slave(sl, cmd); 540 367 else 541 - err = w1_process_command_master(dev, &node->block->msg, 542 - node->m, cmd); 368 + err = w1_process_command_master(dev, cmd); 369 + w1_netlink_check_send(node->block); 543 370 544 - w1_netlink_send_error(&node->block->msg, node->m, cmd, 545 - node->block->portid, err); 371 + w1_netlink_queue_status(node->block, node->msg, cmd, err); 546 372 err = 0; 547 373 548 - cmd_data += cmd->len + sizeof(struct w1_netlink_cmd); 549 - mlen -= cmd->len + sizeof(struct w1_netlink_cmd); 374 + len = sizeof(*cmd) + cmd->len; 375 + cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len); 376 + mlen -= len; 550 377 } 551 378 552 379 if (!cmd || err) 553 - w1_netlink_send_error(&node->block->msg, node->m, cmd, 554 - node->block->portid, err); 380 + w1_netlink_queue_status(node->block, node->msg, cmd, err); 555 381 556 382 /* ref taken in w1_search_slave or w1_search_master_id when building 557 383 * the block ··· 504 442 w1_unref_slave(sl); 505 443 else 506 444 atomic_dec(&dev->refcnt); 507 - dev->portid = 0; 445 + dev->priv = NULL; 508 446 mutex_unlock(&dev->bus_mutex); 509 447 510 448 mutex_lock(&dev->list_mutex); 511 449 list_del(&async_cmd->async_entry); 512 450 mutex_unlock(&dev->list_mutex); 513 451 514 - if (atomic_sub_return(1, &node->block->refcnt) == 0) 515 - kfree(node->block); 452 + w1_unref_block(node->block); 516 453 } 517 454 518 - static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 455 + static void w1_list_count_cmds(struct w1_netlink_msg *msg, int *cmd_count, 456 + u16 *slave_len) 519 457 { 520 - struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1); 458 + struct w1_netlink_cmd *cmd = (struct w1_netlink_cmd *)msg->data; 459 + u16 mlen = msg->len; 460 + u16 len; 461 + int slave_list = 0; 462 + while (mlen) { 463 + if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) 464 + break; 465 + 466 + switch (cmd->cmd) { 467 + case W1_CMD_SEARCH: 468 + case W1_CMD_ALARM_SEARCH: 469 + case W1_CMD_LIST_SLAVES: 470 + ++slave_list; 471 + } 472 + ++*cmd_count; 473 + len = sizeof(*cmd) + cmd->len; 474 + cmd = (struct w1_netlink_cmd *)((u8 *)cmd + len); 475 + mlen -= len; 476 + } 477 + 478 + if (slave_list) { 479 + struct w1_master *dev = w1_search_master_id(msg->id.mst.id); 480 + if (dev) { 481 + /* Bytes, and likely an overstimate, and if it isn't 482 + * the results can still be split between packets. 483 + */ 484 + *slave_len += sizeof(struct w1_reg_num) * slave_list * 485 + (dev->slave_count + dev->max_slave_count); 486 + /* search incremented it */ 487 + atomic_dec(&dev->refcnt); 488 + } 489 + } 490 + } 491 + 492 + static void w1_cn_callback(struct cn_msg *cn, struct netlink_skb_parms *nsp) 493 + { 494 + struct w1_netlink_msg *msg = (struct w1_netlink_msg *)(cn + 1); 521 495 struct w1_slave *sl; 522 496 struct w1_master *dev; 523 497 u16 msg_len; 498 + u16 slave_len = 0; 524 499 int err = 0; 525 500 struct w1_cb_block *block = NULL; 526 501 struct w1_cb_node *node = NULL; 527 502 int node_count = 0; 503 + int cmd_count = 0; 504 + 505 + /* If any unknown flag is set let the application know, that way 506 + * applications can detect the absence of features in kernels that 507 + * don't know about them. http://lwn.net/Articles/587527/ 508 + */ 509 + if (cn->flags & ~(W1_CN_BUNDLE)) { 510 + w1_netlink_send_error(cn, msg, nsp->portid, -EINVAL); 511 + return; 512 + } 528 513 529 514 /* Count the number of master or slave commands there are to allocate 530 515 * space for one cb_node each. 531 516 */ 532 - msg_len = msg->len; 517 + msg_len = cn->len; 533 518 while (msg_len && !err) { 534 - if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { 519 + if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) { 535 520 err = -E2BIG; 536 521 break; 537 522 } 538 523 539 - if (m->type == W1_MASTER_CMD || m->type == W1_SLAVE_CMD) 524 + /* count messages for nodes and allocate any additional space 525 + * required for slave lists 526 + */ 527 + if (msg->type == W1_MASTER_CMD || msg->type == W1_SLAVE_CMD) { 540 528 ++node_count; 529 + w1_list_count_cmds(msg, &cmd_count, &slave_len); 530 + } 541 531 542 - msg_len -= sizeof(struct w1_netlink_msg) + m->len; 543 - m = (struct w1_netlink_msg *)(((u8 *)m) + 544 - sizeof(struct w1_netlink_msg) + m->len); 532 + msg_len -= sizeof(struct w1_netlink_msg) + msg->len; 533 + msg = (struct w1_netlink_msg *)(((u8 *)msg) + 534 + sizeof(struct w1_netlink_msg) + msg->len); 545 535 } 546 - m = (struct w1_netlink_msg *)(msg + 1); 536 + msg = (struct w1_netlink_msg *)(cn + 1); 547 537 if (node_count) { 548 - /* msg->len doesn't include itself */ 549 - long size = sizeof(struct w1_cb_block) + msg->len + 550 - node_count*sizeof(struct w1_cb_node); 551 - block = kmalloc(size, GFP_KERNEL); 538 + int size; 539 + u16 reply_size = sizeof(*cn) + cn->len + slave_len; 540 + if (cn->flags & W1_CN_BUNDLE) { 541 + /* bundling duplicats some of the messages */ 542 + reply_size += 2 * cmd_count * (sizeof(struct cn_msg) + 543 + sizeof(struct w1_netlink_msg) + 544 + sizeof(struct w1_netlink_cmd)); 545 + } 546 + reply_size = MIN(CONNECTOR_MAX_MSG_SIZE, reply_size); 547 + 548 + /* allocate space for the block, a copy of the original message, 549 + * one node per cmd to point into the original message, 550 + * space for replies which is the original message size plus 551 + * space for any list slave data and status messages 552 + * cn->len doesn't include itself which is part of the block 553 + * */ 554 + size = /* block + original message */ 555 + sizeof(struct w1_cb_block) + sizeof(*cn) + cn->len + 556 + /* space for nodes */ 557 + node_count * sizeof(struct w1_cb_node) + 558 + /* replies */ 559 + sizeof(struct cn_msg) + reply_size; 560 + block = kzalloc(size, GFP_KERNEL); 552 561 if (!block) { 553 - w1_netlink_send_error(msg, m, NULL, nsp->portid, 554 - -ENOMEM); 562 + /* if the system is already out of memory, 563 + * (A) will this work, and (B) would it be better 564 + * to not try? 565 + */ 566 + w1_netlink_send_error(cn, msg, nsp->portid, -ENOMEM); 555 567 return; 556 568 } 557 569 atomic_set(&block->refcnt, 1); 558 570 block->portid = nsp->portid; 559 - memcpy(&block->msg, msg, sizeof(*msg) + msg->len); 560 - node = (struct w1_cb_node *)((u8 *)block->msg.data + msg->len); 571 + memcpy(&block->request_cn, cn, sizeof(*cn) + cn->len); 572 + node = (struct w1_cb_node *)(block->request_cn.data + cn->len); 573 + 574 + /* Sneeky, when not bundling, reply_size is the allocated space 575 + * required for the reply, cn_msg isn't part of maxlen so 576 + * it should be reply_size - sizeof(struct cn_msg), however 577 + * when checking if there is enough space, w1_reply_make_space 578 + * is called with the full message size including cn_msg, 579 + * because it isn't known at that time if an additional cn_msg 580 + * will need to be allocated. So an extra cn_msg is added 581 + * above in "size". 582 + */ 583 + block->maxlen = reply_size; 584 + block->first_cn = (struct cn_msg *)(node + node_count); 585 + memset(block->first_cn, 0, sizeof(*block->first_cn)); 561 586 } 562 587 563 - msg_len = msg->len; 588 + msg_len = cn->len; 564 589 while (msg_len && !err) { 565 590 566 591 dev = NULL; 567 592 sl = NULL; 568 593 569 - if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { 594 + if (msg->len + sizeof(struct w1_netlink_msg) > msg_len) { 570 595 err = -E2BIG; 571 596 break; 572 597 } 573 598 574 599 /* execute on this thread, no need to process later */ 575 - if (m->type == W1_LIST_MASTERS) { 576 - err = w1_process_command_root(msg, m, nsp->portid); 600 + if (msg->type == W1_LIST_MASTERS) { 601 + err = w1_process_command_root(cn, nsp->portid); 577 602 goto out_cont; 578 603 } 579 604 580 605 /* All following message types require additional data, 581 606 * check here before references are taken. 582 607 */ 583 - if (!m->len) { 608 + if (!msg->len) { 584 609 err = -EPROTO; 585 610 goto out_cont; 586 611 } 587 612 588 - /* both search calls take reference counts */ 589 - if (m->type == W1_MASTER_CMD) { 590 - dev = w1_search_master_id(m->id.mst.id); 591 - } else if (m->type == W1_SLAVE_CMD) { 592 - sl = w1_search_slave((struct w1_reg_num *)m->id.id); 613 + /* both search calls take references */ 614 + if (msg->type == W1_MASTER_CMD) { 615 + dev = w1_search_master_id(msg->id.mst.id); 616 + } else if (msg->type == W1_SLAVE_CMD) { 617 + sl = w1_search_slave((struct w1_reg_num *)msg->id.id); 593 618 if (sl) 594 619 dev = sl->master; 595 620 } else { 596 621 printk(KERN_NOTICE 597 - "%s: msg: %x.%x, wrong type: %u, len: %u.\n", 598 - __func__, msg->id.idx, msg->id.val, 599 - m->type, m->len); 622 + "%s: cn: %x.%x, wrong type: %u, len: %u.\n", 623 + __func__, cn->id.idx, cn->id.val, 624 + msg->type, msg->len); 600 625 err = -EPROTO; 601 626 goto out_cont; 602 627 } ··· 698 549 atomic_inc(&block->refcnt); 699 550 node->async.cb = w1_process_cb; 700 551 node->block = block; 701 - node->m = (struct w1_netlink_msg *)((u8 *)&block->msg + 702 - (size_t)((u8 *)m - (u8 *)msg)); 552 + node->msg = (struct w1_netlink_msg *)((u8 *)&block->request_cn + 553 + (size_t)((u8 *)msg - (u8 *)cn)); 703 554 node->sl = sl; 704 555 node->dev = dev; 705 556 ··· 710 561 ++node; 711 562 712 563 out_cont: 564 + /* Can't queue because that modifies block and another 565 + * thread could be processing the messages by now and 566 + * there isn't a lock, send directly. 567 + */ 713 568 if (err) 714 - w1_netlink_send_error(msg, m, NULL, nsp->portid, err); 715 - msg_len -= sizeof(struct w1_netlink_msg) + m->len; 716 - m = (struct w1_netlink_msg *)(((u8 *)m) + 717 - sizeof(struct w1_netlink_msg) + m->len); 569 + w1_netlink_send_error(cn, msg, nsp->portid, err); 570 + msg_len -= sizeof(struct w1_netlink_msg) + msg->len; 571 + msg = (struct w1_netlink_msg *)(((u8 *)msg) + 572 + sizeof(struct w1_netlink_msg) + msg->len); 718 573 719 574 /* 720 575 * Let's allow requests for nonexisting devices. ··· 726 573 if (err == -ENODEV) 727 574 err = 0; 728 575 } 729 - if (block && atomic_sub_return(1, &block->refcnt) == 0) 730 - kfree(block); 576 + if (block) 577 + w1_unref_block(block); 731 578 } 732 579 733 580 int w1_init_netlink(void) ··· 744 591 cn_del_callback(&w1_id); 745 592 } 746 593 #else 747 - void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) 594 + void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *cn) 748 595 { 749 596 } 750 597
+36
drivers/w1/w1_netlink.h
··· 28 28 #include "w1.h" 29 29 30 30 /** 31 + * enum w1_cn_msg_flags - bitfield flags for struct cn_msg.flags 32 + * 33 + * @W1_CN_BUNDLE: Request bundling replies into fewer messagse. Be prepared 34 + * to handle multiple struct cn_msg, struct w1_netlink_msg, and 35 + * struct w1_netlink_cmd in one packet. 36 + */ 37 + enum w1_cn_msg_flags { 38 + W1_CN_BUNDLE = 1, 39 + }; 40 + 41 + /** 31 42 * enum w1_netlink_message_types - message type 32 43 * 33 44 * @W1_SLAVE_ADD: notification that a slave device was added ··· 60 49 W1_LIST_MASTERS, 61 50 }; 62 51 52 + /** 53 + * struct w1_netlink_msg - holds w1 message type, id, and result 54 + * 55 + * @type: one of enum w1_netlink_message_types 56 + * @status: kernel feedback for success 0 or errno failure value 57 + * @len: length of data following w1_netlink_msg 58 + * @id: union holding master bus id (msg.id) and slave device id (id[8]). 59 + * @data: start address of any following data 60 + * 61 + * The base message structure for w1 messages over netlink. 62 + * The netlink connector data sequence is, struct nlmsghdr, struct cn_msg, 63 + * then one or more struct w1_netlink_msg (each with optional data). 64 + */ 63 65 struct w1_netlink_msg 64 66 { 65 67 __u8 type; ··· 90 66 91 67 /** 92 68 * enum w1_commands - commands available for master or slave operations 69 + * 93 70 * @W1_CMD_READ: read len bytes 94 71 * @W1_CMD_WRITE: write len bytes 95 72 * @W1_CMD_SEARCH: initiate a standard search, returns only the slave ··· 118 93 W1_CMD_MAX 119 94 }; 120 95 96 + /** 97 + * struct w1_netlink_cmd - holds the command and data 98 + * 99 + * @cmd: one of enum w1_commands 100 + * @res: reserved 101 + * @len: length of data following w1_netlink_cmd 102 + * @data: start address of any following data 103 + * 104 + * One or more struct w1_netlink_cmd is placed starting at w1_netlink_msg.data 105 + * each with optional data. 106 + */ 121 107 struct w1_netlink_cmd 122 108 { 123 109 __u8 cmd;