Page MenuHomeFreeBSD

D3009.diff
No OneTemporary

D3009.diff

Index: head/sys/dev/ahci/ahci.h
===================================================================
--- head/sys/dev/ahci/ahci.h
+++ head/sys/dev/ahci/ahci.h
@@ -482,11 +482,15 @@
device_t dev;
bus_dma_tag_t dma_tag;
int r_rid;
+ int r_msix_tab_rid;
+ int r_msix_pba_rid;
uint16_t vendorid; /* Vendor ID from the bus */
uint16_t deviceid; /* Device ID from the bus */
uint16_t subvendorid; /* Subvendor ID from the bus */
uint16_t subdeviceid; /* Subdevice ID from the bus */
struct resource *r_mem;
+ struct resource *r_msix_table;
+ struct resource *r_msix_pba;
struct rman sc_iomem;
struct ahci_controller_irq {
struct ahci_controller *ctlr;
@@ -621,3 +625,4 @@
bus_dma_tag_t ahci_get_dma_tag(device_t dev, device_t child);
int ahci_ctlr_reset(device_t dev);
int ahci_ctlr_setup(device_t dev);
+void ahci_free_mem(device_t dev);
Index: head/sys/dev/ahci/ahci.c
===================================================================
--- head/sys/dev/ahci/ahci.c
+++ head/sys/dev/ahci/ahci.c
@@ -181,12 +181,12 @@
ctlr->sc_iomem.rm_type = RMAN_ARRAY;
ctlr->sc_iomem.rm_descr = "I/O memory addresses";
if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ ahci_free_mem(dev);
return (error);
}
if ((error = rman_manage_region(&ctlr->sc_iomem,
rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ ahci_free_mem(dev);
rman_fini(&ctlr->sc_iomem);
return (error);
}
@@ -250,8 +250,7 @@
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE, BUS_SPACE_UNRESTRICTED, BUS_SPACE_MAXSIZE,
0, NULL, NULL, &ctlr->dma_tag)) {
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
- ctlr->r_mem);
+ ahci_free_mem(dev);
rman_fini(&ctlr->sc_iomem);
return (ENXIO);
}
@@ -261,8 +260,7 @@
/* Setup interrupts. */
if ((error = ahci_setup_interrupt(dev)) != 0) {
bus_dma_tag_destroy(ctlr->dma_tag);
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
- ctlr->r_mem);
+ ahci_free_mem(dev);
rman_fini(&ctlr->sc_iomem);
return (error);
}
@@ -367,9 +365,26 @@
bus_dma_tag_destroy(ctlr->dma_tag);
/* Free memory. */
rman_fini(&ctlr->sc_iomem);
+ ahci_free_mem(dev);
+ return (0);
+}
+
+void
+ahci_free_mem(device_t dev)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ /* Release memory resources */
if (ctlr->r_mem)
bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
- return (0);
+ if (ctlr->r_msix_table)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ ctlr->r_msix_tab_rid, ctlr->r_msix_table);
+ if (ctlr->r_msix_pba)
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ ctlr->r_msix_pba_rid, ctlr->r_msix_pba);
+
+ ctlr->r_msix_pba = ctlr->r_mem = ctlr->r_msix_table = NULL;
}
int
Index: head/sys/dev/ahci/ahci_pci.c
===================================================================
--- head/sys/dev/ahci/ahci_pci.c
+++ head/sys/dev/ahci/ahci_pci.c
@@ -374,12 +374,39 @@
}
static int
+ahci_pci_read_msix_bars(device_t dev, uint8_t *table_bar, uint8_t *pba_bar)
+{
+ int cap_offset = 0, ret;
+ uint32_t val;
+
+ if ((table_bar == NULL) || (pba_bar == NULL))
+ return (EINVAL);
+
+ ret = pci_find_cap(dev, PCIY_MSIX, &cap_offset);
+ if (ret != 0)
+ return (EINVAL);
+
+ val = pci_read_config(dev, cap_offset + PCIR_MSIX_TABLE, 4);
+ *table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+
+ val = pci_read_config(dev, cap_offset + PCIR_MSIX_PBA, 4);
+ *pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
+
+ return (0);
+}
+
+static int
ahci_pci_attach(device_t dev)
{
struct ahci_controller *ctlr = device_get_softc(dev);
int error, i;
uint32_t devid = pci_get_devid(dev);
uint8_t revid = pci_get_revid(dev);
+ int msi_count, msix_count;
+ uint8_t table_bar = 0, pba_bar = 0;
+
+ msi_count = pci_msi_count(dev);
+ msix_count = pci_msix_count(dev);
i = 0;
while (ahci_ids[i].id != 0 &&
@@ -406,10 +433,57 @@
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&ctlr->r_rid, RF_ACTIVE)))
return ENXIO;
+
+ /* Read MSI-x BAR IDs if supported */
+ if (msix_count > 0) {
+ error = ahci_pci_read_msix_bars(dev, &table_bar, &pba_bar);
+ if (error == 0) {
+ ctlr->r_msix_tab_rid = table_bar;
+ ctlr->r_msix_pba_rid = pba_bar;
+ } else {
+ /* Failed to read BARs, disable MSI-x */
+ msix_count = 0;
+ }
+ }
+
+ /* Allocate resources for MSI-x table and PBA */
+ if (msix_count > 0) {
+ /*
+ * Allocate new MSI-x table only if not
+ * allocated before.
+ */
+ ctlr->r_msix_table = NULL;
+ if (ctlr->r_msix_tab_rid != ctlr->r_rid) {
+ /* Separate BAR for MSI-x */
+ ctlr->r_msix_table = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &ctlr->r_msix_tab_rid, RF_ACTIVE);
+ if (ctlr->r_msix_table == NULL) {
+ ahci_free_mem(dev);
+ return (ENXIO);
+ }
+ }
+
+ /*
+ * Allocate new PBA table only if not
+ * allocated before.
+ */
+ ctlr->r_msix_pba = NULL;
+ if ((ctlr->r_msix_pba_rid != ctlr->r_msix_tab_rid) &&
+ (ctlr->r_msix_pba_rid != ctlr->r_rid)) {
+ /* Separate BAR for PBA */
+ ctlr->r_msix_pba = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &ctlr->r_msix_pba_rid, RF_ACTIVE);
+ if (ctlr->r_msix_pba == NULL) {
+ ahci_free_mem(dev);
+ return (ENXIO);
+ }
+ }
+ }
+
pci_enable_busmaster(dev);
/* Reset controller */
if ((error = ahci_pci_ctlr_reset(dev)) != 0) {
- bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+ ahci_free_mem(dev);
return (error);
};
@@ -426,24 +500,51 @@
resource_int_value(device_get_name(dev),
device_get_unit(dev), "msi", &ctlr->msi);
ctlr->numirqs = 1;
+ if (msi_count == 0 && msix_count == 0)
+ ctlr->msi = 0;
if (ctlr->msi < 0)
ctlr->msi = 0;
- else if (ctlr->msi == 1)
- ctlr->msi = min(1, pci_msi_count(dev));
- else if (ctlr->msi > 1) {
+ else if (ctlr->msi == 1) {
+ msi_count = min(1, msi_count);
+ msix_count = min(1, msix_count);
+ } else if (ctlr->msi > 1)
ctlr->msi = 2;
- ctlr->numirqs = pci_msi_count(dev);
- }
- /* Allocate MSI if needed/present. */
- if (ctlr->msi && pci_alloc_msi(dev, &ctlr->numirqs) != 0) {
- ctlr->msi = 0;
- ctlr->numirqs = 1;
+
+ /* Allocate MSI/MSI-x if needed/present. */
+ if (ctlr->msi > 0) {
+ error = ENXIO;
+
+ /* Try to allocate MSI-x first */
+ if (msix_count > 0) {
+ error = pci_alloc_msix(dev, &msix_count);
+ if (error == 0)
+ ctlr->numirqs = msix_count;
+ }
+
+ /*
+ * Try to allocate MSI if msi_count is greater than 0
+ * and if MSI-x allocation failed.
+ */
+ if ((error != 0) && (msi_count > 0)) {
+ error = pci_alloc_msi(dev, &msi_count);
+ if (error == 0)
+ ctlr->numirqs = msi_count;
+ }
+
+ /* Both MSI and MSI-x allocations failed */
+ if (error != 0) {
+ ctlr->msi = 0;
+ device_printf(dev, "Failed to allocate MSI/MSI-x, "
+ "falling back to INTx\n");
+ }
}
error = ahci_attach(dev);
- if (error != 0)
- if (ctlr->msi)
+ if (error != 0) {
+ if (ctlr->msi > 0)
pci_release_msi(dev);
+ ahci_free_mem(dev);
+ }
return error;
}

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 13, 1:34 PM (18 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15782621
Default Alt Text
D3009.diff (7 KB)

Event Timeline