| Summary: | panic w/nexus + ata (ivar problem) | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Jonathan Lemon <jlemon> |
| Component: | kern | Assignee: | Søren Schmidt <sos> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 5.0-CURRENT | ||
| Hardware: | Any | ||
| OS: | Any | ||
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
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. Responsible Changed From-To: freebsd-bugs->sos Over to Soren who asked for feedback. 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 State Changed From-To: feedback->closed Fixed in 4.2 and later, the ata driver doesn't use the ivar anymore. |
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}