From karl@FS.denninger.net  Fri Nov 27 18:50:46 2009
Return-Path: <karl@FS.denninger.net>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 8A1BB106566C
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 27 Nov 2009 18:50:46 +0000 (UTC)
	(envelope-from karl@FS.denninger.net)
Received: from FS.denninger.net (wsip-70-169-168-7.pn.at.cox.net [70.169.168.7])
	by mx1.freebsd.org (Postfix) with ESMTP id 40C278FC0C
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 27 Nov 2009 18:50:45 +0000 (UTC)
Received: from fs.denninger.net (localhost [127.0.0.1])
	by FS.denninger.net (8.14.3/8.13.1) with SMTP id nARGmhHX004183
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 27 Nov 2009 10:48:44 -0600 (CST)
	(envelope-from karl@FS.denninger.net)
Received: from fs.denninger.net [127.0.0.1] by Spamblock-sys (LOCAL);
	Fri Nov 27 10:48:43 2009
Received: (from root@localhost)
	by FS.denninger.net (8.14.3/8.13.1/Submit) id nARGmh5D004180;
	Fri, 27 Nov 2009 10:48:43 -0600 (CST)
	(envelope-from karl)
Message-Id: <200911271648.nARGmh5D004180@FS.denninger.net>
Date: Fri, 27 Nov 2009 10:48:43 -0600 (CST)
From: Karl Denninger <karl@FS.denninger.net>
Reply-To: Karl Denninger <karl@FS.denninger.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: Serial I/O is terminally screwed under 8.x.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         140947
>Category:       kern
>Synopsis:       [uart] [hang] Serial I/O is terminally screwed under 8.x.
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    marcel
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Nov 27 19:00:06 UTC 2009
>Closed-Date:    Mon Dec 14 17:52:26 UTC 2009
>Last-Modified:  Sun Dec 20 23:28:41 UTC 2009
>Originator:     Karl Denninger
>Release:        FreeBSD 8.0-STABLE i386
>Organization:
Karls Sushi and Packet Smashers
>Environment:
System: FreeBSD FS.denninger.net 8.0-STABLE FreeBSD 8.0-STABLE #3: Fri Nov 27 08:32:51 CST 2009 karl@FS.denninger.net:/usr/obj/usr/src/sys/KSD-SMP i386

puc0: <Oxford Semiconductor OX16PCI954 UARTs> port 0x4060-0x407f,0x4040-0x405f m
em 0x94503000-0x94503fff,0x94502000-0x94502fff irq 16 at device 0.0 on pci3
puc0: [FILTER]
uart2: <16550 or compatible> on puc0
uart2: [FILTER]
uart3: <16550 or compatible> on puc0
uart3: [FILTER]
uart4: <16550 or compatible> on puc0
uart4: [FILTER]
uart5: <16550 or compatible> on puc0
uart5: [FILTER]

puc0@pci0:3:0:0:        class=0x070006 card=0x00001415 chip=0x950a1415 rev=0x00 hdr=0x00
    bar   [10] = type I/O Port, range 32, base 0x4060, size 32, enabled
    bar   [14] = type Memory, range 32, base 0x94503000, size 4096, enabled
    bar   [18] = type I/O Port, range 32, base 0x4040, size 32, enabled
    bar   [1c] = type Memory, range 32, base 0x94502000, size 4096, enabled
    cap 01[40] = powerspec 1  supports D0 D2 D3  current D0

#
# SMP -- Generic kernel configuration file for FreeBSD/i386 SMP
#        Use this for multi-processor machines
#
# $FreeBSD: src/sys/i386/conf/SMP,v 1.5.6.1 2005/09/18 03:37:58 scottl Exp $

include GENERIC

ident           KSD-SMP

# To make an SMP kernel, the next line is needed
#options        SMP                     # Symmetric MultiProcessor Kernel
#
# We also need the firewall, divert, and PPS_SYNC (for the GPS) options
#
options         IPFIREWALL
options         IPDIVERT
options         PPS_SYNC
#
# Rate-shaping requirements
#
options         DUMMYNET
options         HZ=1000
#options                SYSVSHM
#
# Local stuff
#
device          rp              # Comtrol Rocketport Board
device          sound           # Generic sound card drivers

#device         ubsa            # USB Serial Adapters
#device         ucom
#device         uftdi
#device         uplcom

device          umct
device          puc

>Description:
	Serial I/O fails with a lockup after a variable amount of time.  
	Modem-controlled ports are succeptible, especially those that
	require tight adherence to that capability.

	There is no reset possible without rebooting the machine.  Attempts
	to "probe" the port by stopping the running process(es) and
	re-initializing them fail.

	This IDENTICAL board in the IDENTICAL machine was functioning
	properly under 7.x over the space of about a year under extremely
	heavy use.  As soon as 8.x-RC2 was loaded, and subsequently with the
	released version (as seen above) it failed and has remained dead.

	The custom kernel with "PPS_SYNC" is present as one
	of the ports (on the motherboard) is used for a GPS clock under ntpd.
	This port is operating fine - it is relatively low-traffic, of
	course, containing only timecode.  Another port used to talk to an
	APC UPS (again, low traffic) is also ok.

	All ports in use for Hylafax, however, lock up as described above.

	Attempting to limit FIFO depth with 0x100 or 0x200 flags on the
	ports has no effect.


>How-To-Repeat:
	Put a "puc" style board in the machine, set up hylafax, send a few
	dozen faxes.  The driver will wedge.

>Fix:

	




>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-i386->ed 
Responsible-Changed-By: remko 
Responsible-Changed-When: Sat Nov 28 20:43:51 UTC 2009 
Responsible-Changed-Why:  
You are mrtty, can you have a look at this please? 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140947 

From: Ed Schouten <ed@80386.nl>
To: Remko Lodder <remko@FreeBSD.org>
Cc: freebsd-i386@FreeBSD.org
Subject: Re: i386/140947: Serial I/O is terminally screwed under 8.x.
Date: Sun, 29 Nov 2009 14:37:31 +0100

 --s1V7GiNVmT/EiLBY
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 Hello Karl,
 
 Could you attach the output of `pstat -t' to this bug report, please?
 
 --=20
  Ed Schouten <ed@80386.nl>
  WWW: http://80386.nl/
 
 --s1V7GiNVmT/EiLBY
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (FreeBSD)
 
 iEYEARECAAYFAksSeRsACgkQ52SDGA2eCwUOvwCdGZP8CY3Lh6ISJjqFtx7ZsmTp
 c8gAn1D3Efsg4i0/Fw+m/m+yn8cv/kqA
 =S9ck
 -----END PGP SIGNATURE-----
 
 --s1V7GiNVmT/EiLBY--
State-Changed-From-To: open->feedback 
State-Changed-By: linimon 
State-Changed-When: Mon Nov 30 06:29:24 UTC 2009 
State-Changed-Why:  
Note that feedback has been requested.  While here, reclassify, as 
this is probably not i386-specific. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140947 

Date: Wed, 2 Dec 2009 10:23:11 +1100
From: Robert Jenssen <robertjenssen@ozemail.com.au>
To: bug-followup@FreeBSD.org, karl@FS.denninger.net
Cc: Ed Schouten <ed@80386.nl>
Subject: Re:140947:[uart] [hang] Serial I/O is terminally screwed under 8.x.

 I have had a similar problem: testing the USART on an Atmel AT91SAM7S-EK
 board with a simple echo at 115200 baud. On the host /dev/cuau0 is
 initialised with cfmakeraw() and select() has a 1s timeout. After some
 time the echo fails with select() on a read  descriptor timing out.
 "pstat -t" output is then:
 
       LINE   INQ  CAN  LIN  LOW  OUTQ  USE  LOW   COL  SESS  PGID STATE
      dcons     0    0    0    0     0    0    0     0     0     0 -
       dgdb     0    0    0    0     0    0    0     0     0     0 -
   sysmouse  1920    0    0  192     0    0    0     0     0     0 OiY
      ttyu0     0    0    0    0     0    0    0  4662     0     0 IC
 
 Output of uname -a:
 
 FreeBSD kraken 8.0-STABLE FreeBSD 8.0-STABLE #0: Mon Nov 30 16:23:21 EST 2009     root@kraken:/usr/obj/usr/src/sys/KRAKEN  i386

Date: Wed, 2 Dec 2009 15:52:39 +1100
From: Robert Jenssen <robertjenssen@ozemail.com.au>
To: bug-followup@FreeBSD.org, karl@FS.denninger.net
Cc: Ed Schouten <ed@80386.nl>
Subject: Re:140947:[uart] [hang] Serial I/O is terminally screwed under 8.x.

 FWIW, I made a debug kernel with additional options:
 
 makeoptions DEBUG=-g
 options KDTRACE_HOOKS
 options KDB
 options DDB
 
 and could not reproduce the problem. After restoring the original kernel
 the problem returns.

Date: Wed, 2 Dec 2009 08:31:55 +0100
From: Ed Schouten <ed@80386.nl>
To: Robert Jenssen <robertjenssen@ozemail.com.au>
Cc: bug-followup@FreeBSD.org, karl@FS.denninger.net
Subject: Re: 140947:[uart] [hang] Serial I/O is terminally screwed under 8.x.

 --LqIGKb6ivCeGIB65
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 Hi Robert,
 
 * Robert Jenssen <robertjenssen@ozemail.com.au> wrote:
 > I have had a similar problem: testing the USART on an Atmel
 > AT91SAM7S-EK board with a simple echo at 115200 baud. On the host
 > /dev/cuau0 is initialised with cfmakeraw() and select() has a 1s
 > timeout. After some time the echo fails with select() on a read
 > descriptor timing out. "pstat -t" output is then:
 >       LINE   INQ  CAN  LIN  LOW  OUTQ  USE  LOW   COL  SESS  PGID STATE
 >      dcons     0    0    0    0     0    0    0     0     0     0 -
 >       dgdb     0    0    0    0     0    0    0     0     0     0 -
 >   sysmouse  1920    0    0  192     0    0    0     0     0     0 OiY
 >      ttyu0     0    0    0    0     0    0    0  4662     0     0 IC
 
 It's the output of `pstat -t' during operation I'm interested in. When
 the device is closed, there isn't much to see, because the TTY is reset
 to an initial state (see the buffer size of 0).
 
 --=20
  Ed Schouten <ed@80386.nl>
  WWW: http://80386.nl/
 
 --LqIGKb6ivCeGIB65
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (FreeBSD)
 
 iEYEARECAAYFAksWF+sACgkQ52SDGA2eCwVYnwCfWiG7H1lrXM7w7Hg2BFVFt589
 NlsAnREwuLJ6w80kfJJky2Wbb5ojg2zR
 =T/lf
 -----END PGP SIGNATURE-----
 
 --LqIGKb6ivCeGIB65--

Date: Wed, 2 Dec 2009 08:32:57 +0100
From: Ed Schouten <ed@80386.nl>
Cc: bug-followup@FreeBSD.org
Subject: Re: 140947:[uart] [hang] Serial I/O is terminally screwed under 8.x.

 --rXoc3kw+CNDOk2Sr
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 
 FYI, Karl's email address just bounces when I try to send emails to him.
 
 --=20
  Ed Schouten <ed@80386.nl>
  WWW: http://80386.nl/
 
 --rXoc3kw+CNDOk2Sr
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (FreeBSD)
 
 iEYEARECAAYFAksWGCkACgkQ52SDGA2eCwWLXACfdBZXBaQ39yvhrlz+fbOmJZkf
 SM0AnjMg7iTzevo3oO+bYrOXgGuQRiYy
 =0bQR
 -----END PGP SIGNATURE-----
 
 --rXoc3kw+CNDOk2Sr--
State-Changed-From-To: feedback->patched 
State-Changed-By: marcel 
State-Changed-When: Fri Dec 11 03:08:49 UTC 2009 
State-Changed-Why:  
Fix committed to puc(4). MFC in about 3 days. 


Responsible-Changed-From-To: ed->marcel 
Responsible-Changed-By: marcel 
Responsible-Changed-When: Fri Dec 11 03:08:49 UTC 2009 
Responsible-Changed-Why:  
Fix committed to puc(4). MFC in about 3 days. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140947 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/140947: commit references a PR
Date: Fri, 11 Dec 2009 03:08:18 +0000 (UTC)

 Author: marcel
 Date: Fri Dec 11 03:08:07 2009
 New Revision: 200397
 URL: http://svn.freebsd.org/changeset/base/200397
 
 Log:
   Fix interrupt handling. It started off broken and grew worse over time.
   The rewrite of the interrupt handler includes:
   o   loop until all pending interrupts are handled. This closes a
       race condition.
   o   count the number of interrupt sources we handled so that we can
       properly return FILTER_HANDLED or FILTER_STRAY when we break out
       of the loop.
   o   When matching the interrupt source to the devices that have that
       source pending, check only from the set of devices we found to
       have a pending interrupt.
   
   PR:		kern/140947
   MFC after:	3 days
 
 Modified:
   head/sys/dev/puc/puc.c
 
 Modified: head/sys/dev/puc/puc.c
 ==============================================================================
 --- head/sys/dev/puc/puc.c	Fri Dec 11 02:52:14 2009	(r200396)
 +++ head/sys/dev/puc/puc.c	Fri Dec 11 03:08:07 2009	(r200397)
 @@ -129,62 +129,78 @@ puc_intr(void *arg)
  {
  	struct puc_port *port;
  	struct puc_softc *sc = arg;
 -	u_long dev, devs;
 -	int i, idx, ipend, isrc;
 +	u_long ds, dev, devs;
 +	int i, idx, ipend, isrc, nints;
  	uint8_t ilr;
  
 -	devs = sc->sc_serdevs;
 -	if (sc->sc_ilr == PUC_ILR_DIGI) {
 -		idx = 0;
 -		while (devs & (0xfful << idx)) {
 -			ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 -			devs &= ~0ul ^ ((u_long)ilr << idx);
 -			idx += 8;
 -		}
 -	} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +	nints = 0;
 +	while (1) {
  		/*
 -		 * Don't trust the value if it's the same as the option
 -		 * register. It may mean that the ILR is not active and
 -		 * we're reading the option register instead. This may
 -		 * lead to false positives on 8-port boards.
 +		 * Obtain the set of devices with pending interrupts.
  		 */
 -		ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 -		if (ilr != (sc->sc_cfg_data & 0xff))
 -			devs &= (u_long)ilr;
 -	}
 -
 -	ipend = 0;
 -	idx = 0, dev = 1UL;
 -	while (devs != 0UL) {
 -		while ((devs & dev) == 0UL)
 -			idx++, dev <<= 1;
 -		devs &= ~dev;
 -		port = &sc->sc_port[idx];
 -		port->p_ipend = SERDEV_IPEND(port->p_dev);
 -		ipend |= port->p_ipend;
 -	}
 +		devs = sc->sc_serdevs;
 +		if (sc->sc_ilr == PUC_ILR_DIGI) {
 +			idx = 0;
 +			while (devs & (0xfful << idx)) {
 +				ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 +				devs &= ~0ul ^ ((u_long)ilr << idx);
 +				idx += 8;
 +			}
 +		} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +			/*
 +			 * Don't trust the value if it's the same as the option
 +			 * register. It may mean that the ILR is not active and
 +			 * we're reading the option register instead. This may
 +			 * lead to false positives on 8-port boards.
 +			 */
 +			ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 +			if (ilr != (sc->sc_cfg_data & 0xff))
 +				devs &= (u_long)ilr;
 +		}
 +		if (devs == 0UL)
 +			break;
  
 -	i = 0, isrc = SER_INT_OVERRUN;
 -	while (ipend) {
 -		while (i < PUC_ISRCCNT && !(ipend & isrc))
 -			i++, isrc <<= 1;
 -		KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 -		ipend &= ~isrc;
 +		/*
 +		 * Obtain the set of interrupt sources from those devices
 +		 * that have pending interrupts.
 +		 */
 +		ipend = 0;
  		idx = 0, dev = 1UL;
 -		devs = sc->sc_serdevs;
 -		while (devs != 0UL) {
 -			while ((devs & dev) == 0UL)
 +		ds = devs;
 +		while (ds != 0UL) {
 +			while ((ds & dev) == 0UL)
  				idx++, dev <<= 1;
 -			devs &= ~dev;
 +			ds &= ~dev;
  			port = &sc->sc_port[idx];
 -			if (!(port->p_ipend & isrc))
 -				continue;
 -			if (port->p_ihsrc[i] != NULL)
 -				(*port->p_ihsrc[i])(port->p_iharg);
 +			port->p_ipend = SERDEV_IPEND(port->p_dev);
 +			ipend |= port->p_ipend;
 +		}
 +		if (ipend == 0)
 +			break;
 +
 +		i = 0, isrc = SER_INT_OVERRUN;
 +		while (ipend) {
 +			while (i < PUC_ISRCCNT && !(ipend & isrc))
 +				i++, isrc <<= 1;
 +			KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 +			ipend &= ~isrc;
 +			idx = 0, dev = 1UL;
 +			ds = devs;
 +			while (ds != 0UL) {
 +				while ((ds & dev) == 0UL)
 +					idx++, dev <<= 1;
 +				ds &= ~dev;
 +				port = &sc->sc_port[idx];
 +				if (!(port->p_ipend & isrc))
 +					continue;
 +				if (port->p_ihsrc[i] != NULL)
 +					(*port->p_ihsrc[i])(port->p_iharg);
 +				nints++;
 +			}
  		}
 -		return (FILTER_HANDLED);
  	}
 -	return (FILTER_STRAY);
 +
 +	return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY);
  }
  
  int
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/140947: commit references a PR
Date: Mon, 14 Dec 2009 17:42:54 +0000 (UTC)

 Author: marcel
 Date: Mon Dec 14 17:42:40 2009
 New Revision: 200517
 URL: http://svn.freebsd.org/changeset/base/200517
 
 Log:
   MFC rev 200397:
   Fix interrupt handling.
   
   PR:		kern/140947
 
 Modified:
   stable/8/sys/dev/puc/puc.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
 
 Modified: stable/8/sys/dev/puc/puc.c
 ==============================================================================
 --- stable/8/sys/dev/puc/puc.c	Mon Dec 14 17:04:44 2009	(r200516)
 +++ stable/8/sys/dev/puc/puc.c	Mon Dec 14 17:42:40 2009	(r200517)
 @@ -129,62 +129,78 @@ puc_intr(void *arg)
  {
  	struct puc_port *port;
  	struct puc_softc *sc = arg;
 -	u_long dev, devs;
 -	int i, idx, ipend, isrc;
 +	u_long ds, dev, devs;
 +	int i, idx, ipend, isrc, nints;
  	uint8_t ilr;
  
 -	devs = sc->sc_serdevs;
 -	if (sc->sc_ilr == PUC_ILR_DIGI) {
 -		idx = 0;
 -		while (devs & (0xfful << idx)) {
 -			ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 -			devs &= ~0ul ^ ((u_long)ilr << idx);
 -			idx += 8;
 -		}
 -	} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +	nints = 0;
 +	while (1) {
  		/*
 -		 * Don't trust the value if it's the same as the option
 -		 * register. It may mean that the ILR is not active and
 -		 * we're reading the option register instead. This may
 -		 * lead to false positives on 8-port boards.
 +		 * Obtain the set of devices with pending interrupts.
  		 */
 -		ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 -		if (ilr != (sc->sc_cfg_data & 0xff))
 -			devs &= (u_long)ilr;
 -	}
 -
 -	ipend = 0;
 -	idx = 0, dev = 1UL;
 -	while (devs != 0UL) {
 -		while ((devs & dev) == 0UL)
 -			idx++, dev <<= 1;
 -		devs &= ~dev;
 -		port = &sc->sc_port[idx];
 -		port->p_ipend = SERDEV_IPEND(port->p_dev);
 -		ipend |= port->p_ipend;
 -	}
 +		devs = sc->sc_serdevs;
 +		if (sc->sc_ilr == PUC_ILR_DIGI) {
 +			idx = 0;
 +			while (devs & (0xfful << idx)) {
 +				ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 +				devs &= ~0ul ^ ((u_long)ilr << idx);
 +				idx += 8;
 +			}
 +		} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +			/*
 +			 * Don't trust the value if it's the same as the option
 +			 * register. It may mean that the ILR is not active and
 +			 * we're reading the option register instead. This may
 +			 * lead to false positives on 8-port boards.
 +			 */
 +			ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 +			if (ilr != (sc->sc_cfg_data & 0xff))
 +				devs &= (u_long)ilr;
 +		}
 +		if (devs == 0UL)
 +			break;
  
 -	i = 0, isrc = SER_INT_OVERRUN;
 -	while (ipend) {
 -		while (i < PUC_ISRCCNT && !(ipend & isrc))
 -			i++, isrc <<= 1;
 -		KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 -		ipend &= ~isrc;
 +		/*
 +		 * Obtain the set of interrupt sources from those devices
 +		 * that have pending interrupts.
 +		 */
 +		ipend = 0;
  		idx = 0, dev = 1UL;
 -		devs = sc->sc_serdevs;
 -		while (devs != 0UL) {
 -			while ((devs & dev) == 0UL)
 +		ds = devs;
 +		while (ds != 0UL) {
 +			while ((ds & dev) == 0UL)
  				idx++, dev <<= 1;
 -			devs &= ~dev;
 +			ds &= ~dev;
  			port = &sc->sc_port[idx];
 -			if (!(port->p_ipend & isrc))
 -				continue;
 -			if (port->p_ihsrc[i] != NULL)
 -				(*port->p_ihsrc[i])(port->p_iharg);
 +			port->p_ipend = SERDEV_IPEND(port->p_dev);
 +			ipend |= port->p_ipend;
 +		}
 +		if (ipend == 0)
 +			break;
 +
 +		i = 0, isrc = SER_INT_OVERRUN;
 +		while (ipend) {
 +			while (i < PUC_ISRCCNT && !(ipend & isrc))
 +				i++, isrc <<= 1;
 +			KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 +			ipend &= ~isrc;
 +			idx = 0, dev = 1UL;
 +			ds = devs;
 +			while (ds != 0UL) {
 +				while ((ds & dev) == 0UL)
 +					idx++, dev <<= 1;
 +				ds &= ~dev;
 +				port = &sc->sc_port[idx];
 +				if (!(port->p_ipend & isrc))
 +					continue;
 +				if (port->p_ihsrc[i] != NULL)
 +					(*port->p_ihsrc[i])(port->p_iharg);
 +				nints++;
 +			}
  		}
 -		return (FILTER_HANDLED);
  	}
 -	return (FILTER_STRAY);
 +
 +	return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY);
  }
  
  int
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/140947: commit references a PR
Date: Mon, 14 Dec 2009 17:45:29 +0000 (UTC)

 Author: marcel
 Date: Mon Dec 14 17:45:16 2009
 New Revision: 200518
 URL: http://svn.freebsd.org/changeset/base/200518
 
 Log:
   MFC rev 200397:
   Fix interrupt handling.
   
   PR:		kern/140947
 
 Modified:
   stable/7/sys/dev/puc/puc.c
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/dev/puc/puc.c
 ==============================================================================
 --- stable/7/sys/dev/puc/puc.c	Mon Dec 14 17:42:40 2009	(r200517)
 +++ stable/7/sys/dev/puc/puc.c	Mon Dec 14 17:45:16 2009	(r200518)
 @@ -129,62 +129,78 @@ puc_intr(void *arg)
  {
  	struct puc_port *port;
  	struct puc_softc *sc = arg;
 -	u_long dev, devs;
 -	int i, idx, ipend, isrc;
 +	u_long ds, dev, devs;
 +	int i, idx, ipend, isrc, nints;
  	uint8_t ilr;
  
 -	devs = sc->sc_serdevs;
 -	if (sc->sc_ilr == PUC_ILR_DIGI) {
 -		idx = 0;
 -		while (devs & (0xfful << idx)) {
 -			ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 -			devs &= ~0ul ^ ((u_long)ilr << idx);
 -			idx += 8;
 -		}
 -	} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +	nints = 0;
 +	while (1) {
  		/*
 -		 * Don't trust the value if it's the same as the option
 -		 * register. It may mean that the ILR is not active and
 -		 * we're reading the option register instead. This may
 -		 * lead to false positives on 8-port boards.
 +		 * Obtain the set of devices with pending interrupts.
  		 */
 -		ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 -		if (ilr != (sc->sc_cfg_data & 0xff))
 -			devs &= (u_long)ilr;
 -	}
 -
 -	ipend = 0;
 -	idx = 0, dev = 1UL;
 -	while (devs != 0UL) {
 -		while ((devs & dev) == 0UL)
 -			idx++, dev <<= 1;
 -		devs &= ~dev;
 -		port = &sc->sc_port[idx];
 -		port->p_ipend = SERDEV_IPEND(port->p_dev);
 -		ipend |= port->p_ipend;
 -	}
 +		devs = sc->sc_serdevs;
 +		if (sc->sc_ilr == PUC_ILR_DIGI) {
 +			idx = 0;
 +			while (devs & (0xfful << idx)) {
 +				ilr = ~bus_read_1(sc->sc_port[idx].p_rres, 7);
 +				devs &= ~0ul ^ ((u_long)ilr << idx);
 +				idx += 8;
 +			}
 +		} else if (sc->sc_ilr == PUC_ILR_QUATECH) {
 +			/*
 +			 * Don't trust the value if it's the same as the option
 +			 * register. It may mean that the ILR is not active and
 +			 * we're reading the option register instead. This may
 +			 * lead to false positives on 8-port boards.
 +			 */
 +			ilr = bus_read_1(sc->sc_port[0].p_rres, 7);
 +			if (ilr != (sc->sc_cfg_data & 0xff))
 +				devs &= (u_long)ilr;
 +		}
 +		if (devs == 0UL)
 +			break;
  
 -	i = 0, isrc = SER_INT_OVERRUN;
 -	while (ipend) {
 -		while (i < PUC_ISRCCNT && !(ipend & isrc))
 -			i++, isrc <<= 1;
 -		KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 -		ipend &= ~isrc;
 +		/*
 +		 * Obtain the set of interrupt sources from those devices
 +		 * that have pending interrupts.
 +		 */
 +		ipend = 0;
  		idx = 0, dev = 1UL;
 -		devs = sc->sc_serdevs;
 -		while (devs != 0UL) {
 -			while ((devs & dev) == 0UL)
 +		ds = devs;
 +		while (ds != 0UL) {
 +			while ((ds & dev) == 0UL)
  				idx++, dev <<= 1;
 -			devs &= ~dev;
 +			ds &= ~dev;
  			port = &sc->sc_port[idx];
 -			if (!(port->p_ipend & isrc))
 -				continue;
 -			if (port->p_ihsrc[i] != NULL)
 -				(*port->p_ihsrc[i])(port->p_iharg);
 +			port->p_ipend = SERDEV_IPEND(port->p_dev);
 +			ipend |= port->p_ipend;
 +		}
 +		if (ipend == 0)
 +			break;
 +
 +		i = 0, isrc = SER_INT_OVERRUN;
 +		while (ipend) {
 +			while (i < PUC_ISRCCNT && !(ipend & isrc))
 +				i++, isrc <<= 1;
 +			KASSERT(i < PUC_ISRCCNT, ("%s", __func__));
 +			ipend &= ~isrc;
 +			idx = 0, dev = 1UL;
 +			ds = devs;
 +			while (ds != 0UL) {
 +				while ((ds & dev) == 0UL)
 +					idx++, dev <<= 1;
 +				ds &= ~dev;
 +				port = &sc->sc_port[idx];
 +				if (!(port->p_ipend & isrc))
 +					continue;
 +				if (port->p_ihsrc[i] != NULL)
 +					(*port->p_ihsrc[i])(port->p_iharg);
 +				nints++;
 +			}
  		}
 -		return (FILTER_HANDLED);
  	}
 -	return (FILTER_STRAY);
 +
 +	return ((nints > 0) ? FILTER_HANDLED : FILTER_STRAY);
  }
  
  int
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: marcel 
State-Changed-When: Mon Dec 14 17:52:12 UTC 2009 
State-Changed-Why:  
fixed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=140947 
>Unformatted:
