diff --git a/src/add-ons/kernel/drivers/network/3com/pci/glue.c b/src/add-ons/kernel/drivers/network/3com/pci/glue.c index 0bfd328ba5..d414b7d033 100644 --- a/src/add-ons/kernel/drivers/network/3com/pci/glue.c +++ b/src/add-ons/kernel/drivers/network/3com/pci/glue.c @@ -40,6 +40,8 @@ __haiku_disable_interrupts(device_t dev) if (status == 0xffff || (status & XL_INTRS) == 0) return 0; + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK | (status & XL_INTRS)); atomic_or((int32 *)&sc->xl_intr_status, status); return 1; } @@ -48,6 +50,8 @@ __haiku_disable_interrupts(device_t dev) void __haiku_reenable_interrupts(device_t dev) { + struct xl_softc *sc = device_get_softc(dev); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB | XL_INTRS); } diff --git a/src/add-ons/kernel/drivers/network/3com/pci/if_xl.c b/src/add-ons/kernel/drivers/network/3com/pci/if_xl.c index 5727741135..30645bbb89 100644 --- a/src/add-ons/kernel/drivers/network/3com/pci/if_xl.c +++ b/src/add-ons/kernel/drivers/network/3com/pci/if_xl.c @@ -2286,16 +2286,13 @@ xl_intr(void *arg) } #endif - #ifndef __HAIKU__ +#ifndef __HAIKU__ while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && status != 0xFFFF) { #else status = atomic_and((int32 *)&sc->xl_intr_status, 0); - do { + while (true) { #endif - CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_INTR_ACK|(status & XL_INTRS)); - if (status & XL_STAT_UP_COMPLETE) { int curpkts; @@ -2331,10 +2328,13 @@ xl_intr(void *arg) } #ifdef __HAIKU__ status = CSR_READ_2(sc, XL_STATUS); - } while ((status & XL_INTRS) != 0 && status != 0xFFFF); -#else - } + if ((status & XL_INTRS) == 0 || status == 0xffff) + break; + + CSR_WRITE_2(sc, XL_COMMAND, + XL_CMD_INTR_ACK|(status & XL_INTRS)); #endif + } if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { if (sc->xl_type == XL_TYPE_905B) diff --git a/src/libs/compat/freebsd_network/bus.c b/src/libs/compat/freebsd_network/bus.c index 000ad01a68..47762c0d25 100644 --- a/src/libs/compat/freebsd_network/bus.c +++ b/src/libs/compat/freebsd_network/bus.c @@ -49,6 +49,7 @@ struct internal_intr { thread_id thread; sem_id sem; + int32 handling; }; @@ -235,7 +236,7 @@ intr_wrapper(void *data) return B_UNHANDLED_INTERRUPT; release_sem_etc(intr->sem, 1, B_DO_NOT_RESCHEDULE); - return B_INVOKE_SCHEDULER; + return intr->handling ? B_HANDLED_INTERRUPT : B_INVOKE_SCHEDULER; } @@ -264,7 +265,9 @@ intr_handler(void *data) //device_printf(intr->dev, "in soft interrupt handler.\n"); + atomic_or(&intr->handling, 1); intr->handler(intr->arg); + atomic_and(&intr->handling, 0); HAIKU_REENABLE_INTERRUPTS(intr->dev); }