Deleted Added
full compact
netfront.c (185473) netfront.c (185605)
1/*
2 *
3 * Copyright (c) 2004-2006 Kip Macy
4 * All rights reserved.
5 *
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

--- 4 unchanged lines hidden (view full) ---

13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
16 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17 */
18
19
20#include <sys/cdefs.h>
1/*
2 *
3 * Copyright (c) 2004-2006 Kip Macy
4 * All rights reserved.
5 *
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

--- 4 unchanged lines hidden (view full) ---

13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
16 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17 */
18
19
20#include <sys/cdefs.h>
21__FBSDID("$FreeBSD: head/sys/dev/xen/netfront/netfront.c 185473 2008-11-30 12:21:46Z dfr $");
21__FBSDID("$FreeBSD: head/sys/dev/xen/netfront/netfront.c 185605 2008-12-04 07:59:05Z kmacy $");
22
23#include <sys/param.h>
24#include <sys/systm.h>
25#include <sys/sockio.h>
26#include <sys/mbuf.h>
27#include <sys/malloc.h>
22
23#include <sys/param.h>
24#include <sys/systm.h>
25#include <sys/sockio.h>
26#include <sys/mbuf.h>
27#include <sys/malloc.h>
28#include <sys/module.h>
28#include <sys/kernel.h>
29#include <sys/socket.h>
30#include <sys/queue.h>
31#include <sys/sx.h>
32
33#include <net/if.h>
34#include <net/if_arp.h>
35#include <net/ethernet.h>

--- 23 unchanged lines hidden (view full) ---

59#include <sys/rman.h>
60
61#include <machine/intr_machdep.h>
62
63#include <machine/xen/xen-os.h>
64#include <machine/xen/hypervisor.h>
65#include <machine/xen/xen_intr.h>
66#include <machine/xen/evtchn.h>
29#include <sys/kernel.h>
30#include <sys/socket.h>
31#include <sys/queue.h>
32#include <sys/sx.h>
33
34#include <net/if.h>
35#include <net/if_arp.h>
36#include <net/ethernet.h>

--- 23 unchanged lines hidden (view full) ---

60#include <sys/rman.h>
61
62#include <machine/intr_machdep.h>
63
64#include <machine/xen/xen-os.h>
65#include <machine/xen/hypervisor.h>
66#include <machine/xen/xen_intr.h>
67#include <machine/xen/evtchn.h>
67#include <machine/xen/xenbus.h>
68#include <xen/gnttab.h>
69#include <xen/interface/memory.h>
70#include <dev/xen/netfront/mbufq.h>
71#include <machine/xen/features.h>
72#include <xen/interface/io/netif.h>
68#include <xen/gnttab.h>
69#include <xen/interface/memory.h>
70#include <dev/xen/netfront/mbufq.h>
71#include <machine/xen/features.h>
72#include <xen/interface/io/netif.h>
73#include <xen/xenbus/xenbusvar.h>
73
74
75#include "xenbus_if.h"
74
75#define GRANT_INVALID_REF 0
76
77#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
78#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
79
80#ifdef CONFIG_XEN
81static int MODPARM_rx_copy = 0;

--- 29 unchanged lines hidden (view full) ---

111static void xn_ifinit(void *);
112static void xn_stop(struct netfront_info *);
113#ifdef notyet
114static void xn_watchdog(struct ifnet *);
115#endif
116
117static void show_device(struct netfront_info *sc);
118#ifdef notyet
76
77#define GRANT_INVALID_REF 0
78
79#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
80#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
81
82#ifdef CONFIG_XEN
83static int MODPARM_rx_copy = 0;

--- 29 unchanged lines hidden (view full) ---

113static void xn_ifinit(void *);
114static void xn_stop(struct netfront_info *);
115#ifdef notyet
116static void xn_watchdog(struct ifnet *);
117#endif
118
119static void show_device(struct netfront_info *sc);
120#ifdef notyet
119static void netfront_closing(struct xenbus_device *dev);
121static void netfront_closing(device_t dev);
120#endif
121static void netif_free(struct netfront_info *info);
122#endif
123static void netif_free(struct netfront_info *info);
122static int netfront_remove(struct xenbus_device *dev);
124static int netfront_detach(device_t dev);
123
125
124static int talk_to_backend(struct xenbus_device *dev, struct netfront_info *info);
125static int create_netdev(struct xenbus_device *dev, struct ifnet **ifp);
126static int talk_to_backend(device_t dev, struct netfront_info *info);
127static int create_netdev(device_t dev);
126static void netif_disconnect_backend(struct netfront_info *info);
128static void netif_disconnect_backend(struct netfront_info *info);
127static int setup_device(struct xenbus_device *dev, struct netfront_info *info);
129static int setup_device(device_t dev, struct netfront_info *info);
128static void end_access(int ref, void *page);
129
130/* Xenolinux helper functions */
130static void end_access(int ref, void *page);
131
132/* Xenolinux helper functions */
131static int network_connect(struct ifnet *ifp);
133int network_connect(struct netfront_info *);
132
133static void xn_free_rx_ring(struct netfront_info *);
134
135static void xn_free_tx_ring(struct netfront_info *);
136
137static int xennet_get_responses(struct netfront_info *np,
138 struct netfront_rx_info *rinfo, RING_IDX rp, struct mbuf **list,
139 int *pages_flipped_p);

--- 76 unchanged lines hidden (view full) ---

216 */
217
218 grant_ref_t gref_tx_head;
219 grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
220 grant_ref_t gref_rx_head;
221 grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1];
222
223#define TX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
134
135static void xn_free_rx_ring(struct netfront_info *);
136
137static void xn_free_tx_ring(struct netfront_info *);
138
139static int xennet_get_responses(struct netfront_info *np,
140 struct netfront_rx_info *rinfo, RING_IDX rp, struct mbuf **list,
141 int *pages_flipped_p);

--- 76 unchanged lines hidden (view full) ---

218 */
219
220 grant_ref_t gref_tx_head;
221 grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
222 grant_ref_t gref_rx_head;
223 grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1];
224
225#define TX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
224 struct xenbus_device *xbdev;
226 device_t xbdev;
225 int tx_ring_ref;
226 int rx_ring_ref;
227 uint8_t mac[ETHER_ADDR_LEN];
228 struct xn_chain_data xn_cdata; /* mbufs */
229 struct mbuf_head xn_rx_batch; /* head of the batch queue */
230
231 int xn_if_flags;
232 struct callout xn_stat_ch;

--- 89 unchanged lines hidden (view full) ---

322#ifdef DEBUG
323
324#endif
325#define IPRINTK(fmt, args...) \
326 printf("[XEN] " fmt, ##args)
327#define WPRINTK(fmt, args...) \
328 printf("[XEN] " fmt, ##args)
329#define DPRINTK(fmt, args...) \
227 int tx_ring_ref;
228 int rx_ring_ref;
229 uint8_t mac[ETHER_ADDR_LEN];
230 struct xn_chain_data xn_cdata; /* mbufs */
231 struct mbuf_head xn_rx_batch; /* head of the batch queue */
232
233 int xn_if_flags;
234 struct callout xn_stat_ch;

--- 89 unchanged lines hidden (view full) ---

324#ifdef DEBUG
325
326#endif
327#define IPRINTK(fmt, args...) \
328 printf("[XEN] " fmt, ##args)
329#define WPRINTK(fmt, args...) \
330 printf("[XEN] " fmt, ##args)
331#define DPRINTK(fmt, args...) \
330 printf("[XEN] " fmt, ##args)
332 printf("[XEN] %s: " fmt, __func__, ##args)
331
332
333static __inline struct mbuf*
334makembuf (struct mbuf *buf)
335{
336 struct mbuf *m = NULL;
337
338 MGETHDR (m, M_DONTWAIT, MT_DATA);
339
340 if (! m)
341 return 0;
342
333
334
335static __inline struct mbuf*
336makembuf (struct mbuf *buf)
337{
338 struct mbuf *m = NULL;
339
340 MGETHDR (m, M_DONTWAIT, MT_DATA);
341
342 if (! m)
343 return 0;
344
343 M_MOVE_PKTHDR(m, buf);
345 M_MOVE_PKTHDR(m, buf);
344
346
345 m_cljget(m, M_DONTWAIT, MJUMPAGESIZE);
347 m_cljget(m, M_DONTWAIT, MJUMPAGESIZE);
346 m->m_pkthdr.len = buf->m_pkthdr.len;
347 m->m_len = buf->m_len;
348 m->m_pkthdr.len = buf->m_pkthdr.len;
349 m->m_len = buf->m_len;
348 m_copydata(buf, 0, buf->m_pkthdr.len, mtod(m,caddr_t) );
350 m_copydata(buf, 0, buf->m_pkthdr.len, mtod(m,caddr_t) );
349
350 m->m_ext.ext_arg1 = (caddr_t *)(uintptr_t)(vtophys(mtod(m,caddr_t)) >> PAGE_SHIFT);
351
352 m->m_ext.ext_arg1 = (caddr_t *)(uintptr_t)(vtophys(mtod(m,caddr_t)) >> PAGE_SHIFT);
351
353
352 return m;
353}
354
355/**
356 * Read the 'mac' node at the given device's node in the store, and parse that
357 * as colon-separated octets, placing result the given mac array. mac must be
358 * a preallocated array of length ETH_ALEN (as declared in linux/if_ether.h).
359 * Return 0 on success, or errno on error.
360 */
361static int
354 return m;
355}
356
357/**
358 * Read the 'mac' node at the given device's node in the store, and parse that
359 * as colon-separated octets, placing result the given mac array. mac must be
360 * a preallocated array of length ETH_ALEN (as declared in linux/if_ether.h).
361 * Return 0 on success, or errno on error.
362 */
363static int
362xen_net_read_mac(struct xenbus_device *dev, uint8_t mac[])
364xen_net_read_mac(device_t dev, uint8_t mac[])
363{
364 char *s;
365 int i;
366 char *e;
365{
366 char *s;
367 int i;
368 char *e;
367 char *macstr = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
369 char *macstr = xenbus_read(XBT_NIL, xenbus_get_node(dev), "mac", NULL);
368 if (IS_ERR(macstr)) {
369 return PTR_ERR(macstr);
370 }
371 s = macstr;
372 for (i = 0; i < ETHER_ADDR_LEN; i++) {
373 mac[i] = strtoul(s, &e, 16);
374 if (s == e || (e[0] != ':' && e[0] != 0)) {
375 free(macstr, M_DEVBUF);

--- 7 unchanged lines hidden (view full) ---

383
384/**
385 * Entry point to this code when a new device is created. Allocate the basic
386 * structures and the ring buffers for communication with the backend, and
387 * inform the backend of the appropriate details for those. Switch to
388 * Connected state.
389 */
390static int
370 if (IS_ERR(macstr)) {
371 return PTR_ERR(macstr);
372 }
373 s = macstr;
374 for (i = 0; i < ETHER_ADDR_LEN; i++) {
375 mac[i] = strtoul(s, &e, 16);
376 if (s == e || (e[0] != ':' && e[0] != 0)) {
377 free(macstr, M_DEVBUF);

--- 7 unchanged lines hidden (view full) ---

385
386/**
387 * Entry point to this code when a new device is created. Allocate the basic
388 * structures and the ring buffers for communication with the backend, and
389 * inform the backend of the appropriate details for those. Switch to
390 * Connected state.
391 */
392static int
391netfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id)
393netfront_probe(device_t dev)
392{
394{
395
396 if (!strcmp(xenbus_get_type(dev), "vif")) {
397 device_set_desc(dev, "Virtual Network Interface");
398 return (0);
399 }
400
401 return (ENXIO);
402}
403
404static int
405netfront_attach(device_t dev)
406{
393 int err;
407 int err;
394 struct ifnet *ifp;
395 struct netfront_info *info;
396
408
397 printf("netfront_probe() \n");
398
399 err = create_netdev(dev, &ifp);
409 err = create_netdev(dev);
400 if (err) {
401 xenbus_dev_fatal(dev, err, "creating netdev");
402 return err;
403 }
404
410 if (err) {
411 xenbus_dev_fatal(dev, err, "creating netdev");
412 return err;
413 }
414
405 info = ifp->if_softc;
406 dev->dev_driver_data = info;
407
408 return 0;
409}
410
411
412/**
413 * We are reconnecting to the backend, due to a suspend/resume, or a backend
414 * driver restart. We tear down our netif structure and recreate it, but
415 * leave the device-layer structures intact so that this is transparent to the
416 * rest of the kernel.
417 */
418static int
415 return 0;
416}
417
418
419/**
420 * We are reconnecting to the backend, due to a suspend/resume, or a backend
421 * driver restart. We tear down our netif structure and recreate it, but
422 * leave the device-layer structures intact so that this is transparent to the
423 * rest of the kernel.
424 */
425static int
419netfront_resume(struct xenbus_device *dev)
426netfront_resume(device_t dev)
420{
427{
421 struct netfront_info *info = dev->dev_driver_data;
428 struct netfront_info *info = device_get_softc(dev);
422
429
423 DPRINTK("%s\n", dev->nodename);
430 DPRINTK("%s\n", xenbus_get_node(dev));
424
425 netif_disconnect_backend(info);
426 return (0);
427}
428
429
430/* Common code used when first setting up, and when resuming. */
431static int
431
432 netif_disconnect_backend(info);
433 return (0);
434}
435
436
437/* Common code used when first setting up, and when resuming. */
438static int
432talk_to_backend(struct xenbus_device *dev, struct netfront_info *info)
439talk_to_backend(device_t dev, struct netfront_info *info)
433{
434 const char *message;
435 struct xenbus_transaction xbt;
440{
441 const char *message;
442 struct xenbus_transaction xbt;
443 const char *node = xenbus_get_node(dev);
436 int err;
437
438 err = xen_net_read_mac(dev, info->mac);
439 if (err) {
444 int err;
445
446 err = xen_net_read_mac(dev, info->mac);
447 if (err) {
440 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
448 xenbus_dev_fatal(dev, err, "parsing %s/mac", node);
441 goto out;
442 }
443
444 /* Create shared ring, alloc event channel. */
445 err = setup_device(dev, info);
446 if (err)
447 goto out;
448
449 again:
450 err = xenbus_transaction_start(&xbt);
451 if (err) {
452 xenbus_dev_fatal(dev, err, "starting transaction");
453 goto destroy_ring;
454 }
449 goto out;
450 }
451
452 /* Create shared ring, alloc event channel. */
453 err = setup_device(dev, info);
454 if (err)
455 goto out;
456
457 again:
458 err = xenbus_transaction_start(&xbt);
459 if (err) {
460 xenbus_dev_fatal(dev, err, "starting transaction");
461 goto destroy_ring;
462 }
455 err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
463 err = xenbus_printf(xbt, node, "tx-ring-ref","%u",
456 info->tx_ring_ref);
457 if (err) {
458 message = "writing tx ring-ref";
459 goto abort_transaction;
460 }
464 info->tx_ring_ref);
465 if (err) {
466 message = "writing tx ring-ref";
467 goto abort_transaction;
468 }
461 err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
469 err = xenbus_printf(xbt, node, "rx-ring-ref","%u",
462 info->rx_ring_ref);
463 if (err) {
464 message = "writing rx ring-ref";
465 goto abort_transaction;
466 }
470 info->rx_ring_ref);
471 if (err) {
472 message = "writing rx ring-ref";
473 goto abort_transaction;
474 }
467 err = xenbus_printf(xbt, dev->nodename,
475 err = xenbus_printf(xbt, node,
468 "event-channel", "%u", irq_to_evtchn_port(info->irq));
469 if (err) {
470 message = "writing event-channel";
471 goto abort_transaction;
472 }
476 "event-channel", "%u", irq_to_evtchn_port(info->irq));
477 if (err) {
478 message = "writing event-channel";
479 goto abort_transaction;
480 }
473 err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
481 err = xenbus_printf(xbt, node, "request-rx-copy", "%u",
474 info->copying_receiver);
475 if (err) {
476 message = "writing request-rx-copy";
477 goto abort_transaction;
478 }
482 info->copying_receiver);
483 if (err) {
484 message = "writing request-rx-copy";
485 goto abort_transaction;
486 }
479 err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
487 err = xenbus_printf(xbt, node, "feature-rx-notify", "%d", 1);
480 if (err) {
481 message = "writing feature-rx-notify";
482 goto abort_transaction;
483 }
488 if (err) {
489 message = "writing feature-rx-notify";
490 goto abort_transaction;
491 }
484 err = xenbus_printf(xbt, dev->nodename, "feature-no-csum-offload", "%d", 1);
492 err = xenbus_printf(xbt, node, "feature-no-csum-offload", "%d", 1);
485 if (err) {
486 message = "writing feature-no-csum-offload";
487 goto abort_transaction;
488 }
493 if (err) {
494 message = "writing feature-no-csum-offload";
495 goto abort_transaction;
496 }
489 err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
497 err = xenbus_printf(xbt, node, "feature-sg", "%d", 1);
490 if (err) {
491 message = "writing feature-sg";
492 goto abort_transaction;
493 }
494#ifdef HAVE_TSO
498 if (err) {
499 message = "writing feature-sg";
500 goto abort_transaction;
501 }
502#ifdef HAVE_TSO
495 err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
503 err = xenbus_printf(xbt, node, "feature-gso-tcpv4", "%d", 1);
496 if (err) {
497 message = "writing feature-gso-tcpv4";
498 goto abort_transaction;
499 }
500#endif
501
502 err = xenbus_transaction_end(xbt, 0);
503 if (err) {

--- 11 unchanged lines hidden (view full) ---

515 destroy_ring:
516 netif_free(info);
517 out:
518 return err;
519}
520
521
522static int
504 if (err) {
505 message = "writing feature-gso-tcpv4";
506 goto abort_transaction;
507 }
508#endif
509
510 err = xenbus_transaction_end(xbt, 0);
511 if (err) {

--- 11 unchanged lines hidden (view full) ---

523 destroy_ring:
524 netif_free(info);
525 out:
526 return err;
527}
528
529
530static int
523setup_device(struct xenbus_device *dev, struct netfront_info *info)
531setup_device(device_t dev, struct netfront_info *info)
524{
525 netif_tx_sring_t *txs;
526 netif_rx_sring_t *rxs;
527 int err;
528 struct ifnet *ifp;
529
530 ifp = info->xn_ifp;
531

--- 26 unchanged lines hidden (view full) ---

558 FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
559
560 err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
561 if (err < 0)
562 goto fail;
563 info->rx_ring_ref = err;
564
565#if 0
532{
533 netif_tx_sring_t *txs;
534 netif_rx_sring_t *rxs;
535 int err;
536 struct ifnet *ifp;
537
538 ifp = info->xn_ifp;
539

--- 26 unchanged lines hidden (view full) ---

566 FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
567
568 err = xenbus_grant_ring(dev, virt_to_mfn(rxs));
569 if (err < 0)
570 goto fail;
571 info->rx_ring_ref = err;
572
573#if 0
566 network_connect(ifp);
574 network_connect(info);
567#endif
575#endif
568 err = bind_listening_port_to_irqhandler(dev->otherend_id,
576 err = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev),
569 "xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, NULL);
570
571 if (err <= 0) {
572 xenbus_dev_fatal(dev, err,
573 "bind_evtchn_to_irqhandler failed");
574 goto fail;
575 }
576 info->irq = err;

--- 6 unchanged lines hidden (view full) ---

583 netif_free(info);
584 return err;
585}
586
587/**
588 * Callback received when the backend's state changes.
589 */
590static void
577 "xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, NULL);
578
579 if (err <= 0) {
580 xenbus_dev_fatal(dev, err,
581 "bind_evtchn_to_irqhandler failed");
582 goto fail;
583 }
584 info->irq = err;

--- 6 unchanged lines hidden (view full) ---

591 netif_free(info);
592 return err;
593}
594
595/**
596 * Callback received when the backend's state changes.
597 */
598static void
591backend_changed(struct xenbus_device *dev,
592 XenbusState backend_state)
599netfront_backend_changed(device_t dev, XenbusState newstate)
593{
600{
594 struct netfront_info *sc = dev->dev_driver_data;
601 struct netfront_info *sc = device_get_softc(dev);
595
602
596 DPRINTK("\n");
597
598 switch (backend_state) {
603 DPRINTK("newstate=%d\n", newstate);
604
605 switch (newstate) {
599 case XenbusStateInitialising:
600 case XenbusStateInitialised:
601 case XenbusStateConnected:
602 case XenbusStateUnknown:
603 case XenbusStateClosed:
604 case XenbusStateReconfigured:
605 case XenbusStateReconfiguring:
606 case XenbusStateInitialising:
607 case XenbusStateInitialised:
608 case XenbusStateConnected:
609 case XenbusStateUnknown:
610 case XenbusStateClosed:
611 case XenbusStateReconfigured:
612 case XenbusStateReconfiguring:
606 break;
613 break;
607 case XenbusStateInitWait:
614 case XenbusStateInitWait:
608 if (dev->state != XenbusStateInitialising)
615 if (xenbus_get_state(dev) != XenbusStateInitialising)
609 break;
616 break;
610 if (network_connect(sc->xn_ifp) != 0)
617 if (network_connect(sc) != 0)
611 break;
618 break;
612 xenbus_switch_state(dev, XenbusStateConnected);
619 xenbus_set_state(dev, XenbusStateConnected);
613#ifdef notyet
614 (void)send_fake_arp(netdev);
615#endif
620#ifdef notyet
621 (void)send_fake_arp(netdev);
622#endif
616 break; break;
623 break;
617 case XenbusStateClosing:
624 case XenbusStateClosing:
618 xenbus_frontend_closed(dev);
625 xenbus_set_state(dev, XenbusStateClosed);
619 break;
620 }
621}
622
623static void
624xn_free_rx_ring(struct netfront_info *sc)
625{
626#if 0

--- 42 unchanged lines hidden (view full) ---

669 int i;
670
671 for (i = 1; i <= NET_TX_RING_SIZE; i++) {
672 m = np->xn_cdata.xn_tx_chain[i];
673
674 if (((u_long)m) < KERNBASE)
675 continue;
676 gnttab_grant_foreign_access_ref(np->grant_tx_ref[i],
626 break;
627 }
628}
629
630static void
631xn_free_rx_ring(struct netfront_info *sc)
632{
633#if 0

--- 42 unchanged lines hidden (view full) ---

676 int i;
677
678 for (i = 1; i <= NET_TX_RING_SIZE; i++) {
679 m = np->xn_cdata.xn_tx_chain[i];
680
681 if (((u_long)m) < KERNBASE)
682 continue;
683 gnttab_grant_foreign_access_ref(np->grant_tx_ref[i],
677 np->xbdev->otherend_id, virt_to_mfn(mtod(m, vm_offset_t)),
684 xenbus_get_otherend_id(np->xbdev),
685 virt_to_mfn(mtod(m, vm_offset_t)),
678 GNTMAP_readonly);
679 gnttab_release_grant_reference(&np->gref_tx_head,
680 np->grant_tx_ref[i]);
681 np->grant_tx_ref[i] = GRANT_INVALID_REF;
682 add_id_to_freelist(np->tx_mbufs, i);
683 m_freem(m);
684 }
685}
686
687static void
688network_alloc_rx_buffers(struct netfront_info *sc)
689{
686 GNTMAP_readonly);
687 gnttab_release_grant_reference(&np->gref_tx_head,
688 np->grant_tx_ref[i]);
689 np->grant_tx_ref[i] = GRANT_INVALID_REF;
690 add_id_to_freelist(np->tx_mbufs, i);
691 m_freem(m);
692 }
693}
694
695static void
696network_alloc_rx_buffers(struct netfront_info *sc)
697{
698 int otherend_id = xenbus_get_otherend_id(sc->xbdev);
690 unsigned short id;
691 struct mbuf *m_new;
692 int i, batch_target, notify;
693 RING_IDX req_prod;
694 struct xen_memory_reservation reservation;
695 grant_ref_t ref;
696 int nr_flips;
697 netif_rx_request_t *req;

--- 65 unchanged lines hidden (view full) ---

763 sc->grant_rx_ref[id] = ref;
764
765 vaddr = mtod(m_new, vm_offset_t);
766 pfn = vtophys(vaddr) >> PAGE_SHIFT;
767 req = RING_GET_REQUEST(&sc->rx, req_prod + i);
768
769 if (sc->copying_receiver == 0) {
770 gnttab_grant_foreign_transfer_ref(ref,
699 unsigned short id;
700 struct mbuf *m_new;
701 int i, batch_target, notify;
702 RING_IDX req_prod;
703 struct xen_memory_reservation reservation;
704 grant_ref_t ref;
705 int nr_flips;
706 netif_rx_request_t *req;

--- 65 unchanged lines hidden (view full) ---

772 sc->grant_rx_ref[id] = ref;
773
774 vaddr = mtod(m_new, vm_offset_t);
775 pfn = vtophys(vaddr) >> PAGE_SHIFT;
776 req = RING_GET_REQUEST(&sc->rx, req_prod + i);
777
778 if (sc->copying_receiver == 0) {
779 gnttab_grant_foreign_transfer_ref(ref,
771 sc->xbdev->otherend_id, pfn);
780 otherend_id, pfn);
772 sc->rx_pfn_array[nr_flips] = PFNTOMFN(pfn);
773 if (!xen_feature(XENFEAT_auto_translated_physmap)) {
774 /* Remove this page before passing
775 * back to Xen.
776 */
777 set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
778 MULTI_update_va_mapping(&sc->rx_mcl[i],
779 vaddr, 0, 0);
780 }
781 nr_flips++;
782 } else {
783 gnttab_grant_foreign_access_ref(ref,
781 sc->rx_pfn_array[nr_flips] = PFNTOMFN(pfn);
782 if (!xen_feature(XENFEAT_auto_translated_physmap)) {
783 /* Remove this page before passing
784 * back to Xen.
785 */
786 set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
787 MULTI_update_va_mapping(&sc->rx_mcl[i],
788 vaddr, 0, 0);
789 }
790 nr_flips++;
791 } else {
792 gnttab_grant_foreign_access_ref(ref,
784 sc->xbdev->otherend_id,
793 otherend_id,
785 PFNTOMFN(pfn), 0);
786 }
787 req->id = id;
788 req->gref = ref;
789
790 sc->rx_pfn_array[i] =
791 vtomach(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT;
792 }

--- 500 unchanged lines hidden (view full) ---

1293 XN_RX_LOCK(sc);
1294 xn_tick_locked(sc);
1295 XN_RX_UNLOCK(sc);
1296
1297}
1298static void
1299xn_start_locked(struct ifnet *ifp)
1300{
794 PFNTOMFN(pfn), 0);
795 }
796 req->id = id;
797 req->gref = ref;
798
799 sc->rx_pfn_array[i] =
800 vtomach(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT;
801 }

--- 500 unchanged lines hidden (view full) ---

1302 XN_RX_LOCK(sc);
1303 xn_tick_locked(sc);
1304 XN_RX_UNLOCK(sc);
1305
1306}
1307static void
1308xn_start_locked(struct ifnet *ifp)
1309{
1310 int otherend_id;
1301 unsigned short id;
1302 struct mbuf *m_head, *new_m;
1303 struct netfront_info *sc;
1304 netif_tx_request_t *tx;
1305 RING_IDX i;
1306 grant_ref_t ref;
1307 u_long mfn, tx_bytes;
1308 int notify;
1309
1310 sc = ifp->if_softc;
1311 unsigned short id;
1312 struct mbuf *m_head, *new_m;
1313 struct netfront_info *sc;
1314 netif_tx_request_t *tx;
1315 RING_IDX i;
1316 grant_ref_t ref;
1317 u_long mfn, tx_bytes;
1318 int notify;
1319
1320 sc = ifp->if_softc;
1321 otherend_id = xenbus_get_otherend_id(sc->xbdev);
1311 tx_bytes = 0;
1312
1313 if (!netfront_carrier_ok(sc))
1314 return;
1315
1316 for (i = sc->tx.req_prod_pvt; TRUE; i++) {
1317 IF_DEQUEUE(&ifp->if_snd, m_head);
1318 if (m_head == NULL)

--- 13 unchanged lines hidden (view full) ---

1332 * of fragments or hit the end of the mbuf chain.
1333 */
1334 new_m = makembuf(m_head);
1335 tx = RING_GET_REQUEST(&sc->tx, i);
1336 tx->id = id;
1337 ref = gnttab_claim_grant_reference(&sc->gref_tx_head);
1338 KASSERT((short)ref >= 0, ("Negative ref"));
1339 mfn = virt_to_mfn(mtod(new_m, vm_offset_t));
1322 tx_bytes = 0;
1323
1324 if (!netfront_carrier_ok(sc))
1325 return;
1326
1327 for (i = sc->tx.req_prod_pvt; TRUE; i++) {
1328 IF_DEQUEUE(&ifp->if_snd, m_head);
1329 if (m_head == NULL)

--- 13 unchanged lines hidden (view full) ---

1343 * of fragments or hit the end of the mbuf chain.
1344 */
1345 new_m = makembuf(m_head);
1346 tx = RING_GET_REQUEST(&sc->tx, i);
1347 tx->id = id;
1348 ref = gnttab_claim_grant_reference(&sc->gref_tx_head);
1349 KASSERT((short)ref >= 0, ("Negative ref"));
1350 mfn = virt_to_mfn(mtod(new_m, vm_offset_t));
1340 gnttab_grant_foreign_access_ref(ref, sc->xbdev->otherend_id,
1351 gnttab_grant_foreign_access_ref(ref, otherend_id,
1341 mfn, GNTMAP_readonly);
1342 tx->gref = sc->grant_tx_ref[id] = ref;
1343 tx->size = new_m->m_pkthdr.len;
1344#if 0
1345 tx->flags = (skb->ip_summed == CHECKSUM_HW) ? NETTXF_csum_blank : 0;
1346#endif
1347 tx->flags = 0;
1348 new_m->m_next = NULL;

--- 189 unchanged lines hidden (view full) ---

1538
1539 xn_free_rx_ring(sc);
1540 xn_free_tx_ring(sc);
1541
1542 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1543}
1544
1545/* START of Xenolinux helper functions adapted to FreeBSD */
1352 mfn, GNTMAP_readonly);
1353 tx->gref = sc->grant_tx_ref[id] = ref;
1354 tx->size = new_m->m_pkthdr.len;
1355#if 0
1356 tx->flags = (skb->ip_summed == CHECKSUM_HW) ? NETTXF_csum_blank : 0;
1357#endif
1358 tx->flags = 0;
1359 new_m->m_next = NULL;

--- 189 unchanged lines hidden (view full) ---

1549
1550 xn_free_rx_ring(sc);
1551 xn_free_tx_ring(sc);
1552
1553 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1554}
1555
1556/* START of Xenolinux helper functions adapted to FreeBSD */
1546static int
1547network_connect(struct ifnet *ifp)
1557int
1558network_connect(struct netfront_info *np)
1548{
1559{
1549 struct netfront_info *np;
1550 int i, requeue_idx, err;
1551 grant_ref_t ref;
1552 netif_rx_request_t *req;
1553 u_int feature_rx_copy, feature_rx_flip;
1554
1560 int i, requeue_idx, err;
1561 grant_ref_t ref;
1562 netif_rx_request_t *req;
1563 u_int feature_rx_copy, feature_rx_flip;
1564
1555 printf("network_connect\n");
1556
1557 np = ifp->if_softc;
1558 err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
1565 err = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
1559 "feature-rx-copy", "%u", &feature_rx_copy);
1560 if (err != 1)
1561 feature_rx_copy = 0;
1566 "feature-rx-copy", "%u", &feature_rx_copy);
1567 if (err != 1)
1568 feature_rx_copy = 0;
1562 err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
1569 err = xenbus_scanf(XBT_NIL, xenbus_get_otherend_path(np->xbdev),
1563 "feature-rx-flip", "%u", &feature_rx_flip);
1564 if (err != 1)
1565 feature_rx_flip = 1;
1566
1567 /*
1568 * Copy packets on receive path if:
1569 * (a) This was requested by user, and the backend supports it; or
1570 * (b) Flipping was requested, but this is unsupported by the backend.
1571 */
1572 np->copying_receiver = ((MODPARM_rx_copy && feature_rx_copy) ||
1573 (MODPARM_rx_flip && !feature_rx_flip));
1574
1575 XN_LOCK(np);
1576 /* Recovery procedure: */
1577 err = talk_to_backend(np->xbdev, np);
1578 if (err)
1570 "feature-rx-flip", "%u", &feature_rx_flip);
1571 if (err != 1)
1572 feature_rx_flip = 1;
1573
1574 /*
1575 * Copy packets on receive path if:
1576 * (a) This was requested by user, and the backend supports it; or
1577 * (b) Flipping was requested, but this is unsupported by the backend.
1578 */
1579 np->copying_receiver = ((MODPARM_rx_copy && feature_rx_copy) ||
1580 (MODPARM_rx_flip && !feature_rx_flip));
1581
1582 XN_LOCK(np);
1583 /* Recovery procedure: */
1584 err = talk_to_backend(np->xbdev, np);
1585 if (err)
1579 return (err);
1586 return (err);
1580
1581 /* Step 1: Reinitialise variables. */
1582 netif_release_tx_bufs(np);
1583
1584 /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
1585 for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
1586 struct mbuf *m;
1587
1588 if (np->rx_mbufs[i] == NULL)
1589 continue;
1590
1591 m = np->rx_mbufs[requeue_idx] = xennet_get_rx_mbuf(np, i);
1592 ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
1593 req = RING_GET_REQUEST(&np->rx, requeue_idx);
1594
1595 if (!np->copying_receiver) {
1596 gnttab_grant_foreign_transfer_ref(ref,
1587
1588 /* Step 1: Reinitialise variables. */
1589 netif_release_tx_bufs(np);
1590
1591 /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
1592 for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
1593 struct mbuf *m;
1594
1595 if (np->rx_mbufs[i] == NULL)
1596 continue;
1597
1598 m = np->rx_mbufs[requeue_idx] = xennet_get_rx_mbuf(np, i);
1599 ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
1600 req = RING_GET_REQUEST(&np->rx, requeue_idx);
1601
1602 if (!np->copying_receiver) {
1603 gnttab_grant_foreign_transfer_ref(ref,
1597 np->xbdev->otherend_id,
1604 xenbus_get_otherend_id(np->xbdev),
1598 vtophys(mtod(m, vm_offset_t)));
1599 } else {
1600 gnttab_grant_foreign_access_ref(ref,
1605 vtophys(mtod(m, vm_offset_t)));
1606 } else {
1607 gnttab_grant_foreign_access_ref(ref,
1601 np->xbdev->otherend_id,
1608 xenbus_get_otherend_id(np->xbdev),
1602 vtophys(mtod(m, vm_offset_t)), 0);
1603 }
1604 req->gref = ref;
1605 req->id = requeue_idx;
1606
1607 requeue_idx++;
1608 }
1609

--- 10 unchanged lines hidden (view full) ---

1620 xn_txeof(np);
1621 XN_TX_UNLOCK(np);
1622 network_alloc_rx_buffers(np);
1623 XN_UNLOCK(np);
1624
1625 return (0);
1626}
1627
1609 vtophys(mtod(m, vm_offset_t)), 0);
1610 }
1611 req->gref = ref;
1612 req->id = requeue_idx;
1613
1614 requeue_idx++;
1615 }
1616

--- 10 unchanged lines hidden (view full) ---

1627 xn_txeof(np);
1628 XN_TX_UNLOCK(np);
1629 network_alloc_rx_buffers(np);
1630 XN_UNLOCK(np);
1631
1632 return (0);
1633}
1634
1628
1629static void
1630show_device(struct netfront_info *sc)
1631{
1632#ifdef DEBUG
1633 if (sc) {
1634 IPRINTK("<vif handle=%u %s(%s) evtchn=%u irq=%u tx=%p rx=%p>\n",
1635 sc->xn_ifno,
1636 be_state_name[sc->xn_backend_state],
1637 sc->xn_user_state ? "open" : "closed",
1638 sc->xn_evtchn,
1639 sc->xn_irq,
1640 sc->xn_tx_if,
1641 sc->xn_rx_if);
1642 } else {
1643 IPRINTK("<vif NULL>\n");
1644 }
1645#endif
1646}
1647
1635static void
1636show_device(struct netfront_info *sc)
1637{
1638#ifdef DEBUG
1639 if (sc) {
1640 IPRINTK("<vif handle=%u %s(%s) evtchn=%u irq=%u tx=%p rx=%p>\n",
1641 sc->xn_ifno,
1642 be_state_name[sc->xn_backend_state],
1643 sc->xn_user_state ? "open" : "closed",
1644 sc->xn_evtchn,
1645 sc->xn_irq,
1646 sc->xn_tx_if,
1647 sc->xn_rx_if);
1648 } else {
1649 IPRINTK("<vif NULL>\n");
1650 }
1651#endif
1652}
1653
1648static int ifno = 0;
1649
1650/** Create a network device.
1651 * @param handle device handle
1652 */
1654/** Create a network device.
1655 * @param handle device handle
1656 */
1653static int
1654create_netdev(struct xenbus_device *dev, struct ifnet **ifpp)
1657int
1658create_netdev(device_t dev)
1655{
1656 int i;
1657 struct netfront_info *np;
1658 int err;
1659 struct ifnet *ifp;
1660
1659{
1660 int i;
1661 struct netfront_info *np;
1662 int err;
1663 struct ifnet *ifp;
1664
1661 np = (struct netfront_info *)malloc(sizeof(struct netfront_info),
1662 M_DEVBUF, M_NOWAIT);
1663 if (np == NULL)
1664 return (ENOMEM);
1665 np = device_get_softc(dev);
1665
1666
1666 memset(np, 0, sizeof(struct netfront_info));
1667
1668 np->xbdev = dev;
1669
1670 XN_LOCK_INIT(np, xennetif);
1671 np->rx_target = RX_MIN_TARGET;
1672 np->rx_min_target = RX_MIN_TARGET;
1673 np->rx_max_target = RX_MAX_TARGET;
1674
1675 /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */

--- 18 unchanged lines hidden (view full) ---

1694 printf("#### netfront can't alloc rx grant refs\n");
1695 gnttab_free_grant_references(np->gref_tx_head);
1696 err = ENOMEM;
1697 goto exit;
1698 }
1699
1700 err = xen_net_read_mac(dev, np->mac);
1701 if (err) {
1667 np->xbdev = dev;
1668
1669 XN_LOCK_INIT(np, xennetif);
1670 np->rx_target = RX_MIN_TARGET;
1671 np->rx_min_target = RX_MIN_TARGET;
1672 np->rx_max_target = RX_MAX_TARGET;
1673
1674 /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */

--- 18 unchanged lines hidden (view full) ---

1693 printf("#### netfront can't alloc rx grant refs\n");
1694 gnttab_free_grant_references(np->gref_tx_head);
1695 err = ENOMEM;
1696 goto exit;
1697 }
1698
1699 err = xen_net_read_mac(dev, np->mac);
1700 if (err) {
1702 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
1701 xenbus_dev_fatal(dev, err, "parsing %s/mac",
1702 xenbus_get_node(dev));
1703 goto out;
1704 }
1705
1706 /* Set up ifnet structure */
1703 goto out;
1704 }
1705
1706 /* Set up ifnet structure */
1707 *ifpp = ifp = np->xn_ifp = if_alloc(IFT_ETHER);
1707 ifp = np->xn_ifp = if_alloc(IFT_ETHER);
1708 ifp->if_softc = np;
1708 ifp->if_softc = np;
1709 if_initname(ifp, "xn", ifno++/* ifno */);
1709 if_initname(ifp, "xn", device_get_unit(dev));
1710 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1711 ifp->if_ioctl = xn_ioctl;
1712 ifp->if_output = ether_output;
1713 ifp->if_start = xn_start;
1714#ifdef notyet
1715 ifp->if_watchdog = xn_watchdog;
1716#endif
1717 ifp->if_init = xn_ifinit;

--- 21 unchanged lines hidden (view full) ---

1739
1740/**
1741 * Handle the change of state of the backend to Closing. We must delete our
1742 * device-layer structures now, to ensure that writes are flushed through to
1743 * the backend. Once is this done, we can switch to Closed in
1744 * acknowledgement.
1745 */
1746#if 0
1710 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1711 ifp->if_ioctl = xn_ioctl;
1712 ifp->if_output = ether_output;
1713 ifp->if_start = xn_start;
1714#ifdef notyet
1715 ifp->if_watchdog = xn_watchdog;
1716#endif
1717 ifp->if_init = xn_ifinit;

--- 21 unchanged lines hidden (view full) ---

1739
1740/**
1741 * Handle the change of state of the backend to Closing. We must delete our
1742 * device-layer structures now, to ensure that writes are flushed through to
1743 * the backend. Once is this done, we can switch to Closed in
1744 * acknowledgement.
1745 */
1746#if 0
1747static void netfront_closing(struct xenbus_device *dev)
1747static void netfront_closing(device_t dev)
1748{
1749#if 0
1750 struct netfront_info *info = dev->dev_driver_data;
1751
1752 DPRINTK("netfront_closing: %s removed\n", dev->nodename);
1753
1754 close_netdev(info);
1755#endif
1756 xenbus_switch_state(dev, XenbusStateClosed);
1757}
1758#endif
1759
1748{
1749#if 0
1750 struct netfront_info *info = dev->dev_driver_data;
1751
1752 DPRINTK("netfront_closing: %s removed\n", dev->nodename);
1753
1754 close_netdev(info);
1755#endif
1756 xenbus_switch_state(dev, XenbusStateClosed);
1757}
1758#endif
1759
1760static int netfront_remove(struct xenbus_device *dev)
1760static int netfront_detach(device_t dev)
1761{
1761{
1762 struct netfront_info *info = dev->dev_driver_data;
1762 struct netfront_info *info = device_get_softc(dev);
1763
1763
1764 DPRINTK("%s\n", dev->nodename);
1764 DPRINTK("%s\n", xenbus_get_node(dev));
1765
1766 netif_free(info);
1765
1766 netif_free(info);
1767 free(info, M_DEVBUF);
1768
1769 return 0;
1770}
1771
1772
1773static void netif_free(struct netfront_info *info)
1774{
1775 netif_disconnect_backend(info);

--- 25 unchanged lines hidden (view full) ---

1801
1802
1803static void end_access(int ref, void *page)
1804{
1805 if (ref != GRANT_INVALID_REF)
1806 gnttab_end_foreign_access(ref, page);
1807}
1808
1767
1768 return 0;
1769}
1770
1771
1772static void netif_free(struct netfront_info *info)
1773{
1774 netif_disconnect_backend(info);

--- 25 unchanged lines hidden (view full) ---

1800
1801
1802static void end_access(int ref, void *page)
1803{
1804 if (ref != GRANT_INVALID_REF)
1805 gnttab_end_foreign_access(ref, page);
1806}
1807
1809
1810/* ** Driver registration ** */
1808/* ** Driver registration ** */
1809static device_method_t netfront_methods[] = {
1810 /* Device interface */
1811 DEVMETHOD(device_probe, netfront_probe),
1812 DEVMETHOD(device_attach, netfront_attach),
1813 DEVMETHOD(device_detach, netfront_detach),
1814 DEVMETHOD(device_shutdown, bus_generic_shutdown),
1815 DEVMETHOD(device_suspend, bus_generic_suspend),
1816 DEVMETHOD(device_resume, netfront_resume),
1817
1818 /* Xenbus interface */
1819 DEVMETHOD(xenbus_backend_changed, netfront_backend_changed),
1811
1820
1821 { 0, 0 }
1822};
1812
1823
1813static struct xenbus_device_id netfront_ids[] = {
1814 { "vif" },
1815 { "" }
1816};
1817
1818
1819static struct xenbus_driver netfront = {
1820 .name = "vif",
1821 .ids = netfront_ids,
1822 .probe = netfront_probe,
1823 .remove = netfront_remove,
1824 .resume = netfront_resume,
1825 .otherend_changed = backend_changed,
1826};
1827
1828static void
1829netif_init(void *unused)
1830{
1831 if (!is_running_on_xen())
1832 return;
1833
1834 if (is_initial_xendomain())
1835 return;
1836
1837 IPRINTK("Initialising virtual ethernet driver.\n");
1838
1839 xenbus_register_frontend(&netfront);
1840}
1841
1842SYSINIT(xennetif, SI_SUB_PSEUDO, SI_ORDER_SECOND, netif_init, NULL);
1843
1844
1845/*
1846 * Local variables:
1847 * mode: C
1848 * c-set-style: "BSD"
1849 * c-basic-offset: 8
1850 * tab-width: 4
1851 * indent-tabs-mode: t
1852 * End:
1853 */
1824static driver_t netfront_driver = {
1825 "xn",
1826 netfront_methods,
1827 sizeof(struct netfront_info),
1828};
1829devclass_t netfront_devclass;
1830
1831DRIVER_MODULE(xe, xenbus, netfront_driver, netfront_devclass, 0, 0);