* Re: R: R: How to avoid serial port buffer overruns? [not found] ` <fa.f1Jp2YDS6/xT0GB2fsQq98CdRtA@ifi.uio.no> @ 2006-08-18 23:16 ` Robert Hancock 0 siblings, 0 replies; 3+ messages in thread From: Robert Hancock @ 2006-08-18 23:16 UTC (permalink / raw) To: linux-os (Dick Johnson), linux-kernel; +Cc: Giampaolo Tomassoni linux-os (Dick Johnson) wrote: > Apparently to handle these kinds of kludges, the kernel > interrupt code was modified so that the device-driver > code needs to returna value to the kernel core code. > If the value is not IRQ_HANDLED, then the ISR will be > called again. If your ISR never returns IRQ_HANDLED, > then the kernel core code will shut you off when it > detects a loop of (last I checked) 10,000 spins. This isn't to handle the edge-triggered case, that return value is to shut off the interrupt entirely in the case of a device that is asserting its interrupt but no driver claims to be handling it. Otherwise the interrupt storm could cause the machine to simply lock up. It doesn't just disable that ISR either, the interrupt line is disabled in the interrupt controller which may disable other devices using that line. -- Robert Hancock Saskatoon, SK, Canada To email, remove "nospam" from hancockr@nospamshaw.ca Home Page: http://www.roberthancock.com/ ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: R: How to avoid serial port buffer overruns?
@ 2006-08-18 14:30 Robert Hancock
2006-08-18 14:58 ` R: " Giampaolo Tomassoni
0 siblings, 1 reply; 3+ messages in thread
From: Robert Hancock @ 2006-08-18 14:30 UTC (permalink / raw)
To: Giampaolo Tomassoni; +Cc: Linux Kernel ML
Giampaolo Tomassoni wrote:
> I beg your pardon: I'm not used that much to interrupts handling in Linux, but this piece of code from sound/drivers/serial-u16550.c in a linux-2.6.16:
>
> static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
> {
> snd_uart16550_t *uart;
>
> uart = (snd_uart16550_t *) dev_id;
> spin_lock(&uart->open_lock);
> if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
> spin_unlock(&uart->open_lock);
> return IRQ_NONE;
> }
> inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */
> snd_uart16550_io_loop(uart);
> spin_unlock(&uart->open_lock);
> return IRQ_HANDLED;
> }
>
> means to me that IRQ_HANDLED is returned even when the interrupt is not issued by the specific UART. This may lead to problems when two or more uarts share the same irq line and the irq line is edge-triggered instead of level-triggered, as is the case with ISA.
>
> To my knowledge, IRQ_HANDLED should be returned when an interrupt had been served by that specific device handler. Returning a IRQ_HANDLED when the device didn't request for service, in the best case cuases interrupt latencies, in the worst (like in an ISA environment) impairs servicing requests from devices sharing the same IRQ line.
>
> The byte returned from inb(uart->base + UART_IIR) can be used to detect if this is the requesting UART.
>
> Am I wrong?
IRQ_HANDLED vs. IRQ_NONE has no effect on what interrupt handlers are
called, etc. It is only used to detect if an interrupt is firing without
being handled by any driver, in this case the kernel can detect this and
disable the interrupt.
I'm not sure exactly why the driver is returning IRQ_HANDLED all the
time, but edge-triggered interrupts are always tricky and there may be a
case where it can't reliably detect this. Returning IRQ_HANDLED is the
safe thing to do if you cannot be sure if your device raised an
interrupt or not.
--
Robert Hancock Saskatoon, SK, Canada
To email, remove "nospam" from hancockr@nospamshaw.ca
Home Page: http://www.roberthancock.com/
^ permalink raw reply [flat|nested] 3+ messages in thread* R: R: How to avoid serial port buffer overruns? 2006-08-18 14:30 Robert Hancock @ 2006-08-18 14:58 ` Giampaolo Tomassoni 2006-08-18 15:34 ` linux-os (Dick Johnson) 0 siblings, 1 reply; 3+ messages in thread From: Giampaolo Tomassoni @ 2006-08-18 14:58 UTC (permalink / raw) To: Robert Hancock; +Cc: Linux Kernel ML > -----Messaggio originale----- > Da: Robert Hancock [mailto:hancockr@shaw.ca] > Inviato: venerdì 18 agosto 2006 16.31 > A: Giampaolo Tomassoni > Cc: Linux Kernel ML > Oggetto: Re: R: How to avoid serial port buffer overruns? > > IRQ_HANDLED vs. IRQ_NONE has no effect on what interrupt handlers are > called, etc. It is only used to detect if an interrupt is firing without > being handled by any driver, in this case the kernel can detect this and > disable the interrupt. > > I'm not sure exactly why the driver is returning IRQ_HANDLED all the > time, but edge-triggered interrupts are always tricky and there may be a > case where it can't reliably detect this. Returning IRQ_HANDLED is the > safe thing to do if you cannot be sure if your device raised an > interrupt or not. Oh, I see. This in handle_IRQ_event in /kernel/irq/handle.c confirms what you said: do { ret = action->handler(irq, action->dev_id, regs); if (ret == IRQ_HANDLED) status |= action->flags; retval |= ret; action = action->next; } while (action); There is no escape from the loop when the handler returns IRQ_HANDLED. Thanks, giampaolo > > -- > Robert Hancock Saskatoon, SK, Canada > To email, remove "nospam" from hancockr@nospamshaw.ca > Home Page: http://www.roberthancock.com/ > ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: R: R: How to avoid serial port buffer overruns? 2006-08-18 14:58 ` R: " Giampaolo Tomassoni @ 2006-08-18 15:34 ` linux-os (Dick Johnson) 0 siblings, 0 replies; 3+ messages in thread From: linux-os (Dick Johnson) @ 2006-08-18 15:34 UTC (permalink / raw) To: Giampaolo Tomassoni; +Cc: Robert Hancock, Linux Kernel ML On Fri, 18 Aug 2006, Giampaolo Tomassoni wrote: >> -----Messaggio originale----- >> Da: Robert Hancock [mailto:hancockr@shaw.ca] >> Inviato: venerdì 18 agosto 2006 16.31 >> A: Giampaolo Tomassoni >> Cc: Linux Kernel ML >> Oggetto: Re: R: How to avoid serial port buffer overruns? >> >> IRQ_HANDLED vs. IRQ_NONE has no effect on what interrupt handlers are >> called, etc. It is only used to detect if an interrupt is firing without >> being handled by any driver, in this case the kernel can detect this and >> disable the interrupt. >> >> I'm not sure exactly why the driver is returning IRQ_HANDLED all the >> time, but edge-triggered interrupts are always tricky and there may be a >> case where it can't reliably detect this. Returning IRQ_HANDLED is the >> safe thing to do if you cannot be sure if your device raised an >> interrupt or not. > > Oh, I see. This in handle_IRQ_event in /kernel/irq/handle.c confirms what you said: > > do { > ret = action->handler(irq, action->dev_id, regs); > if (ret == IRQ_HANDLED) > status |= action->flags; > retval |= ret; > action = action->next; > } while (action); > > There is no escape from the loop when the handler returns IRQ_HANDLED. > > Thanks, > > giampaolo > >> >> -- >> Robert Hancock Saskatoon, SK, Canada >> To email, remove "nospam" from hancockr@nospamshaw.ca >> Home Page: http://www.roberthancock.com/ >> Hardware designed for shared interrupts use what's called open-collector or open-drain outputs. This allows all devices to be connected as a "wired-OR". Vcc | R |--------------|--------IRQ... / / 1 ------|| -----|| \ | \ | | | Ve | Ve 2 ----------------| In this case, any device can pull down on the IRQ line. The wire will remain active LOW until all the hardware interrupt demands are satisfied. This is used for "level" interrupts. Hardware designed for edge interrupts use active devices to pull a normally-low line up. This produces an edge which is latched by the interrupt controller. Since the interrupt controller has only one latch per input any subsequent edges that occur before the first instance of an interrupt is serviced (which clears the latch), will be lost. This is why devices that produce edges upon interrupt request can't be shared. However, some people who claim to know more than the designers of the devices, reason that if upon any interrupt all of the devices sharing the edge-type line, are checked for an interrupt request, then the devices will eventually all get serviced without losing any interrupts. The reasoning is faulty because the only way to accomplish this logic is, if you have N devices sharing an interrupt, then all N interrupt service routines need to be called N times to handle all the possibilities of hardware interrupt requests happening before the latch is reset. Apparently to handle these kinds of kludges, the kernel interrupt code was modified so that the device-driver code needs to returna value to the kernel core code. If the value is not IRQ_HANDLED, then the ISR will be called again. If your ISR never returns IRQ_HANDLED, then the kernel core code will shut you off when it detects a loop of (last I checked) 10,000 spins. Any device that uses an edge-type interrupt intended to be shared is broken by design. There are kludges that allow for lost interrupt recovery, such as kicking the device ISR off a timer-queue, but they are kludges, something to get bad hardware out the door. The 8250 UART and its modern counterparts use edge-type interrupt requests. If you have a special clone (there are some) that can programmed to use level interrupts, then you need to select an IRQ that can be programmed for level operation without screwing up the rest of the computer. This generally means that you can't use the default IRQ3 or IRQ4. Cheers, Dick Johnson Penguin : Linux version 2.6.16.24 on an i686 machine (5592.62 BogoMips). New book: http://www.AbominableFirebug.com/ _ \x1a\x04 **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-08-18 23:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <fa.QIapfCxFpNcj7ZdkL+1slt8AXnQ@ifi.uio.no>
[not found] ` <fa.f1Jp2YDS6/xT0GB2fsQq98CdRtA@ifi.uio.no>
2006-08-18 23:16 ` R: R: How to avoid serial port buffer overruns? Robert Hancock
2006-08-18 14:30 Robert Hancock
2006-08-18 14:58 ` R: " Giampaolo Tomassoni
2006-08-18 15:34 ` linux-os (Dick Johnson)
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox