ia64/xen-unstable

changeset 339:edd0a15b4e05

bitkeeper revision 1.154 (3e7af107VaUd3AaItgryI3J0mrJQ1Q)

network.c, dev.c, vif.h, network.h, tg3.c:
Allow reecive of net packets at arbitrary offset in a page. We can now properly support broken NICs which cannot do unaligned receives.
author kaf24@scramble.cl.cam.ac.uk
date Fri Mar 21 11:01:27 2003 +0000 (2003-03-21)
parents 0e31b8633858
children 082bd5f74c47 6c0d4e714b9c
files xen/drivers/net/tg3.c xen/include/hypervisor-ifs/network.h xen/include/xeno/vif.h xen/net/dev.c xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c
line diff
     1.1 --- a/xen/drivers/net/tg3.c	Thu Mar 20 22:01:55 2003 +0000
     1.2 +++ b/xen/drivers/net/tg3.c	Fri Mar 21 11:01:27 2003 +0000
     1.3 @@ -6338,12 +6338,9 @@ static int __devinit tg3_get_invariants(
     1.4  		tp->dev->hard_start_xmit = tg3_start_xmit;
     1.5  
     1.6  	tp->rx_offset = 2;
     1.7 -/* XXX Xen: we trust our ASICs, for better or worse ;-) */
     1.8 -#if 0
     1.9  	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
    1.10  	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
    1.11  		tp->rx_offset = 0;
    1.12 -#endif
    1.13  
    1.14  	/* By default, disable wake-on-lan.  User can change this
    1.15  	 * using ETHTOOL_SWOL.
     2.1 --- a/xen/include/hypervisor-ifs/network.h	Thu Mar 20 22:01:55 2003 +0000
     2.2 +++ b/xen/include/hypervisor-ifs/network.h	Fri Mar 21 11:01:27 2003 +0000
     2.3 @@ -15,15 +15,17 @@
     2.4  #include <linux/types.h>
     2.5  
     2.6  typedef struct tx_entry_st {
     2.7 -	unsigned long  addr;   /* machine address of packet */
     2.8 -	unsigned short size;   /* in bytes */
     2.9 -        unsigned short status; /* per descriptor status. */
    2.10 +    unsigned long  addr;   /* machine address of packet (IN VAR) */
    2.11 +    unsigned short size;   /* in bytes (IN VAR) */
    2.12 +    unsigned char  status; /* per descriptor status (OUT VAR) */
    2.13 +    unsigned char  _unused;
    2.14  } tx_entry_t;
    2.15  
    2.16  typedef struct rx_entry_st {
    2.17 -	unsigned long  addr;   /* machine address of PTE to swizzle */
    2.18 -	unsigned short size;   /* in bytes */
    2.19 -        unsigned short status; /* per descriptor status. */
    2.20 +    unsigned long  addr;   /* machine address of PTE to swizzle (IN VAR) */
    2.21 +    unsigned short size;   /* in bytes (OUT VAR) */
    2.22 +    unsigned char  status; /* per descriptor status (OUT VAR) */
    2.23 +    unsigned char  offset; /* offset in page of received pkt (OUT VAR) */
    2.24  } rx_entry_t;
    2.25  
    2.26  #define TX_RING_SIZE 256
    2.27 @@ -120,12 +122,9 @@ typedef struct net_rule_ent_st
    2.28  /* Drop a new rule down to the network tables. */
    2.29  int add_net_rule(net_rule_t *rule);
    2.30  
    2.31 -
    2.32 -/* Descriptor status values:
    2.33 - */
    2.34 -
    2.35 -#define RING_STATUS_OK               0  // Everything is gravy.
    2.36 -#define RING_STATUS_ERR_CFU         -1  // Copy from user problems.
    2.37 -#define RING_STATUS_BAD_PAGE        -2  // What they gave us was pure evil.
    2.38 +/* Descriptor status values */
    2.39 +#define RING_STATUS_OK               0  /* Everything is gravy. */
    2.40 +#define RING_STATUS_ERR_CFU          1  /* Copy from user problems. */
    2.41 +#define RING_STATUS_BAD_PAGE         2  /* What they gave us was pure evil */
    2.42  
    2.43  #endif
     3.1 --- a/xen/include/xeno/vif.h	Thu Mar 20 22:01:55 2003 +0000
     3.2 +++ b/xen/include/xeno/vif.h	Fri Mar 21 11:01:27 2003 +0000
     3.3 @@ -28,7 +28,8 @@
     3.4  typedef struct rx_shadow_entry_st {
     3.5      unsigned long  addr;
     3.6      unsigned short size;
     3.7 -    unsigned short status;
     3.8 +    unsigned char  status;
     3.9 +    unsigned char  offset;
    3.10      unsigned long  flush_count;
    3.11  } rx_shadow_entry_t;
    3.12  
    3.13 @@ -36,7 +37,8 @@ typedef struct tx_shadow_entry_st {
    3.14      void          *header;
    3.15      unsigned long  payload;
    3.16      unsigned short size;
    3.17 -    unsigned short status;
    3.18 +    unsigned char  status;
    3.19 +    unsigned char  _unused;
    3.20  } tx_shadow_entry_t;
    3.21  
    3.22  typedef struct net_shadow_ring_st {
     4.1 --- a/xen/net/dev.c	Thu Mar 20 22:01:55 2003 +0000
     4.2 +++ b/xen/net/dev.c	Fri Mar 21 11:01:27 2003 +0000
     4.3 @@ -506,9 +506,10 @@ void deliver_packet(struct sk_buff *skb,
     4.4      }
     4.5  
     4.6      rx = shadow_ring->rx_ring + i;
     4.7 -    if ( (skb->len + ETH_HLEN) < rx->size )
     4.8 -        rx->size = skb->len + ETH_HLEN;
     4.9 -            
    4.10 +    ASSERT(skb->len <= PAGE_SIZE);
    4.11 +    rx->size   = skb->len;
    4.12 +    rx->offset = (unsigned char)((unsigned long)skb->data & ~PAGE_MASK);
    4.13 +
    4.14      spin_lock_irqsave(&vif->domain->page_lock, flags);
    4.15  
    4.16      g_pte = map_domain_mem(rx->addr);
    4.17 @@ -559,7 +560,7 @@ void deliver_packet(struct sk_buff *skb,
    4.18  int netif_rx(struct sk_buff *skb)
    4.19  {
    4.20      unsigned long cpu_mask;
    4.21 -    int this_cpu = smp_processor_id();
    4.22 +    int offset, this_cpu = smp_processor_id();
    4.23      unsigned long flags;
    4.24      net_vif_t *vif;
    4.25  
    4.26 @@ -567,23 +568,25 @@ int netif_rx(struct sk_buff *skb)
    4.27  
    4.28      ASSERT(skb->skb_type == SKB_ZERO_COPY);
    4.29      ASSERT((skb->data - skb->head) == (18 + ETH_HLEN));
    4.30 -        
    4.31 +
    4.32 +    /*
    4.33 +     * Offset will include 16 bytes padding from dev_alloc_skb, 14 bytes for 
    4.34 +     * ethernet header, plus any other alignment padding added by the driver.
    4.35 +     */
    4.36 +    offset = (int)skb->data & ~PAGE_MASK; 
    4.37      skb->head = (u8 *)map_domain_mem(((skb->pf - frame_table) << PAGE_SHIFT));
    4.38 -    skb->data = skb->head;
    4.39 -    skb_reserve(skb,18); /* 18 is the 16 from dev_alloc_skb plus 2 for
    4.40 -                            IP header alignment. */
    4.41 +    skb->data = skb->nh.raw = skb->head + offset;
    4.42 +    skb->tail = skb->data + skb->len;
    4.43 +    skb_push(skb, ETH_HLEN);
    4.44      skb->mac.raw = skb->data;
    4.45 -    skb->data += ETH_HLEN;
    4.46 -    skb->nh.raw = skb->data;
    4.47 -        
    4.48 +
    4.49      netdev_rx_stat[this_cpu].total++;
    4.50  
    4.51      if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
    4.52          skb->src_vif = VIF_PHYSICAL_INTERFACE;
    4.53                  
    4.54      if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
    4.55 -        skb->dst_vif = __net_get_target_vif(skb->mac.raw, 
    4.56 -                                            skb->len, skb->src_vif);
    4.57 +        skb->dst_vif = __net_get_target_vif(skb->data, skb->len, skb->src_vif);
    4.58          
    4.59      if ( ((vif = sys_vif_list[skb->dst_vif]) == NULL) ||
    4.60           (skb->dst_vif <= VIF_PHYSICAL_INTERFACE) )
    4.61 @@ -1959,8 +1962,8 @@ long do_net_update(void)
    4.62               * This copy assumes that rx_shadow_entry_t is an extension of 
    4.63               * rx_net_entry_t extra fields must be tacked on to the end.
    4.64               */
    4.65 -            if ( copy_from_user( shadow_ring->rx_ring+i, net_ring->rx_ring+i, 
    4.66 -                                 sizeof (rx_entry_t) ) )
    4.67 +            if ( copy_from_user(shadow_ring->rx_ring+i, net_ring->rx_ring+i, 
    4.68 +                                sizeof (rx_entry_t) ) )
    4.69              {
    4.70                  DPRINTK("Bad copy_from_user for rx ring\n");
    4.71                  shadow_ring->rx_ring[i].status = RING_STATUS_ERR_CFU;
     5.1 --- a/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c	Thu Mar 20 22:01:55 2003 +0000
     5.2 +++ b/xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/network/network.c	Fri Mar 21 11:01:27 2003 +0000
     5.3 @@ -230,7 +230,6 @@ static void network_alloc_rx_buffers(str
     5.4          skb = dev_alloc_skb(RX_BUF_SIZE);
     5.5          if ( skb == NULL ) break;
     5.6          skb->dev = dev;
     5.7 -        skb_reserve(skb, 2); /* word align the IP header */
     5.8          np->rx_skb_ring[i] = skb;
     5.9          np->net_ring->rx_ring[i].addr = get_ppte((unsigned long)skb->head); 
    5.10          np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */
    5.11 @@ -317,25 +316,20 @@ static void network_rx_int(int irq, void
    5.12      struct net_device *dev = (struct net_device *)dev_id;
    5.13      struct net_private *np = dev->priv;
    5.14      struct sk_buff *skb;
    5.15 +    rx_entry_t *rx;
    5.16      
    5.17   again:
    5.18      for ( i = np->rx_idx; i != np->net_ring->rx_cons; i = RX_RING_INC(i) )
    5.19      {
    5.20 -        if (np->net_ring->rx_ring[i].status != RING_STATUS_OK)
    5.21 -        {
    5.22 -            printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", 
    5.23 -                   np->net_ring->rx_ring[i].status);
    5.24 -            continue;
    5.25 -        }
    5.26 +        rx  = &np->net_ring->rx_ring[i];
    5.27          skb = np->rx_skb_ring[i];
    5.28  
    5.29 -        phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] =
    5.30 -            (*(unsigned long *)phys_to_virt(
    5.31 -                machine_to_phys(np->net_ring->rx_ring[i].addr))
    5.32 -                ) >> PAGE_SHIFT;
    5.33 -
    5.34 -        skb_put(skb, np->net_ring->rx_ring[i].size);
    5.35 -        skb->protocol = eth_type_trans(skb, dev);
    5.36 +        if ( rx->status != RING_STATUS_OK )
    5.37 +        {
    5.38 +            printk(KERN_ALERT "bad buffer on RX ring!(%d)\n", rx->status);
    5.39 +            dev_kfree_skb_any(skb);
    5.40 +            continue;
    5.41 +        }
    5.42  
    5.43          /*
    5.44           * Set up shinfo -- from alloc_skb This was particularily nasty:  the
    5.45 @@ -346,6 +340,22 @@ static void network_rx_int(int irq, void
    5.46          skb_shinfo(skb)->nr_frags = 0;
    5.47          skb_shinfo(skb)->frag_list = NULL;
    5.48                                  
    5.49 +        phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] =
    5.50 +            (*(unsigned long *)phys_to_virt(machine_to_phys(rx->addr))
    5.51 +                ) >> PAGE_SHIFT;
    5.52 +
    5.53 +        if ( rx->offset < 16 )
    5.54 +        {
    5.55 +            printk(KERN_ALERT "need pkt offset >= 16 (got %d)\n", rx->offset);
    5.56 +            dev_kfree_skb_any(skb);
    5.57 +            continue;
    5.58 +        }
    5.59 +        
    5.60 +        skb_reserve(skb, rx->offset - 16);
    5.61 +
    5.62 +        skb_put(skb, np->net_ring->rx_ring[i].size);
    5.63 +        skb->protocol = eth_type_trans(skb, dev);
    5.64 +
    5.65          np->stats.rx_packets++;
    5.66  
    5.67          np->stats.rx_bytes += np->net_ring->rx_ring[i].size;