aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/siis
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2009-12-07 18:37:50 +0000
committerAlexander Motin <mav@FreeBSD.org>2009-12-07 18:37:50 +0000
commit30053681376de445a4510ca5983ec111bcbaee2c (patch)
tree3450921ffed6287366eb04abf72a1c13db2866c1 /sys/dev/siis
parentf1a6fd5d07725932c0052191666564f03e8d28c9 (diff)
downloadsrc-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.c16
-rw-r--r--sys/dev/siis/siis.h1
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;