Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

ahci: Use MSI if device support it.

  • Loading branch information...
commit 9783883ae1a6a13fe8f96b5938cb141382fdbf2a 1 parent 9dc47ee
Sepherosa Ziehau authored
Showing with 39 additions and 4 deletions.
  1. +4 −0 sys/dev/disk/ahci/ahci.h
  2. +35 −4 sys/dev/disk/ahci/ahci_attach.c
View
4 sys/dev/disk/ahci/ahci.h
@@ -453,6 +453,7 @@ struct ahci_softc {
bus_space_tag_t sc_iot; /* split from sc_regs */
bus_space_handle_t sc_ioh; /* split from sc_regs */
+ int sc_irq_type;
int sc_rid_irq; /* saved bus RIDs */
int sc_rid_regs;
u_int32_t sc_cap; /* capabilities */
@@ -486,6 +487,9 @@ struct ahci_softc {
};
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
+#define AHCI_IRQ_TYPE_LEGACY 0
+#define AHCI_IRQ_TYPE_MSI 1
+
struct ahci_device {
pci_vendor_id_t ad_vendor;
pci_product_id_t ad_product;
View
39 sys/dev/disk/ahci/ahci_attach.c
@@ -74,6 +74,9 @@ static const struct ahci_device ahci_devices[] = {
ahci_pci_attach, ahci_pci_detach, "AHCI-PCI-SATA" }
};
+static int ahci_msi_enable = 1;
+TUNABLE_INT("hw.ahci.msi.enable", &ahci_msi_enable);
+
/*
* Match during probe and attach. The device does not yet have a softc.
*/
@@ -165,10 +168,11 @@ ahci_pci_attach(device_t dev)
struct ahci_port *ap;
const char *gen;
u_int32_t cap, pi, reg;
+ u_int irq_flags;
bus_addr_t addr;
- int i;
- int error;
+ int i, error, msi_enable;
const char *revision;
+ char env[64];
if (pci_read_config(dev, PCIR_COMMAND, 2) & 0x0400) {
device_printf(dev, "BIOS disabled PCI interrupt, "
@@ -177,14 +181,37 @@ ahci_pci_attach(device_t dev)
pci_read_config(dev, PCIR_COMMAND, 2) & ~0x0400, 2);
}
+ sc->sc_dev = dev;
/*
* Map the AHCI controller's IRQ and BAR(5) (hardware registers)
*/
- sc->sc_dev = dev;
+ msi_enable = ahci_msi_enable;
+ ksnprintf(env, sizeof(env), "hw.%s.msi.enable",
+ device_get_nameunit(dev));
+ kgetenv_int(env, &msi_enable);
+
sc->sc_rid_irq = AHCI_IRQ_RID;
+ sc->sc_irq_type = AHCI_IRQ_TYPE_LEGACY;
+ irq_flags = RF_SHAREABLE | RF_ACTIVE;
+
+ if (msi_enable) {
+ int cpu = -1;
+
+ ksnprintf(env, sizeof(env), "hw.%s.msi.cpu",
+ device_get_nameunit(dev));
+ kgetenv_int(env, &cpu);
+ if (cpu >= ncpus)
+ cpu = ncpus - 1;
+
+ if (pci_alloc_msi(dev, &sc->sc_rid_irq, 1, cpu) == 0) {
+ irq_flags &= ~RF_SHAREABLE;
+ sc->sc_irq_type = AHCI_IRQ_TYPE_MSI;
+ }
+ }
+
sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq,
- RF_SHAREABLE | RF_ACTIVE);
+ irq_flags);
if (sc->sc_irq == NULL) {
device_printf(dev, "unable to map interrupt\n");
ahci_pci_detach(dev);
@@ -529,6 +556,10 @@ ahci_pci_detach(device_t dev)
sc->sc_rid_irq, sc->sc_irq);
sc->sc_irq = NULL;
}
+
+ if (sc->sc_irq_type == AHCI_IRQ_TYPE_MSI)
+ pci_release_msi(dev);
+
if (sc->sc_regs) {
bus_release_resource(dev, SYS_RES_MEMORY,
sc->sc_rid_regs, sc->sc_regs);
Please sign in to comment.
Something went wrong with that request. Please try again.