Selaa lähdekoodia

[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>
tags/v1.20.1
Michael Brown 10 vuotta sitten
vanhempi
commit
b2c7b6a85e
1 muutettua tiedostoa jossa 13 lisäystä ja 8 poistoa
  1. 13
    8
      src/drivers/net/intel.c

+ 13
- 8
src/drivers/net/intel.c Näytä tiedosto

@@ -456,19 +456,20 @@ void intel_refill_rx ( struct intel_nic *intel ) {
456 456
 	unsigned int rx_idx;
457 457
 	unsigned int rx_tail;
458 458
 	physaddr_t address;
459
+	unsigned int refilled = 0;
459 460
 
461
+	/* Refill ring */
460 462
 	while ( ( intel->rx.prod - intel->rx.cons ) < INTEL_RX_FILL ) {
461 463
 
462 464
 		/* Allocate I/O buffer */
463 465
 		iobuf = alloc_iob ( INTEL_RX_MAX_LEN );
464 466
 		if ( ! iobuf ) {
465 467
 			/* Wait for next refill */
466
-			return;
468
+			break;
467 469
 		}
468 470
 
469 471
 		/* Get next receive descriptor */
470 472
 		rx_idx = ( intel->rx.prod++ % INTEL_NUM_RX_DESC );
471
-		rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC );
472 473
 		rx = &intel->rx.desc[rx_idx];
473 474
 
474 475
 		/* Populate receive descriptor */
@@ -477,20 +478,24 @@ void intel_refill_rx ( struct intel_nic *intel ) {
477 478
 		rx->length = 0;
478 479
 		rx->status = 0;
479 480
 		rx->errors = 0;
480
-		wmb();
481 481
 
482 482
 		/* Record I/O buffer */
483 483
 		assert ( intel->rx_iobuf[rx_idx] == NULL );
484 484
 		intel->rx_iobuf[rx_idx] = iobuf;
485 485
 
486
-		/* Push descriptor to card */
487
-		profile_start ( &intel_vm_refill_profiler );
488
-		writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT );
489
-		profile_stop ( &intel_vm_refill_profiler );
490
-
491 486
 		DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx,
492 487
 			( ( unsigned long long ) address ),
493 488
 			( ( unsigned long long ) address + INTEL_RX_MAX_LEN ) );
489
+		refilled++;
490
+	}
491
+
492
+	/* Push descriptors to card, if applicable */
493
+	if ( refilled ) {
494
+		wmb();
495
+		rx_tail = ( intel->rx.prod % INTEL_NUM_RX_DESC );
496
+		profile_start ( &intel_vm_refill_profiler );
497
+		writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT );
498
+		profile_stop ( &intel_vm_refill_profiler );
494 499
 	}
495 500
 }
496 501
 

Loading…
Peruuta
Tallenna