Commit 1b07da51 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller

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: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 48330e08
...@@ -442,6 +442,8 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -442,6 +442,8 @@ static int netvsc_probe(struct hv_device *dev,
if (!net) if (!net)
return -ENOMEM; return -ENOMEM;
netif_carrier_off(net);
net_device_ctx = netdev_priv(net); net_device_ctx = netdev_priv(net);
net_device_ctx->device_ctx = dev; net_device_ctx->device_ctx = dev;
hv_set_drvdata(dev, net); hv_set_drvdata(dev, net);
...@@ -473,6 +475,8 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -473,6 +475,8 @@ static int netvsc_probe(struct hv_device *dev,
pr_err("Unable to register netdev.\n"); pr_err("Unable to register netdev.\n");
rndis_filter_device_remove(dev); rndis_filter_device_remove(dev);
free_netdev(net); free_netdev(net);
} else {
schedule_delayed_work(&net_device_ctx->dwork, 0);
} }
return ret; return ret;
......
...@@ -243,6 +243,22 @@ static int rndis_filter_send_request(struct rndis_device *dev, ...@@ -243,6 +243,22 @@ static int rndis_filter_send_request(struct rndis_device *dev,
return ret; return ret;
} }
static void rndis_set_link_state(struct rndis_device *rdev,
struct rndis_request *request)
{
u32 link_status;
struct rndis_query_complete *query_complete;
query_complete = &request->response_msg.msg.query_complete;
if (query_complete->status == RNDIS_STATUS_SUCCESS &&
query_complete->info_buflen == sizeof(u32)) {
memcpy(&link_status, (void *)((unsigned long)query_complete +
query_complete->info_buf_offset), sizeof(u32));
rdev->link_state = link_status != 0;
}
}
static void rndis_filter_receive_response(struct rndis_device *dev, static void rndis_filter_receive_response(struct rndis_device *dev,
struct rndis_message *resp) struct rndis_message *resp)
{ {
...@@ -272,6 +288,10 @@ static void rndis_filter_receive_response(struct rndis_device *dev, ...@@ -272,6 +288,10 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
sizeof(struct rndis_message) + RNDIS_EXT_LEN) { sizeof(struct rndis_message) + RNDIS_EXT_LEN) {
memcpy(&request->response_msg, resp, memcpy(&request->response_msg, resp,
resp->msg_len); resp->msg_len);
if (request->request_msg.ndis_msg_type ==
RNDIS_MSG_QUERY && request->request_msg.msg.
query_req.oid == RNDIS_OID_GEN_MEDIA_CONNECT_STATUS)
rndis_set_link_state(dev, request);
} else { } else {
netdev_err(ndev, netdev_err(ndev,
"rndis response buffer overflow " "rndis response buffer overflow "
...@@ -620,7 +640,6 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev) ...@@ -620,7 +640,6 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev)
ret = rndis_filter_query_device(dev, ret = rndis_filter_query_device(dev,
RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
&link_status, &size); &link_status, &size);
dev->link_state = (link_status != 0) ? true : false;
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment