ia64/xen-unstable

changeset 1387:839302343688

bitkeeper revision 1.891.5.1 (40a4ee0eTiPczG5OYaAX2-NUVdmi1Q)

More batching and pipelining in network backend.
author kaf24@scramble.cl.cam.ac.uk
date Fri May 14 16:04:30 2004 +0000 (2004-05-14)
parents a693ae3c0f60
children bf3fc7825f74
files xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c
line diff
     1.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c	Fri May 14 14:21:38 2004 +0000
     1.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c	Fri May 14 16:04:30 2004 +0000
     1.3 @@ -52,12 +52,24 @@ static unsigned long mmap_vstart;
     1.4  static u16 pending_id[MAX_PENDING_REQS];
     1.5  static netif_t *pending_netif[MAX_PENDING_REQS];
     1.6  static u16 pending_ring[MAX_PENDING_REQS];
     1.7 -static spinlock_t pend_prod_lock = SPIN_LOCK_UNLOCKED;
     1.8  typedef unsigned int PEND_RING_IDX;
     1.9  #define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
    1.10  static PEND_RING_IDX pending_prod, pending_cons;
    1.11  #define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
    1.12  
    1.13 +/* Freed TX SKBs get batched on this ring before return to pending_ring. */
    1.14 +static u16 dealloc_ring[MAX_PENDING_REQS];
    1.15 +static spinlock_t dealloc_lock = SPIN_LOCK_UNLOCKED;
    1.16 +static PEND_RING_IDX dealloc_prod, dealloc_cons;
    1.17 +
    1.18 +typedef struct {
    1.19 +    u16 idx;
    1.20 +    netif_tx_request_t req;
    1.21 +    netif_t *netif;
    1.22 +} tx_info_t;
    1.23 +static struct sk_buff_head tx_queue;
    1.24 +static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
    1.25 +
    1.26  static struct list_head net_schedule_list;
    1.27  static spinlock_t net_schedule_list_lock;
    1.28  
    1.29 @@ -215,7 +227,7 @@ static void net_rx_action(unsigned long 
    1.30          mcl[0].op = __HYPERVISOR_update_va_mapping;
    1.31          mcl[0].args[0] = vdata >> PAGE_SHIFT;
    1.32          mcl[0].args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
    1.33 -        mcl[0].args[2] = UVMF_INVLPG;
    1.34 +        mcl[0].args[2] = 0;
    1.35          mcl[1].op = __HYPERVISOR_mmu_update;
    1.36          mcl[1].args[0] = (unsigned long)mmu;
    1.37          mcl[1].args[1] = 4;
    1.38 @@ -232,9 +244,10 @@ static void net_rx_action(unsigned long 
    1.39              break;
    1.40      }
    1.41  
    1.42 -    if ( (mcl - rx_mcl) == 0 )
    1.43 +    if ( mcl == rx_mcl )
    1.44          return;
    1.45  
    1.46 +    mcl[-2].args[2] = UVMF_FLUSH_TLB;
    1.47      (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
    1.48  
    1.49      mcl = rx_mcl;
    1.50 @@ -369,7 +382,51 @@ static void net_tx_action(unsigned long 
    1.51      u16 pending_idx;
    1.52      NETIF_RING_IDX i;
    1.53      struct page *page;
    1.54 +    multicall_entry_t *mcl;
    1.55  
    1.56 +    if ( (i = dealloc_cons) == dealloc_prod )
    1.57 +        goto skip_dealloc;
    1.58 +
    1.59 +    mcl = tx_mcl;
    1.60 +    while ( i != dealloc_prod )
    1.61 +    {
    1.62 +        pending_idx = dealloc_ring[MASK_PEND_IDX(i++)];
    1.63 +        mcl[0].op = __HYPERVISOR_update_va_mapping;
    1.64 +        mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
    1.65 +        mcl[0].args[1] = 0;
    1.66 +        mcl[0].args[2] = 0;
    1.67 +        mcl++;        
    1.68 +    }
    1.69 +
    1.70 +    mcl[-1].args[2] = UVMF_FLUSH_TLB;
    1.71 +    (void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl);
    1.72 +
    1.73 +    while ( dealloc_cons != dealloc_prod )
    1.74 +    {
    1.75 +        pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
    1.76 +
    1.77 +        netif = pending_netif[pending_idx];
    1.78 +
    1.79 +        spin_lock(&netif->tx_lock);
    1.80 +        make_tx_response(netif, pending_id[pending_idx], NETIF_RSP_OKAY);
    1.81 +        spin_unlock(&netif->tx_lock);
    1.82 +        
    1.83 +        pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
    1.84 +        
    1.85 +        /*
    1.86 +         * Scheduling checks must happen after the above response is posted.
    1.87 +         * This avoids a possible race with a guest OS on another CPU.
    1.88 +         */
    1.89 +        mb();
    1.90 +        if ( (netif->tx_req_cons != netif->tx->req_prod) &&
    1.91 +             ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
    1.92 +            add_to_net_schedule_list_tail(netif);
    1.93 +        
    1.94 +        netif_put(netif);
    1.95 +    }
    1.96 +
    1.97 + skip_dealloc:
    1.98 +    mcl = tx_mcl;
    1.99      while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
   1.100              !list_empty(&net_schedule_list) )
   1.101      {
   1.102 @@ -440,29 +497,61 @@ static void net_tx_action(unsigned long 
   1.103  
   1.104          pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
   1.105  
   1.106 -        if ( HYPERVISOR_update_va_mapping_otherdomain(
   1.107 -            MMAP_VADDR(pending_idx) >> PAGE_SHIFT,
   1.108 -            (pte_t) { (txreq.addr & PAGE_MASK) | __PAGE_KERNEL },
   1.109 -            0, netif->domid) != 0 )
   1.110 -        {
   1.111 -            DPRINTK("Bad page frame\n");
   1.112 -            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   1.113 -            netif_put(netif);
   1.114 -            continue;
   1.115 -        }
   1.116 -        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
   1.117 -            txreq.addr >> PAGE_SHIFT;
   1.118 -
   1.119          if ( unlikely((skb = alloc_skb(PKT_PROT_LEN, GFP_ATOMIC)) == NULL) )
   1.120          {
   1.121              DPRINTK("Can't allocate a skb in start_xmit.\n");
   1.122              make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   1.123              netif_put(netif);
   1.124 -            HYPERVISOR_update_va_mapping(MMAP_VADDR(pending_idx) >> PAGE_SHIFT,
   1.125 -                                         (pte_t) { 0 }, UVMF_INVLPG);
   1.126              break;
   1.127          }
   1.128 +
   1.129 +        mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
   1.130 +        mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
   1.131 +        mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
   1.132 +        mcl[0].args[2] = 0;
   1.133 +        mcl[0].args[3] = (unsigned long)netif->domid;
   1.134 +        mcl[0].args[4] = (unsigned long)(netif->domid>>32);
   1.135 +        mcl++;
   1.136          
   1.137 +        ((tx_info_t *)&skb->cb[0])->idx = pending_idx;
   1.138 +        ((tx_info_t *)&skb->cb[0])->netif = netif;
   1.139 +        memcpy(&((tx_info_t *)&skb->cb[0])->req, &txreq, sizeof(txreq));
   1.140 +        __skb_queue_tail(&tx_queue, skb);
   1.141 +
   1.142 +        pending_cons++;
   1.143 +
   1.144 +        /* Filled the batch queue? */
   1.145 +        if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) )
   1.146 +            break;
   1.147 +    }
   1.148 +
   1.149 +    if ( mcl == tx_mcl )
   1.150 +        return;
   1.151 +
   1.152 +    (void)HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl);
   1.153 +
   1.154 +    mcl = tx_mcl;
   1.155 +    while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
   1.156 +    {
   1.157 +        pending_idx = ((tx_info_t *)&skb->cb[0])->idx;
   1.158 +        netif       = ((tx_info_t *)&skb->cb[0])->netif;
   1.159 +        memcpy(&txreq, &((tx_info_t *)&skb->cb[0])->req, sizeof(txreq));
   1.160 +
   1.161 +        /* Check the remap error code. */
   1.162 +        if ( unlikely(mcl[0].args[5] != 0) )
   1.163 +        {
   1.164 +            DPRINTK("Bad page frame\n");
   1.165 +            make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
   1.166 +            netif_put(netif);
   1.167 +            kfree_skb(skb);
   1.168 +            mcl++;
   1.169 +            pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
   1.170 +            continue;
   1.171 +        }
   1.172 +
   1.173 +        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
   1.174 +            txreq.addr >> PAGE_SHIFT;
   1.175 +
   1.176          __skb_put(skb, PKT_PROT_LEN);
   1.177          memcpy(skb->data, 
   1.178                 (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
   1.179 @@ -491,42 +580,23 @@ static void net_tx_action(unsigned long 
   1.180          netif->stats.tx_bytes += txreq.size;
   1.181          netif->stats.tx_packets++;
   1.182  
   1.183 -        pending_cons++;
   1.184 -
   1.185          netif_rx(skb);
   1.186          netif->dev->last_rx = jiffies;
   1.187 +
   1.188 +        mcl++;
   1.189      }
   1.190  }
   1.191  
   1.192  static void netif_page_release(struct page *page)
   1.193  {
   1.194      unsigned long flags;
   1.195 -    netif_t *netif;
   1.196 -    u16 pending_idx;
   1.197 -
   1.198 -    pending_idx = page - virt_to_page(mmap_vstart);
   1.199 -
   1.200 -    netif = pending_netif[pending_idx];
   1.201 +    u16 pending_idx = page - virt_to_page(mmap_vstart);
   1.202  
   1.203 -    HYPERVISOR_update_va_mapping(MMAP_VADDR(pending_idx) >> PAGE_SHIFT,
   1.204 -                                 (pte_t) { 0 }, UVMF_INVLPG);
   1.205 -        
   1.206 -    spin_lock(&netif->tx_lock);
   1.207 -    make_tx_response(netif, pending_id[pending_idx], NETIF_RSP_OKAY);
   1.208 -    spin_unlock(&netif->tx_lock);
   1.209 +    spin_lock_irqsave(&dealloc_lock, flags);
   1.210 +    dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
   1.211 +    spin_unlock_irqrestore(&dealloc_lock, flags);
   1.212  
   1.213 -    /*
   1.214 -     * Scheduling checks must happen after the above response is posted.
   1.215 -     * This avoids a possible race with a guest OS on another CPU.
   1.216 -     */
   1.217 -    mb();
   1.218 -    netif_schedule_work(netif);
   1.219 -
   1.220 -    netif_put(netif);
   1.221 - 
   1.222 -    spin_lock_irqsave(&pend_prod_lock, flags);
   1.223 -    pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
   1.224 -    spin_unlock_irqrestore(&pend_prod_lock, flags);
   1.225 +    tasklet_schedule(&net_tx_tasklet);
   1.226  }
   1.227  
   1.228  #if 0
   1.229 @@ -627,6 +697,7 @@ static int __init init_module(void)
   1.230          return 0;
   1.231  
   1.232      skb_queue_head_init(&rx_queue);
   1.233 +    skb_queue_head_init(&tx_queue);
   1.234  
   1.235      netif_interface_init();
   1.236