From nobody  Mon Jun  1 13:07:25 1998
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id NAA20243;
          Mon, 1 Jun 1998 13:07:25 -0700 (PDT)
          (envelope-from nobody)
Message-Id: <199806012007.NAA20243@hub.freebsd.org>
Date: Mon, 1 Jun 1998 13:07:25 -0700 (PDT)
From: nick.hibma@jrc.it
To: freebsd-gnats-submit@freebsd.org
Subject: pci_unmap_int (pci/pci.c) does not properly unmask an interrupt
X-Send-Pr-Version: www-1.0

>Number:         6819
>Category:       kern
>Synopsis:       [PATCH] pci_unmap_int (pci/pci.c) does not properly unmask an interrupt
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jun  1 13:10:00 PDT 1998
>Closed-Date:    Mon Jul 12 05:38:20 PDT 1999
>Last-Modified:  Mon Jul 12 05:40:06 PDT 1999
>Originator:     Nick Hibma
>Release:        2.2.1
>Organization:
None
>Environment:
FreeBSD heidi.plazza.it 2.2.1-RELEASE FreeBSD 2.2.1-RELEASE #48: Mon Jun  1 20:37:12 CEST 1998     toor@heidi.plazza.it:/usr/src/sys/compile/HEIDI  i386
>Description:
Unmapping an interrupt used by a PCI device is incorrectly done. Mapping
it, unmapping it and then mapping it again results it a failing mapping.

Unmapping is done, but somehow the unmapping is not done completely in
pci_unmap_int. After the failed attempt the to map the interrupt another 
try is succesfull:

pci_map_int (succesfull)
pci_unmap_int (succesfull)
pci_map_int (fails)
pci_map_int (succesfull) <<<<<<<<<<<<<<<<<<<<
pci_unmap_int (succesfull)
pci_map_int (fails)
pci_map_int (succesfull) <<<<<<<<<<<<<<<<<<<<
etc.
>How-To-Repeat:
Load an LKM module that registers a PCI interrupt with pci_map_int and can be unloaded unmapping the interrupt with pci_unmap_int.

Load the LKM, unload it and load it again. The LKM should complain about
not being able to map the interrupt. Loading it a second time should be
succesfull.

Possible LKM to be used: USB stack http://www.etla.net/~n_hibma/usb/usb.pl

This LKM maps the interrupt as bio_imask.
>Fix:
Moved the exclusion of the interrupt mask below the part detaching the
irq.

Reason for this is that in pci_imask_exclude the interrupt is masked out
but after calling update_intr_masks the bit is set again in *maskptr,
because the interrupt has not yet been detached.

This fix should be checked by someone who knows what he is doing, when
interrupts are concerned, because I am a nono in that field (any field
actually, but don't tell anyone :-).

diff -C3 pci.c.orig pci.c

*** pci.c.orig  Mon Jun  1 21:59:24 1998
--- pci.c       Mon Jun  1 21:55:35 1998
***************
*** 1392,1397 ****
--- 1392,1399 ----
        if (irq == 0xff)
                return (0);
  
+       oldspl = splq (1ul << irq);
+ 
        /*
        **      Search and unlink interrupt descriptor.
        */
***************
*** 1415,1423 ****
                irq, this->pcid_handler, this->pcid_argument,
                this->pcid_tag.tag, this->pcid_tally);
  
-       if (!getintdescbymptr (irq, this->pcid_maskptr))
-               (void) pcibus->pb_imaskexc (irq, this->pcid_maskptr);
- 
        /*
        **      If this irq no longer included in the mask, remove it.
        */
--- 1417,1422 ----
***************
*** 1437,1444 ****
  
        } else if (tail->pcid_next == NULL) {
  
-               oldspl = splq (1ul << irq);
- 
                /*
                **      Remove the shared int handler.
                **      Install the last remaining handler.
--- 1436,1441 ----
***************
*** 1455,1465 ****
  
                if (result)
                        printf ("\tirq %d: cannot install handler.\n", irq);
- 
-               splx (oldspl);
        };
  
        free (this, M_DEVBUF);
        return (1);
  }
  
--- 1452,1464 ----
  
                if (result)
                        printf ("\tirq %d: cannot install handler.\n", irq);
        };
  
+       if (!getintdescbymptr (irq, this->pcid_maskptr))
+               (void) pcibus->pb_imaskexc (irq, this->pcid_maskptr);
+ 
        free (this, M_DEVBUF);
+       splx (oldspl);
        return (1);
  }

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: phk 
State-Changed-When: Tue Jun 2 04:17:40 PDT 1998 
State-Changed-Why:  
awaiting committer 
State-Changed-From-To: suspended->closed 
State-Changed-By: n_hibma 
State-Changed-When: Mon Jul 12 05:38:20 PDT 1999 
State-Changed-Why:  
The interrupt management code has changed drastically and the patch is 
no longer applicable. If the problem still exists, it looks like it will 
have moved to the mother bus of PCI (nexus?). 
>Unformatted:
