direct-io.hg

changeset 1831:51332b88e187

bitkeeper revision 1.1108.4.1 (40fccf15MMHXnf0_66am3vGFf6fVDA)

Merge net frontend drivers in 2.4 and 2.6.
Fix some bugs that would cause crashes in low-memory conditions.
There may well be some bugs still lurking, but better hidden than
before!
author kaf24@scramble.cl.cam.ac.uk
date Tue Jul 20 07:51:49 2004 +0000 (2004-07-20)
parents 1a488e40456a
children 79d5d57de7d1
files .rootkeys linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c linux-2.4.26-xen-sparse/mkbuildtree linux-2.6.7-xen-sparse/drivers/xen/net/network.c
line diff
     1.1 --- a/.rootkeys	Sun Jul 18 16:38:30 2004 +0000
     1.2 +++ b/.rootkeys	Tue Jul 20 07:51:49 2004 +0000
     1.3 @@ -72,7 +72,6 @@ 4097ba83glWYwQTkbPqgLIlYDOPVLg linux-2.4
     1.4  4097ba837h2tuiweIWp-voNVzCRI6g linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c
     1.5  4087cf0d5dudKw_DecIJgOhLlBF_0Q linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c
     1.6  405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/Makefile
     1.7 -405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c
     1.8  4097ba83Qy2eafeFUhGhm6_4iMIIDw linux-2.4.26-xen-sparse/arch/xen/drivers/netif/netif.h
     1.9  3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.26-xen-sparse/arch/xen/kernel/Makefile
    1.10  4075806dE5mQwlVUf8-t3YXjiMMWDQ linux-2.4.26-xen-sparse/arch/xen/kernel/ctrl_if.c
    1.11 @@ -199,7 +198,7 @@ 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6
    1.12  40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.7-xen-sparse/drivers/xen/evtchn/evtchn.c
    1.13  40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.7-xen-sparse/drivers/xen/net/Kconfig
    1.14  40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.7-xen-sparse/drivers/xen/net/Makefile
    1.15 -40f56239vUsbJCS9tGFfRVi1YZlGEg linux-2.6.7-xen-sparse/drivers/xen/net/network.c
    1.16 +405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.7-xen-sparse/drivers/xen/net/network.c
    1.17  40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/desc.h
    1.18  40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/e820.h
    1.19  40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.7-xen-sparse/include/asm-xen/asm-i386/fixmap.h
     2.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c	Sun Jul 18 16:38:30 2004 +0000
     2.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c	Tue Jul 20 07:51:49 2004 +0000
     2.3 @@ -495,7 +495,7 @@ static void net_tx_action(unsigned long 
     2.4  
     2.5          pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
     2.6  
     2.7 -        if ( unlikely((skb = dev_alloc_skb(PKT_PROT_LEN)) == NULL) )
     2.8 +        if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) )
     2.9          {
    2.10              DPRINTK("Can't allocate a skb in start_xmit.\n");
    2.11              make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
    2.12 @@ -503,6 +503,9 @@ static void net_tx_action(unsigned long 
    2.13              break;
    2.14          }
    2.15  
    2.16 +        /* Packets passed to netif_rx() must have some headroom. */
    2.17 +        skb_reserve(skb, 16);
    2.18 +
    2.19          mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
    2.20          mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
    2.21          mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
     3.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/frontend/main.c	Sun Jul 18 16:38:30 2004 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,867 +0,0 @@
     3.4 -/******************************************************************************
     3.5 - * arch/xen/drivers/netif/frontend/main.c
     3.6 - * 
     3.7 - * Virtual network driver for conversing with remote driver backends.
     3.8 - * 
     3.9 - * Copyright (c) 2002-2004, K A Fraser
    3.10 - */
    3.11 -
    3.12 -#include <linux/config.h>
    3.13 -#include <linux/module.h>
    3.14 -
    3.15 -#include <linux/kernel.h>
    3.16 -#include <linux/sched.h>
    3.17 -#include <linux/slab.h>
    3.18 -#include <linux/string.h>
    3.19 -#include <linux/errno.h>
    3.20 -
    3.21 -#include <linux/netdevice.h>
    3.22 -#include <linux/inetdevice.h>
    3.23 -#include <linux/etherdevice.h>
    3.24 -#include <linux/skbuff.h>
    3.25 -#include <linux/init.h>
    3.26 -
    3.27 -#include <asm/io.h>
    3.28 -#include <net/sock.h>
    3.29 -#include <net/pkt_sched.h>
    3.30 -
    3.31 -#include <asm/evtchn.h>
    3.32 -#include <asm/ctrl_if.h>
    3.33 -
    3.34 -#include <asm/page.h>
    3.35 -
    3.36 -#include "../netif.h"
    3.37 -
    3.38 -#define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
    3.39 -
    3.40 -static void network_tx_buf_gc(struct net_device *dev);
    3.41 -static void network_alloc_rx_buffers(struct net_device *dev);
    3.42 -
    3.43 -static unsigned long rx_pfn_array[NETIF_RX_RING_SIZE];
    3.44 -static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE+1];
    3.45 -static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
    3.46 -
    3.47 -static struct list_head dev_list;
    3.48 -
    3.49 -struct net_private
    3.50 -{
    3.51 -    struct list_head list;
    3.52 -    struct net_device *dev;
    3.53 -
    3.54 -    struct net_device_stats stats;
    3.55 -    NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
    3.56 -    unsigned int tx_full;
    3.57 -    
    3.58 -    netif_tx_interface_t *tx;
    3.59 -    netif_rx_interface_t *rx;
    3.60 -
    3.61 -    spinlock_t   tx_lock;
    3.62 -    spinlock_t   rx_lock;
    3.63 -
    3.64 -    unsigned int handle;
    3.65 -    unsigned int evtchn;
    3.66 -    unsigned int irq;
    3.67 -
    3.68 -    /* What is the status of our connection to the remote backend? */
    3.69 -#define BEST_CLOSED       0
    3.70 -#define BEST_DISCONNECTED 1
    3.71 -#define BEST_CONNECTED    2
    3.72 -    unsigned int backend_state;
    3.73 -
    3.74 -    /* Is this interface open or closed (down or up)? */
    3.75 -#define UST_CLOSED        0
    3.76 -#define UST_OPEN          1
    3.77 -    unsigned int user_state;
    3.78 -
    3.79 -    /*
    3.80 -     * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
    3.81 -     * array is an index into a chain of free entries.
    3.82 -     */
    3.83 -    struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1];
    3.84 -    struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
    3.85 -};
    3.86 -
    3.87 -/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
    3.88 -#define ADD_ID_TO_FREELIST(_list, _id)             \
    3.89 -    (_list)[(_id)] = (_list)[0];                   \
    3.90 -    (_list)[0]     = (void *)(unsigned long)(_id);
    3.91 -#define GET_ID_FROM_FREELIST(_list)                \
    3.92 - ({ unsigned long _id = (unsigned long)(_list)[0]; \
    3.93 -    (_list)[0]  = (_list)[_id];                    \
    3.94 -    (unsigned short)_id; })
    3.95 -
    3.96 -static struct net_device *find_dev_by_handle(unsigned int handle)
    3.97 -{
    3.98 -    struct list_head *ent;
    3.99 -    struct net_private *np;
   3.100 -    list_for_each ( ent, &dev_list )
   3.101 -    {
   3.102 -        np = list_entry(ent, struct net_private, list);
   3.103 -        if ( np->handle == handle )
   3.104 -            return np->dev;
   3.105 -    }
   3.106 -    return NULL;
   3.107 -}
   3.108 -
   3.109 -/** Network interface info. */
   3.110 -struct netif_ctrl {
   3.111 -    /** Number of interfaces. */
   3.112 -    int interface_n;
   3.113 -    /** Number of connected interfaces. */
   3.114 -    int connected_n;
   3.115 -    /** Error code. */
   3.116 -    int err;
   3.117 -};
   3.118 -
   3.119 -static struct netif_ctrl netctrl;
   3.120 -
   3.121 -static void netctrl_init(void)
   3.122 -{
   3.123 -    memset(&netctrl, 0, sizeof(netctrl));
   3.124 -    netctrl.interface_n = -1;
   3.125 -}
   3.126 -
   3.127 -/** Get or set a network interface error.
   3.128 - */
   3.129 -static int netctrl_err(int err)
   3.130 -{
   3.131 -    if(err < 0 && !netctrl.err){
   3.132 -        netctrl.err = err;
   3.133 -        printk(KERN_WARNING "%s> err=%d\n", __FUNCTION__, err);
   3.134 -    }
   3.135 -    return netctrl.err;
   3.136 -}
   3.137 -
   3.138 -/** Test if all network interfaces are connected.
   3.139 - *
   3.140 - * @return 1 if all connected, 0 if not, negative error code otherwise
   3.141 - */
   3.142 -static int netctrl_connected(void)
   3.143 -{
   3.144 -    int ok = 0;
   3.145 -    ok = (netctrl.err ? netctrl.err :
   3.146 -          (netctrl.connected_n == netctrl.interface_n));
   3.147 -    return ok;
   3.148 -}
   3.149 -
   3.150 -/** Count the connected network interfaces.
   3.151 - *
   3.152 - * @return connected count
   3.153 - */
   3.154 -static int netctrl_connected_count(void)
   3.155 -{
   3.156 -    
   3.157 -    struct list_head *ent;
   3.158 -    struct net_private *np;
   3.159 -    unsigned int connected;
   3.160 -
   3.161 -    connected = 0;
   3.162 -    
   3.163 -    list_for_each(ent, &dev_list)
   3.164 -    {
   3.165 -        np = list_entry(ent, struct net_private, list);
   3.166 -        if ( np->backend_state == BEST_CONNECTED )
   3.167 -            connected++;
   3.168 -    }
   3.169 -
   3.170 -    netctrl.connected_n = connected;
   3.171 -    return connected;
   3.172 -}
   3.173 -
   3.174 -static int network_open(struct net_device *dev)
   3.175 -{
   3.176 -    struct net_private *np = dev->priv;
   3.177 -
   3.178 -    memset(&np->stats, 0, sizeof(np->stats));
   3.179 -
   3.180 -    np->user_state = UST_OPEN;
   3.181 -
   3.182 -    network_alloc_rx_buffers(dev);
   3.183 -    np->rx->event = np->rx_resp_cons + 1;
   3.184 -
   3.185 -    netif_start_queue(dev);
   3.186 -
   3.187 -    return 0;
   3.188 -}
   3.189 -
   3.190 -
   3.191 -static void network_tx_buf_gc(struct net_device *dev)
   3.192 -{
   3.193 -    NETIF_RING_IDX i, prod;
   3.194 -    unsigned short id;
   3.195 -    struct net_private *np = dev->priv;
   3.196 -    struct sk_buff *skb;
   3.197 -
   3.198 -    if ( np->backend_state != BEST_CONNECTED )
   3.199 -        return;
   3.200 -
   3.201 -    do {
   3.202 -        prod = np->tx->resp_prod;
   3.203 -
   3.204 -        for ( i = np->tx_resp_cons; i != prod; i++ )
   3.205 -        {
   3.206 -            id  = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
   3.207 -            skb = np->tx_skbs[id];
   3.208 -            ADD_ID_TO_FREELIST(np->tx_skbs, id);
   3.209 -            dev_kfree_skb_any(skb);
   3.210 -        }
   3.211 -        
   3.212 -        np->tx_resp_cons = prod;
   3.213 -        
   3.214 -        /*
   3.215 -         * Set a new event, then check for race with update of tx_cons. Note
   3.216 -         * that it is essential to schedule a callback, no matter how few
   3.217 -         * buffers are pending. Even if there is space in the transmit ring,
   3.218 -         * higher layers may be blocked because too much data is outstanding:
   3.219 -         * in such cases notification from Xen is likely to be the only kick
   3.220 -         * that we'll get.
   3.221 -         */
   3.222 -        np->tx->event = 
   3.223 -            prod + ((np->tx->req_prod - prod) >> 1) + 1;
   3.224 -        mb();
   3.225 -    }
   3.226 -    while ( prod != np->tx->resp_prod );
   3.227 -
   3.228 -    if ( np->tx_full && 
   3.229 -         ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE) )
   3.230 -    {
   3.231 -        np->tx_full = 0;
   3.232 -        if ( np->user_state == UST_OPEN )
   3.233 -            netif_wake_queue(dev);
   3.234 -    }
   3.235 -}
   3.236 -
   3.237 -
   3.238 -static void network_alloc_rx_buffers(struct net_device *dev)
   3.239 -{
   3.240 -    unsigned short id;
   3.241 -    struct net_private *np = dev->priv;
   3.242 -    struct sk_buff *skb;
   3.243 -    NETIF_RING_IDX i = np->rx->req_prod;
   3.244 -    int nr_pfns = 0;
   3.245 -
   3.246 -    /* Make sure the batch is large enough to be worthwhile (1/2 ring). */
   3.247 -    if ( unlikely((i - np->rx_resp_cons) > (NETIF_RX_RING_SIZE/2)) || 
   3.248 -         unlikely(np->backend_state != BEST_CONNECTED) )
   3.249 -        return;
   3.250 -
   3.251 -    do {
   3.252 -        skb = dev_alloc_skb(RX_BUF_SIZE);
   3.253 -        if ( unlikely(skb == NULL) )
   3.254 -            break;
   3.255 -
   3.256 -        skb->dev = dev;
   3.257 -
   3.258 -        if ( unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) )
   3.259 -            panic("alloc_skb needs to provide us page-aligned buffers.");
   3.260 -
   3.261 -        id = GET_ID_FROM_FREELIST(np->rx_skbs);
   3.262 -
   3.263 -        np->rx_skbs[id] = skb;
   3.264 -        
   3.265 -        np->rx->ring[MASK_NETIF_RX_IDX(i)].req.id = id;
   3.266 -        
   3.267 -        rx_pfn_array[nr_pfns] = virt_to_machine(skb->head) >> PAGE_SHIFT;
   3.268 -
   3.269 -        rx_mcl[nr_pfns].op = __HYPERVISOR_update_va_mapping;
   3.270 -        rx_mcl[nr_pfns].args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
   3.271 -        rx_mcl[nr_pfns].args[1] = 0;
   3.272 -        rx_mcl[nr_pfns].args[2] = 0;
   3.273 -
   3.274 -        nr_pfns++;
   3.275 -    }
   3.276 -    while ( (++i - np->rx_resp_cons) != NETIF_RX_RING_SIZE );
   3.277 -
   3.278 -    /*
   3.279 -     * We may have allocated buffers which have entries outstanding in the page
   3.280 -     * update queue -- make sure we flush those first!
   3.281 -     */
   3.282 -    flush_page_update_queue();
   3.283 -
   3.284 -    /* After all PTEs have been zapped we blow away stale TLB entries. */
   3.285 -    rx_mcl[nr_pfns-1].args[2] = UVMF_FLUSH_TLB;
   3.286 -
   3.287 -    /* Give away a batch of pages. */
   3.288 -    rx_mcl[nr_pfns].op = __HYPERVISOR_dom_mem_op;
   3.289 -    rx_mcl[nr_pfns].args[0] = MEMOP_decrease_reservation;
   3.290 -    rx_mcl[nr_pfns].args[1] = (unsigned long)rx_pfn_array;
   3.291 -    rx_mcl[nr_pfns].args[2] = (unsigned long)nr_pfns;
   3.292 -
   3.293 -    /* Zap PTEs and give away pages in one big multicall. */
   3.294 -    (void)HYPERVISOR_multicall(rx_mcl, nr_pfns+1);
   3.295 -
   3.296 -    /* Check return status of HYPERVISOR_dom_mem_op(). */
   3.297 -    if ( rx_mcl[nr_pfns].args[5] != nr_pfns )
   3.298 -        panic("Unable to reduce memory reservation\n");
   3.299 -
   3.300 -    np->rx->req_prod = i;
   3.301 -}
   3.302 -
   3.303 -
   3.304 -static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
   3.305 -{
   3.306 -    unsigned short id;
   3.307 -    struct net_private *np = (struct net_private *)dev->priv;
   3.308 -    netif_tx_request_t *tx;
   3.309 -    NETIF_RING_IDX i;
   3.310 -
   3.311 -    if ( unlikely(np->tx_full) )
   3.312 -    {
   3.313 -        printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name);
   3.314 -        netif_stop_queue(dev);
   3.315 -        return -ENOBUFS;
   3.316 -    }
   3.317 -
   3.318 -    if ( unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >=
   3.319 -                  PAGE_SIZE) )
   3.320 -    {
   3.321 -        struct sk_buff *new_skb = dev_alloc_skb(RX_BUF_SIZE);
   3.322 -        if ( unlikely(new_skb == NULL) )
   3.323 -            return 1;
   3.324 -        skb_put(new_skb, skb->len);
   3.325 -        memcpy(new_skb->data, skb->data, skb->len);
   3.326 -        dev_kfree_skb(skb);
   3.327 -        skb = new_skb;
   3.328 -    }
   3.329 -    
   3.330 -    spin_lock_irq(&np->tx_lock);
   3.331 -
   3.332 -    if ( np->backend_state != BEST_CONNECTED )
   3.333 -    {
   3.334 -        spin_unlock_irq(&np->tx_lock);
   3.335 -        return 1;
   3.336 -    }
   3.337 -
   3.338 -    i = np->tx->req_prod;
   3.339 -
   3.340 -    id = GET_ID_FROM_FREELIST(np->tx_skbs);
   3.341 -    np->tx_skbs[id] = skb;
   3.342 -
   3.343 -    tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
   3.344 -
   3.345 -    tx->id   = id;
   3.346 -    tx->addr = virt_to_machine(skb->data);
   3.347 -    tx->size = skb->len;
   3.348 -
   3.349 -    wmb();
   3.350 -    np->tx->req_prod = i + 1;
   3.351 -
   3.352 -    network_tx_buf_gc(dev);
   3.353 -
   3.354 -    if ( (i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1) )
   3.355 -    {
   3.356 -        np->tx_full = 1;
   3.357 -        netif_stop_queue(dev);
   3.358 -    }
   3.359 -
   3.360 -    spin_unlock_irq(&np->tx_lock);
   3.361 -
   3.362 -    np->stats.tx_bytes += skb->len;
   3.363 -    np->stats.tx_packets++;
   3.364 -
   3.365 -    /* Only notify Xen if there are no outstanding responses. */
   3.366 -    mb();
   3.367 -    if ( np->tx->resp_prod == i )
   3.368 -        notify_via_evtchn(np->evtchn);
   3.369 -
   3.370 -    return 0;
   3.371 -}
   3.372 -
   3.373 -
   3.374 -static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
   3.375 -{
   3.376 -    struct net_device *dev = dev_id;
   3.377 -    struct net_private *np = dev->priv;
   3.378 -    unsigned long flags;
   3.379 -
   3.380 -    spin_lock_irqsave(&np->tx_lock, flags);
   3.381 -    network_tx_buf_gc(dev);
   3.382 -    spin_unlock_irqrestore(&np->tx_lock, flags);
   3.383 -
   3.384 -    if ( (np->rx_resp_cons != np->rx->resp_prod) &&
   3.385 -         (np->user_state == UST_OPEN) )
   3.386 -        netif_rx_schedule(dev);
   3.387 -}
   3.388 -
   3.389 -
   3.390 -static int netif_poll(struct net_device *dev, int *pbudget)
   3.391 -{
   3.392 -    struct net_private *np = dev->priv;
   3.393 -    struct sk_buff *skb;
   3.394 -    netif_rx_response_t *rx;
   3.395 -    NETIF_RING_IDX i;
   3.396 -    mmu_update_t *mmu = rx_mmu;
   3.397 -    multicall_entry_t *mcl = rx_mcl;
   3.398 -    int work_done, budget, more_to_do = 1;
   3.399 -    struct sk_buff_head rxq;
   3.400 -    unsigned long flags;
   3.401 -
   3.402 -    spin_lock(&np->rx_lock);
   3.403 -
   3.404 -    if ( np->backend_state != BEST_CONNECTED )
   3.405 -    {
   3.406 -        spin_unlock(&np->rx_lock);
   3.407 -        return 0;
   3.408 -    }
   3.409 -
   3.410 -    skb_queue_head_init(&rxq);
   3.411 -
   3.412 -    if ( (budget = *pbudget) > dev->quota )
   3.413 -        budget = dev->quota;
   3.414 -
   3.415 -    for ( i = np->rx_resp_cons, work_done = 0; 
   3.416 -          (i != np->rx->resp_prod) && (work_done < budget); 
   3.417 -          i++, work_done++ )
   3.418 -    {
   3.419 -        rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
   3.420 -
   3.421 -        skb = np->rx_skbs[rx->id];
   3.422 -        ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
   3.423 -
   3.424 -        if ( unlikely(rx->status <= 0) )
   3.425 -        {
   3.426 -            /* Gate this error. We get a (valid) slew of them on suspend. */
   3.427 -            if ( np->user_state != UST_OPEN )
   3.428 -                printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
   3.429 -            dev_kfree_skb(skb);
   3.430 -            continue;
   3.431 -        }
   3.432 -
   3.433 -        skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK);
   3.434 -        skb_put(skb, rx->status);
   3.435 -
   3.436 -        np->stats.rx_packets++;
   3.437 -        np->stats.rx_bytes += rx->status;
   3.438 -
   3.439 -        /* Remap the page. */
   3.440 -        mmu->ptr  = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
   3.441 -        mmu->val  = __pa(skb->head) >> PAGE_SHIFT;
   3.442 -        mmu++;
   3.443 -        mcl->op = __HYPERVISOR_update_va_mapping;
   3.444 -        mcl->args[0] = (unsigned long)skb->head >> PAGE_SHIFT;
   3.445 -        mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL;
   3.446 -        mcl->args[2] = 0;
   3.447 -        mcl++;
   3.448 -
   3.449 -        phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = 
   3.450 -            rx->addr >> PAGE_SHIFT;
   3.451 -
   3.452 -        __skb_queue_tail(&rxq, skb);
   3.453 -    }
   3.454 -
   3.455 -    /* Do all the remapping work, and M->P updates, in one big hypercall. */
   3.456 -    if ( likely((mcl - rx_mcl) != 0) )
   3.457 -    {
   3.458 -        mcl->op = __HYPERVISOR_mmu_update;
   3.459 -        mcl->args[0] = (unsigned long)rx_mmu;
   3.460 -        mcl->args[1] = mmu - rx_mmu;
   3.461 -        mcl->args[2] = 0;
   3.462 -        mcl++;
   3.463 -        (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
   3.464 -    }
   3.465 -
   3.466 -    while ( (skb = __skb_dequeue(&rxq)) != NULL )
   3.467 -    {
   3.468 -        /* Set the shared-info area, which is hidden behind the real data. */
   3.469 -        atomic_set(&(skb_shinfo(skb)->dataref), 1);
   3.470 -        skb_shinfo(skb)->nr_frags = 0;
   3.471 -        skb_shinfo(skb)->frag_list = NULL;
   3.472 -
   3.473 -        /* Ethernet-specific work. Delayed to here as it peeks the header. */
   3.474 -        skb->protocol = eth_type_trans(skb, dev);
   3.475 -
   3.476 -        /* Pass it up. */
   3.477 -        netif_rx(skb);
   3.478 -        dev->last_rx = jiffies;
   3.479 -    }
   3.480 -
   3.481 -    np->rx_resp_cons = i;
   3.482 -
   3.483 -    network_alloc_rx_buffers(dev);
   3.484 -
   3.485 -    *pbudget   -= work_done;
   3.486 -    dev->quota -= work_done;
   3.487 -
   3.488 -    if ( work_done < budget )
   3.489 -    {
   3.490 -        local_irq_save(flags);
   3.491 -
   3.492 -        np->rx->event = i + 1;
   3.493 -    
   3.494 -        /* Deal with hypervisor racing our resetting of rx_event. */
   3.495 -        mb();
   3.496 -        if ( np->rx->resp_prod == i )
   3.497 -        {
   3.498 -            __netif_rx_complete(dev);
   3.499 -            more_to_do = 0;
   3.500 -        }
   3.501 -
   3.502 -        local_irq_restore(flags);
   3.503 -    }
   3.504 -
   3.505 -    spin_unlock(&np->rx_lock);
   3.506 -
   3.507 -    return more_to_do;
   3.508 -}
   3.509 -
   3.510 -
   3.511 -static int network_close(struct net_device *dev)
   3.512 -{
   3.513 -    struct net_private *np = dev->priv;
   3.514 -    np->user_state = UST_CLOSED;
   3.515 -    netif_stop_queue(np->dev);
   3.516 -    return 0;
   3.517 -}
   3.518 -
   3.519 -
   3.520 -static struct net_device_stats *network_get_stats(struct net_device *dev)
   3.521 -{
   3.522 -    struct net_private *np = (struct net_private *)dev->priv;
   3.523 -    return &np->stats;
   3.524 -}
   3.525 -
   3.526 -
   3.527 -static void network_connect(struct net_device *dev,
   3.528 -                            netif_fe_interface_status_changed_t *status)
   3.529 -{
   3.530 -    struct net_private *np;
   3.531 -    int i, requeue_idx;
   3.532 -    netif_tx_request_t *tx;
   3.533 -
   3.534 -    np = dev->priv;
   3.535 -    spin_lock_irq(&np->rx_lock);
   3.536 -    spin_lock(&np->tx_lock);
   3.537 -
   3.538 -    /* Recovery procedure: */
   3.539 -
   3.540 -    /* Step 1: Reinitialise variables. */
   3.541 -    np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
   3.542 -    np->rx->event = 1;
   3.543 -
   3.544 -    /* Step 2: Rebuild the RX and TX ring contents.
   3.545 -     * NB. We could just free the queued TX packets now but we hope
   3.546 -     * that sending them out might do some good.  We have to rebuild
   3.547 -     * the RX ring because some of our pages are currently flipped out
   3.548 -     * so we can't just free the RX skbs.
   3.549 -     * NB2. Freelist index entries are always going to be less than
   3.550 -     *  __PAGE_OFFSET, whereas pointers to skbs will always be equal or
   3.551 -     * greater than __PAGE_OFFSET: we use this property to distinguish
   3.552 -     * them.
   3.553 -     */
   3.554 -
   3.555 -    /* Rebuild the TX buffer freelist and the TX ring itself.
   3.556 -     * NB. This reorders packets.  We could keep more private state
   3.557 -     * to avoid this but maybe it doesn't matter so much given the
   3.558 -     * interface has been down.
   3.559 -     */
   3.560 -    for ( requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++ )
   3.561 -    {
   3.562 -            if ( (unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET )
   3.563 -            {
   3.564 -                struct sk_buff *skb = np->tx_skbs[i];
   3.565 -                
   3.566 -                tx = &np->tx->ring[requeue_idx++].req;
   3.567 -                
   3.568 -                tx->id   = i;
   3.569 -                tx->addr = virt_to_machine(skb->data);
   3.570 -                tx->size = skb->len;
   3.571 -                
   3.572 -                np->stats.tx_bytes += skb->len;
   3.573 -                np->stats.tx_packets++;
   3.574 -            }
   3.575 -    }
   3.576 -    wmb();
   3.577 -    np->tx->req_prod = requeue_idx;
   3.578 -
   3.579 -    /* Rebuild the RX buffer freelist and the RX ring itself. */
   3.580 -    for ( requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++ )
   3.581 -        if ( (unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET )
   3.582 -            np->rx->ring[requeue_idx++].req.id = i;
   3.583 -    wmb();                
   3.584 -    np->rx->req_prod = requeue_idx;
   3.585 -
   3.586 -    /* Step 3: All public and private state should now be sane.  Get
   3.587 -     * ready to start sending and receiving packets and give the driver
   3.588 -     * domain a kick because we've probably just requeued some
   3.589 -     * packets.
   3.590 -     */
   3.591 -    np->backend_state = BEST_CONNECTED;
   3.592 -    notify_via_evtchn(status->evtchn);  
   3.593 -    network_tx_buf_gc(dev);
   3.594 -
   3.595 -    if ( np->user_state == UST_OPEN )
   3.596 -        netif_start_queue(dev);
   3.597 -
   3.598 -    spin_unlock(&np->tx_lock);
   3.599 -    spin_unlock_irq(&np->rx_lock);
   3.600 -}
   3.601 -
   3.602 -static void netif_status_change(netif_fe_interface_status_changed_t *status)
   3.603 -{
   3.604 -    ctrl_msg_t                   cmsg;
   3.605 -    netif_fe_interface_connect_t up;
   3.606 -    struct net_device *dev;
   3.607 -    struct net_private *np;
   3.608 -    
   3.609 -    if ( netctrl.interface_n <= 0 )
   3.610 -    {
   3.611 -        printk(KERN_WARNING "Status change: no interfaces\n");
   3.612 -        return;
   3.613 -    }
   3.614 -
   3.615 -    dev = find_dev_by_handle(status->handle);
   3.616 -    if(!dev){
   3.617 -        printk(KERN_WARNING "Status change: invalid netif handle %u\n",
   3.618 -               status->handle);
   3.619 -         return;
   3.620 -    }
   3.621 -    np  = dev->priv;
   3.622 -    
   3.623 -    switch ( status->status )
   3.624 -    {
   3.625 -    case NETIF_INTERFACE_STATUS_DESTROYED:
   3.626 -        printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n",
   3.627 -               np->backend_state);
   3.628 -        break;
   3.629 -
   3.630 -    case NETIF_INTERFACE_STATUS_DISCONNECTED:
   3.631 -        if ( np->backend_state != BEST_CLOSED )
   3.632 -        {
   3.633 -            printk(KERN_WARNING "Unexpected netif-DISCONNECTED message"
   3.634 -                   " in state %d\n", np->backend_state);
   3.635 -	    printk(KERN_INFO "Attempting to reconnect network interface\n");
   3.636 -
   3.637 -            /* Begin interface recovery.
   3.638 -	     *
   3.639 -	     * NB. Whilst we're recovering, we turn the carrier state off.  We
   3.640 -	     * take measures to ensure that this device isn't used for
   3.641 -	     * anything.  We also stop the queue for this device.  Various
   3.642 -	     * different approaches (e.g. continuing to buffer packets) have
   3.643 -	     * been tested but don't appear to improve the overall impact on
   3.644 -             * TCP connections.
   3.645 -	     *
   3.646 -             * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
   3.647 -             * is initiated by a special "RESET" message - disconnect could
   3.648 -             * just mean we're not allowed to use this interface any more.
   3.649 -             */
   3.650 -
   3.651 -            /* Stop old i/f to prevent errors whilst we rebuild the state. */
   3.652 -            spin_lock_irq(&np->tx_lock);
   3.653 -            spin_lock(&np->rx_lock);
   3.654 -            netif_stop_queue(dev);
   3.655 -            np->backend_state = BEST_DISCONNECTED;
   3.656 -            spin_unlock(&np->rx_lock);
   3.657 -            spin_unlock_irq(&np->tx_lock);
   3.658 -
   3.659 -            /* Free resources. */
   3.660 -            free_irq(np->irq, dev);
   3.661 -            unbind_evtchn_from_irq(np->evtchn);
   3.662 -	    free_page((unsigned long)np->tx);
   3.663 -            free_page((unsigned long)np->rx);
   3.664 -        }
   3.665 -
   3.666 -        /* Move from CLOSED to DISCONNECTED state. */
   3.667 -        np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
   3.668 -        np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
   3.669 -        memset(np->tx, 0, PAGE_SIZE);
   3.670 -        memset(np->rx, 0, PAGE_SIZE);
   3.671 -        np->backend_state = BEST_DISCONNECTED;
   3.672 -
   3.673 -        /* Construct an interface-CONNECT message for the domain controller. */
   3.674 -        cmsg.type      = CMSG_NETIF_FE;
   3.675 -        cmsg.subtype   = CMSG_NETIF_FE_INTERFACE_CONNECT;
   3.676 -        cmsg.length    = sizeof(netif_fe_interface_connect_t);
   3.677 -        up.handle      = status->handle;
   3.678 -        up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
   3.679 -        up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
   3.680 -        memcpy(cmsg.msg, &up, sizeof(up));
   3.681 -        
   3.682 -        /* Tell the controller to bring up the interface. */
   3.683 -        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   3.684 -        break;
   3.685 -
   3.686 -    case NETIF_INTERFACE_STATUS_CONNECTED:
   3.687 -        if ( np->backend_state == BEST_CLOSED )
   3.688 -        {
   3.689 -            printk(KERN_WARNING "Unexpected netif-CONNECTED message"
   3.690 -                   " in state %d\n", np->backend_state);
   3.691 -            break;
   3.692 -        }
   3.693 -
   3.694 -        memcpy(dev->dev_addr, status->mac, ETH_ALEN);
   3.695 -
   3.696 -        network_connect(dev, status);
   3.697 -
   3.698 -        np->evtchn = status->evtchn;
   3.699 -        np->irq = bind_evtchn_to_irq(np->evtchn);
   3.700 -        (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, 
   3.701 -                          dev->name, dev);
   3.702 -        
   3.703 -        netctrl_connected_count();
   3.704 -        break;
   3.705 -
   3.706 -    default:
   3.707 -        printk(KERN_WARNING "Status change to unknown value %d\n", 
   3.708 -               status->status);
   3.709 -        break;
   3.710 -    }
   3.711 -}
   3.712 -
   3.713 -/** Create a network device.
   3.714 - * @param handle device handle
   3.715 - * @param val return parameter for created device
   3.716 - * @return 0 on success, error code otherwise
   3.717 - */
   3.718 -static int create_netdev(int handle, struct net_device **val)
   3.719 -{
   3.720 -    int i, err = 0;
   3.721 -    struct net_device *dev = NULL;
   3.722 -    struct net_private *np = NULL;
   3.723 -
   3.724 -    if ( (dev = alloc_etherdev(sizeof(struct net_private))) == NULL )
   3.725 -    {
   3.726 -        printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__);
   3.727 -        err = -ENOMEM;
   3.728 -        goto exit;
   3.729 -    }
   3.730 -
   3.731 -    np                = dev->priv;
   3.732 -    np->backend_state = BEST_CLOSED;
   3.733 -    np->user_state    = UST_CLOSED;
   3.734 -    np->handle        = handle;
   3.735 -    
   3.736 -    spin_lock_init(&np->tx_lock);
   3.737 -    spin_lock_init(&np->rx_lock);
   3.738 -
   3.739 -    /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
   3.740 -    for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ )
   3.741 -        np->tx_skbs[i] = (void *)(i+1);
   3.742 -    for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ )
   3.743 -        np->rx_skbs[i] = (void *)(i+1);
   3.744 -
   3.745 -    dev->open            = network_open;
   3.746 -    dev->hard_start_xmit = network_start_xmit;
   3.747 -    dev->stop            = network_close;
   3.748 -    dev->get_stats       = network_get_stats;
   3.749 -    dev->poll            = netif_poll;
   3.750 -    dev->weight          = 64;
   3.751 -    
   3.752 -    if ( (err = register_netdev(dev)) != 0 )
   3.753 -    {
   3.754 -        printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
   3.755 -        goto exit;
   3.756 -    }
   3.757 -    np->dev = dev;
   3.758 -    list_add(&np->list, &dev_list);
   3.759 -
   3.760 -  exit:
   3.761 -    if ( (err != 0) && (dev != NULL ) )
   3.762 -        kfree(dev);
   3.763 -    else if ( val != NULL )
   3.764 -        *val = dev;
   3.765 -    return err;
   3.766 -}
   3.767 -
   3.768 -/*
   3.769 - * Initialize the network control interface. Set the number of network devices
   3.770 - * and create them.
   3.771 - */
   3.772 -static void netif_driver_status_change(
   3.773 -    netif_fe_driver_status_changed_t *status)
   3.774 -{
   3.775 -    int err = 0;
   3.776 -    int i;
   3.777 -    
   3.778 -    netctrl.interface_n = status->nr_interfaces;
   3.779 -    netctrl.connected_n = 0;
   3.780 -
   3.781 -    for ( i = 0; i < netctrl.interface_n; i++ )
   3.782 -    {
   3.783 -        if ( (err = create_netdev(i, NULL)) != 0 )
   3.784 -        {
   3.785 -            netctrl_err(err);
   3.786 -            break;
   3.787 -        }
   3.788 -    }
   3.789 -}
   3.790 -
   3.791 -static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
   3.792 -{
   3.793 -    int respond = 1;
   3.794 -
   3.795 -    switch ( msg->subtype )
   3.796 -    {
   3.797 -    case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
   3.798 -        if ( msg->length != sizeof(netif_fe_interface_status_changed_t) )
   3.799 -            goto error;
   3.800 -        netif_status_change((netif_fe_interface_status_changed_t *)
   3.801 -                            &msg->msg[0]);
   3.802 -        break;
   3.803 -
   3.804 -    case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
   3.805 -        if ( msg->length != sizeof(netif_fe_driver_status_changed_t) )
   3.806 -            goto error;
   3.807 -        netif_driver_status_change((netif_fe_driver_status_changed_t *)
   3.808 -                                   &msg->msg[0]);
   3.809 -        /* Message is a response */
   3.810 -        respond = 0;
   3.811 -        break;
   3.812 -
   3.813 -    error:
   3.814 -    default:
   3.815 -        msg->length = 0;
   3.816 -        break;
   3.817 -    }
   3.818 -
   3.819 -    if ( respond )
   3.820 -        ctrl_if_send_response(msg);
   3.821 -}
   3.822 -
   3.823 -
   3.824 -static int __init netif_init(void)
   3.825 -{
   3.826 -    ctrl_msg_t                       cmsg;
   3.827 -    netif_fe_driver_status_changed_t st;
   3.828 -    int err = 0, wait_i, wait_n = 20;
   3.829 -
   3.830 -    if ( (start_info.flags & SIF_INITDOMAIN) ||
   3.831 -         (start_info.flags & SIF_NET_BE_DOMAIN) )
   3.832 -        return 0;
   3.833 -
   3.834 -    printk("Initialising Xen virtual ethernet frontend driver");
   3.835 -
   3.836 -    INIT_LIST_HEAD(&dev_list);
   3.837 -
   3.838 -    netctrl_init();
   3.839 -
   3.840 -    (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
   3.841 -                                    CALLBACK_IN_BLOCKING_CONTEXT);
   3.842 -
   3.843 -    /* Send a driver-UP notification to the domain controller. */
   3.844 -    cmsg.type      = CMSG_NETIF_FE;
   3.845 -    cmsg.subtype   = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
   3.846 -    cmsg.length    = sizeof(netif_fe_driver_status_changed_t);
   3.847 -    st.status      = NETIF_DRIVER_STATUS_UP;
   3.848 -    st.nr_interfaces = 0;
   3.849 -    memcpy(cmsg.msg, &st, sizeof(st));
   3.850 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   3.851 -
   3.852 -    /* Wait for all interfaces to be connected. */
   3.853 -    for ( wait_i = 0; ; wait_i++)
   3.854 -    {
   3.855 -        if ( (err = (wait_i < wait_n) ? netctrl_connected() : -ENETDOWN) != 0 )
   3.856 -        {
   3.857 -            err = (err > 0) ? 0 : err;
   3.858 -            break;
   3.859 -        }
   3.860 -        set_current_state(TASK_INTERRUPTIBLE);
   3.861 -        schedule_timeout(1);
   3.862 -     }
   3.863 -
   3.864 -    if ( err )
   3.865 -        ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
   3.866 -
   3.867 -    return err;
   3.868 -}
   3.869 -
   3.870 -__initcall(netif_init);
     4.1 --- a/linux-2.4.26-xen-sparse/mkbuildtree	Sun Jul 18 16:38:30 2004 +0000
     4.2 +++ b/linux-2.4.26-xen-sparse/mkbuildtree	Tue Jul 20 07:51:49 2004 +0000
     4.3 @@ -225,5 +225,5 @@ ln -sf ../../i386/mm/extable.c
     4.4  ln -sf ../../i386/mm/pageattr.c 
     4.5  cd ../drivers/console
     4.6  ln -sf ../../../../${LINUX_26}/drivers/xen/console/console.c 
     4.7 -#cd ../netif/frontend
     4.8 -#ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c
     4.9 +cd ../netif/frontend
    4.10 +ln -sf ../../../../../${LINUX_26}/drivers/xen/net/network.c main.c
     5.1 --- a/linux-2.6.7-xen-sparse/drivers/xen/net/network.c	Sun Jul 18 16:38:30 2004 +0000
     5.2 +++ b/linux-2.6.7-xen-sparse/drivers/xen/net/network.c	Tue Jul 20 07:51:49 2004 +0000
     5.3 @@ -1,6 +1,4 @@
     5.4  /******************************************************************************
     5.5 - * network.c
     5.6 - * 
     5.7   * Virtual network driver for conversing with remote driver backends.
     5.8   * 
     5.9   * Copyright (c) 2002-2004, K A Fraser
    5.10 @@ -8,13 +6,12 @@
    5.11  
    5.12  #include <linux/config.h>
    5.13  #include <linux/module.h>
    5.14 -
    5.15 +#include <linux/version.h>
    5.16  #include <linux/kernel.h>
    5.17  #include <linux/sched.h>
    5.18  #include <linux/slab.h>
    5.19  #include <linux/string.h>
    5.20  #include <linux/errno.h>
    5.21 -
    5.22  #include <linux/netdevice.h>
    5.23  #include <linux/inetdevice.h>
    5.24  #include <linux/etherdevice.h>
    5.25 @@ -30,7 +27,13 @@
    5.26  
    5.27  #include <asm/page.h>
    5.28  
    5.29 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    5.30  #include <asm-xen/netif.h>
    5.31 +#else
    5.32 +#include "../netif.h"
    5.33 +#define irqreturn_t void
    5.34 +#define IRQ_HANDLED
    5.35 +#endif
    5.36  
    5.37  #define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */
    5.38  
    5.39 @@ -368,7 +371,7 @@ static int network_start_xmit(struct sk_
    5.40  }
    5.41  
    5.42  
    5.43 -static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
    5.44 +static void netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
    5.45  {
    5.46      struct net_device *dev = dev_id;
    5.47      struct net_private *np = dev->priv;
    5.48 @@ -381,8 +384,6 @@ static irqreturn_t netif_int(int irq, vo
    5.49      if ( (np->rx_resp_cons != np->rx->resp_prod) &&
    5.50           (np->user_state == UST_OPEN) )
    5.51          netif_rx_schedule(dev);
    5.52 -
    5.53 -    return IRQ_HANDLED;
    5.54  }
    5.55  
    5.56  
    5.57 @@ -417,18 +418,25 @@ static int netif_poll(struct net_device 
    5.58      {
    5.59          rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
    5.60  
    5.61 -        skb = np->rx_skbs[rx->id];
    5.62 -        ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
    5.63 -
    5.64 +        /*
    5.65 +         * An error here is very odd. Usually indicates a backend bug,
    5.66 +         * low-memory condition, or that we didn't have reservation headroom.
    5.67 +         * Whatever - print an error and queue the id again straight away.
    5.68 +         */
    5.69          if ( unlikely(rx->status <= 0) )
    5.70          {
    5.71              /* Gate this error. We get a (valid) slew of them on suspend. */
    5.72 -            if ( np->user_state != UST_OPEN )
    5.73 +            if ( np->user_state == UST_OPEN )
    5.74                  printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
    5.75 -            dev_kfree_skb(skb);
    5.76 +            np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id;
    5.77 +            wmb();
    5.78 +            np->rx->req_prod++;
    5.79              continue;
    5.80          }
    5.81  
    5.82 +        skb = np->rx_skbs[rx->id];
    5.83 +        ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
    5.84 +
    5.85          skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK);
    5.86          skb_put(skb, rx->status);
    5.87