aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2012-06-29 01:03:38 +0100
committerMichael Brown <mcb30@ipxe.org>2012-06-29 01:06:00 +0100
commit76d9c1a00120d5b93d6f717bab867462a7a83f11 (patch)
treea2ac65fdebeefe167ebe92dc9696fdcc707d160c /src/arch
parent85917ba8dd7814856be12f8c00ef755547166fad (diff)
downloadipxe-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.c24
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 ) {