[PATCH 1/2] msi: set 'En' bit of MSI Mapping Capability on HT platform

From: peerchen
Date: Sat Nov 24 2007 - 22:22:12 EST


According to the HyperTransport spec, 'En' indicate if the MSI Mapping is active. So it should be set when enable the MSI.

The patch base on kernel 2.6.24-rc3

Signed-off-by: Andy Currid <acurrid@xxxxxxxxxx>
Signed-off-by: Peer Chen <pchen@xxxxxxxxxx>

---
--- linux-2.6.24-rc3/drivers/pci/msi.c.orig 2007-11-23 17:28:45.000000000 -0500
+++ linux-2.6.24-rc3/drivers/pci/msi.c 2007-11-23 17:50:59.000000000 -0500
@@ -20,6 +20,8 @@
#include <asm/errno.h>
#include <asm/io.h>

+#include <asm/k8.h>
+
#include "pci.h"
#include "msi.h"

@@ -290,6 +292,99 @@ void pci_restore_msi_state(struct pci_de
}
#endif /* CONFIG_PM */

+/*
+ * pci_enable_msi_ht_cap - Set the HT MSI mapping capability En bit of
+ * a device.
+ *
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ */
+
+static int pci_enable_msi_ht_cap(struct pci_dev *dev)
+{
+ int pos;
+ u8 flags;
+
+ if ((pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING)) != 0)
+ {
+ pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags);
+ pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+ flags | HT_MSI_FLAGS_ENABLE);
+
+ printk(KERN_INFO "PCI: %s: enabled HT MSI mapping\n", pci_name(dev));
+ }
+
+ return pos;
+}
+
+/**
+ * pci_check_msi_ht_cap - check for and enable the MSI mapping capability En bit
+ * of devices or upstream bridge on HT-base system.
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ *
+ * Search if device support ht MSI mapping capability on HT-base
+ * platform, if yes, enable the En bit. If device can't support MSI mapping,
+ * search the the upstream bridge for that capability, enable En bit find it,
+ * otherwise disable the MSI function if device and upstream bridge can't
+ * support MSI mapping capability.
+ **/
+
+static int pci_check_msi_ht_cap(struct pci_dev *dev)
+{
+ struct pci_dev *bridge_dev;
+
+ if (num_k8_northbridges != 0) { /* If the system is the HT-base */
+
+ /* Check for upstream NVIDIA host bridges */
+
+ if (((bridge_dev = pci_find_slot(0, 0)) != NULL) &&
+ (bridge_dev->vendor == PCI_VENDOR_ID_NVIDIA)) {
+ switch (bridge_dev->device) {
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC0:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC1:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC2:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC3:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC4:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC5:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC6:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_C51_MEMC7:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_MEMC:
+
+ pci_enable_msi_ht_cap(bridge_dev);
+
+ bridge_dev = NULL;
+ while ((bridge_dev = pci_get_device(PCI_VENDOR_ID_NVIDIA,
+ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_MEMC, bridge_dev))
+ != NULL) {
+ pci_enable_msi_ht_cap(bridge_dev);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ if (pci_enable_msi_ht_cap(dev) != 0) {
+ return 0;
+ } else {
+ /* Get upstream bridge device handle */
+
+ bridge_dev = dev->bus->self;
+ while(bridge_dev != 0) {
+ if (pci_enable_msi_ht_cap(bridge_dev) != 0) {
+ return 0;
+ } else
+ bridge_dev = bridge_dev->bus->self;
+ }
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
/**
* msi_capability_init - configure device's MSI capability structure
* @dev: pointer to the pci_dev data structure of MSI device function
@@ -510,6 +605,10 @@ int pci_enable_msi(struct pci_dev* dev)
status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI);
if (status)
return status;
+
+ status = pci_check_msi_ht_cap(dev);
+ if(status)
+ return status;

WARN_ON(!!dev->msi_enabled);

@@ -606,6 +705,10 @@ int pci_enable_msix(struct pci_dev* dev,
if (status)
return status;

+ status = pci_check_msi_ht_cap(dev);
+ if(status)
+ return status;
+
pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
pci_read_config_word(dev, msi_control_reg(pos), &control);
nr_entries = multi_msix_capable(control);
-

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/