diff options
| author | Michael Brown | 2012-06-29 02:03:38 +0200 |
|---|---|---|
| committer | Michael Brown | 2012-06-29 02:06:00 +0200 |
| commit | 76d9c1a00120d5b93d6f717bab867462a7a83f11 (patch) | |
| tree | a2ac65fdebeefe167ebe92dc9696fdcc707d160c /src | |
| parent | [monojob] Check for keypresses only once per timer tick (diff) | |
| download | ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.tar.gz ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.tar.xz ipxe-76d9c1a00120d5b93d6f717bab867462a7a83f11.zip | |
[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')
| -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 190144156..def44113d 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 ) { |
