mirror of
https://github.com/xcat2/xNBA.git
synced 2025-01-11 18:27:56 +00:00
Work around Etherboot 5.4 bug when multiple packets are received.
This commit is contained in:
parent
ca4bd3e24e
commit
2dc8ed1eb8
@ -45,8 +45,20 @@ struct undi_nic {
|
||||
unsigned int irq;
|
||||
/** Currently processing ISR */
|
||||
int isr_processing;
|
||||
/** Bug workarounds */
|
||||
int hacks;
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup undi_hacks UNDI workarounds
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Work around Etherboot 5.4 bugs */
|
||||
#define UNDI_HACK_EB54 0x0001
|
||||
|
||||
/** @} */
|
||||
|
||||
static void undinet_close ( struct net_device *netdev );
|
||||
|
||||
/*****************************************************************************
|
||||
@ -245,6 +257,9 @@ static struct segoff prev_handler[ IRQ_MAX + 1 ];
|
||||
static volatile uint8_t __text16 ( trigger_count ) = 0;
|
||||
#define trigger_count __use_text16 ( trigger_count )
|
||||
|
||||
/** Last observed trigger count */
|
||||
static unsigned int last_trigger_count = 0;
|
||||
|
||||
/**
|
||||
* Hook UNDI interrupt service routine
|
||||
*
|
||||
@ -292,7 +307,6 @@ static void undinet_unhook_isr ( unsigned int irq ) {
|
||||
* @ret triggered ISR has been triggered since last check
|
||||
*/
|
||||
static int undinet_isr_triggered ( void ) {
|
||||
static unsigned int last_trigger_count = 0;
|
||||
unsigned int this_trigger_count;
|
||||
|
||||
/* Read trigger_count. Do this only once; it is volatile */
|
||||
@ -470,9 +484,15 @@ static void undinet_poll ( struct net_device *netdev, unsigned int rx_quota ) {
|
||||
undi_isr.Frame.segment,
|
||||
undi_isr.Frame.offset, frag_len );
|
||||
if ( iob_len ( iobuf ) == len ) {
|
||||
/* Whole packet received; deliver it */
|
||||
netdev_rx ( netdev, iobuf );
|
||||
iobuf = NULL;
|
||||
--rx_quota;
|
||||
/* Etherboot 5.4 fails to return all packets
|
||||
* under mild load; pretend it retriggered.
|
||||
*/
|
||||
if ( undinic->hacks & UNDI_HACK_EB54 )
|
||||
--last_trigger_count;
|
||||
}
|
||||
break;
|
||||
case PXENV_UNDI_ISR_OUT_DONE:
|
||||
@ -592,6 +612,7 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
struct s_PXENV_UNDI_STARTUP undi_startup;
|
||||
struct s_PXENV_UNDI_INITIALIZE undi_initialize;
|
||||
struct s_PXENV_UNDI_GET_INFORMATION undi_info;
|
||||
struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
|
||||
struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
|
||||
struct s_PXENV_UNDI_CLEANUP undi_cleanup;
|
||||
struct s_PXENV_STOP_UNDI stop_undi;
|
||||
@ -649,6 +670,21 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
|
||||
undinic, eth_ntoa ( netdev->ll_addr ), undinic->irq );
|
||||
|
||||
/* Get interface information */
|
||||
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
|
||||
if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
|
||||
&undi_iface,
|
||||
sizeof ( undi_iface ) ) ) != 0 )
|
||||
goto err_undi_get_iface_info;
|
||||
DBGC ( undinic, "UNDINIC %p has type %s and link speed %ld\n",
|
||||
undinic, undi_iface.IfaceType, undi_iface.LinkSpeed );
|
||||
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
|
||||
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
|
||||
DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
|
||||
undinic );
|
||||
undinic->hacks |= UNDI_HACK_EB54;
|
||||
}
|
||||
|
||||
/* Point to NIC specific routines */
|
||||
netdev->open = undinet_open;
|
||||
netdev->close = undinet_close;
|
||||
@ -663,6 +699,7 @@ int undinet_probe ( struct undi_device *undi ) {
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
err_undi_get_iface_info:
|
||||
err_bad_irq:
|
||||
err_undi_get_information:
|
||||
err_undi_initialize:
|
||||
|
Loading…
x
Reference in New Issue
Block a user