[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:
parent
85917ba8dd
commit
76d9c1a001
|
@ -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 ) {
|
||||||
|
|
Reference in New Issue