diff options
author | Michael Brown <mcb30@ipxe.org> | 2012-06-29 01:03:38 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-06-29 01:06:00 +0100 |
commit | 76d9c1a00120d5b93d6f717bab867462a7a83f11 (patch) | |
tree | a2ac65fdebeefe167ebe92dc9696fdcc707d160c /src/arch | |
parent | 85917ba8dd7814856be12f8c00ef755547166fad (diff) | |
download | ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.zip ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.tar.gz ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.tar.bz2 |
[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>
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/i386/drivers/net/undinet.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 1901441..def4411 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -70,6 +70,9 @@ struct undi_nic { /** Delay between retries of PXENV_UNDI_INITIALIZE */ #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 ); /** 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 io_buffer *iobuf = NULL; size_t len; + size_t reserve_len; size_t frag_len; size_t max_frag_len; int rc; @@ -346,6 +350,8 @@ static void undinet_poll ( struct net_device *netdev ) { /* Packet fragment received */ len = undi_isr.FrameLength; frag_len = undi_isr.BufferLength; + reserve_len = ( -undi_isr.FrameHeaderLength & + ( UNDI_RX_ALIGN - 1 ) ); if ( ( len == 0 ) || ( len < frag_len ) ) { /* Don't laugh. VMWare does it. */ DBGC ( undinic, "UNDINIC %p reported insane " @@ -354,15 +360,17 @@ static void undinet_poll ( struct net_device *netdev ) { netdev_rx_err ( netdev, NULL, -EINVAL ); break; } - if ( ! iobuf ) - iobuf = alloc_iob ( len ); if ( ! iobuf ) { - DBGC ( undinic, "UNDINIC %p could not " - "allocate %zd bytes for RX buffer\n", - undinic, len ); - /* Fragment will be dropped */ - netdev_rx_err ( netdev, NULL, -ENOMEM ); - goto done; + iobuf = alloc_iob ( reserve_len + len ); + if ( ! iobuf ) { + DBGC ( undinic, "UNDINIC %p could not " + "allocate %zd bytes for RX " + "buffer\n", undinic, len ); + /* Fragment will be dropped */ + netdev_rx_err ( netdev, NULL, -ENOMEM ); + goto done; + } + iob_reserve ( iobuf, reserve_len ); } max_frag_len = iob_tailroom ( iobuf ); if ( frag_len > max_frag_len ) { |