1fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen/*
2fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Copyright (c) 2009, Microsoft Corporation.
3fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
4fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is free software; you can redistribute it and/or modify it
5fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * under the terms and conditions of the GNU General Public License,
6fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * version 2, as published by the Free Software Foundation.
7fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
8fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT
9fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * more details.
12fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
13fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * You should have received a copy of the GNU General Public License along with
14fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA.
16fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
17fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Authors:
18d0e94d17ed8590d53252212414a627125825b379Haiyang Zhang *   Haiyang Zhang <haiyangz@microsoft.com>
19fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *   Hank Janssen  <hjanssen@microsoft.com>
20fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen */
21eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen
23fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/init.h>
249079ce691255792009c446d8c3382507b8d38635K. Y. Srinivasan#include <linux/atomic.h>
25fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/module.h>
26fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/highmem.h>
27fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/device.h>
28fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/io.h>
29fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/delay.h>
30fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/netdevice.h>
31fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/inetdevice.h>
32fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/etherdevice.h>
33fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/skbuff.h>
34fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <linux/in.h>
355a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
36fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <net/arp.h>
37fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <net/route.h>
38fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <net/sock.h>
39fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include <net/pkt_sched.h>
403f335ea2131b14bca2333b4316c8d4dd737e30dbK. Y. Srinivasan
415ca7252a7e2be5e05772f202d94e173b7224e7a9K. Y. Srinivasan#include "hyperv_net.h"
42fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
43fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssenstruct net_device_context {
4402fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	/* point back to our device context */
456bad88dac0e648c6978a02c6afb0dc2f4fa484bbK. Y. Srinivasan	struct hv_device *device_ctx;
46122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	struct delayed_work dwork;
47792df87228965c58c307877af00498641584bd47Wenqi Ma	struct work_struct work;
48fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen};
49fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
50fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
5199c8da0f4f4f1d14a8cd42b29dfa5625a1491662Hank Janssenstatic int ring_size = 128;
52450d7a4b7ace20fb1cbb4d87ccbccbac3f8895d0Stephen Hemmingermodule_param(ring_size, int, S_IRUGO);
53450d7a4b7ace20fb1cbb4d87ccbccbac3f8895d0Stephen HemmingerMODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
54fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
55d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhangstatic void do_set_multicast(struct work_struct *w)
56d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang{
57792df87228965c58c307877af00498641584bd47Wenqi Ma	struct net_device_context *ndevctx =
58792df87228965c58c307877af00498641584bd47Wenqi Ma		container_of(w, struct net_device_context, work);
59d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	struct netvsc_device *nvdev;
60d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	struct rndis_device *rdev;
61d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang
62d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	nvdev = hv_get_drvdata(ndevctx->device_ctx);
63792df87228965c58c307877af00498641584bd47Wenqi Ma	if (nvdev == NULL || nvdev->ndev == NULL)
64792df87228965c58c307877af00498641584bd47Wenqi Ma		return;
65d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang
66d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	rdev = nvdev->extension;
67d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	if (rdev == NULL)
68792df87228965c58c307877af00498641584bd47Wenqi Ma		return;
69d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang
70792df87228965c58c307877af00498641584bd47Wenqi Ma	if (nvdev->ndev->flags & IFF_PROMISC)
71d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang		rndis_filter_set_packet_filter(rdev,
72d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang			NDIS_PACKET_TYPE_PROMISCUOUS);
73d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang	else
74d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang		rndis_filter_set_packet_filter(rdev,
75d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang			NDIS_PACKET_TYPE_BROADCAST |
76d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang			NDIS_PACKET_TYPE_ALL_MULTICAST |
77d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang			NDIS_PACKET_TYPE_DIRECTED);
78d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang}
79d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang
804e9bfefa3c0262726607d7633cbcbec7a3f50df4Greg Kroah-Hartmanstatic void netvsc_set_multicast_list(struct net_device *net)
81fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
82792df87228965c58c307877af00498641584bd47Wenqi Ma	struct net_device_context *net_device_ctx = netdev_priv(net);
83d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71Haiyang Zhang
84792df87228965c58c307877af00498641584bd47Wenqi Ma	schedule_work(&net_device_ctx->work);
85fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
86fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
87fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssenstatic int netvsc_open(struct net_device *net)
88fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
89fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	struct net_device_context *net_device_ctx = netdev_priv(net);
906bad88dac0e648c6978a02c6afb0dc2f4fa484bbK. Y. Srinivasan	struct hv_device *device_obj = net_device_ctx->device_ctx;
9102fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	int ret = 0;
92fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
93d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang	/* Open up the device */
94d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang	ret = rndis_filter_open(device_obj);
95d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang	if (ret != 0) {
96d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang		netdev_err(net, "unable to open device (ret %d).\n", ret);
97d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang		return ret;
98fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
99fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
100d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang	netif_start_queue(net);
101d515d0ff36a7afd528f32e3511780ad8385d957eHaiyang Zhang
102fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return ret;
103fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
104fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
105fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssenstatic int netvsc_close(struct net_device *net)
106fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
107fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	struct net_device_context *net_device_ctx = netdev_priv(net);
1086bad88dac0e648c6978a02c6afb0dc2f4fa484bbK. Y. Srinivasan	struct hv_device *device_obj = net_device_ctx->device_ctx;
10902fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	int ret;
110fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
1110a282538cc1977655004cdb2eb25dd2b63f20637Haiyang Zhang	netif_tx_disable(net);
112fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
113792df87228965c58c307877af00498641584bd47Wenqi Ma	/* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
114792df87228965c58c307877af00498641584bd47Wenqi Ma	cancel_work_sync(&net_device_ctx->work);
1159c26aa0d763a8390177f50ae841148706a249793Haiyang Zhang	ret = rndis_filter_close(device_obj);
116fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	if (ret != 0)
117eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen		netdev_err(net, "unable to close device (ret %d).\n", ret);
118fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
119fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return ret;
120fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
121fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
122fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssenstatic void netvsc_xmit_completion(void *context)
123fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
1244193d4f41ca771d03d43aa9c38d70a7438e59ca7Nicolas Palix	struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
12502fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	struct sk_buff *skb = (struct sk_buff *)
12672a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		(unsigned long)packet->completion.send.send_completion_tid;
127fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
128fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	kfree(packet);
129fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
1301d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang	if (skb)
131b220f5f925b8938747bfe4a61e362d132bdd9544Stephen Hemminger		dev_kfree_skb_any(skb);
132fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
133fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
13402fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartmanstatic int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
135fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
136fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	struct net_device_context *net_device_ctx = netdev_priv(net);
1374193d4f41ca771d03d43aa9c38d70a7438e59ca7Nicolas Palix	struct hv_netvsc_packet *packet;
13802fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	int ret;
1394d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	unsigned int i, num_pages, npg_data;
140fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
141c31c151b1c4a29da4dc92212aa8648fb4f8557b9Haiyang Zhang	/* Add multipages for skb->data and additional 2 for RNDIS */
1424d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
1434d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		>> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
144c31c151b1c4a29da4dc92212aa8648fb4f8557b9Haiyang Zhang	num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;
145fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
146454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Allocate a netvsc packet based on # of frags. */
14702fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	packet = kzalloc(sizeof(struct hv_netvsc_packet) +
1486048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger			 (num_pages * sizeof(struct hv_page_buffer)) +
1491f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang			 sizeof(struct rndis_filter_packet) +
1501f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang			 NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
15102fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	if (!packet) {
152bf769375c9175b29fe72b10394888e0090c6b133Haiyang Zhang		/* out of memory, drop packet */
153eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen		netdev_err(net, "unable to allocate hv_netvsc_packet\n");
154b220f5f925b8938747bfe4a61e362d132bdd9544Stephen Hemminger
155b220f5f925b8938747bfe4a61e362d132bdd9544Stephen Hemminger		dev_kfree_skb(skb);
156b220f5f925b8938747bfe4a61e362d132bdd9544Stephen Hemminger		net->stats.tx_dropped++;
157bb6d5e76fb4fba9aa36726db41404512f3286c0fEric Dumazet		return NETDEV_TX_OK;
158fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
159fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
1601f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang	packet->vlan_tci = skb->vlan_tci;
1611f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang
16272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	packet->extension = (void *)(unsigned long)packet +
16302fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman				sizeof(struct hv_netvsc_packet) +
1646048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger				    (num_pages * sizeof(struct hv_page_buffer));
165fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
166c31c151b1c4a29da4dc92212aa8648fb4f8557b9Haiyang Zhang	/* If the rndis msg goes beyond 1 page, we will add 1 later */
167c31c151b1c4a29da4dc92212aa8648fb4f8557b9Haiyang Zhang	packet->page_buf_cnt = num_pages - 1;
168fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
169454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Initialize it from the skb */
1704d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	packet->total_data_buflen = skb->len;
171fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
1726048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger	/* Start filling in the page buffers starting after RNDIS buffer. */
173ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
174ca623ad3558f71efa08ec0fdefd79989a32a88e2Haiyang Zhang	packet->page_buf[1].offset
1756048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger		= (unsigned long)skb->data & (PAGE_SIZE - 1);
1764d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	if (npg_data == 1)
1774d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[1].len = skb_headlen(skb);
1784d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	else
1794d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[1].len = PAGE_SIZE
1804d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang			- packet->page_buf[1].offset;
1814d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
1824d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	for (i = 2; i <= npg_data; i++) {
1834d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i].pfn = virt_to_phys(skb->data
1844d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang			+ PAGE_SIZE * (i-1)) >> PAGE_SHIFT;
1854d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i].offset = 0;
1864d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i].len = PAGE_SIZE;
1874d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	}
1884d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	if (npg_data > 1)
1894d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[npg_data].len = (((unsigned long)skb->data
1904d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang			+ skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1;
1916048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger
1926048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger	/* Additional fragments are after SKB data */
1936048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1949e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet		const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
1956048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger
1964d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i+npg_data+1].pfn =
1974d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang			page_to_pfn(skb_frag_page(f));
1984d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i+npg_data+1].offset = f->page_offset;
1994d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		packet->page_buf[i+npg_data+1].len = skb_frag_size(f);
200fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
201fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
202454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Set the completion routine */
20372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	packet->completion.send.send_completion = netvsc_xmit_completion;
20472a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	packet->completion.send.send_completion_ctx = packet;
20572a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	packet->completion.send.send_completion_tid = (unsigned long)skb;
206fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
20755acb696a8d43ff37cc5e30837bd8e635aff2ba9K. Y. Srinivasan	ret = rndis_filter_send(net_device_ctx->device_ctx,
20802fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman				  packet);
20902fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	if (ret == 0) {
210b852fdcefc782b6751f96a8ea09471efd844b6bfStephen Hemminger		net->stats.tx_bytes += skb->len;
211b852fdcefc782b6751f96a8ea09471efd844b6bfStephen Hemminger		net->stats.tx_packets++;
212b220f5f925b8938747bfe4a61e362d132bdd9544Stephen Hemminger	} else {
2138a5f9edc4dd6c1f9fb2446a36e7cd44b79412271Haiyang Zhang		kfree(packet);
214fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
215fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
216da24e906cbfc08171d24a2b7cf66fad565fdd121Haiyang Zhang	return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
217fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
218fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2193e18951955797872558dad615851a4ca63b2770eHank Janssen/*
22002fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman * netvsc_linkstatus_callback - Link up/down notification
22102fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman */
22290ef117a30b64dd37b735bfbacbc5ae014a9f74fK. Y. Srinivasanvoid netvsc_linkstatus_callback(struct hv_device *device_obj,
22302fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman				       unsigned int status)
224fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
2252ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *net;
226c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang	struct net_device_context *ndev_ctx;
2272ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct netvsc_device *net_device;
2282ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan
2292ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(device_obj);
2302ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net = net_device->ndev;
231fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
23202fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	if (!net) {
233eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen		netdev_err(net, "got link status but net device "
234eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen				"not initialized yet\n");
235fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
236fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
237fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
23802fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	if (status == 1) {
239fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		netif_carrier_on(net);
240fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		netif_wake_queue(net);
241c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang		ndev_ctx = netdev_priv(net);
242c4b6a2eaf1c14810a4803d658f68614365978738Haiyang Zhang		schedule_delayed_work(&ndev_ctx->dwork, 0);
243122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
24402fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	} else {
245fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		netif_carrier_off(net);
2460a282538cc1977655004cdb2eb25dd2b63f20637Haiyang Zhang		netif_tx_disable(net);
247fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
248fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
249fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2503e18951955797872558dad615851a4ca63b2770eHank Janssen/*
2513e18951955797872558dad615851a4ca63b2770eHank Janssen * netvsc_recv_callback -  Callback when we receive a packet from the
2523e18951955797872558dad615851a4ca63b2770eHank Janssen * "wire" on the specified device.
25302fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman */
254f79adf8f135a6dead5967a7266bd894e8f293529K. Y. Srinivasanint netvsc_recv_callback(struct hv_device *device_obj,
25502fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman				struct hv_netvsc_packet *packet)
256fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
2576f4c44460750dd4eb9926a58ab1ad0ceacef8284Haiyang Zhang	struct net_device *net;
258fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	struct sk_buff *skb;
259fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2606f4c44460750dd4eb9926a58ab1ad0ceacef8284Haiyang Zhang	net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
26102fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	if (!net) {
262eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen		netdev_err(net, "got receive callback but net device"
263eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen			" not initialized yet\n");
264fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return 0;
265fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
266fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2679495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	/* Allocate a skb - TODO direct I/O to pages? */
26872a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
2699495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	if (unlikely(!skb)) {
2709495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger		++net->stats.rx_dropped;
2719495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger		return 0;
2729495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	}
273fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
27402fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	/*
27502fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	 * Copy to skb. This copy is needed here since the memory pointed by
27602fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	 * hv_netvsc_packet cannot be deallocated
27702fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	 */
278453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang	memcpy(skb_put(skb, packet->total_data_buflen), packet->data,
279453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang		packet->total_data_buflen);
280fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
281fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	skb->protocol = eth_type_trans(skb, net);
282fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	skb->ip_summed = CHECKSUM_NONE;
2831f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang	skb->vlan_tci = packet->vlan_tci;
284fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2859495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	net->stats.rx_packets++;
28648c3883999cb06246911e29356d194f96f1c75efWei Yongjun	net->stats.rx_bytes += packet->total_data_buflen;
2879495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger
28802fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	/*
28902fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	 * Pass the skb back up. Network stack will deallocate the skb when it
2909495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	 * is done.
2919495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	 * TODO - use NAPI?
29202fafbc619a57dd4b850ed6af47a40bbb8e1eae8Greg Kroah-Hartman	 */
2939495c282baf53ec7bfffcb9dd9f40cb10d4240e0Stephen Hemminger	netif_rx(skb);
294fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
295fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return 0;
296fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
297fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
298f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemmingerstatic void netvsc_get_drvinfo(struct net_device *net,
299f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger			       struct ethtool_drvinfo *info)
300f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger{
301d31b20fcc89efa8c5d3f5ea2720e08a286b69a36Haiyang Zhang	strcpy(info->driver, KBUILD_MODNAME);
302f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger	strcpy(info->version, HV_DRV_VERSION);
303f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger	strcpy(info->fw_version, "N/A");
304f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger}
305f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger
3064d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhangstatic int netvsc_change_mtu(struct net_device *ndev, int mtu)
3074d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang{
3084d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	struct net_device_context *ndevctx = netdev_priv(ndev);
3094d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	struct hv_device *hdev =  ndevctx->device_ctx;
3104d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
3114d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	struct netvsc_device_info device_info;
3124d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	int limit = ETH_DATA_LEN;
3134d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3144d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	if (nvdev == NULL || nvdev->destroy)
3154d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		return -ENODEV;
3164d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3174d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
3184d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		limit = NETVSC_MTU;
3194d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3204d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	if (mtu < 68 || mtu > limit)
3214d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		return -EINVAL;
3224d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3234d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	nvdev->start_remove = true;
3244d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	cancel_delayed_work_sync(&ndevctx->dwork);
325792df87228965c58c307877af00498641584bd47Wenqi Ma	cancel_work_sync(&ndevctx->work);
3260a282538cc1977655004cdb2eb25dd2b63f20637Haiyang Zhang	netif_tx_disable(ndev);
3274d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	rndis_filter_device_remove(hdev);
3284d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3294d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	ndev->mtu = mtu;
3304d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3314d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	ndevctx->device_ctx = hdev;
3324d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	hv_set_drvdata(hdev, ndev);
3334d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	device_info.ring_size = ring_size;
3344d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	rndis_filter_device_add(hdev, &device_info);
3354d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	netif_wake_queue(ndev);
3364d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
3374d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	return 0;
3384d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang}
3394d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
340f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemmingerstatic const struct ethtool_ops ethtool_ops = {
341f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger	.get_drvinfo	= netvsc_get_drvinfo,
342f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger	.get_link	= ethtool_op_get_link,
343f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger};
344f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger
345df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartmanstatic const struct net_device_ops device_ops = {
346df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	.ndo_open =			netvsc_open,
347df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	.ndo_stop =			netvsc_close,
348df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	.ndo_start_xmit =		netvsc_start_xmit,
349afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode =		netvsc_set_multicast_list,
3504d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	.ndo_change_mtu =		netvsc_change_mtu,
351b681b5886bb5d1f5b6750a0ed7c62846da7ccea4Haiyang Zhang	.ndo_validate_addr =		eth_validate_addr,
352b681b5886bb5d1f5b6750a0ed7c62846da7ccea4Haiyang Zhang	.ndo_set_mac_address =		eth_mac_addr,
353df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman};
354df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
355c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang/*
356c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang * Send GARP packet to network peers after migrations.
357c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang * After Quick Migration, the network is not immediately operational in the
358c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
359122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang * another netif_notify_peers() into a delayed work, otherwise GARP packet
360c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang * will not be sent after quick migration, and cause network disconnection.
361c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang */
362c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhangstatic void netvsc_send_garp(struct work_struct *w)
363c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang{
364c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang	struct net_device_context *ndev_ctx;
365c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang	struct net_device *net;
3662ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct netvsc_device *net_device;
367c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang
368122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	ndev_ctx = container_of(w, struct net_device_context, dwork.work);
3692ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(ndev_ctx->device_ctx);
3702ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net = net_device->ndev;
371c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang	netif_notify_peers(net);
372c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang}
373c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang
374c996edcf1c451b81740abbcca5257ed7e353fcc6Haiyang Zhang
37584946899bd50035c50d88da9da809aa25de60471K. Y. Srinivasanstatic int netvsc_probe(struct hv_device *dev,
37684946899bd50035c50d88da9da809aa25de60471K. Y. Srinivasan			const struct hv_vmbus_device_id *dev_id)
377df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman{
378df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	struct net_device *net = NULL;
379df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	struct net_device_context *net_device_ctx;
380df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	struct netvsc_device_info device_info;
381df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	int ret;
382df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
383546d9e101e7a71e6202f47a13ddcd9b8fb05a52eStephen Hemminger	net = alloc_etherdev(sizeof(struct net_device_context));
384df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	if (!net)
38551a805d0ce0f78810fd90d4e9eafd8a0ab4bdb58K. Y. Srinivasan		return -ENOMEM;
386df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
387df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	/* Set initial state */
388df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	netif_carrier_off(net);
389df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
390df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	net_device_ctx = netdev_priv(net);
3919efd21e1f53359e2f4e53ba87002c69a7908142bK. Y. Srinivasan	net_device_ctx->device_ctx = dev;
3922ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	hv_set_drvdata(dev, net);
393122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
394792df87228965c58c307877af00498641584bd47Wenqi Ma	INIT_WORK(&net_device_ctx->work, do_set_multicast);
395df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
396df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	net->netdev_ops = &device_ops;
397df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
3986048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger	/* TODO: Add GSO and Checksum offload */
399877a344b28b51b695d6baaeecb15d0eb6c90daefMichał Mirosław	net->hw_features = NETIF_F_SG;
4001f5f3a75e216fe771b8d6805e0bb2f43595a6ee1Haiyang Zhang	net->features = NETIF_F_SG | NETIF_F_HW_VLAN_TX;
4016048718d719f460abba8eaff1c0122247b2c3d91Stephen Hemminger
402f82f4ad7bf9dc3c7268080cc2afdff897e1d72caStephen Hemminger	SET_ETHTOOL_OPS(net, &ethtool_ops);
4039efd21e1f53359e2f4e53ba87002c69a7908142bK. Y. Srinivasan	SET_NETDEV_DEV(net, &dev->device);
404df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
405df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	ret = register_netdev(net);
406df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	if (ret != 0) {
407692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang		pr_err("Unable to register netdev.\n");
408df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman		free_netdev(net);
409692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang		goto out;
410df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	}
411df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
412692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	/* Notify the netvsc driver of the new device */
413692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	device_info.ring_size = ring_size;
414692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	ret = rndis_filter_device_add(dev, &device_info);
415692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	if (ret != 0) {
416692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang		netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
417692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang		unregister_netdev(net);
418df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman		free_netdev(net);
4192ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan		hv_set_drvdata(dev, NULL);
420692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang		return ret;
421df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	}
422692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
423692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang
424692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhang	netif_carrier_on(net);
425df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
426692e084e773b76c30a3e5d823db131ed1a15924aHaiyang Zhangout:
427df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	return ret;
428df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman}
429df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
430415b023ab8d6dfb88f106163a7f202a8665fb20aK. Y. Srinivasanstatic int netvsc_remove(struct hv_device *dev)
431df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman{
4322ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *net;
433122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	struct net_device_context *ndev_ctx;
4342ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct netvsc_device *net_device;
4352ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan
4362ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(dev);
4372ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net = net_device->ndev;
438df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
439df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	if (net == NULL) {
440415b023ab8d6dfb88f106163a7f202a8665fb20aK. Y. Srinivasan		dev_err(&dev->device, "No net device to remove\n");
441df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman		return 0;
442df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	}
443df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
4444d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	net_device->start_remove = true;
4454d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang
446122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	ndev_ctx = netdev_priv(net);
447122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang	cancel_delayed_work_sync(&ndev_ctx->dwork);
448792df87228965c58c307877af00498641584bd47Wenqi Ma	cancel_work_sync(&ndev_ctx->work);
449122a5f6410f49c28e901e4a911a110b675b8bd55Haiyang Zhang
450df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	/* Stop outbound asap */
4510a282538cc1977655004cdb2eb25dd2b63f20637Haiyang Zhang	netif_tx_disable(net);
452df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
453df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	unregister_netdev(net);
454df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
455df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	/*
456df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	 * Call to the vsc driver to let it know that the device is being
457df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	 * removed
458df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	 */
459df06bcff819555bf9aca38b2f8263920836fe851Haiyang Zhang	rndis_filter_device_remove(dev);
460df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
461df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman	free_netdev(net);
462df06bcff819555bf9aca38b2f8263920836fe851Haiyang Zhang	return 0;
463df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman}
464df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
465345c4cc3b953a43464776701918e22c7e30cedd0K. Y. Srinivasanstatic const struct hv_vmbus_device_id id_table[] = {
466c45cf2d4976e2fcde68d88898a37af70f2caaf5dGreg Kroah-Hartman	/* Network guid */
467c45cf2d4976e2fcde68d88898a37af70f2caaf5dGreg Kroah-Hartman	{ VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
468c45cf2d4976e2fcde68d88898a37af70f2caaf5dGreg Kroah-Hartman		       0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) },
469c45cf2d4976e2fcde68d88898a37af70f2caaf5dGreg Kroah-Hartman	{ },
470345c4cc3b953a43464776701918e22c7e30cedd0K. Y. Srinivasan};
471345c4cc3b953a43464776701918e22c7e30cedd0K. Y. Srinivasan
472345c4cc3b953a43464776701918e22c7e30cedd0K. Y. SrinivasanMODULE_DEVICE_TABLE(vmbus, id_table);
473345c4cc3b953a43464776701918e22c7e30cedd0K. Y. Srinivasan
474f1542a6605ea657b1e20aefc08e1d8859c1703dbK. Y. Srinivasan/* The one and only one */
475fde0ef9b235d8cb141e3aa35fdc7e9889e3a4cb3K. Y. Srinivasanstatic struct  hv_driver netvsc_drv = {
476d31b20fcc89efa8c5d3f5ea2720e08a286b69a36Haiyang Zhang	.name = KBUILD_MODNAME,
477345c4cc3b953a43464776701918e22c7e30cedd0K. Y. Srinivasan	.id_table = id_table,
478fde0ef9b235d8cb141e3aa35fdc7e9889e3a4cb3K. Y. Srinivasan	.probe = netvsc_probe,
479fde0ef9b235d8cb141e3aa35fdc7e9889e3a4cb3K. Y. Srinivasan	.remove = netvsc_remove,
480d48909703054bc5759dea5859b00325b3871210aK. Y. Srinivasan};
481f1542a6605ea657b1e20aefc08e1d8859c1703dbK. Y. Srinivasan
482a9869c94251a7a1c9bb369baa0e7917b9d315b37K. Y. Srinivasanstatic void __exit netvsc_drv_exit(void)
483fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
484768fa21919b7f30b77f0b3ba94939f5556d111d5Greg Kroah-Hartman	vmbus_driver_unregister(&netvsc_drv);
485fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
486fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4871fde28cffb6953487e0ab96a4123f4443d499364K. Y. Srinivasanstatic int __init netvsc_drv_init(void)
488df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman{
489768fa21919b7f30b77f0b3ba94939f5556d111d5Greg Kroah-Hartman	return vmbus_driver_register(&netvsc_drv);
490df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman}
491df2fff28ec9e120d458e56e210557c6a1416e819Greg Kroah-Hartman
49226c14cc119204adc218259251919c5198d07dafeHank JanssenMODULE_LICENSE("GPL");
49326c14cc119204adc218259251919c5198d07dafeHank JanssenMODULE_VERSION(HV_DRV_VERSION);
4947880fc54c985b4fbc0fab77f81b7f09610194e1cStephen HemmingerMODULE_DESCRIPTION("Microsoft Hyper-V network driver");
495fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4961fde28cffb6953487e0ab96a4123f4443d499364K. Y. Srinivasanmodule_init(netvsc_drv_init);
497a9869c94251a7a1c9bb369baa0e7917b9d315b37K. Y. Srinivasanmodule_exit(netvsc_drv_exit);
498