Browse Source

i7300_idle: Disable ioat channel only on platforms where ile driver can load

Based on input from Andi Kleen:
share the platform detection code with ioat_dma and disable the channel in
dma engine only for specific platforms.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Venki Pallipadi 16 years ago
parent
commit
3ad0b02e4c
3 changed files with 89 additions and 71 deletions
  1. 4 1
      drivers/dma/ioat_dma.c
  2. 2 70
      drivers/idle/i7300_idle.c
  3. 83 0
      include/linux/i7300_idle.h

+ 4 - 1
drivers/dma/ioat_dma.c

@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/workqueue.h>
+#include <linux/i7300_idle.h>
 #include "ioatdma.h"
 #include "ioatdma_registers.h"
 #include "ioatdma_hw.h"
@@ -172,7 +173,9 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device)
 	xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
 
 #if CONFIG_I7300_IDLE_IOAT_CHANNEL
-	device->common.chancnt--;
+	if (i7300_idle_platform_probe(NULL, NULL) == 0) {
+		device->common.chancnt--;
+	}
 #endif
 	for (i = 0; i < device->common.chancnt; i++) {
 		ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);

+ 2 - 70
drivers/idle/i7300_idle.c

@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/debugfs.h>
 #include <linux/stop_machine.h>
+#include <linux/i7300_idle.h>
 
 #include <asm/idle.h>
 
@@ -505,77 +506,8 @@ static struct notifier_block i7300_idle_nb = {
 	.notifier_call = i7300_idle_notifier,
 };
 
-/*
- * I/O AT controls (PCI bus 0 device 8 function 0)
- * DIMM controls (PCI bus 0 device 16 function 1)
- */
-#define IOAT_BUS 0
-#define IOAT_DEVFN PCI_DEVFN(8, 0)
-#define MEMCTL_BUS 0
-#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
-
-struct fbd_ioat {
-	unsigned int vendor;
-	unsigned int ioat_dev;
-};
-
-/*
- * The i5000 chip-set has the same hooks as the i7300
- * but support is disabled by default because this driver
- * has not been validated on that platform.
- */
-#define SUPPORT_I5000 0
-
-static const struct fbd_ioat fbd_ioat_list[] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
-#if SUPPORT_I5000
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
-#endif
-	{0, 0}
-};
-
-/* table of devices that work with this driver */
-static const struct pci_device_id pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
-#if SUPPORT_I5000
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
-#endif
-	{ } /* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
-/* Check for known platforms with I/O-AT */
-static int __init i7300_idle_platform_probe(void)
-{
-	int i;
-
-	fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
-	if (!fbd_dev)
-		return -ENODEV;
-
-	for (i = 0; pci_tbl[i].vendor != 0; i++) {
-		if (fbd_dev->vendor == pci_tbl[i].vendor &&
-		    fbd_dev->device == pci_tbl[i].device) {
-			break;
-		}
-	}
-	if (pci_tbl[i].vendor == 0)
-		return -ENODEV;
-
-	ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
-	if (!ioat_dev)
-		return -ENODEV;
-
-	for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
-		if (ioat_dev->vendor == fbd_ioat_list[i].vendor &&
-		    ioat_dev->device == fbd_ioat_list[i].ioat_dev) {
-			return 0;
-		}
-	}
-	return -ENODEV;
-}
-
 int stats_open_generic(struct inode *inode, struct file *fp)
 {
 	fp->private_data = inode->i_private;
@@ -617,7 +549,7 @@ static int __init i7300_idle_init(void)
 	cpus_clear(idle_cpumask);
 	total_us = 0;
 
-	if (i7300_idle_platform_probe())
+	if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev))
 		return -ENODEV;
 
 	if (i7300_idle_thrt_save())

+ 83 - 0
include/linux/i7300_idle.h

@@ -0,0 +1,83 @@
+
+#ifndef I7300_IDLE_H
+#define I7300_IDLE_H
+
+#include <linux/pci.h>
+
+/*
+ * I/O AT controls (PCI bus 0 device 8 function 0)
+ * DIMM controls (PCI bus 0 device 16 function 1)
+ */
+#define IOAT_BUS 0
+#define IOAT_DEVFN PCI_DEVFN(8, 0)
+#define MEMCTL_BUS 0
+#define MEMCTL_DEVFN PCI_DEVFN(16, 1)
+
+struct fbd_ioat {
+	unsigned int vendor;
+	unsigned int ioat_dev;
+};
+
+/*
+ * The i5000 chip-set has the same hooks as the i7300
+ * but support is disabled by default because this driver
+ * has not been validated on that platform.
+ */
+#define SUPPORT_I5000 0
+
+static const struct fbd_ioat fbd_ioat_list[] = {
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB},
+#if SUPPORT_I5000
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT},
+#endif
+	{0, 0}
+};
+
+/* table of devices that work with this driver */
+static const struct pci_device_id pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) },
+#if SUPPORT_I5000
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
+#endif
+	{ } /* Terminating entry */
+};
+
+/* Check for known platforms with I/O-AT */
+static inline int i7300_idle_platform_probe(struct pci_dev **fbd_dev,
+						struct pci_dev **ioat_dev)
+{
+	int i;
+	struct pci_dev *memdev, *dmadev;
+
+	memdev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN);
+	if (!memdev)
+		return -ENODEV;
+
+	for (i = 0; pci_tbl[i].vendor != 0; i++) {
+		if (memdev->vendor == pci_tbl[i].vendor &&
+		    memdev->device == pci_tbl[i].device) {
+			break;
+		}
+	}
+	if (pci_tbl[i].vendor == 0)
+		return -ENODEV;
+
+	dmadev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN);
+	if (!dmadev)
+		return -ENODEV;
+
+	for (i = 0; fbd_ioat_list[i].vendor != 0; i++) {
+		if (dmadev->vendor == fbd_ioat_list[i].vendor &&
+		    dmadev->device == fbd_ioat_list[i].ioat_dev) {
+			if (fbd_dev)
+				*fbd_dev = memdev;
+			if (ioat_dev)
+				*ioat_dev = dmadev;
+
+			return 0;
+		}
+	}
+	return -ENODEV;
+}
+
+#endif