Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a494e71 authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller
Browse files

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: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0f802fb
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ struct rndis_device {

	enum rndis_device_state state;
	bool link_state;
	bool link_change;
	atomic_t new_req_id;

	spinlock_t request_lock;
@@ -185,7 +186,7 @@ int netvsc_device_remove(struct hv_device *device);
int netvsc_send(struct hv_device *device,
		struct hv_netvsc_packet *packet);
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,
			struct hv_netvsc_packet *packet,
			struct ndis_tcp_ip_checksum_info *csum_info);
+26 −4
Original line number Diff line number Diff line
@@ -579,8 +579,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 * netvsc_linkstatus_callback - Link up/down notification
 */
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_context *ndev_ctx;
	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);
	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;

@@ -597,7 +610,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
		return;

	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, msecs_to_jiffies(20));
	} else {
@@ -767,7 +780,9 @@ static void netvsc_link_change(struct work_struct *w)
	struct net_device *net;
	struct netvsc_device *net_device;
	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();

@@ -782,10 +797,17 @@ static void netvsc_link_change(struct work_struct *w)
	} else {
		netif_carrier_on(net);
		notify = true;
		if (rdev->link_change) {
			rdev->link_change = false;
			refresh = true;
		}
	}

	rtnl_unlock();

	if (refresh)
		call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);

	if (notify)
		netdev_notify_peers(net);
}
+1 −20
Original line number Diff line number Diff line
@@ -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
 * return NULL if not found.
@@ -464,7 +445,7 @@ int rndis_filter_receive(struct hv_device *dev,

	case RNDIS_MSG_INDICATE:
		/* notification msgs */
		rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
		netvsc_linkstatus_callback(dev, rndis_msg);
		break;
	default:
		netdev_err(ndev,
+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@
#define	RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION	0x40010012
#define RNDIS_STATUS_WW_INDICATION		RDIA_SPECIFIC_INDICATION
#define RNDIS_STATUS_LINK_SPEED_CHANGE		0x40010013L
#define RNDIS_STATUS_NETWORK_CHANGE		0x40010018

#define RNDIS_STATUS_NOT_RESETTABLE		0x80010001
#define RNDIS_STATUS_SOFT_ERRORS		0x80010003