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

hyperv: Move state setting for link query

It moves the state setting for query into rndis_filter_receive_response().
All callbacks including query-complete and status-callback are synchronized
by channel->inbound_lock. This prevents pentential race between them.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Haiyang Zhang and committed by
David S. Miller
1b07da51 48330e08

+24 -1
+4
drivers/net/hyperv/netvsc_drv.c
··· 442 442 if (!net) 443 443 return -ENOMEM; 444 444 445 + netif_carrier_off(net); 446 + 445 447 net_device_ctx = netdev_priv(net); 446 448 net_device_ctx->device_ctx = dev; 447 449 hv_set_drvdata(dev, net); ··· 475 473 pr_err("Unable to register netdev.\n"); 476 474 rndis_filter_device_remove(dev); 477 475 free_netdev(net); 476 + } else { 477 + schedule_delayed_work(&net_device_ctx->dwork, 0); 478 478 } 479 479 480 480 return ret;
+20 -1
drivers/net/hyperv/rndis_filter.c
··· 243 243 return ret; 244 244 } 245 245 246 + static void rndis_set_link_state(struct rndis_device *rdev, 247 + struct rndis_request *request) 248 + { 249 + u32 link_status; 250 + struct rndis_query_complete *query_complete; 251 + 252 + query_complete = &request->response_msg.msg.query_complete; 253 + 254 + if (query_complete->status == RNDIS_STATUS_SUCCESS && 255 + query_complete->info_buflen == sizeof(u32)) { 256 + memcpy(&link_status, (void *)((unsigned long)query_complete + 257 + query_complete->info_buf_offset), sizeof(u32)); 258 + rdev->link_state = link_status != 0; 259 + } 260 + } 261 + 246 262 static void rndis_filter_receive_response(struct rndis_device *dev, 247 263 struct rndis_message *resp) 248 264 { ··· 288 272 sizeof(struct rndis_message) + RNDIS_EXT_LEN) { 289 273 memcpy(&request->response_msg, resp, 290 274 resp->msg_len); 275 + if (request->request_msg.ndis_msg_type == 276 + RNDIS_MSG_QUERY && request->request_msg.msg. 277 + query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS) 278 + rndis_set_link_state(dev, request); 291 279 } else { 292 280 netdev_err(ndev, 293 281 "rndis response buffer overflow " ··· 640 620 ret = rndis_filter_query_device(dev, 641 621 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, 642 622 &link_status, &size); 643 - dev->link_state = (link_status != 0) ? true : false; 644 623 645 624 return ret; 646 625 }