From c5c041a5ba9b5d05013436b29e741b6fc0b26b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Fri, 29 Aug 2014 00:34:25 +0200 Subject: [PATCH] pc_serial: fix KDL on close It's working \o/ Just need to figure out why it waits for \n to transmit. We now only destroy the cookies in the free hook. Mention pending DPC as soon as when inside the irq handler. Also limit the number of loops in the IRQ handler to avoid busy looping. It only happened when testing with normal priority but you never know... --- .../drivers/ports/pc_serial/SerialDevice.cpp | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp index 7c2fbdc301..7774e20d90 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp @@ -346,7 +346,13 @@ SerialDevice::IsInterruptPending() // the next time we'll read we'll miss the IRQ condition // so we just cache the value for the real handler fCachedIIR = ReadReg8(IIR); - return ((fCachedIIR & IIR_PENDING) == 0); // 0 means yes + + bool pending = (fCachedIIR & IIR_PENDING) == 0; + + if (pending) + atomic_add(&fPendingDPC, 1); + + return pending; // 0 means yes } @@ -358,10 +364,9 @@ SerialDevice::InterruptHandler() uint8 iir, lsr, msr; uint8 buffer[64]; + int tries = 8; // avoid busy looping TRACE(("InterruptHandler()\n")); - atomic_add(&fPendingDPC, 1); - // start with the first (cached) irq condition iir = fCachedIIR; while ((iir & IIR_PENDING) == 0) { // 0 means yes @@ -455,6 +460,10 @@ SerialDevice::InterruptHandler() ret = B_HANDLED_INTERRUPT; TRACE(("IRQ:h\n")); + // enough for now + if (tries-- == 0) + break; + // check the next IRQ condition iir = ReadReg8(IIR); } @@ -654,19 +663,12 @@ SerialDevice::Close() fDeviceOpen = false; + gTTYModule->tty_close_cookie(fSystemTTYCookie); + gTTYModule->tty_close_cookie(fDeviceTTYCookie); + //XXX: we shouldn't have to do this! bool en = false; Service(fMasterTTY, TTYENABLE, &en, sizeof(en)); - // XXX: shouldn't we tty_close_cookie() as well ?? - - // wait until currently executing DPC is done. In case another one - // is run beyond this point it will just bail out on !IsOpen(). - while (atomic_get(&fPendingDPC)) - snooze(1000); - - gTTYModule->tty_destroy_cookie(fSystemTTYCookie); - gTTYModule->tty_destroy_cookie(fDeviceTTYCookie); - fSystemTTYCookie = fDeviceTTYCookie = NULL; return status; } @@ -677,6 +679,15 @@ SerialDevice::Free() { status_t status = B_OK; + // wait until currently executing DPC is done. In case another one + // is run beyond this point it will just bail out on !IsOpen(). + while (atomic_get(&fPendingDPC)) + snooze(1000); + + gTTYModule->tty_destroy_cookie(fSystemTTYCookie); + gTTYModule->tty_destroy_cookie(fDeviceTTYCookie); + fSystemTTYCookie = fDeviceTTYCookie = NULL; + gTTYModule->tty_destroy(fMasterTTY); gTTYModule->tty_destroy(fSlaveTTY); fMasterTTY = fSlaveTTY = NULL;