[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <200711251121445151346@gmail.com>
Date: Sun, 25 Nov 2007 11:21:48 +0800
From: "peerchen" <peerchen@...il.com>
To: "linux-kernel" <linux-kernel@...r.kernel.org>
Cc: "akpm" <akpm@...ux-foundation.org>, "pchen" <pchen@...dia.com>,
"acurrid" <acurrid@...dia.com>
Subject: [PATCH 1/2] msi: set 'En' bit of MSI Mapping Capability on HT platform
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@...dia.com>
Signed-off-by: Peer Chen <pchen@...dia.com>
---
--- 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@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists