summaryrefslogtreecommitdiffstats
path: root/src/drivers/net/intel.c
diff options
context:
space:
mode:
authorMichael Brown2014-04-27 23:35:48 +0200
committerMichael Brown2014-04-28 00:14:48 +0200
commitb2c7b6a85e8078d5b6692156cb9850590a8ff6aa (patch)
treefa3fe7b8b21e8f80294c8001d046c84b32aadd4a /src/drivers/net/intel.c
parent[intel] Profile common virtual machine operations (diff)
downloadipxe-b2c7b6a85e8078d5b6692156cb9850590a8ff6aa.tar.gz
ipxe-b2c7b6a85e8078d5b6692156cb9850590a8ff6aa.tar.xz
ipxe-b2c7b6a85e8078d5b6692156cb9850590a8ff6aa.zip
[intel] Push new RX descriptors in batches
Inside a virtual machine, writing the RX ring tail pointer may incur a substantial overhead of processing inside the hypervisor. Minimise this overhead by writing the tail pointer once per batch of descriptors, rather than once per descriptor. Profiling under qemu-kvm (version 1.6.2) shows that this reduces the amount of time taken to refill the RX descriptor ring by around 90%. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/net/intel.c')
-rw-r--r--src/drivers/net/intel.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c
index 5abcdd7f..6684bdbd 100644
--- a/src/drivers/net/intel.c
+++ b/src/drivers/net/intel.c
@@ -456,19 +456,20 @@ void intel_refill_rx ( struct intel_nic *intel ) {
unsigned int rx_idx;
unsigned int rx_tail;
physaddr_t address;
+ unsigned int refilled = 0;
+ /* Refill ring */
while ( ( intel->rx.prod - intel->rx.cons ) < INTEL_RX_FILL ) {
/* Allocate I/O buffer */
iobuf = alloc_iob ( INTEL_RX_MAX_LEN );
if ( ! iobuf ) {
/* Wait for next refill */
- return;
+ break;
}
/* Get next receive descriptor */
rx_idx = ( intel->rx.prod++ % INTEL_NUM_RX_DESC );
- rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC );
rx = &intel->rx.desc[rx_idx];
/* Populate receive descriptor */
@@ -477,20 +478,24 @@ void intel_refill_rx ( struct intel_nic *intel ) {
rx->length = 0;
rx->status = 0;
rx->errors = 0;
- wmb();
/* Record I/O buffer */
assert ( intel->rx_iobuf[rx_idx] == NULL );
intel->rx_iobuf[rx_idx] = iobuf;
- /* Push descriptor to card */
- profile_start ( &intel_vm_refill_profiler );
- writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT );
- profile_stop ( &intel_vm_refill_profiler );
-
DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx,
( ( unsigned long long ) address ),
( ( unsigned long long ) address + INTEL_RX_MAX_LEN ) );
+ refilled++;
+ }
+
+ /* Push descriptors to card, if applicable */
+ if ( refilled ) {
+ wmb();
+ rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC );
+ profile_start ( &intel_vm_refill_profiler );
+ writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT );
+ profile_stop ( &intel_vm_refill_profiler );
}
}