From 3a494e710367c0a233d86bcde9853781859fc008 Mon Sep 17 00:00:00 2001 From: Haiyang Zhang Date: Thu, 19 Jun 2014 18:34:36 -0700 Subject: 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 Reviewed-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'drivers/net/hyperv/netvsc_drv.c') diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 4fd71b75e666..9b27ca8c1d39 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -579,8 +579,9 @@ drop: * 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); } -- cgit v1.2.3 From 316158feff0078b266d6e423adb016d12eb96a5a Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 9 Jul 2014 16:23:59 +0200 Subject: hyperv: Add netpoll support In order to have at least a netconsole to debug kernel issues on Windows Azure this patch implements netpoll support. Sending packets is easy, netvsc_start_xmit() does already everything needed. Signed-off-by: Richard Weinberger Acked-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/hyperv/netvsc_drv.c') diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 9b27ca8c1d39..a9c5eaadc426 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -749,6 +749,14 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p) return err; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void netvsc_poll_controller(struct net_device *net) +{ + /* As netvsc_start_xmit() works synchronous we don't have to + * trigger anything here. + */ +} +#endif static const struct ethtool_ops ethtool_ops = { .get_drvinfo = netvsc_get_drvinfo, @@ -764,6 +772,9 @@ static const struct net_device_ops device_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = netvsc_set_mac_addr, .ndo_select_queue = netvsc_select_queue, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = netvsc_poll_controller, +#endif }; /* -- cgit v1.2.3 From dedb845ded56ded1c62f5398a94ffa8615d4592d Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Sun, 28 Sep 2014 22:16:43 -0700 Subject: hyperv: Fix a bug in netvsc_start_xmit() After the packet is successfully sent, we should not touch the skb as it may have been freed. This patch is based on the work done by Long Li . In this version of the patch I have fixed issues pointed out by David. David, please queue this up for stable. Signed-off-by: K. Y. Srinivasan Tested-by: Long Li Tested-by: Sitsofe Wheeler Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/hyperv/netvsc_drv.c') diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index a9c5eaadc426..0fcb5e7eb073 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -387,6 +387,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) int hdr_offset; u32 net_trans_info; u32 hash; + u32 skb_length = skb->len; /* We will atmost need two pages to describe the rndis @@ -562,7 +563,7 @@ do_send: drop: if (ret == 0) { - net->stats.tx_bytes += skb->len; + net->stats.tx_bytes += skb_length; net->stats.tx_packets++; } else { kfree(packet); -- cgit v1.2.3