david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[undi] Align the received frame payload for faster processing

The undinet driver always has to make a copy of the received frame
into an I/O buffer.  Align this copy sensibly so that subsequent
operations are as fast as possible.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2012-06-29 01:03:38 +01:00
parent 85917ba8dd
commit 76d9c1a001
1 changed files with 16 additions and 8 deletions

View File

@ -70,6 +70,9 @@ struct undi_nic {
/** Delay between retries of PXENV_UNDI_INITIALIZE */ /** Delay between retries of PXENV_UNDI_INITIALIZE */
#define UNDI_INITIALIZE_RETRY_DELAY_MS 200 #define UNDI_INITIALIZE_RETRY_DELAY_MS 200
/** Alignment of received frame payload */
#define UNDI_RX_ALIGN 16
static void undinet_close ( struct net_device *netdev ); static void undinet_close ( struct net_device *netdev );
/** Address of UNDI entry point */ /** Address of UNDI entry point */
@ -299,6 +302,7 @@ static void undinet_poll ( struct net_device *netdev ) {
struct s_PXENV_UNDI_ISR undi_isr; struct s_PXENV_UNDI_ISR undi_isr;
struct io_buffer *iobuf = NULL; struct io_buffer *iobuf = NULL;
size_t len; size_t len;
size_t reserve_len;
size_t frag_len; size_t frag_len;
size_t max_frag_len; size_t max_frag_len;
int rc; int rc;
@ -346,6 +350,8 @@ static void undinet_poll ( struct net_device *netdev ) {
/* Packet fragment received */ /* Packet fragment received */
len = undi_isr.FrameLength; len = undi_isr.FrameLength;
frag_len = undi_isr.BufferLength; frag_len = undi_isr.BufferLength;
reserve_len = ( -undi_isr.FrameHeaderLength &
( UNDI_RX_ALIGN - 1 ) );
if ( ( len == 0 ) || ( len < frag_len ) ) { if ( ( len == 0 ) || ( len < frag_len ) ) {
/* Don't laugh. VMWare does it. */ /* Don't laugh. VMWare does it. */
DBGC ( undinic, "UNDINIC %p reported insane " DBGC ( undinic, "UNDINIC %p reported insane "
@ -354,15 +360,17 @@ static void undinet_poll ( struct net_device *netdev ) {
netdev_rx_err ( netdev, NULL, -EINVAL ); netdev_rx_err ( netdev, NULL, -EINVAL );
break; break;
} }
if ( ! iobuf )
iobuf = alloc_iob ( len );
if ( ! iobuf ) { if ( ! iobuf ) {
DBGC ( undinic, "UNDINIC %p could not " iobuf = alloc_iob ( reserve_len + len );
"allocate %zd bytes for RX buffer\n", if ( ! iobuf ) {
undinic, len ); DBGC ( undinic, "UNDINIC %p could not "
/* Fragment will be dropped */ "allocate %zd bytes for RX "
netdev_rx_err ( netdev, NULL, -ENOMEM ); "buffer\n", undinic, len );
goto done; /* Fragment will be dropped */
netdev_rx_err ( netdev, NULL, -ENOMEM );
goto done;
}
iob_reserve ( iobuf, reserve_len );
} }
max_frag_len = iob_tailroom ( iobuf ); max_frag_len = iob_tailroom ( iobuf );
if ( frag_len > max_frag_len ) { if ( frag_len > max_frag_len ) {