Date: Thu, 09 Feb 2006 15:37:07 +0100 From: =?ISO-8859-1?Q?S=F8ren_Schmidt?= <sos@deepcore.dk> To: Wilko Bulte <wb@freebie.xs4all.nl> Cc: stable@freebsd.org Subject: Re: Showstopper ATA bug in 6.1-PRE? Message-ID: <43EB5393.5090502@deepcore.dk> In-Reply-To: <20060208221056.GA1299@freebie.xs4all.nl> References: <20060208194603.GA689@freebie.xs4all.nl> <43EA5C50.5020804@deepcore.dk> <20060208213704.GA703@freebie.xs4all.nl> <43EA6625.2070106@deepcore.dk> <20060208221056.GA1299@freebie.xs4all.nl>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------000801080306030609050702 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Wilko Bulte wrote: > On Wed, Feb 08, 2006 at 10:44:05PM +0100, Sren Schmidt wrote.. >> Wilko Bulte wrote: >>> On Wed, Feb 08, 2006 at 10:02:08PM +0100, Sren Schmidt wrote.. >>>> Wilko Bulte wrote: >>>>> Hi Soren, >>>>> >>>>> I just went to 6.1-PRE on my main machine, coming from 6.0-STABLE >>>>> of roughly end of december. >>>>> >>>>> And I hit some stuff that really worries me: >>>>> >>>>> - the freshly built kernel keels over with (hand transcribed): >>>>> >>>>> ata3: reiniting channel SATA connect ... >>>>> SATA connected >>>>> sata_connect_devices 0x1 <ATA_MASTER> >>>>> >>>>> ad6: req=0xC35ba0c8 SETFEATURES SETTRANSFERMODE semaphore timeout >>>>> !! DANGER Will RObinson !! >>>>> >>>>> (... is where I cannot read my own handwriting, it scrolled quite fast on >>>>> the screen..) >>>>> >>>>> Boot device is a SATA RAID1 on a Promise 2300. >>>> Hmm, that should not happen. Could you try to backstep just ATA to >>>> before the MFC, that is 24/1/06 and let me know if that helps please ? >>> First impression is that the problem is gone. None of the previously >>> reported errors are seen. I am running a level 0 dump from disk to disk >>> to see if the box remains stable. Given that this is my primary machine >>> I sure hope it will be :-) >>> >>>>> Another snag is that my ad10 disk on 6.0-STABLE suddenly became ad12 on >>>>> 6.1-PRE >>>> Hmm that is because there is only 2 ports on your promise which is now >>>> correctly identified, before it was errounsly found as 3 ports. >>> Ah, OK. I would suggest a note to the Release Note writers would be a good >>> thing, devices changing location after an upgrade in the -stable branch >>> is unnerving ;-) >> Well, the good thing is that I can reproduce the error here, the bad >> thing is that it slipped through testing on -current... >> Oh, well, I'll look into it ASAP... > > Thank you Soren! OK, had a few this afternoon, could you try this patch and let me know if it helps, at least it makes the problem go away on my testbed.. -Søren --------------000801080306030609050702 Content-Type: text/plain; name="prom-p1" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="prom-p1" Index: ata-chipset.c =================================================================== RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-chipset.c,v retrieving revision 1.156 diff -u -r1.156 ata-chipset.c --- ata-chipset.c 6 Feb 2006 19:17:48 -0000 1.156 +++ ata-chipset.c 9 Feb 2006 13:20:06 -0000 @@ -2861,10 +2861,10 @@ { ATA_PDC20377, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20377" }, { ATA_PDC20378, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20378" }, { ATA_PDC20379, 0, PRMIO, PRCMBO, ATA_SA150, "PDC20379" }, - { ATA_PDC20571, 0, PRMIO, PRSATA2, ATA_SA150, "PDC20571" }, + { ATA_PDC20571, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20571" }, { ATA_PDC20575, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20575" }, { ATA_PDC20579, 0, PRMIO, PRCMBO2, ATA_SA150, "PDC20579" }, - { ATA_PDC20771, 0, PRMIO, PRSATA2, ATA_SA300, "PDC20771" }, + { ATA_PDC20771, 0, PRMIO, PRCMBO2, ATA_SA300, "PDC20771" }, { ATA_PDC40775, 0, PRMIO, PRCMBO2, ATA_SA300, "PDC40775" }, { ATA_PDC20617, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20617" }, { ATA_PDC20618, 0, PRMIO, PRPATA, ATA_UDMA6, "PDC20618" }, @@ -2925,6 +2925,7 @@ ata_promise_chipinit(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); + int fake_reg, stat_reg; if (ata_setup_interrupt(dev)) return ENXIO; @@ -2962,8 +2963,7 @@ &ctlr->r_rid2, RF_ACTIVE))) goto failnfree; - switch (ctlr->chip->cfg2) { - case PRSX4X: { + if (ctlr->chip->cfg2 == PRSX4X) { struct ata_promise_sx4 *hpkt; u_int32_t dimm = ATA_INL(ctlr->r_res2, 0x000c0080); @@ -2998,58 +2998,55 @@ ctlr->setmode = ata_promise_setmode; ctlr->channels = 4; return 0; - } - case PRPATA: - case PRCMBO: - case PRSATA: - /* - * older "mio" type controllers need an interrupt intercept - * function to compensate for the "reset on read" type interrupt - * status register they have. - */ - if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || + } + + /* mio type controllers need an interrupt intercept */ + if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) || bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, ata_promise_mio_intr, ctlr, &ctlr->handle)) { device_printf(dev, "unable to setup interrupt\n"); goto failnfree; - } - /* prime fake interrupt register */ - ATA_OUTL(ctlr->r_res2, 0x060, 0xffffffff); - break; } - - ctlr->allocate = ata_promise_mio_allocate; - ctlr->reset = ata_promise_mio_reset; - ctlr->dmainit = ata_promise_mio_dmainit; - ctlr->setmode = ata_promise_mio_setmode; - switch (ctlr->chip->cfg2) { case PRPATA: ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x01) > 0) + ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 2; - return 0; - + goto sata150; case PRCMBO: - ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff); - ctlr->channels = ((ATA_INL(ctlr->r_res2, 0x48) & 0x02) > 0) + 3; - return 0; - + ctlr->channels = 3; + goto sata150; case PRSATA: - ATA_OUTL(ctlr->r_res2, 0x06c, 0x000000ff); ctlr->channels = 4; - return 0; +sata150: + fake_reg = 0x60; + stat_reg = 0x6c; + break; - case PRCMBO2: - ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff); + case PRCMBO2: ctlr->channels = 3; - return 0; - + goto sataii; case PRSATA2: - ATA_OUTL(ctlr->r_res2, 0x060, 0x000000ff); + default: ctlr->channels = 4; - return 0; +sataii: + fake_reg = 0x54; + stat_reg = 0x60; + break; } + + /* prime fake interrupt register */ + ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff); + + /* clear SATA status */ + ATA_OUTL(ctlr->r_res2, stat_reg, 0x000000ff); + + ctlr->allocate = ata_promise_mio_allocate; + ctlr->reset = ata_promise_mio_reset; + ctlr->dmainit = ata_promise_mio_dmainit; + ctlr->setmode = ata_promise_mio_setmode; + + return 0; } failnfree: @@ -3297,7 +3294,21 @@ { struct ata_pci_controller *ctlr = data; struct ata_channel *ch; - int unit; + u_int32_t vector; + int unit, fake_reg; + + switch (ctlr->chip->cfg2) { + case PRPATA: + case PRCMBO: + case PRSATA: + fake_reg = 0x60; + break; + case PRCMBO2: + case PRSATA2: + default: + fake_reg = 0x54; + break; + } /* * since reading interrupt status register on early "mio" chips @@ -3306,13 +3317,16 @@ * store the bits in an unused register in the chip so we can read * it from there safely to get around this "feature". */ - ATA_OUTL(ctlr->r_res2, 0x060, ATA_INL(ctlr->r_res2, 0x040)); + vector = ATA_INL(ctlr->r_res2, 0x040); + ATA_OUTL(ctlr->r_res2, 0x040, vector); + ATA_OUTL(ctlr->r_res2, fake_reg, vector); for (unit = 0; unit < ctlr->channels; unit++) { if ((ch = ctlr->interrupt[unit].argument)) ctlr->interrupt[unit].function(ch); } - ATA_OUTL(ctlr->r_res2, 0x060, 0xffffffff); + + ATA_OUTL(ctlr->r_res2, fake_reg, 0xffffffff); } static int @@ -3321,37 +3335,30 @@ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); struct ata_connect_task *tp; - u_int32_t vector, status; + u_int32_t fake_reg, stat_reg, vector, status; switch (ctlr->chip->cfg2) { case PRPATA: - case PRSATA: case PRCMBO: - /* read and acknowledge interrupt */ - vector = ATA_INL(ctlr->r_res2, 0x0060); - - /* read and clear interface status */ - status = ATA_INL(ctlr->r_res2, 0x006c); - ATA_OUTL(ctlr->r_res2, 0x006c, status & (0x00000011 << ch->unit)); + case PRSATA: + fake_reg = 0x60; + stat_reg = 0x6c; break; - + case PRCMBO2: case PRSATA2: - case PRCMBO2: -critical_enter(); - /* read and acknowledge interrupt */ - vector = ATA_INL(ctlr->r_res2, 0x0040); - ATA_OUTL(ctlr->r_res2, 0x0040, (1 << (ch->unit + 1))); - - /* read and clear interface status */ - status = ATA_INL(ctlr->r_res2, 0x0060); - ATA_OUTL(ctlr->r_res2, 0x0060, status & (0x00000011 << ch->unit)); -critical_exit(); - break; - default: - return 0; + fake_reg = 0x54; + stat_reg = 0x60; + break; } + /* read and acknowledge interrupt */ + vector = ATA_INL(ctlr->r_res2, fake_reg); + + /* read and clear interface status */ + status = ATA_INL(ctlr->r_res2, stat_reg); + ATA_OUTL(ctlr->r_res2, stat_reg, status & (0x00000011 << ch->unit)); + /* check for and handle disconnect events */ if ((status & (0x00000001 << ch->unit)) && (tp = (struct ata_connect_task *) Index: ata-pci.c =================================================================== RCS file: /nfs/export/ncvs/src/sys/dev/ata/ata-pci.c,v retrieving revision 1.114 diff -u -r1.114 ata-pci.c --- ata-pci.c 25 Jan 2006 23:07:42 -0000 1.114 +++ ata-pci.c 9 Feb 2006 13:31:10 -0000 @@ -34,6 +34,7 @@ #include <sys/module.h> #include <sys/ata.h> #include <sys/bus.h> +#include <sys/conf.h> #include <sys/malloc.h> #include <sys/sema.h> #include <sys/taskqueue.h> @@ -443,7 +444,7 @@ { struct ata_channel *ch = device_get_softc(dev); - if (!ata_legacy(device_get_parent(dev)) && + if ((dumping || !ata_legacy(device_get_parent(dev))) && ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) || (ch->dma->flags & ATA_DMA_ACTIVE))) { int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; --------------000801080306030609050702--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?43EB5393.5090502>