hyperv: Add handler for RNDIS_STATUS_NETWORK_CHANGE event
The RNDIS_STATUS_NETWORK_CHANGE event is received after the Hyper-V host sleep or hibernation. We refresh network at this time. MS-TFS: 135162 Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> Reviewed-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
e0f802fbca
Коммит
3a494e7103
|
@ -170,6 +170,7 @@ struct rndis_device {
|
||||||
|
|
||||||
enum rndis_device_state state;
|
enum rndis_device_state state;
|
||||||
bool link_state;
|
bool link_state;
|
||||||
|
bool link_change;
|
||||||
atomic_t new_req_id;
|
atomic_t new_req_id;
|
||||||
|
|
||||||
spinlock_t request_lock;
|
spinlock_t request_lock;
|
||||||
|
@ -185,7 +186,7 @@ int netvsc_device_remove(struct hv_device *device);
|
||||||
int netvsc_send(struct hv_device *device,
|
int netvsc_send(struct hv_device *device,
|
||||||
struct hv_netvsc_packet *packet);
|
struct hv_netvsc_packet *packet);
|
||||||
void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||||
unsigned int status);
|
struct rndis_message *resp);
|
||||||
int netvsc_recv_callback(struct hv_device *device_obj,
|
int netvsc_recv_callback(struct hv_device *device_obj,
|
||||||
struct hv_netvsc_packet *packet,
|
struct hv_netvsc_packet *packet,
|
||||||
struct ndis_tcp_ip_checksum_info *csum_info);
|
struct ndis_tcp_ip_checksum_info *csum_info);
|
||||||
|
|
|
@ -579,8 +579,9 @@ drop:
|
||||||
* netvsc_linkstatus_callback - Link up/down notification
|
* netvsc_linkstatus_callback - Link up/down notification
|
||||||
*/
|
*/
|
||||||
void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||||
unsigned int status)
|
struct rndis_message *resp)
|
||||||
{
|
{
|
||||||
|
struct rndis_indicate_status *indicate = &resp->msg.indicate_status;
|
||||||
struct net_device *net;
|
struct net_device *net;
|
||||||
struct net_device_context *ndev_ctx;
|
struct net_device_context *ndev_ctx;
|
||||||
struct netvsc_device *net_device;
|
struct netvsc_device *net_device;
|
||||||
|
@ -589,7 +590,19 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||||
net_device = hv_get_drvdata(device_obj);
|
net_device = hv_get_drvdata(device_obj);
|
||||||
rdev = net_device->extension;
|
rdev = net_device->extension;
|
||||||
|
|
||||||
rdev->link_state = status != 1;
|
switch (indicate->status) {
|
||||||
|
case RNDIS_STATUS_MEDIA_CONNECT:
|
||||||
|
rdev->link_state = false;
|
||||||
|
break;
|
||||||
|
case RNDIS_STATUS_MEDIA_DISCONNECT:
|
||||||
|
rdev->link_state = true;
|
||||||
|
break;
|
||||||
|
case RNDIS_STATUS_NETWORK_CHANGE:
|
||||||
|
rdev->link_change = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
net = net_device->ndev;
|
net = net_device->ndev;
|
||||||
|
|
||||||
|
@ -597,7 +610,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ndev_ctx = netdev_priv(net);
|
ndev_ctx = netdev_priv(net);
|
||||||
if (status == 1) {
|
if (!rdev->link_state) {
|
||||||
schedule_delayed_work(&ndev_ctx->dwork, 0);
|
schedule_delayed_work(&ndev_ctx->dwork, 0);
|
||||||
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
|
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
|
||||||
} else {
|
} else {
|
||||||
|
@ -767,7 +780,9 @@ static void netvsc_link_change(struct work_struct *w)
|
||||||
struct net_device *net;
|
struct net_device *net;
|
||||||
struct netvsc_device *net_device;
|
struct netvsc_device *net_device;
|
||||||
struct rndis_device *rdev;
|
struct rndis_device *rdev;
|
||||||
bool notify;
|
bool notify, refresh = false;
|
||||||
|
char *argv[] = { "/etc/init.d/network", "restart", NULL };
|
||||||
|
char *envp[] = { "HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
|
||||||
|
@ -782,10 +797,17 @@ static void netvsc_link_change(struct work_struct *w)
|
||||||
} else {
|
} else {
|
||||||
netif_carrier_on(net);
|
netif_carrier_on(net);
|
||||||
notify = true;
|
notify = true;
|
||||||
|
if (rdev->link_change) {
|
||||||
|
rdev->link_change = false;
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
|
if (refresh)
|
||||||
|
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
netdev_notify_peers(net);
|
netdev_notify_peers(net);
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,25 +320,6 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
|
|
||||||
struct rndis_message *resp)
|
|
||||||
{
|
|
||||||
struct rndis_indicate_status *indicate =
|
|
||||||
&resp->msg.indicate_status;
|
|
||||||
|
|
||||||
if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
|
|
||||||
netvsc_linkstatus_callback(
|
|
||||||
dev->net_dev->dev, 1);
|
|
||||||
} else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
|
|
||||||
netvsc_linkstatus_callback(
|
|
||||||
dev->net_dev->dev, 0);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* TODO:
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the Per-Packet-Info with the specified type
|
* Get the Per-Packet-Info with the specified type
|
||||||
* return NULL if not found.
|
* return NULL if not found.
|
||||||
|
@ -464,7 +445,7 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||||
|
|
||||||
case RNDIS_MSG_INDICATE:
|
case RNDIS_MSG_INDICATE:
|
||||||
/* notification msgs */
|
/* notification msgs */
|
||||||
rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
|
netvsc_linkstatus_callback(dev, rndis_msg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
netdev_err(ndev,
|
netdev_err(ndev,
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012
|
#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012
|
||||||
#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION
|
#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION
|
||||||
#define RNDIS_STATUS_LINK_SPEED_CHANGE 0x40010013L
|
#define RNDIS_STATUS_LINK_SPEED_CHANGE 0x40010013L
|
||||||
|
#define RNDIS_STATUS_NETWORK_CHANGE 0x40010018
|
||||||
|
|
||||||
#define RNDIS_STATUS_NOT_RESETTABLE 0x80010001
|
#define RNDIS_STATUS_NOT_RESETTABLE 0x80010001
|
||||||
#define RNDIS_STATUS_SOFT_ERRORS 0x80010003
|
#define RNDIS_STATUS_SOFT_ERRORS 0x80010003
|
||||||
|
|
Загрузка…
Ссылка в новой задаче