ia64/xen-unstable
changeset 234:682fc9ed30dc
bitkeeper revision 1.92 (3e5a3f34hhxCW-jAvvD9l1pqUdV3PQ)
dev.c, vif.h, xen_block.c:
More robust handling of ring indexes in network code.
dev.c, vif.h, xen_block.c:
More robust handling of ring indexes in network code.
author | kaf24@labyrinth.cl.cam.ac.uk |
---|---|
date | Mon Feb 24 15:50:12 2003 +0000 (2003-02-24) |
parents | 4c0c962a443f |
children | d7d0a23b2e07 |
files | xen-2.4.16/drivers/block/xen_block.c xen-2.4.16/include/xeno/vif.h xen-2.4.16/net/dev.c |
line diff
1.1 --- a/xen-2.4.16/drivers/block/xen_block.c Mon Feb 24 15:15:51 2003 +0000 1.2 +++ b/xen-2.4.16/drivers/block/xen_block.c Mon Feb 24 15:50:12 2003 +0000 1.3 @@ -17,7 +17,7 @@ 1.4 #include <xeno/keyhandler.h> 1.5 #include <xeno/interrupt.h> 1.6 1.7 -#if 1 1.8 +#if 0 1.9 #define DPRINTK(_f, _a...) printk( _f , ## _a ) 1.10 #else 1.11 #define DPRINTK(_f, _a...) ((void)0)
2.1 --- a/xen-2.4.16/include/xeno/vif.h Mon Feb 24 15:15:51 2003 +0000 2.2 +++ b/xen-2.4.16/include/xeno/vif.h Mon Feb 24 15:50:12 2003 +0000 2.3 @@ -42,8 +42,26 @@ typedef struct tx_shadow_entry_st { 2.4 typedef struct net_shadow_ring_st { 2.5 rx_shadow_entry_t *rx_ring; 2.6 tx_shadow_entry_t *tx_ring; 2.7 - unsigned int rx_prod, rx_cons, rx_idx; 2.8 - unsigned int tx_prod, tx_cons, tx_idx; 2.9 + 2.10 + /* 2.11 + * Private copy of producer. Follows guest OS version, but never 2.12 + * catches up with our consumer index. 2.13 + */ 2.14 + unsigned int rx_prod; 2.15 + /* Points at next buffer to be filled by NIC. Chases rx_prod. */ 2.16 + unsigned int rx_idx; 2.17 + /* Points at next buffer to be returned to the guest OS. Chases rx_idx. */ 2.18 + unsigned int rx_cons; 2.19 + 2.20 + /* 2.21 + * Private copy of producer. Follows guest OS version, but never 2.22 + * catches up with our consumer index. 2.23 + */ 2.24 + unsigned int tx_prod; 2.25 + /* Points at next buffer to be scheduled. Chases tx_prod. */ 2.26 + unsigned int tx_idx; 2.27 + /* Points at next buffer to be returned to the guest OS. Chases tx_idx. */ 2.28 + unsigned int tx_cons; 2.29 } net_shadow_ring_t; 2.30 2.31 typedef struct net_vif_st {
3.1 --- a/xen-2.4.16/net/dev.c Mon Feb 24 15:15:51 2003 +0000 3.2 +++ b/xen-2.4.16/net/dev.c Mon Feb 24 15:50:12 2003 +0000 3.3 @@ -38,7 +38,7 @@ 3.4 #define rtnl_lock() ((void)0) 3.5 #define rtnl_unlock() ((void)0) 3.6 3.7 -#if 0 3.8 +#if 1 3.9 #define DPRINTK(_f, _a...) printk(_f , ## _a) 3.10 #else 3.11 #define DPRINTK(_f, _a...) ((void)0) 3.12 @@ -497,7 +497,7 @@ void deliver_packet(struct sk_buff *skb, 3.13 } 3.14 shadow_ring = vif->shadow_ring; 3.15 3.16 - if ( (i = shadow_ring->rx_cons) == shadow_ring->rx_prod ) 3.17 + if ( (i = shadow_ring->rx_idx) == shadow_ring->rx_prod ) 3.18 { 3.19 return; 3.20 } 3.21 @@ -505,7 +505,7 @@ void deliver_packet(struct sk_buff *skb, 3.22 if ( shadow_ring->rx_ring[i].status != RING_STATUS_OK ) 3.23 { 3.24 DPRINTK("Bad buffer in deliver_packet()\n"); 3.25 - shadow_ring->rx_cons = RX_RING_INC(i); 3.26 + shadow_ring->rx_idx = RX_RING_INC(i); 3.27 return; 3.28 } 3.29 3.30 @@ -537,7 +537,7 @@ void deliver_packet(struct sk_buff *skb, 3.31 /* Our skbuff now points at the guest's old frame. */ 3.32 skb->pf = g_pfn; 3.33 3.34 - shadow_ring->rx_cons = RX_RING_INC(i); 3.35 + shadow_ring->rx_idx = RX_RING_INC(i); 3.36 } 3.37 3.38 /** 3.39 @@ -684,7 +684,7 @@ static void add_to_net_schedule_list_tai 3.40 static void tx_skb_release(struct sk_buff *skb) 3.41 { 3.42 int i; 3.43 - net_ring_t *ring; 3.44 + net_vif_t *vif = sys_vif_list[skb->src_vif]; 3.45 3.46 for ( i = 0; i < skb_shinfo(skb)->nr_frags; i++ ) 3.47 put_page_tot(skb_shinfo(skb)->frags[i].page); 3.48 @@ -694,16 +694,20 @@ static void tx_skb_release(struct sk_buf 3.49 3.50 skb_shinfo(skb)->nr_frags = 0; 3.51 3.52 + /* This would mean that the guest OS has fiddled with our index. */ 3.53 + if ( vif->shadow_ring->tx_cons != vif->net_ring->tx_cons ) 3.54 + DPRINTK("Shadow and shared rings out of sync (%d/%d)\n", 3.55 + vif->shadow_ring->tx_cons, vif->net_ring->tx_cons); 3.56 + 3.57 /* 3.58 * XXX This assumes that, per vif, SKBs are processed in-order! 3.59 * Also assumes no concurrency. This is safe because each vif 3.60 * maps to one NIC. This is executed in NIC interrupt code, so we have 3.61 * mutual exclusion from do_IRQ(). 3.62 */ 3.63 - ring = sys_vif_list[skb->src_vif]->net_ring; 3.64 - ring->tx_cons = TX_RING_INC(ring->tx_cons); 3.65 - 3.66 - if ( ring->tx_cons == ring->tx_event ) 3.67 + vif->shadow_ring->tx_cons = TX_RING_INC(vif->shadow_ring->tx_cons); 3.68 + vif->net_ring->tx_cons = vif->shadow_ring->tx_cons; 3.69 + if ( vif->net_ring->tx_cons == vif->net_ring->tx_event ) 3.70 set_bit(_EVENT_NET_TX, 3.71 &sys_vif_list[skb->src_vif]->domain->shared_info->events); 3.72 } 3.73 @@ -803,29 +807,27 @@ void update_shared_ring(void) 3.74 { 3.75 net_ring = current->net_vif_list[nvif]->net_ring; 3.76 shadow_ring = current->net_vif_list[nvif]->shadow_ring; 3.77 - 3.78 - if ( shadow_ring->rx_idx != net_ring->rx_cons ) 3.79 - { 3.80 + 3.81 + /* This would mean that the guest OS has fiddled with our index. */ 3.82 + if ( shadow_ring->rx_cons != net_ring->rx_cons ) 3.83 DPRINTK("Shadow and shared rings out of sync (%d/%d)\n", 3.84 - shadow_ring->rx_idx, net_ring->rx_cons); 3.85 - } 3.86 + shadow_ring->rx_cons, net_ring->rx_cons); 3.87 3.88 - while ( (shadow_ring->rx_idx != shadow_ring->rx_cons) && 3.89 - (net_ring->rx_cons != net_ring->rx_prod) ) 3.90 + while ( shadow_ring->rx_cons != shadow_ring->rx_idx ) 3.91 { 3.92 - rx = shadow_ring->rx_ring + shadow_ring->rx_idx; 3.93 + rx = shadow_ring->rx_ring + shadow_ring->rx_cons; 3.94 copy_to_user(net_ring->rx_ring + net_ring->rx_cons, rx, 3.95 sizeof(rx_entry_t)); 3.96 3.97 - shadow_ring->rx_idx = RX_RING_INC(shadow_ring->rx_idx); 3.98 - net_ring->rx_cons = RX_RING_INC(net_ring->rx_cons); 3.99 - 3.100 if ( rx->flush_count == tlb_flush_count[smp_processor_id()] ) 3.101 __flush_tlb(); 3.102 3.103 - if ( net_ring->rx_cons == net_ring->rx_event ) 3.104 + shadow_ring->rx_cons = RX_RING_INC(shadow_ring->rx_cons); 3.105 + 3.106 + if ( shadow_ring->rx_cons == net_ring->rx_event ) 3.107 set_bit(_EVENT_NET_RX, &s->events); 3.108 } 3.109 + net_ring->rx_cons = shadow_ring->rx_cons; 3.110 } 3.111 } 3.112 3.113 @@ -1820,8 +1822,14 @@ long do_net_update(void) 3.114 * PHASE 1 -- TRANSMIT RING 3.115 */ 3.116 3.117 + /* 3.118 + * Collect up new transmit buffers. We collect up to the guest OS's 3.119 + * new producer index, but take care not to catch up with our own 3.120 + * consumer index. 3.121 + */ 3.122 for ( i = shadow_ring->tx_prod; 3.123 - i != net_ring->tx_prod; 3.124 + (i != net_ring->tx_prod) && 3.125 + (((shadow_ring->tx_cons-i) & (TX_RING_SIZE-1)) != 1); 3.126 i = TX_RING_INC(i) ) 3.127 { 3.128 if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) ) 3.129 @@ -1836,13 +1844,13 @@ long do_net_update(void) 3.130 3.131 if ( tx.size < PKT_PROT_LEN ) 3.132 { 3.133 - DPRINTK("Runt packet %ld\n", tx.size); 3.134 + DPRINTK("Runt packet %d\n", tx.size); 3.135 continue; 3.136 } 3.137 3.138 if ( ((tx.addr & ~PAGE_MASK) + tx.size) >= PAGE_SIZE ) 3.139 { 3.140 - DPRINTK("tx.addr: %lx, size: %lu, end: %lu\n", 3.141 + DPRINTK("tx.addr: %lx, size: %u, end: %lu\n", 3.142 tx.addr, tx.size, (tx.addr &~PAGE_MASK) + tx.size); 3.143 continue; 3.144 } 3.145 @@ -1906,15 +1914,23 @@ long do_net_update(void) 3.146 } 3.147 smp_wmb(); /* Let other CPUs see new descriptors first. */ 3.148 shadow_ring->tx_prod = i; 3.149 + 3.150 + /* XXX: This should be more consevative. */ 3.151 add_to_net_schedule_list_tail(current_vif); 3.152 - tasklet_schedule(&net_tx_tasklet); /* XXX */ 3.153 + tasklet_schedule(&net_tx_tasklet); 3.154 3.155 /* 3.156 * PHASE 2 -- RECEIVE RING 3.157 */ 3.158 3.159 + /* 3.160 + * Collect up new receive buffers. We collect up to the guest OS's 3.161 + * new producer index, but take care not to catch up with our own 3.162 + * consumer index. 3.163 + */ 3.164 for ( i = shadow_ring->rx_prod; 3.165 - i != net_ring->rx_prod; 3.166 + (i != net_ring->rx_prod) && 3.167 + (((shadow_ring->rx_cons-i) & (RX_RING_SIZE-1)) != 1); 3.168 i = RX_RING_INC(i) ) 3.169 { 3.170 /*