mirror of https://github.com/ipxe/ipxe.git
[undi] Profile transmit and receive datapaths
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/19/head
parent
50689a8974
commit
402ce65632
|
@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
#include <ipxe/netdevice.h>
|
#include <ipxe/netdevice.h>
|
||||||
#include <ipxe/if_ether.h>
|
#include <ipxe/if_ether.h>
|
||||||
#include <ipxe/ethernet.h>
|
#include <ipxe/ethernet.h>
|
||||||
|
#include <ipxe/profile.h>
|
||||||
#include <undi.h>
|
#include <undi.h>
|
||||||
#include <undinet.h>
|
#include <undinet.h>
|
||||||
#include <pxeparent.h>
|
#include <pxeparent.h>
|
||||||
|
@ -79,6 +80,26 @@ static void undinet_close ( struct net_device *netdev );
|
||||||
/** Address of UNDI entry point */
|
/** Address of UNDI entry point */
|
||||||
static SEGOFF16_t undinet_entry;
|
static SEGOFF16_t undinet_entry;
|
||||||
|
|
||||||
|
/** Transmit profiler */
|
||||||
|
static struct profiler undinet_tx_profiler __profiler =
|
||||||
|
{ .name = "undinet.tx" };
|
||||||
|
|
||||||
|
/** Transmit call profiler */
|
||||||
|
static struct profiler undinet_tx_call_profiler __profiler =
|
||||||
|
{ .name = "undinet.tx_call" };
|
||||||
|
|
||||||
|
/** IRQ profiler */
|
||||||
|
static struct profiler undinet_irq_profiler __profiler =
|
||||||
|
{ .name = "undinet.irq" };
|
||||||
|
|
||||||
|
/** ISR call profiler */
|
||||||
|
static struct profiler undinet_isr_call_profiler __profiler =
|
||||||
|
{ .name = "undinet.isr_call" };
|
||||||
|
|
||||||
|
/** Receive profiler */
|
||||||
|
static struct profiler undinet_rx_profiler __profiler =
|
||||||
|
{ .name = "undinet.rx" };
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* UNDI interrupt service routine
|
* UNDI interrupt service routine
|
||||||
|
@ -194,6 +215,9 @@ static int undinet_transmit ( struct net_device *netdev,
|
||||||
size_t len;
|
size_t len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* Start profiling */
|
||||||
|
profile_start ( &undinet_tx_profiler );
|
||||||
|
|
||||||
/* Technically, we ought to make sure that the previous
|
/* Technically, we ought to make sure that the previous
|
||||||
* transmission has completed before we re-use the buffer.
|
* transmission has completed before we re-use the buffer.
|
||||||
* However, many PXE stacks (including at least some Intel PXE
|
* However, many PXE stacks (including at least some Intel PXE
|
||||||
|
@ -256,14 +280,16 @@ static int undinet_transmit ( struct net_device *netdev,
|
||||||
undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
|
undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
|
||||||
|
|
||||||
/* Issue PXE API call */
|
/* Issue PXE API call */
|
||||||
|
profile_start ( &undinet_tx_call_profiler );
|
||||||
if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
|
if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
|
||||||
&undi_transmit,
|
&undi_transmit,
|
||||||
sizeof ( undi_transmit ) ) ) != 0 )
|
sizeof ( undi_transmit ) ) ) != 0 )
|
||||||
goto done;
|
goto done;
|
||||||
|
profile_stop ( &undinet_tx_call_profiler );
|
||||||
|
|
||||||
/* Free I/O buffer */
|
/* Free I/O buffer */
|
||||||
netdev_tx_complete ( netdev, iobuf );
|
netdev_tx_complete ( netdev, iobuf );
|
||||||
|
profile_stop ( &undinet_tx_profiler );
|
||||||
done:
|
done:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -316,10 +342,12 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||||
*/
|
*/
|
||||||
if ( ! undinet_isr_triggered() ) {
|
if ( ! undinet_isr_triggered() ) {
|
||||||
/* Allow interrupt to occur */
|
/* Allow interrupt to occur */
|
||||||
|
profile_start ( &undinet_irq_profiler );
|
||||||
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
|
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
|
||||||
"nop\n\t"
|
"nop\n\t"
|
||||||
"nop\n\t"
|
"nop\n\t"
|
||||||
"cli\n\t" ) : : );
|
"cli\n\t" ) : : );
|
||||||
|
profile_stop ( &undinet_irq_profiler );
|
||||||
|
|
||||||
/* If interrupts are known to be supported,
|
/* If interrupts are known to be supported,
|
||||||
* then do nothing on this poll; wait for the
|
* then do nothing on this poll; wait for the
|
||||||
|
@ -339,16 +367,19 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||||
|
|
||||||
/* Run through the ISR loop */
|
/* Run through the ISR loop */
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
|
profile_start ( &undinet_isr_call_profiler );
|
||||||
if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
|
if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
|
||||||
&undi_isr,
|
&undi_isr,
|
||||||
sizeof ( undi_isr ) ) ) != 0 )
|
sizeof ( undi_isr ) ) ) != 0 )
|
||||||
break;
|
break;
|
||||||
|
profile_stop ( &undinet_isr_call_profiler );
|
||||||
switch ( undi_isr.FuncFlag ) {
|
switch ( undi_isr.FuncFlag ) {
|
||||||
case PXENV_UNDI_ISR_OUT_TRANSMIT:
|
case PXENV_UNDI_ISR_OUT_TRANSMIT:
|
||||||
/* We don't care about transmit completions */
|
/* We don't care about transmit completions */
|
||||||
break;
|
break;
|
||||||
case PXENV_UNDI_ISR_OUT_RECEIVE:
|
case PXENV_UNDI_ISR_OUT_RECEIVE:
|
||||||
/* Packet fragment received */
|
/* Packet fragment received */
|
||||||
|
profile_start ( &undinet_rx_profiler );
|
||||||
len = undi_isr.FrameLength;
|
len = undi_isr.FrameLength;
|
||||||
frag_len = undi_isr.BufferLength;
|
frag_len = undi_isr.BufferLength;
|
||||||
reserve_len = ( -undi_isr.FrameHeaderLength &
|
reserve_len = ( -undi_isr.FrameHeaderLength &
|
||||||
|
@ -393,6 +424,7 @@ static void undinet_poll ( struct net_device *netdev ) {
|
||||||
if ( undinic->hacks & UNDI_HACK_EB54 )
|
if ( undinic->hacks & UNDI_HACK_EB54 )
|
||||||
--last_trigger_count;
|
--last_trigger_count;
|
||||||
}
|
}
|
||||||
|
profile_stop ( &undinet_rx_profiler );
|
||||||
break;
|
break;
|
||||||
case PXENV_UNDI_ISR_OUT_DONE:
|
case PXENV_UNDI_ISR_OUT_DONE:
|
||||||
/* Processing complete */
|
/* Processing complete */
|
||||||
|
|
Loading…
Reference in New Issue