summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/i386/drivers/net/undinet.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c
index 7571574d7..56bd62886 100644
--- a/src/arch/i386/drivers/net/undinet.c
+++ b/src/arch/i386/drivers/net/undinet.c
@@ -253,16 +253,24 @@ static void undinet_poll ( struct net_device *netdev ) {
int rc;
if ( ! undinic->isr_processing ) {
- /* If interrupts are supported, then do nothing unless
- * the ISR has been triggered.
+ /* Allow interrupt to occur. Do this even if
+ * interrupts are not known to be supported, since
+ * some cards erroneously report that they do not
+ * support interrupts.
*/
- if ( undinic->irq_supported && ( ! undinet_isr_triggered() ) ){
+ if ( ! undinet_isr_triggered() ) {
/* Allow interrupt to occur */
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
"nop\n\t"
"nop\n\t"
"cli\n\t" ) : : );
- return;
+
+ /* If interrupts are known to be supported,
+ * then do nothing on this poll; wait for the
+ * interrupt to be triggered.
+ */
+ if ( undinic->irq_supported )
+ return;
}
/* Start ISR processing */
@@ -361,8 +369,8 @@ static int undinet_open ( struct net_device *netdev ) {
struct s_PXENV_UNDI_OPEN undi_open;
int rc;
- /* Hook interrupt service routine and enable interrupt if supported */
- if ( undinic->irq_supported ) {
+ /* Hook interrupt service routine and enable interrupt if applicable */
+ if ( undinic->irq ) {
undinet_hook_isr ( undinic->irq );
enable_irq ( undinic->irq );
send_eoi ( undinic->irq );
@@ -431,8 +439,8 @@ static void undinet_close ( struct net_device *netdev ) {
pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
&undi_close, sizeof ( undi_close ) );
- /* Disable interrupt and unhook ISR if supported */
- if ( undinic->irq_supported ) {
+ /* Disable interrupt and unhook ISR if applicable */
+ if ( undinic->irq ) {
disable_irq ( undinic->irq );
undinet_unhook_isr ( undinic->irq );
}
@@ -532,8 +540,14 @@ int undinet_probe ( struct undi_device *undi ) {
goto err_undi_get_information;
memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
undinic->irq = undi_info.IntNumber;
- DBGC ( undinic, "UNDINIC %p has MAC address %s\n",
- undinic, eth_ntoa ( netdev->hw_addr ) );
+ if ( undinic->irq > IRQ_MAX ) {
+ DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n",
+ undinic, undinic->irq );
+ rc = -EINVAL;
+ goto err_bad_irq;
+ }
+ DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
+ undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
/* Get interface information */
memset ( &undi_iface, 0, sizeof ( undi_iface ) );
@@ -544,17 +558,10 @@ int undinet_probe ( struct undi_device *undi ) {
DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
undi_iface.ServiceFlags );
- if ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) {
- if ( undinic->irq > IRQ_MAX ) {
- DBGC ( undinic, "UNDINIC %p has invalid IRQ %d\n",
- undinic, undinic->irq );
- rc = -EINVAL;
- goto err_bad_irq;
- }
+ if ( undi_iface.ServiceFlags & SUPPORTED_IRQ )
undinic->irq_supported = 1;
- DBGC ( undinic, "UNDINIC %p uses IRQ %d\n",
- undinic, undinic->irq );
- }
+ DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
+ ( undinic->irq_supported ? "interrupt" : "polling" ) );
if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
sizeof ( undi_iface.IfaceType ) ) == 0 ) {
DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
@@ -573,8 +580,8 @@ int undinet_probe ( struct undi_device *undi ) {
return 0;
err_register:
- err_bad_irq:
err_undi_get_iface_info:
+ err_bad_irq:
err_undi_get_information:
err_undi_initialize:
/* Shut down UNDI stack */