From owner-p4-projects@FreeBSD.ORG Fri Jan 4 09:05:43 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1726A16A46C; Fri, 4 Jan 2008 09:05:43 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CEFA016A421 for ; Fri, 4 Jan 2008 09:05:42 +0000 (UTC) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BD67813C459 for ; Fri, 4 Jan 2008 09:05:42 +0000 (UTC) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m0495gaf067147 for ; Fri, 4 Jan 2008 09:05:42 GMT (envelope-from kmacy@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m0495g02067127 for perforce@freebsd.org; Fri, 4 Jan 2008 09:05:42 GMT (envelope-from kmacy@freebsd.org) Date: Fri, 4 Jan 2008 09:05:42 GMT Message-Id: <200801040905.m0495g02067127@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to kmacy@freebsd.org using -f From: Kip Macy To: Perforce Change Reviews Cc: Subject: PERFORCE change 132473 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Jan 2008 09:05:43 -0000 http://perforce.freebsd.org/chv.cgi?CH=132473 Change 132473 by kmacy@pandemonium:kmacy:xen31 on 2008/01/04 09:04:42 - pull in most recent public xen headers from hg - set interface version to immediately prior to addition of hyperpage - update grant table interface to provide runtime sized grant tables - add virtual network interface to build and bring it more in line with latest linux version Affected files ... .. //depot/projects/xen31/sys/conf/files#13 edit .. //depot/projects/xen31/sys/dev/xen/blkfront/block.h#3 edit .. //depot/projects/xen31/sys/dev/xen/console/xencons_ring.c#5 edit .. //depot/projects/xen31/sys/dev/xen/netfront/mbufq.h#1 add .. //depot/projects/xen31/sys/dev/xen/netfront/netfront.c#2 edit .. //depot/projects/xen31/sys/i386/i386/trap.c#6 edit .. //depot/projects/xen31/sys/i386/i386/vm_machdep.c#5 edit .. //depot/projects/xen31/sys/i386/include/cpufunc.h#6 edit .. //depot/projects/xen31/sys/i386/include/pmap.h#8 edit .. //depot/projects/xen31/sys/i386/include/xen/evtchn.h#5 edit .. //depot/projects/xen31/sys/i386/include/xen/features.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/hypercall.h#5 edit .. //depot/projects/xen31/sys/i386/include/xen/hypervisor-ifs.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/hypervisor.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-os.h#4 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/COPYING#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/acm.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/acm_ops.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-ia64.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-powerpc.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-x86/xen-x86_32.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-x86/xen-x86_64.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-x86/xen.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-x86_32.h#4 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/arch-x86_64.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/callback.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/dom0_ops.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/domctl.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/elfstructs.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/event_channel.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/features.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/foreign/Makefile#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/foreign/mkchecker.py#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/foreign/mkheader.py#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/foreign/reference.size#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/foreign/structs.py#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/grant_table.h#4 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/e820.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/hvm_info_table.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/hvm_op.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/ioreq.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/params.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/save.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/hvm/vmx_assist.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/blkif.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/console.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/fbif.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/kbdif.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/netif.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/pciif.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/protocols.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/ring.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/tpmif.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/io/xs_wire.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/kexec.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/libelf.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/memory.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/nmi.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/platform.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/sched.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/sched_ctl.h#2 delete .. //depot/projects/xen31/sys/i386/include/xen/xen-public/sysctl.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/trace.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/version.h#2 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/xen-compat.h#3 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/xen.h#5 edit .. //depot/projects/xen31/sys/i386/include/xen/xen-public/xencomm.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xen-public/xenoprof.h#1 add .. //depot/projects/xen31/sys/i386/include/xen/xenpmap.h#6 edit .. //depot/projects/xen31/sys/i386/include/xen/xenvar.h#5 edit .. //depot/projects/xen31/sys/i386/isa/npx.c#3 edit .. //depot/projects/xen31/sys/i386/xen/pmap.c#11 edit .. //depot/projects/xen31/sys/i386/xen/xen_machdep.c#12 edit .. //depot/projects/xen31/sys/sys/cdefs.h#3 edit .. //depot/projects/xen31/sys/xen/evtchn/evtchn_dev.c#2 edit .. //depot/projects/xen31/sys/xen/gnttab.c#3 edit .. //depot/projects/xen31/sys/xen/gnttab.h#2 edit .. //depot/projects/xen31/sys/xen/xenbus/xenbus_xs.c#9 edit Differences ... ==== //depot/projects/xen31/sys/conf/files#13 (text+ko) ==== @@ -2110,6 +2110,7 @@ vm/vm_zeroidle.c standard vm/vnode_pager.c standard xen/gnttab.c optional xen +xen/features.c optional xen xen/evtchn/evtchn.c optional xen xen/evtchn/evtchn_dev.c optional xen xen/xenbus/xenbus_client.c optional xen @@ -2121,6 +2122,7 @@ dev/xen/console/console.c optional xen dev/xen/console/xencons_ring.c optional xen dev/xen/blkfront/blkfront.c optional xen +dev/xen/netfront/netfront.c optional xen # gnu/fs/xfs/xfs_alloc.c optional xfs \ ==== //depot/projects/xen31/sys/dev/xen/blkfront/block.h#3 (text+ko) ==== @@ -1,5 +1,6 @@ #ifndef __XEN_DRIVERS_BLOCK_H__ #define __XEN_DRIVERS_BLOCK_H__ +#include struct xlbd_type_info { ==== //depot/projects/xen31/sys/dev/xen/console/xencons_ring.c#5 (text+ko) ==== @@ -21,6 +21,7 @@ #include +#include #include ==== //depot/projects/xen31/sys/dev/xen/netfront/netfront.c#2 (text+ko) ==== @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -54,20 +55,37 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #define GRANT_INVALID_REF 0 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) +#ifdef CONFIG_XEN +static int MODPARM_rx_copy = 0; +module_param_named(rx_copy, MODPARM_rx_copy, bool, 0); +MODULE_PARM_DESC(rx_copy, "Copy packets from network card (rather than flip)"); +static int MODPARM_rx_flip = 0; +module_param_named(rx_flip, MODPARM_rx_flip, bool, 0); +MODULE_PARM_DESC(rx_flip, "Flip packets from network card (rather than copy)"); +#else +static const int MODPARM_rx_copy = 1; +static const int MODPARM_rx_flip = 0; +#endif + +#define RX_COPY_THRESHOLD 256 struct netfront_info; static void xn_txeof(struct netfront_info *); @@ -89,18 +107,20 @@ #endif static void show_device(struct netfront_info *sc); +#ifdef notyet static void netfront_closing(struct xenbus_device *dev); +#endif static void netif_free(struct netfront_info *info); static int netfront_remove(struct xenbus_device *dev); static int talk_to_backend(struct xenbus_device *dev, struct netfront_info *info); -static int create_netdev(int handle, struct xenbus_device *dev, struct ifnet **ifp); +static int create_netdev(struct xenbus_device *dev, struct ifnet **ifp); static void netif_disconnect_backend(struct netfront_info *info); static int setup_device(struct xenbus_device *dev, struct netfront_info *info); static void end_access(int ref, void *page); /* Xenolinux helper functions */ -static void network_connect(struct ifnet *ifp); +static int network_connect(struct ifnet *ifp); static void xn_free_rx_ring(struct netfront_info *); @@ -118,7 +138,7 @@ * not the other way around. The size must track the free index arrays. */ struct xn_chain_data { - struct mbuf *xn_tx_chain[NET_TX_RING_SIZE+1]; + struct mbuf *xn_tx_chain[NET_TX_RING_SIZE+1]; struct mbuf *xn_rx_chain[NET_RX_RING_SIZE+1]; }; @@ -160,75 +180,67 @@ unsigned long tx_compressed; }; -struct netfront_info -{ - struct ifnet *xn_ifp; +struct netfront_info { + + struct ifnet *xn_ifp; - struct net_device_stats stats; - unsigned int tx_full; + struct net_device_stats stats; + unsigned int tx_full; - netif_tx_front_ring_t tx; - netif_rx_front_ring_t rx; + netif_tx_front_ring_t tx; + netif_rx_front_ring_t rx; - struct mtx tx_lock; - struct mtx rx_lock; + struct mtx tx_lock; + struct mtx rx_lock; - unsigned int handle; - unsigned int evtchn, irq; - - /* What is the status of our connection to the remote backend? */ -#define BEST_CLOSED 0 -#define BEST_DISCONNECTED 1 -#define BEST_CONNECTED 2 - unsigned int backend_state; - - /* Is this interface open or closed (down or up)? */ -#define UST_CLOSED 0 -#define UST_OPEN 1 - unsigned int user_state; - + unsigned int handle; + unsigned int irq; + unsigned int copying_receiver; + unsigned int carrier; + /* Receive-ring batched refills. */ #define RX_MIN_TARGET 32 #define RX_MAX_TARGET NET_RX_RING_SIZE - int rx_min_target, rx_max_target, rx_target; + int rx_min_target, rx_max_target, rx_target; - /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. - */ + /* + * {tx,rx}_skbs store outstanding skbuffs. The first entry in each + * array is an index into a chain of free entries. + */ - grant_ref_t gref_tx_head; - grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; - grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1]; + grant_ref_t gref_tx_head; + grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1]; + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1]; - struct xenbus_device *xbdev; - int tx_ring_ref; - int rx_ring_ref; - uint8_t mac[ETHER_ADDR_LEN]; - struct xn_chain_data xn_cdata; /* mbufs */ +#define TX_MAX_TARGET min(NET_RX_RING_SIZE, 256) + struct xenbus_device *xbdev; + int tx_ring_ref; + int rx_ring_ref; + uint8_t mac[ETHER_ADDR_LEN]; + struct xn_chain_data xn_cdata; /* mbufs */ unsigned short xn_rx_free_idxs[NET_RX_RING_SIZE+1]; unsigned short xn_tx_free_idxs[NET_RX_RING_SIZE+1]; - struct mbuf *xn_rx_batch; /* head of the batch queue */ - struct mbuf *xn_rx_batchtail; - int xn_rx_batchlen; /* how many queued */ - int xn_if_flags; - struct callout xn_stat_ch; + struct mbuf_head xn_rx_batch; /* head of the batch queue */ + int xn_if_flags; + struct callout xn_stat_ch; }; +#define rx_mbufs xn_cdata.xn_rx_chain +#define tx_mbufs xn_cdata.xn_tx_chain #define XN_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->tx_lock, #_name"_tx", "network transmit lock", MTX_SPIN); \ - mtx_init(&(_sc)->rx_lock, #_name"_rx", "network receive lock", MTX_SPIN); -#define XN_RX_LOCK(_sc) mtx_lock_spin(&(_sc)->rx_lock) -#define XN_RX_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->rx_lock) -#define XN_TX_LOCK(_sc) mtx_lock_spin(&(_sc)->tx_lock) -#define XN_TX_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->tx_lock) -#define XN_LOCK(_sc) mtx_lock_spin(&(_sc)->tx_lock); \ - mtx_lock_spin(&(_sc)->rx_lock); -#define XN_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->rx_lock); \ - mtx_unlock_spin(&(_sc)->tx_lock) + mtx_init(&(_sc)->tx_lock, #_name"_tx", "network transmit lock", MTX_DEF); \ + mtx_init(&(_sc)->rx_lock, #_name"_rx", "network receive lock", MTX_DEF); +#define XN_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_lock) +#define XN_RX_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_lock) +#define XN_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_lock) +#define XN_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_lock) +#define XN_LOCK(_sc) mtx_lock(&(_sc)->tx_lock); \ + mtx_lock(&(_sc)->rx_lock); +#define XN_UNLOCK(_sc) mtx_unlock(&(_sc)->rx_lock); \ + mtx_unlock(&(_sc)->tx_lock) #define XN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_lock, MA_OWNED); \ mtx_assert(&(_sc)->tx_lock, MA_OWNED); #define XN_RX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rx_lock, MA_OWNED); @@ -236,22 +248,62 @@ #define XN_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_lock); \ mtx_destroy(&(_sc)->tx_lock); +#define netfront_carrier_on(netif) ((netif)->carrier = 1) +#define netfront_carrier_off(netif) ((netif)->carrier = 0) +#define netfront_carrier_ok(netif) ((netif)->carrier) + /* Access macros for acquiring freeing slots in xn_free_{tx,rx}_idxs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned short _id = (_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) -#define FREELIST_EMPTY(_list, _maxid) \ - ((_list)[0] == (_maxid+1)) + + + +/* + * Access macros for acquiring freeing slots in tx_skbs[]. + */ + +static inline void +add_id_to_freelist(struct mbuf **list, unsigned short id) +{ + list[id] = list[0]; + list[0] = (void *)(unsigned long)id; +} + +static inline unsigned short +get_id_from_freelist(struct mbuf **list) +{ + unsigned int id = (unsigned int)(unsigned long)list[0]; + list[0] = list[id]; + return (id); +} + +static inline int +xennet_rxidx(RING_IDX idx) +{ + return idx & (NET_RX_RING_SIZE - 1); +} + +static inline struct mbuf * +xennet_get_rx_mbuf(struct netfront_info *np, + RING_IDX ri) +{ + int i = xennet_rxidx(ri); + struct mbuf *m; + + m = np->rx_mbufs[i]; + np->rx_mbufs[i] = NULL; + return (m); +} + +static inline grant_ref_t +xennet_get_rx_ref(struct netfront_info *np, RING_IDX ri) +{ + int i = xennet_rxidx(ri); + grant_ref_t ref = np->grant_rx_ref[i]; + np->grant_rx_ref[i] = GRANT_INVALID_REF; + return ref; +} + #ifdef DEBUG -static char *be_state_name[] = { - [BEST_CLOSED] = "closed", - [BEST_DISCONNECTED] = "disconnected", - [BEST_CONNECTED] = "connected", -}; + #endif #define IPRINTK(fmt, args...) \ printf("[XEN] " fmt, ##args) @@ -269,15 +321,19 @@ if (! m) return 0; - - M_MOVE_PKTHDR(m, buf); + + M_MOVE_PKTHDR(m, buf); MCLGET (m, M_DONTWAIT); m->m_pkthdr.len = buf->m_pkthdr.len; m->m_len = buf->m_len; - m_copydata(buf, 0, buf->m_pkthdr.len, mtod(m,caddr_t) ); - m->m_ext.ext_args = (vm_paddr_t *)vtophys(mtod(m,caddr_t)); + m_copydata(buf, 0, buf->m_pkthdr.len, mtod(m,caddr_t) ); + /* + * XXX this will break on > 4GB + * + */ + m->m_ext.ext_args = (caddr_t *)(uintptr_t)vtophys(mtod(m,caddr_t)); return m; } @@ -294,7 +350,7 @@ char *s; int i; char *e; - char *macstr = xenbus_read(NULL, dev->nodename, "mac", NULL); + char *macstr = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL); if (IS_ERR(macstr)) { return PTR_ERR(macstr); } @@ -323,27 +379,20 @@ int err; struct ifnet *ifp; struct netfront_info *info; - unsigned int handle; - - err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle); - if (err != 1) { - xenbus_dev_fatal(dev, err, "reading handle"); - return err; - } - err = create_netdev(handle, dev, &ifp); + err = create_netdev(dev, &ifp); if (err) { xenbus_dev_fatal(dev, err, "creating netdev"); return err; } info = ifp->if_softc; - dev->data = info; + dev->dev_driver_data = info; err = talk_to_backend(dev, info); if (err) { free(info, M_DEVBUF); - dev->data = NULL; + dev->dev_driver_data = NULL; return err; } @@ -360,7 +409,7 @@ static int netfront_resume(struct xenbus_device *dev) { - struct netfront_info *info = dev->data; + struct netfront_info *info = dev->dev_driver_data; DPRINTK("%s\n", dev->nodename); @@ -374,21 +423,26 @@ talk_to_backend(struct xenbus_device *dev, struct netfront_info *info) { const char *message; - struct xenbus_transaction *xbt; + struct xenbus_transaction xbt; int err; - + + err = xen_net_read_mac(dev, info->mac); + if (err) { + xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); + goto out; + } + /* Create shared ring, alloc event channel. */ err = setup_device(dev, info); if (err) goto out; again: - xbt = xenbus_transaction_start(); - if (IS_ERR(xbt)) { + err = xenbus_transaction_start(&xbt); + if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_ring; } - err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", info->tx_ring_ref); if (err) { @@ -402,18 +456,35 @@ goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, - "event-channel", "%u", info->evtchn); + "event-channel", "%u", irq_to_evtchn_port(info->irq)); if (err) { message = "writing event-channel"; goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u", + info->copying_receiver); + if (err) { + message = "writing request-rx-copy"; + goto abort_transaction; + } - err = xenbus_printf(xbt, dev->nodename, - "state", "%d", XenbusStateConnected); + err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1); + if (err) { + message = "writing feature-rx-notify"; + goto abort_transaction; + } + err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); + if (err) { + message = "writing feature-sg"; + goto abort_transaction; + } +#ifdef HAVE_TSO + err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1); if (err) { - message = "writing frontend XenbusStateConnected"; + message = "writing feature-gso-tcpv4"; goto abort_transaction; } +#endif err = xenbus_transaction_end(xbt, 0); if (err) { @@ -451,47 +522,47 @@ info->tx.sring = NULL; info->irq = 0; - txs = (netif_tx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + txs = (netif_tx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO); if (!txs) { err = ENOMEM; xenbus_dev_fatal(dev, err, "allocating tx ring page"); goto fail; } - rxs = (netif_rx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT); + SHARED_RING_INIT(txs); + FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); + err = xenbus_grant_ring(dev, virt_to_mfn(txs)); + if (err < 0) + goto fail; + info->tx_ring_ref = err; + + + rxs = (netif_rx_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO); if (!rxs) { err = ENOMEM; xenbus_dev_fatal(dev, err, "allocating rx ring page"); goto fail; } - memset(txs, 0, PAGE_SIZE); - memset(rxs, 0, PAGE_SIZE); - info->backend_state = BEST_DISCONNECTED; - - SHARED_RING_INIT(txs); - FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); - SHARED_RING_INIT(rxs); FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); - err = xenbus_grant_ring(dev, virt_to_mfn(txs)); - if (err < 0) - goto fail; - info->tx_ring_ref = err; - err = xenbus_grant_ring(dev, virt_to_mfn(rxs)); if (err < 0) goto fail; info->rx_ring_ref = err; - err = xenbus_alloc_evtchn(dev, &info->evtchn); - if (err) - goto fail; - +#if 0 network_connect(ifp); +#endif + err = bind_listening_port_to_irqhandler(dev->otherend_id, + "xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, NULL); - info->irq = bind_evtchn_to_irqhandler( - info->evtchn, "xn", xn_intr, info, INTR_TYPE_NET | INTR_MPSAFE, NULL); - + if (err <= 0) { + xenbus_dev_fatal(dev, err, + "bind_evtchn_to_irqhandler failed"); + goto fail; + } + info->irq = err; + show_device(info); return 0; @@ -508,26 +579,34 @@ static void backend_changed(struct xenbus_device *dev, XenbusState backend_state) { + struct netfront_info *sc = dev->dev_driver_data; + DPRINTK("\n"); + switch (backend_state) { case XenbusStateInitialising: - case XenbusStateInitWait: case XenbusStateInitialised: case XenbusStateConnected: case XenbusStateUnknown: case XenbusStateClosed: - break; - + break; + case XenbusStateInitWait: + if (dev->state != XenbusStateInitialising) + break; + if (network_connect(sc->xn_ifp) != 0) + break; + xenbus_switch_state(dev, XenbusStateConnected); +#ifdef notyet + (void)send_fake_arp(netdev); +#endif + break; break; case XenbusStateClosing: - netfront_closing(dev); + xenbus_frontend_closed(dev); break; } } - - - static void xn_free_rx_ring(struct netfront_info *sc) { @@ -564,19 +643,52 @@ #endif } +static inline int +netfront_tx_slot_available(struct netfront_info *np) +{ + return ((np->tx.req_prod_pvt - np->tx.rsp_cons) < + (TX_MAX_TARGET - /* MAX_SKB_FRAGS */ 24 - 2)); +} +static void +netif_release_tx_bufs(struct netfront_info *np) +{ + struct mbuf *m; + int i; + + for (i = 1; i <= NET_TX_RING_SIZE; i++) { + m = np->xn_cdata.xn_tx_chain[i]; + + if (m == NULL) + continue; + gnttab_grant_foreign_access_ref( + np->grant_tx_ref[i], np->xbdev->otherend_id, + virt_to_mfn(mtod(m, vm_offset_t)), + GNTMAP_readonly); + gnttab_release_grant_reference( + &np->gref_tx_head, np->grant_tx_ref[i]); + np->grant_tx_ref[i] = GRANT_INVALID_REF; + add_id_to_freelist(np->tx_mbufs, i); + m_freem(m); + } +} + static void network_alloc_rx_buffers(struct netfront_info *sc) { unsigned short id; - struct mbuf *m_new, *next; - int i, batch_target; + struct mbuf *m_new; + int i, batch_target, notify; RING_IDX req_prod; struct xen_memory_reservation reservation; grant_ref_t ref; + int nr_flips; + netif_rx_request_t *req; + vm_offset_t vaddr; + unsigned long pfn; + + req_prod = sc->rx.req_prod_pvt; - req_prod = sc->rx.req_prod_pvt; - - if (unlikely(sc->backend_state != BEST_CONNECTED) ) + if (unlikely(sc->carrier == 0)) return; /* @@ -586,110 +698,136 @@ * ourself and for other kernel subsystems. */ batch_target = sc->rx_target - (req_prod - sc->rx.rsp_cons); - for (i = sc->xn_rx_batchlen; i < batch_target; i++, sc->xn_rx_batchlen++) { + for (i = mbufq_len(&sc->xn_rx_batch); i < batch_target; i++) { MGETHDR(m_new, M_DONTWAIT, MT_DATA); if (m_new == NULL) - break; - - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - m_freem(m_new); - break; + goto no_mbuf; + + m_cljget(m_new, M_DONTWAIT, MJUMPAGESIZE); + if ((m_new->m_flags & M_EXT) == 0) { + m_freem(m_new); + +no_mbuf: + if (i != 0) + goto refill; + /* + * XXX set timer + */ + break; } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + m_new->m_len = m_new->m_pkthdr.len = MJUMPAGESIZE; /* queue the mbufs allocated */ - if (!sc->xn_rx_batch) - sc->xn_rx_batch = m_new; - - if (sc->xn_rx_batchtail) - sc->xn_rx_batchtail->m_next = m_new; - sc->xn_rx_batchtail = m_new; + mbufq_tail(&sc->xn_rx_batch, m_new); } /* Is the batch large enough to be worthwhile? */ - if ( i < (sc->rx_target/2) ) - return; - - for (i = 0, m_new = sc->xn_rx_batch; m_new; - i++, sc->xn_rx_batchlen--, m_new = next) { + if (i < (sc->rx_target/2)) { + if (req_prod >sc->rx.sring->req_prod) + goto push; + return; + } + /* Adjust our floating fill target if we risked running out of buffers. */ + if ( ((req_prod - sc->rx.sring->rsp_prod) < (sc->rx_target / 4)) && + ((sc->rx_target *= 2) > sc->rx_max_target) ) + sc->rx_target = sc->rx_max_target; - next = m_new->m_next; - m_new->m_next = NULL; +refill: + for (nr_flips = i = 0; ; i++) { + if ((m_new = mbufq_dequeue(&sc->xn_rx_batch)) == NULL) + break; - m_new->m_ext.ext_args = (vm_paddr_t *)vtophys(m_new->m_ext.ext_buf); + m_new->m_ext.ext_args = (vm_paddr_t *)(uintptr_t)vtophys(m_new->m_ext.ext_buf); + id = xennet_rxidx(req_prod + 1); + + KASSERT(id != 0, ("alloc_rx_buffers: found free receive index of 0\n")); + PANIC_IF(sc->xn_cdata.xn_rx_chain[id] != NULL); + sc->xn_cdata.xn_rx_chain[id] = m_new; - id = GET_ID_FROM_FREELIST(sc->xn_rx_free_idxs); - KASSERT(id != 0, ("alloc_rx_buffers: found free receive index of 0\n")); - sc->xn_cdata.xn_rx_chain[id] = m_new; + ref = gnttab_claim_grant_reference(&sc->gref_rx_head); + PANIC_IF((signed short)ref < 0); + sc->grant_rx_ref[id] = ref; + + vaddr = mtod(m_new, vm_offset_t); + pfn = vtophys(vaddr) >> PAGE_SHIFT; + req = RING_GET_REQUEST(&sc->rx, req_prod + i); + + if (sc->copying_receiver == 0) { + gnttab_grant_foreign_transfer_ref(ref, + sc->xbdev->otherend_id, + pfn); + rx_pfn_array[nr_flips] = PFNTOMFN(pfn); + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + /* Remove this page before passing + * back to Xen. + */ + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + MULTI_update_va_mapping(&rx_mcl[i], + vaddr, 0, 0); + } + nr_flips++; + } else { + gnttab_grant_foreign_access_ref(ref, + sc->xbdev->otherend_id, + PFNTOMFN(pfn), + 0); + } + req->id = id; + req->gref = ref; - - RING_GET_REQUEST(&sc->rx, req_prod + i)->id = id; - ref = gnttab_claim_grant_reference(&sc->gref_rx_head); - PANIC_IF((signed short)ref < 0); - sc->grant_rx_ref[id] = ref; - gnttab_grant_foreign_transfer_ref(ref, - sc->xbdev->otherend_id); - RING_GET_REQUEST(&sc->rx, req_prod + i)->gref = ref; - - - rx_pfn_array[i] = vtomach(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT; - - /* Remove this page from pseudo phys map before passing back to Xen. */ - xen_phys_machine[((unsigned long)m_new->m_ext.ext_args >> PAGE_SHIFT)] - = INVALID_P2M_ENTRY; - - rx_mcl[i].op = __HYPERVISOR_update_va_mapping; - rx_mcl[i].args[0] = (unsigned long)mtod(m_new,vm_offset_t); - rx_mcl[i].args[1] = 0; - rx_mcl[i].args[2] = 0; - rx_mcl[i].args[3] = 0; - + rx_pfn_array[i] = vtomach(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT; } KASSERT(i, ("no mbufs processed")); /* should have returned earlier */ - KASSERT(sc->xn_rx_batchlen == 0, ("not all mbufs processed")); - sc->xn_rx_batch = sc->xn_rx_batchtail = NULL; - + KASSERT(mbufq_len(&sc->xn_rx_batch) == 0, ("not all mbufs processed")); /* * We may have allocated buffers which have entries outstanding - in the page * update queue -- make sure we flush those first! */ + * in the page * update queue -- make sure we flush those first! + */ PT_UPDATES_FLUSH(); - - /* After all PTEs have been zapped we blow away stale TLB entries. */ - rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_LOCAL; - - /* Give away a batch of pages. */ - rx_mcl[i].op = __HYPERVISOR_memory_op; - rx_mcl[i].args[0] = XENMEM_decrease_reservation; - rx_mcl[i].args[1] = (unsigned long)&reservation; - - reservation.extent_start = rx_pfn_array; - reservation.nr_extents = i; - reservation.extent_order = 0; - reservation.address_bits = 0; - reservation.domid = DOMID_SELF; - + if (nr_flips != 0) { #ifdef notyet - /* Tell the ballon driver what is going on. */ - balloon_update_driver_allowance(i); + /* Tell the ballon driver what is going on. */ + balloon_update_driver_allowance(i); #endif + set_xen_guest_handle(reservation.extent_start, rx_pfn_array); + reservation.nr_extents = i; + reservation.extent_order = 0; + reservation.address_bits = 0; + reservation.domid = DOMID_SELF; + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + + /* After all PTEs have been zapped, flush the TLB. */ + rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = + UVMF_TLB_FLUSH|UVMF_ALL; - /* Zap PTEs and give away pages in one big multicall. */ - (void)HYPERVISOR_multicall(rx_mcl, i+1); + /* Give away a batch of pages. */ + rx_mcl[i].op = __HYPERVISOR_memory_op; + rx_mcl[i].args[0] = XENMEM_decrease_reservation; + rx_mcl[i].args[1] = (unsigned long)&reservation; + /* Zap PTEs and give away pages in one big multicall. */ + (void)HYPERVISOR_multicall(rx_mcl, i+1); - /* Check return status of HYPERVISOR_dom_mem_op(). */ - if (unlikely(rx_mcl[i].result != i)) - panic("Unable to reduce memory reservation\n"); - + /* Check return status of HYPERVISOR_dom_mem_op(). */ + if (unlikely(rx_mcl[i].result != i)) + panic("Unable to reduce memory reservation\n"); + + } else { + if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation) != i) + panic("Unable to reduce memory reservation\n"); + } + } else { + wmb(); + } + /* Above is a suitable barrier to ensure backend will see requests. */ sc->rx.req_prod_pvt = req_prod + i; - RING_PUSH_REQUESTS(&sc->rx); - - /* Adjust our floating fill target if we risked running out of buffers. */ - if ( ((req_prod - sc->rx.sring->rsp_prod) < (sc->rx_target / 4)) && - ((sc->rx_target *= 2) > sc->rx_max_target) ) - sc->rx_target = sc->rx_max_target; +push: + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->rx, notify); + if (notify) + notify_remote_via_irq(sc->irq); } static void @@ -704,9 +842,8 @@ unsigned long mfn; grant_ref_t ref; - XN_RX_LOCK_ASSERT(np); - if (np->backend_state != BEST_CONNECTED) + if (!netfront_carrier_ok(np)) return; ifp = np->xn_ifp; @@ -752,7 +889,7 @@ m = (struct mbuf *)np->xn_cdata.xn_rx_chain[rx->id]; if (m->m_next) panic("mbuf is already part of a valid mbuf chain"); - ADD_ID_TO_FREELIST(np->xn_rx_free_idxs, rx->id); + add_id_to_freelist(np->xn_cdata.xn_rx_chain, rx->id); m->m_data += rx->offset;/* (rx->addr & PAGE_MASK); */ m->m_pkthdr.len = m->m_len = rx->status; @@ -847,7 +984,7 @@ XN_TX_LOCK_ASSERT(np); - if (np->backend_state != BEST_CONNECTED) + if (!netfront_carrier_ok(np)) return; ifp = np->xn_ifp; @@ -878,7 +1015,7 @@ np->grant_tx_ref[id] = GRANT_INVALID_REF; np->xn_cdata.xn_tx_chain[id] = NULL; - ADD_ID_TO_FREELIST(np->xn_tx_free_idxs, id); + add_id_to_freelist(np->xn_cdata.xn_tx_chain, id); m_freem(m); } np->tx.rsp_cons = prod; @@ -919,7 +1056,7 @@ while (np->rx.rsp_cons != np->rx.sring->rsp_prod && - np->user_state == UST_OPEN && + likely(netfront_carrier_ok(np)) && ifp->if_drv_flags & IFF_DRV_RUNNING) { XN_RX_LOCK(np); @@ -975,7 +1112,7 @@ tx_bytes = 0; - if (sc->backend_state != BEST_CONNECTED) + if (!netfront_carrier_ok(sc)) >>> TRUNCATED FOR MAIL (1000 lines) <<<