Staging: hv: coding style cleanup of include/HvVpApi.h
[linux-2.6-block.git] / drivers / staging / hv / netvsc_drv.c
CommitLineData
fceaf24a
HJ
1/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Hank Janssen <hjanssen@microsoft.com>
20 *
21 */
22
fceaf24a
HJ
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/highmem.h>
26#include <linux/device.h>
fceaf24a 27#include <linux/io.h>
fceaf24a
HJ
28#include <linux/delay.h>
29#include <linux/netdevice.h>
30#include <linux/inetdevice.h>
31#include <linux/etherdevice.h>
32#include <linux/skbuff.h>
33#include <linux/in.h>
34#include <net/arp.h>
35#include <net/route.h>
36#include <net/sock.h>
37#include <net/pkt_sched.h>
38
4983b39a 39#include "osd.h"
c86f3e2a
GKH
40#include "include/logging.h"
41#include "include/vmbus.h"
fceaf24a 42
c86f3e2a 43#include "include/NetVscApi.h"
fceaf24a
HJ
44
45MODULE_LICENSE("GPL");
46
454f18a9
BP
47
48/* Static decl */
49
fceaf24a
HJ
50static int netvsc_probe(struct device *device);
51static int netvsc_remove(struct device *device);
52static int netvsc_open(struct net_device *net);
53static void netvsc_xmit_completion(void *context);
54static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net);
4193d4f4 55static int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *Packet);
fceaf24a
HJ
56static int netvsc_close(struct net_device *net);
57static struct net_device_stats *netvsc_get_stats(struct net_device *net);
3d3b5518 58static void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status);
fceaf24a 59
454f18a9
BP
60
61/* Data types */
62
fceaf24a 63struct net_device_context {
454f18a9 64 struct device_context *device_ctx; /* point back to our device context */
fceaf24a
HJ
65 struct net_device_stats stats;
66};
67
68struct netvsc_driver_context {
454f18a9 69 /* !! These must be the first 2 fields !! */
fceaf24a
HJ
70 struct driver_context drv_ctx;
71 NETVSC_DRIVER_OBJECT drv_obj;
72};
73
454f18a9
BP
74
75/* Globals */
76
fceaf24a
HJ
77
78static int netvsc_ringbuffer_size = NETVSC_DEVICE_RING_BUFFER_SIZE;
79
454f18a9 80/* The one and only one */
fceaf24a
HJ
81static struct netvsc_driver_context g_netvsc_drv;
82
454f18a9
BP
83
84/* Routines */
85
fceaf24a
HJ
86
87/*++
88
89Name: netvsc_drv_init()
90
91Desc: NetVsc driver initialization
92
93--*/
bd1de709 94static int netvsc_drv_init(PFN_DRIVERINITIALIZE pfn_drv_init)
fceaf24a
HJ
95{
96 int ret=0;
97 NETVSC_DRIVER_OBJECT *net_drv_obj=&g_netvsc_drv.drv_obj;
98 struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
99
100 DPRINT_ENTER(NETVSC_DRV);
101
102 vmbus_get_interface(&net_drv_obj->Base.VmbusChannelInterface);
103
104 net_drv_obj->RingBufferSize = netvsc_ringbuffer_size;
105 net_drv_obj->OnReceiveCallback = netvsc_recv_callback;
106 net_drv_obj->OnLinkStatusChanged = netvsc_linkstatus_callback;
107
454f18a9 108 /* Callback to client driver to complete the initialization */
fceaf24a
HJ
109 pfn_drv_init(&net_drv_obj->Base);
110
111 drv_ctx->driver.name = net_drv_obj->Base.name;
caf26a31 112 memcpy(&drv_ctx->class_id, &net_drv_obj->Base.deviceType, sizeof(struct hv_guid));
fceaf24a 113
fceaf24a
HJ
114 drv_ctx->probe = netvsc_probe;
115 drv_ctx->remove = netvsc_remove;
fceaf24a 116
454f18a9 117 /* The driver belongs to vmbus */
5d48a1c2 118 ret = vmbus_child_driver_register(drv_ctx);
fceaf24a
HJ
119
120 DPRINT_EXIT(NETVSC_DRV);
121
122 return ret;
123}
124
125/*++
126
127Name: netvsc_get_stats()
128
129Desc: Get the network stats
130
131--*/
132static struct net_device_stats *netvsc_get_stats(struct net_device *net)
133{
134 struct net_device_context *net_device_ctx = netdev_priv(net);
135
136 return &net_device_ctx->stats;
137}
138
139/*++
140
141Name: netvsc_set_multicast_list()
142
143Desc: Set the multicast list
144
145Remark: No-op here
146--*/
4e9bfefa 147static void netvsc_set_multicast_list(struct net_device *net)
fceaf24a
HJ
148{
149}
150
151
c86f3e2a
GKH
152static const struct net_device_ops device_ops = {
153 .ndo_open = netvsc_open,
154 .ndo_stop = netvsc_close,
155 .ndo_start_xmit = netvsc_start_xmit,
156 .ndo_get_stats = netvsc_get_stats,
157 .ndo_set_multicast_list = netvsc_set_multicast_list,
158};
159
fceaf24a
HJ
160/*++
161
162Name: netvsc_probe()
163
164Desc: Add the specified new device to this driver
165
166--*/
167static int netvsc_probe(struct device *device)
168{
169 int ret=0;
170
171 struct driver_context *driver_ctx = driver_to_driver_context(device->driver);
172 struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
173 NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
174
175 struct device_context *device_ctx = device_to_device_context(device);
3d3b5518 176 struct hv_device *device_obj = &device_ctx->device_obj;
fceaf24a
HJ
177
178 struct net_device *net = NULL;
179 struct net_device_context *net_device_ctx;
180 NETVSC_DEVICE_INFO device_info;
181
182 DPRINT_ENTER(NETVSC_DRV);
183
184 if (!net_drv_obj->Base.OnDeviceAdd)
185 {
186 return -1;
187 }
188
189 net = alloc_netdev(sizeof(struct net_device_context), "seth%d", ether_setup);
454f18a9 190 /* net = alloc_etherdev(sizeof(struct net_device_context)); */
fceaf24a
HJ
191 if (!net)
192 {
193 return -1;
194 }
195
454f18a9 196 /* Set initial state */
fceaf24a
HJ
197 netif_carrier_off(net);
198 netif_stop_queue(net);
199
200 net_device_ctx = netdev_priv(net);
201 net_device_ctx->device_ctx = device_ctx;
621d7fb7 202 dev_set_drvdata(device, net);
fceaf24a 203
454f18a9 204 /* Notify the netvsc driver of the new device */
fceaf24a
HJ
205 ret = net_drv_obj->Base.OnDeviceAdd(device_obj, (void*)&device_info);
206 if (ret != 0)
207 {
208 free_netdev(net);
621d7fb7 209 dev_set_drvdata(device, NULL);
fceaf24a
HJ
210
211 DPRINT_ERR(NETVSC_DRV, "unable to add netvsc device (ret %d)", ret);
212 return ret;
213 }
214
454f18a9
BP
215 /* If carrier is still off ie we did not get a link status callback, update it if necessary */
216 /* FIXME: We should use a atomic or test/set instead to avoid getting out of sync with the device's link status */
fceaf24a
HJ
217 if (!netif_carrier_ok(net))
218 {
219 if (!device_info.LinkState)
220 {
221 netif_carrier_on(net);
222 }
223 }
224
225 memcpy(net->dev_addr, device_info.MacAddr, ETH_ALEN);
226
c86f3e2a 227 net->netdev_ops = &device_ops;
fceaf24a 228
fceaf24a
HJ
229 SET_NETDEV_DEV(net, device);
230
231 ret = register_netdev(net);
232 if (ret != 0)
233 {
454f18a9 234 /* Remove the device and release the resource */
fceaf24a
HJ
235 net_drv_obj->Base.OnDeviceRemove(device_obj);
236 free_netdev(net);
237 }
238
239 DPRINT_EXIT(NETVSC_DRV);
240
241 return ret;
242}
243
244static int netvsc_remove(struct device *device)
245{
246 int ret=0;
247 struct driver_context *driver_ctx = driver_to_driver_context(device->driver);
248 struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
249 NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
250
251 struct device_context *device_ctx = device_to_device_context(device);
621d7fb7 252 struct net_device *net = dev_get_drvdata(&device_ctx->device);
3d3b5518 253 struct hv_device *device_obj = &device_ctx->device_obj;
fceaf24a
HJ
254
255 DPRINT_ENTER(NETVSC_DRV);
256
257 if (net == NULL)
258 {
259 DPRINT_INFO(NETVSC, "no net device to remove");
260 DPRINT_EXIT(NETVSC_DRV);
261 return 0;
262 }
263
264 if (!net_drv_obj->Base.OnDeviceRemove)
265 {
266 DPRINT_EXIT(NETVSC_DRV);
267 return -1;
268 }
269
454f18a9 270 /* Stop outbound asap */
fceaf24a 271 netif_stop_queue(net);
454f18a9 272 /* netif_carrier_off(net); */
fceaf24a
HJ
273
274 unregister_netdev(net);
275
454f18a9 276 /* Call to the vsc driver to let it know that the device is being removed */
fceaf24a
HJ
277 ret = net_drv_obj->Base.OnDeviceRemove(device_obj);
278 if (ret != 0)
279 {
454f18a9 280 /* TODO: */
fceaf24a
HJ
281 DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
282 }
283
284 free_netdev(net);
285
286 DPRINT_EXIT(NETVSC_DRV);
287
288 return ret;
289}
290
291/*++
292
293Name: netvsc_open()
294
295Desc: Open the specified interface device
296
297--*/
298static int netvsc_open(struct net_device *net)
299{
300 int ret=0;
301 struct net_device_context *net_device_ctx = netdev_priv(net);
302 struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
303 struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
304 NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
305
3d3b5518 306 struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
fceaf24a
HJ
307
308 DPRINT_ENTER(NETVSC_DRV);
309
310 if (netif_carrier_ok(net))
311 {
312 memset(&net_device_ctx->stats, 0 , sizeof(struct net_device_stats));
313
454f18a9 314 /* Open up the device */
fceaf24a
HJ
315 ret = net_drv_obj->OnOpen(device_obj);
316 if (ret != 0)
317 {
318 DPRINT_ERR(NETVSC_DRV, "unable to open device (ret %d).", ret);
319 return ret;
320 }
321
322 netif_start_queue(net);
323 }
324 else
325 {
326 DPRINT_ERR(NETVSC_DRV, "unable to open device...link is down.");
327 }
328
329 DPRINT_EXIT(NETVSC_DRV);
330 return ret;
331}
332
333/*++
334
335Name: netvsc_close()
336
337Desc: Close the specified interface device
338
339--*/
340static int netvsc_close(struct net_device *net)
341{
342 int ret=0;
343 struct net_device_context *net_device_ctx = netdev_priv(net);
344 struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
345 struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
346 NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
347
3d3b5518 348 struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
fceaf24a
HJ
349
350 DPRINT_ENTER(NETVSC_DRV);
351
352 netif_stop_queue(net);
353
354 ret = net_drv_obj->OnClose(device_obj);
355 if (ret != 0)
356 {
357 DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
358 }
359
360 DPRINT_EXIT(NETVSC_DRV);
361
362 return ret;
363}
364
365
366/*++
367
368Name: netvsc_xmit_completion()
369
370Desc: Send completion processing
371
372--*/
373static void netvsc_xmit_completion(void *context)
374{
4193d4f4 375 struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context;
c4b0bc94 376 struct sk_buff *skb = (struct sk_buff *)(unsigned long)packet->Completion.Send.SendCompletionTid;
fceaf24a
HJ
377 struct net_device* net;
378
379 DPRINT_ENTER(NETVSC_DRV);
380
381 kfree(packet);
382
383 if (skb)
384 {
385 net = skb->dev;
386
387 dev_kfree_skb_any(skb);
388
389 if (netif_queue_stopped(net))
390 {
391 DPRINT_INFO(NETVSC_DRV, "net device (%p) waking up...", net);
392
393 netif_wake_queue(net);
394 }
395 }
396
397 DPRINT_EXIT(NETVSC_DRV);
398}
399
400/*++
401
402Name: netvsc_start_xmit()
403
404Desc: Start a send
405
406--*/
407static int netvsc_start_xmit (struct sk_buff *skb, struct net_device *net)
408{
409 int ret=0;
410 struct net_device_context *net_device_ctx = netdev_priv(net);
411 struct driver_context *driver_ctx = driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
412 struct netvsc_driver_context *net_drv_ctx = (struct netvsc_driver_context*)driver_ctx;
413 NETVSC_DRIVER_OBJECT *net_drv_obj = &net_drv_ctx->drv_obj;
414
415 int i=0;
4193d4f4 416 struct hv_netvsc_packet *packet;
fceaf24a
HJ
417 int num_frags;
418 int retries=0;
419
420 DPRINT_ENTER(NETVSC_DRV);
421
454f18a9 422 /* Support only 1 chain of frags */
fceaf24a
HJ
423 ASSERT(skb_shinfo(skb)->frag_list == NULL);
424 ASSERT(skb->dev == net);
425
426 DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d", skb->len, skb->data_len);
427
454f18a9 428 /* Add 1 for skb->data and any additional ones requested */
fceaf24a
HJ
429 num_frags = skb_shinfo(skb)->nr_frags + 1 + net_drv_obj->AdditionalRequestPageBufferCount;
430
454f18a9 431 /* Allocate a netvsc packet based on # of frags. */
4193d4f4 432 packet = kzalloc(sizeof(struct hv_netvsc_packet) + (num_frags * sizeof(PAGE_BUFFER)) + net_drv_obj->RequestExtSize, GFP_ATOMIC);
fceaf24a
HJ
433 if (!packet)
434 {
4193d4f4 435 DPRINT_ERR(NETVSC_DRV, "unable to allocate hv_netvsc_packet");
fceaf24a
HJ
436 return -1;
437 }
438
4193d4f4 439 packet->Extension = (void*)(unsigned long)packet + sizeof(struct hv_netvsc_packet) + (num_frags * sizeof(PAGE_BUFFER)) ;
fceaf24a 440
454f18a9 441 /* Setup the rndis header */
fceaf24a
HJ
442 packet->PageBufferCount = num_frags;
443
454f18a9
BP
444 /* TODO: Flush all write buffers/ memory fence ??? */
445 /* wmb(); */
fceaf24a 446
454f18a9 447 /* Initialize it from the skb */
fceaf24a
HJ
448 ASSERT(skb->data);
449 packet->TotalDataBufferLength = skb->len;
450
454f18a9 451 /* Start filling in the page buffers starting at AdditionalRequestPageBufferCount offset */
fceaf24a
HJ
452 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
453 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Offset = (unsigned long)skb->data & (PAGE_SIZE -1);
454 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Length = skb->len - skb->data_len;
455
456 ASSERT((skb->len - skb->data_len) <= PAGE_SIZE);
457
458 for (i=net_drv_obj->AdditionalRequestPageBufferCount+1; i<num_frags; i++)
459 {
460 packet->PageBuffers[i].Pfn = page_to_pfn(skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page);
461 packet->PageBuffers[i].Offset = skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page_offset;
462 packet->PageBuffers[i].Length = skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].size;
463 }
464
454f18a9 465 /* Set the completion routine */
fceaf24a
HJ
466 packet->Completion.Send.OnSendCompletion = netvsc_xmit_completion;
467 packet->Completion.Send.SendCompletionContext = packet;
c4b0bc94 468 packet->Completion.Send.SendCompletionTid = (unsigned long)skb;
fceaf24a
HJ
469
470retry_send:
471 ret = net_drv_obj->OnSend(&net_device_ctx->device_ctx->device_obj, packet);
472
473 if (ret == 0)
474 {
fceaf24a
HJ
475 ret = NETDEV_TX_OK;
476 net_device_ctx->stats.tx_bytes += skb->len;
477 net_device_ctx->stats.tx_packets++;
478 }
479 else
480 {
481 retries++;
482 if (retries < 4)
483 {
484 DPRINT_ERR(NETVSC_DRV, "unable to send...retrying %d...", retries);
485 udelay(100);
486 goto retry_send;
487 }
488
454f18a9 489 /* no more room or we are shutting down */
fceaf24a
HJ
490 DPRINT_ERR(NETVSC_DRV, "unable to send (%d)...marking net device (%p) busy", ret, net);
491 DPRINT_INFO(NETVSC_DRV, "net device (%p) stopping", net);
492
493 ret = NETDEV_TX_BUSY;
494 net_device_ctx->stats.tx_dropped++;
495
496 netif_stop_queue(net);
497
454f18a9 498 /* Null it since the caller will free it instead of the completion routine */
fceaf24a
HJ
499 packet->Completion.Send.SendCompletionTid = 0;
500
454f18a9 501 /* Release the resources since we will not get any send completion */
fceaf24a
HJ
502 netvsc_xmit_completion((void*)packet);
503 }
504
505 DPRINT_DBG(NETVSC_DRV, "# of xmits %lu total size %lu", net_device_ctx->stats.tx_packets, net_device_ctx->stats.tx_bytes);
506
507 DPRINT_EXIT(NETVSC_DRV);
508 return ret;
509}
510
511
512/*++
513
514Name: netvsc_linkstatus_callback()
515
516Desc: Link up/down notification
517
518--*/
3d3b5518 519static void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status)
fceaf24a
HJ
520{
521 struct device_context* device_ctx = to_device_context(device_obj);
621d7fb7 522 struct net_device* net = dev_get_drvdata(&device_ctx->device);
fceaf24a
HJ
523
524 DPRINT_ENTER(NETVSC_DRV);
525
526 if (!net)
527 {
528 DPRINT_ERR(NETVSC_DRV, "got link status but net device not initialized yet");
529 return;
530 }
531
532 if (status == 1)
533 {
534 netif_carrier_on(net);
535 netif_wake_queue(net);
536 }
537 else
538 {
539 netif_carrier_off(net);
540 netif_stop_queue(net);
541 }
542 DPRINT_EXIT(NETVSC_DRV);
543}
544
545
546/*++
547
548Name: netvsc_recv_callback()
549
550Desc: Callback when we receive a packet from the "wire" on the specify device
551
552--*/
4193d4f4 553static int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet)
fceaf24a
HJ
554{
555 int ret=0;
556 struct device_context *device_ctx = to_device_context(device_obj);
621d7fb7 557 struct net_device *net = dev_get_drvdata(&device_ctx->device);
fceaf24a
HJ
558 struct net_device_context *net_device_ctx;
559
560 struct sk_buff *skb;
561 void *data;
562 int i=0;
563 unsigned long flags;
564
565 DPRINT_ENTER(NETVSC_DRV);
566
567 if (!net)
568 {
569 DPRINT_ERR(NETVSC_DRV, "got receive callback but net device not initialized yet");
570 return 0;
571 }
572
573 net_device_ctx = netdev_priv(net);
574
454f18a9
BP
575 /* Allocate a skb - TODO preallocate this */
576 /* skb = alloc_skb(packet->TotalDataBufferLength, GFP_ATOMIC); */
577 skb = dev_alloc_skb(packet->TotalDataBufferLength + 2); /* Pad 2-bytes to align IP header to 16 bytes */
fceaf24a
HJ
578 ASSERT(skb);
579 skb_reserve(skb, 2);
580 skb->dev = net;
581
454f18a9 582 /* for kmap_atomic */
fceaf24a
HJ
583 local_irq_save(flags);
584
4193d4f4 585 /* Copy to skb. This copy is needed here since the memory pointed by hv_netvsc_packet */
454f18a9 586 /* cannot be deallocated */
fceaf24a
HJ
587 for (i=0; i<packet->PageBufferCount; i++)
588 {
589 data = kmap_atomic(pfn_to_page(packet->PageBuffers[i].Pfn), KM_IRQ1);
590 data = (void*)(unsigned long)data + packet->PageBuffers[i].Offset;
591
592 memcpy(skb_put(skb, packet->PageBuffers[i].Length), data, packet->PageBuffers[i].Length);
593
594 kunmap_atomic((void*)((unsigned long)data - packet->PageBuffers[i].Offset), KM_IRQ1);
595 }
596
597 local_irq_restore(flags);
598
599 skb->protocol = eth_type_trans(skb, net);
600
601 skb->ip_summed = CHECKSUM_NONE;
602
454f18a9 603 /* Pass the skb back up. Network stack will deallocate the skb when it is done */
fceaf24a
HJ
604 ret = netif_rx(skb);
605
606 switch (ret)
607 {
608 case NET_RX_DROP:
609 net_device_ctx->stats.rx_dropped++;
610 break;
611 default:
612 net_device_ctx->stats.rx_packets++;
613 net_device_ctx->stats.rx_bytes += skb->len;
614 break;
615
616 }
617 DPRINT_DBG(NETVSC_DRV, "# of recvs %lu total size %lu", net_device_ctx->stats.rx_packets, net_device_ctx->stats.rx_bytes);
618
619 DPRINT_EXIT(NETVSC_DRV);
620
621 return 0;
622}
623
624static int netvsc_drv_exit_cb(struct device *dev, void *data)
625{
626 struct device **curr = (struct device **)data;
627 *curr = dev;
454f18a9 628 return 1; /* stop iterating */
fceaf24a
HJ
629}
630
631/*++
632
633Name: netvsc_drv_exit()
634
635Desc:
636
637--*/
bd1de709 638static void netvsc_drv_exit(void)
fceaf24a
HJ
639{
640 NETVSC_DRIVER_OBJECT *netvsc_drv_obj=&g_netvsc_drv.drv_obj;
641 struct driver_context *drv_ctx=&g_netvsc_drv.drv_ctx;
fceaf24a 642 struct device *current_dev=NULL;
2295ba2e 643 int ret;
fceaf24a
HJ
644
645 DPRINT_ENTER(NETVSC_DRV);
646
647 while (1)
648 {
649 current_dev = NULL;
650
454f18a9 651 /* Get the device */
2295ba2e
BP
652 ret = driver_for_each_device(&drv_ctx->driver, NULL,
653 (void *) &current_dev,
654 netvsc_drv_exit_cb);
655
656 if (ret)
657 DPRINT_WARN(NETVSC_DRV,
658 "driver_for_each_device returned %d", ret);
659
fceaf24a
HJ
660
661 if (current_dev == NULL)
662 break;
663
454f18a9 664 /* Initiate removal from the top-down */
fceaf24a
HJ
665 DPRINT_INFO(NETVSC_DRV, "unregistering device (%p)...", current_dev);
666
667 device_unregister(current_dev);
668 }
669
670 if (netvsc_drv_obj->Base.OnCleanup)
671 netvsc_drv_obj->Base.OnCleanup(&netvsc_drv_obj->Base);
672
673 vmbus_child_driver_unregister(drv_ctx);
674
675 DPRINT_EXIT(NETVSC_DRV);
676
677 return;
678}
679
680static int __init netvsc_init(void)
681{
682 int ret;
683
684 DPRINT_ENTER(NETVSC_DRV);
685 DPRINT_INFO(NETVSC_DRV, "Netvsc initializing....");
686
687 ret = netvsc_drv_init(NetVscInitialize);
688
689 DPRINT_EXIT(NETVSC_DRV);
690
691 return ret;
692}
693
694static void __exit netvsc_exit(void)
695{
696 DPRINT_ENTER(NETVSC_DRV);
697
698 netvsc_drv_exit();
699
700 DPRINT_EXIT(NETVSC_DRV);
701}
702
703module_param(netvsc_ringbuffer_size, int, S_IRUGO);
704
705module_init(netvsc_init);
706module_exit(netvsc_exit);