Date: Wed, 8 Dec 2004 18:22:18 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Mike Tancsa <mike@sentex.net> Cc: freebsd-gnats-submit@freebsd.org Subject: Re: misc/74786: Smartlink Modem causes interrupt storm on RELENG_4 and RELENG_5 Message-ID: <20041208172619.Y1156@epsplex.bde.org> In-Reply-To: <6.2.0.14.0.20041207100615.0335e328@64.7.153.2> References: <200412062027.iB6KR1jE096684@www.freebsd.org> <6.2.0.14.0.20041207100615.0335e328@64.7.153.2>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 7 Dec 2004, Mike Tancsa wrote: > At 06:55 PM 06/12/2004, Bruce Evans wrote: > >On Mon, 6 Dec 2004, Mike Tancsa wrote: > ... > > > where irq12 is the IRQ shared by the modem and the USB port. However, > > because all IRQ 12s get throttled, the modem is unusable. e.g. trying to > > cu -l /dev/cuaa4 and typing atz takes about 5 seconds. > > > >Does a storm occur when both devices are successfully attached? Hmm, the > >above is consistent with the following combination: > >1. only usb being attached > >2. the sio device still driving the interrupt but sio not being called to > > handle the interrupt > Yes, that sounds correct. I think I understand this now. sio can indeed drive the interrupt (after you open an sio device, but not immediately at the end of the attach except in the serial console case). The main bugs are: 1. sio asks for exclusive access to the interrupt for no good reason (some buses like isa might only support exclusive accesses, but sio doesn't care). uhci gets access first in your configuration, so allocation of the interrupt resource fails. 2. Error handling for the failure in (1) is null, so both devices are "successfully" attached. 3. sio sets a flag to tell it to use polling if there is no interrupt resource, but it doesn't set the flag if the interrupt resource couldn't be allocated or if the interrupt couldn't be set up. 4. Upper layers provide negative help for debugging (3) using their own version of (3). They print "irq N" in boot messages if an interrupt resource justs exists. This doesn't mean that the device is using it. 5. Device interrupts are still enabled in polling mode. This depends on nothing else sucessfully setting up the (shared) interrupt. Try this fix. For the uhci-sio conflict, it should avoid problem (1) (please try it with the RF_SHAREABLE flag removed so that if this is indeed the primary problem then the new diagnostic will verify it). This should move the conflict later, to one between usb's use of normal interrupt mode and sio's request for fast interrupt mode. There were already sufficient diagnostics for this. The patch adds some more. Since usb got the interrupt first, sio will fall back to normal mode. If sio goes first then the attach of usb would probably fail. The patch doesn't change these bevhaviours. The patch adds another fallback to polled mode if setup of normal mode mode fails and fixes some related resource leaks. It also increases the polling frequency if possible. Polled mode mostly works at 115200 bps provided the UART is buffered and HZ >= 1000. With unbuffered UARTs and HZ = 100, only 4800 bos mostly works. I only tested with some fudged isa conflicts because all my machines are configured to not have any shared irqs for serial devices and hints are just hints so they can't be used to force conflicts excet for isa. %%% Index: sio.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sio/sio.c,v retrieving revision 1.442 diff -u -2 -r1.442 sio.c --- sio.c 25 Jun 2004 10:51:33 -0000 1.442 +++ sio.c 8 Dec 2004 06:09:12 -0000 @@ -1165,7 +1165,14 @@ pps_init(&com->pps); + if (com->no_irq) + goto over_irq_setup; rid = 0; - com->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); - if (com->irqres) { + com->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + if (com->irqres == NULL) { + device_printf(dev, "interrupt resource allocation failed\n"); + device_printf(dev, "falling back to polled mode\n"); + com->no_irq = TRUE; + } else { ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, INTR_TYPE_TTY | INTR_FAST, @@ -1178,6 +1185,11 @@ device_printf(dev, "unable to activate interrupt in fast mode - using normal mode\n"); } - if (ret) + if (ret != 0) { device_printf(dev, "could not activate interrupt\n"); + bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres); + com->irqres = NULL; + device_printf(dev, "falling back to polled mode\n"); + com->no_irq = TRUE; + } #if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \ defined(ALT_BREAK_TO_DEBUGGER)) @@ -1191,4 +1203,9 @@ #endif } +over_irq_setup: + if (com->no_irq) { + outb(com->modem_ctl_port, com->mcr_image &= ~MCR_IENABLE); + device_printf(dev, "polled mode\n"); + } return (0); @@ -2647,5 +2664,5 @@ /* * Set our timeout period to 1 second if no polled devices are open. - * Otherwise set it to max(1/200, 1/hz). + * Otherwise, set it to max(1/1000, 1/hz). * Enable timeouts iff some device is open. */ @@ -2659,5 +2676,5 @@ someopen = TRUE; if (com->poll || com->poll_output) { - sio_timeout = hz > 200 ? hz / 200 : 1; + sio_timeout = hz > 1000 ? hz / 1000 : 1; break; } %%% Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041208172619.Y1156>