summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/pci.c46
-rw-r--r--sys/dev/pci/pci_pci.c8
-rw-r--r--sys/dev/pci/pcivar.h10
3 files changed, 59 insertions, 5 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 0e8647f..ee27e9a 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -562,11 +562,12 @@ pci_read_extcap(device_t pcib, pcicfgregs *cfg)
cfg->domain, cfg->bus,
cfg->slot, cfg->func,
(long long)addr);
- }
+ } else
+ addr = MSI_INTEL_ADDR_BASE;
- /* Enable MSI -> HT mapping. */
- val |= PCIM_HTCMD_MSI_ENABLE;
- WREG(ptr + PCIR_HT_COMMAND, val, 2);
+ cfg->ht.ht_msimap = ptr;
+ cfg->ht.ht_msictrl = val;
+ cfg->ht.ht_msiaddr = addr;
break;
}
break;
@@ -1095,6 +1096,9 @@ pci_enable_msix(device_t dev, u_int index, uint64_t address, uint32_t data)
bus_write_4(msix->msix_table_res, offset, address & 0xffffffff);
bus_write_4(msix->msix_table_res, offset + 4, address >> 32);
bus_write_4(msix->msix_table_res, offset + 8, data);
+
+ /* Enable MSI -> HT mapping. */
+ pci_ht_map_msi(dev, address);
}
void
@@ -1534,6 +1538,34 @@ pci_msix_count_method(device_t dev, device_t child)
}
/*
+ * HyperTransport MSI mapping control
+ */
+void
+pci_ht_map_msi(device_t dev, uint64_t addr)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(dev);
+ struct pcicfg_ht *ht = &dinfo->cfg.ht;
+
+ if (!ht->ht_msimap)
+ return;
+
+ if (addr && !(ht->ht_msictrl & PCIM_HTCMD_MSI_ENABLE) &&
+ ht->ht_msiaddr >> 20 == addr >> 20) {
+ /* Enable MSI -> HT mapping. */
+ ht->ht_msictrl |= PCIM_HTCMD_MSI_ENABLE;
+ pci_write_config(dev, ht->ht_msimap + PCIR_HT_COMMAND,
+ ht->ht_msictrl, 2);
+ }
+
+ if (!addr && ht->ht_msictrl & PCIM_HTCMD_MSI_ENABLE) {
+ /* Disable MSI -> HT mapping. */
+ ht->ht_msictrl &= ~PCIM_HTCMD_MSI_ENABLE;
+ pci_write_config(dev, ht->ht_msimap + PCIR_HT_COMMAND,
+ ht->ht_msictrl, 2);
+ }
+}
+
+/*
* Support for MSI message signalled interrupts.
*/
void
@@ -1558,6 +1590,9 @@ pci_enable_msi(device_t dev, uint64_t address, uint16_t data)
msi->msi_ctrl |= PCIM_MSICTRL_MSI_ENABLE;
pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl,
2);
+
+ /* Enable MSI -> HT mapping. */
+ pci_ht_map_msi(dev, address);
}
void
@@ -1566,6 +1601,9 @@ pci_disable_msi(device_t dev)
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct pcicfg_msi *msi = &dinfo->cfg.msi;
+ /* Disable MSI -> HT mapping. */
+ pci_ht_map_msi(dev, 0);
+
/* Disable MSI in the control register. */
msi->msi_ctrl &= ~PCIM_MSICTRL_MSI_ENABLE;
pci_write_config(dev, msi->msi_location + PCIR_MSI_CTRL, msi->msi_ctrl,
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 033ea74..13fa065 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -607,9 +607,15 @@ pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
uint32_t *data)
{
device_t bus;
+ int error;
bus = device_get_parent(pcib);
- return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data));
+ error = PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data);
+ if (error)
+ return (error);
+
+ pci_ht_map_msi(pcib, *addr);
+ return (0);
}
/*
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 7cb4c29..3c4c54d 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -115,6 +115,13 @@ struct pcicfg_msix {
struct resource *msix_pba_res; /* Resource containing PBA. */
};
+/* Interesting values for HyperTransport */
+struct pcicfg_ht {
+ uint8_t ht_msimap; /* Offset of MSI mapping cap registers. */
+ uint16_t ht_msictrl; /* MSI mapping control */
+ uint64_t ht_msiaddr; /* MSI mapping base address */
+};
+
/* config header information common to all header types */
typedef struct pcicfg {
struct device *dev; /* device which owns this */
@@ -156,6 +163,7 @@ typedef struct pcicfg {
struct pcicfg_vpd vpd; /* pci vital product data */
struct pcicfg_msi msi; /* pci msi */
struct pcicfg_msix msix; /* pci msi-x */
+ struct pcicfg_ht ht; /* HyperTransport */
} pcicfgregs;
/* additional type 1 device config header information (PCI to PCI bridge) */
@@ -455,6 +463,8 @@ int pci_pending_msix(device_t dev, u_int index);
int pci_msi_device_blacklisted(device_t dev);
+void pci_ht_map_msi(device_t dev, uint64_t addr);
+
#endif /* _SYS_BUS_H_ */
/*
OpenPOWER on IntegriCloud