Bug 21773

Summary: panic w/nexus + ata (ivar problem)
Product: Base System Reporter: Jonathan Lemon <jlemon>
Component: kernAssignee: Søren Schmidt <sos>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.0-CURRENT   
Hardware: Any   
OS: Any   

Description Jonathan Lemon 2000-10-05 17:40:00 UTC
	After the nexus/ivar change around Sep 28, my kernel no longer
	boots.  This seems to be a disagreement over how ivars are used
	in the kernel.  Within nexus_alloc_resource(), we have the 
	following:

#define DEVTONX(dev)       ((struct nexus_device *)device_get_ivars(dev))
		struct nexus_device *ndev = DEVTONX(child);

	where ``child'' happens to be ata1.  However, within ata/ata-all.c,
	There is the following statement:

		device_set_ivars(child, (void *)(uintptr_t) unit);

	So when nexus_alloc_resource() is called, it ends up treating the
	unit as a pointer.  I'm not sure what the new world order mandates
	here; what is the legal usage of ivar?

	Additional debug infromation from the nexus_alloc_resource()
	stack frame:

(kgdb) p *dev
$4 = {ops = 0xc0a57000, link = {tqe_next = 0x0, tqe_prev = 0xc0721410}, 
  parent = 0xc0721400, children = {tqh_first = 0xc0a6f300, 
    tqh_last = 0xc0a6f184}, driver = 0xc02fb38c, devclass = 0xc0725300, 
  unit = 0, nameunit = 0xc071d640 "nexus0", desc = 0x0, busy = 0, 
  state = DS_ALIVE, devflags = 0, flags = 19, order = 0 '\000', 
  pad = 0 '\000', ivars = 0x0, softc = 0xc071d620}
(kgdb) p *child
$5 = {ops = 0xc0a43000, link = {tqe_next = 0x0, tqe_prev = 0xc0a70804}, 
  parent = 0xc0a70f00, children = {tqh_first = 0x0, tqh_last = 0xc0a70790}, 
  driver = 0xc02f5ce4, devclass = 0xc0718ce0, unit = 1, 
  nameunit = 0xc071d390 "ata1", desc = 0x0, busy = 0, state = DS_NOTPRESENT, 
  devflags = 0, flags = 3, order = 0 '\000', pad = 0 '\000', ivars = 0x1, 
  softc = 0xc0a70680}
Comment 1 sos 2000-10-05 19:19:01 UTC
It seems Jonathan Lemon wrote:
> 
> 	After the nexus/ivar change around Sep 28, my kernel no longer
> 	boots.  This seems to be a disagreement over how ivars are used
> 	in the kernel.  Within nexus_alloc_resource(), we have the 
> 	following:
> 
> #define DEVTONX(dev)       ((struct nexus_device *)device_get_ivars(dev))
> 		struct nexus_device *ndev = DEVTONX(child);
> 
> 	where ``child'' happens to be ata1.  However, within ata/ata-all.c,
> 	There is the following statement:
> 
> 		device_set_ivars(child, (void *)(uintptr_t) unit);
> 
> 	So when nexus_alloc_resource() is called, it ends up treating the
> 	unit as a pointer.  I'm not sure what the new world order mandates
> 	here; what is the legal usage of ivar?

Not sure either, but the below patch makes ata use the ivar as a pointer,
could you try that out for me please, I'm still a PRE_SMPNG as i need
working machines....

Index: ata-all.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.74
diff -u -r1.74 ata-all.c
--- ata-all.c	2000/10/05 08:28:06	1.74
+++ ata-all.c	2000/10/05 16:02:49
@@ -358,6 +359,7 @@
 ata_pci_add_child(device_t dev, int unit)
 {
     device_t child;
+    int *ivar;
 
     /* check if this is located at one of the std addresses */
     if (ATA_MASTERDEV(dev)) {
@@ -368,7 +370,10 @@
 	if (!(child = device_add_child(dev, "ata", 2)))
 	    return ENOMEM;
     }
-    device_set_ivars(child, (void *)(uintptr_t) unit);
+    if (!(ivar = (int *)malloc(sizeof(int *), M_ATA, M_NOWAIT)))
+	return ENOMEM;
+    *ivar = unit;
+    device_set_ivars(child, ivar);
     return 0;
 }
 
@@ -492,7 +497,7 @@
 ata_pci_print_child(device_t dev, device_t child)
 {
     struct ata_softc *scp = device_get_softc(child);
-    int unit = (uintptr_t) device_get_ivars(child);
+    int unit = *((int *)device_get_ivars(child));
     int retval = 0;
 
     retval += bus_print_child_header(dev, child);
@@ -511,7 +516,7 @@
 		       u_long start, u_long end, u_long count, u_int flags)
 {
     struct ata_pci_softc *sc = device_get_softc(dev);
-    int unit = (intptr_t)device_get_ivars(child);
+    int unit = *((int *)device_get_ivars(child));
     int myrid;
 
     if (type == SYS_RES_IOPORT) {
@@ -601,7 +606,7 @@
 			 struct resource *r)
 {
     struct ata_pci_softc *sc = device_get_softc(dev);
-    int unit = (uintptr_t) device_get_ivars(child);
+    int unit = *((int *)device_get_ivars(child));
     int myrid = 0;
 
     if (type == SYS_RES_IOPORT) {
@@ -725,8 +730,8 @@
     struct ata_softc *scp = device_get_softc(dev);
 
     /* kids of pci ata chipsets has their physical unit number in ivars */
-    scp->unit = (uintptr_t) device_get_ivars(dev);
+    scp->unit = *((int *)device_get_ivars(dev));
     scp->chiptype = pci_get_devid(device_get_parent(dev));
     return ata_probe(dev);
 }
 

-Søren
Comment 2 Johan Karlsson freebsd_committer freebsd_triage 2000-10-10 23:08:23 UTC
State Changed
From-To: open->feedback

Hi Jonathan 
Did you try Sorens patch? 

Please report back to  
'FreeBSD-gnats-submit@FreeBSD.ORG' 
with the subject of this message preserved. 




Comment 3 Johan Karlsson freebsd_committer freebsd_triage 2000-10-10 23:08:23 UTC
Responsible Changed
From-To: freebsd-bugs->sos

Over to Soren who asked for feedback.
Comment 4 peter 2000-10-11 11:15:18 UTC
Actually, this is most likely caused by a missing bus method.  I'd be
curious to see an actual stack trace from a -g kernel and/or a
configuration that can reproduce it.  Is this from an isa-only attachment
by any chance?

sos's patch might stop the panic, but it will not stop nexus being fed an
incorrect ivar.

Cheers,
-Peter
--
Peter Wemm - peter@FreeBSD.org; peter@yahoo-inc.com; peter@netplex.com.au
"All of this is for nothing if we don't go to the stars" - JMS/B5
Comment 5 Søren Schmidt freebsd_committer freebsd_triage 2000-11-14 08:33:36 UTC
State Changed
From-To: feedback->closed

Fixed in 4.2 and later, the ata driver doesn't use the ivar anymore.