diff options
author | Alexander Motin <mav@FreeBSD.org> | 2009-12-07 18:37:50 +0000 |
---|---|---|
committer | Alexander Motin <mav@FreeBSD.org> | 2009-12-07 18:37:50 +0000 |
commit | 30053681376de445a4510ca5983ec111bcbaee2c (patch) | |
tree | 3450921ffed6287366eb04abf72a1c13db2866c1 /sys/dev/siis | |
parent | f1a6fd5d07725932c0052191666564f03e8d28c9 (diff) | |
download | src-30053681376de445a4510ca5983ec111bcbaee2c.tar.gz src-30053681376de445a4510ca5983ec111bcbaee2c.zip |
Explicitly acknowledge MSI completion, as required by SiI3124 datasheet.
It makes MSI working there. Later (and cheaper) PCIe chips (3132/3531)
still randomly crashing system in few seconds of high MSI rates, generating
something inaporopriate, like NMI or "Fatal trap 30".
Notes
Notes:
svn path=/head/; revision=200223
Diffstat (limited to 'sys/dev/siis')
-rw-r--r-- | sys/dev/siis/siis.c | 16 | ||||
-rw-r--r-- | sys/dev/siis/siis.h | 1 |
2 files changed, 14 insertions, 3 deletions
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index 813753f8272e..a47ce2cebb1b 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -143,6 +143,7 @@ siis_attach(device_t dev) if (!(ctlr->r_gmem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_grid, RF_ACTIVE))) return (ENXIO); + ctlr->gctl = ATA_INL(ctlr->r_gmem, SIIS_GCTL); /* Channels memory */ ctlr->r_rid = PCIR_BAR(2); if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, @@ -221,7 +222,8 @@ siis_suspend(device_t dev) bus_generic_suspend(dev); /* Put controller into reset state. */ - ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, SIIS_GCTL_GRESET); + ctlr->gctl |= SIIS_GCTL_GRESET; + ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl); return 0; } @@ -231,10 +233,13 @@ siis_resume(device_t dev) struct siis_controller *ctlr = device_get_softc(dev); /* Put controller into reset state. */ - ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, SIIS_GCTL_GRESET); + ctlr->gctl |= SIIS_GCTL_GRESET; + ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl); DELAY(10000); /* Get controller out of reset state and enable port interrupts. */ - ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, 0x0000000f); + ctlr->gctl &= ~(SIIS_GCTL_GRESET | SIIS_GCTL_I2C_IE); + ctlr->gctl |= 0x0000000f; + ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, ctlr->gctl); return (bus_generic_resume(dev)); } @@ -288,6 +293,11 @@ siis_intr(void *data) ctlr->interrupt[unit].function(arg); } } + /* Acknowledge interrupt, if MSI enabled. */ + if (ctlr->irq.r_irq_rid) { + ATA_OUTL(ctlr->r_gmem, SIIS_GCTL, + ctlr->gctl | SIIS_GCTL_MSIACK); + } } static struct resource * diff --git a/sys/dev/siis/siis.h b/sys/dev/siis/siis.h index 097f7ff5a425..2f8c046d7ce1 100644 --- a/sys/dev/siis/siis.h +++ b/sys/dev/siis/siis.h @@ -403,6 +403,7 @@ struct siis_controller { } irq; int quirks; int channels; + uint32_t gctl; struct { void (*function)(void *); void *argument; |