Commit 3ad0b02e4c1d5feba44b8ff48dccd1ba61a826b0
Committed by
Len Brown
1 parent
27471fdb32
Exists in
master
and in
39 other branches
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>
Showing 3 changed files with 89 additions and 71 deletions Side-by-side Diff
drivers/dma/ioat_dma.c
... | ... | @@ -33,6 +33,7 @@ |
33 | 33 | #include <linux/delay.h> |
34 | 34 | #include <linux/dma-mapping.h> |
35 | 35 | #include <linux/workqueue.h> |
36 | +#include <linux/i7300_idle.h> | |
36 | 37 | #include "ioatdma.h" |
37 | 38 | #include "ioatdma_registers.h" |
38 | 39 | #include "ioatdma_hw.h" |
... | ... | @@ -172,7 +173,9 @@ |
172 | 173 | xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); |
173 | 174 | |
174 | 175 | #if CONFIG_I7300_IDLE_IOAT_CHANNEL |
175 | - device->common.chancnt--; | |
176 | + if (i7300_idle_platform_probe(NULL, NULL) == 0) { | |
177 | + device->common.chancnt--; | |
178 | + } | |
176 | 179 | #endif |
177 | 180 | for (i = 0; i < device->common.chancnt; i++) { |
178 | 181 | ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL); |
drivers/idle/i7300_idle.c
... | ... | @@ -25,6 +25,7 @@ |
25 | 25 | #include <linux/delay.h> |
26 | 26 | #include <linux/debugfs.h> |
27 | 27 | #include <linux/stop_machine.h> |
28 | +#include <linux/i7300_idle.h> | |
28 | 29 | |
29 | 30 | #include <asm/idle.h> |
30 | 31 | |
31 | 32 | |
... | ... | @@ -505,77 +506,8 @@ |
505 | 506 | .notifier_call = i7300_idle_notifier, |
506 | 507 | }; |
507 | 508 | |
508 | -/* | |
509 | - * I/O AT controls (PCI bus 0 device 8 function 0) | |
510 | - * DIMM controls (PCI bus 0 device 16 function 1) | |
511 | - */ | |
512 | -#define IOAT_BUS 0 | |
513 | -#define IOAT_DEVFN PCI_DEVFN(8, 0) | |
514 | -#define MEMCTL_BUS 0 | |
515 | -#define MEMCTL_DEVFN PCI_DEVFN(16, 1) | |
516 | - | |
517 | -struct fbd_ioat { | |
518 | - unsigned int vendor; | |
519 | - unsigned int ioat_dev; | |
520 | -}; | |
521 | - | |
522 | -/* | |
523 | - * The i5000 chip-set has the same hooks as the i7300 | |
524 | - * but support is disabled by default because this driver | |
525 | - * has not been validated on that platform. | |
526 | - */ | |
527 | -#define SUPPORT_I5000 0 | |
528 | - | |
529 | -static const struct fbd_ioat fbd_ioat_list[] = { | |
530 | - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB}, | |
531 | -#if SUPPORT_I5000 | |
532 | - {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT}, | |
533 | -#endif | |
534 | - {0, 0} | |
535 | -}; | |
536 | - | |
537 | -/* table of devices that work with this driver */ | |
538 | -static const struct pci_device_id pci_tbl[] = { | |
539 | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) }, | |
540 | -#if SUPPORT_I5000 | |
541 | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, | |
542 | -#endif | |
543 | - { } /* Terminating entry */ | |
544 | -}; | |
545 | - | |
546 | 509 | MODULE_DEVICE_TABLE(pci, pci_tbl); |
547 | 510 | |
548 | -/* Check for known platforms with I/O-AT */ | |
549 | -static int __init i7300_idle_platform_probe(void) | |
550 | -{ | |
551 | - int i; | |
552 | - | |
553 | - fbd_dev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN); | |
554 | - if (!fbd_dev) | |
555 | - return -ENODEV; | |
556 | - | |
557 | - for (i = 0; pci_tbl[i].vendor != 0; i++) { | |
558 | - if (fbd_dev->vendor == pci_tbl[i].vendor && | |
559 | - fbd_dev->device == pci_tbl[i].device) { | |
560 | - break; | |
561 | - } | |
562 | - } | |
563 | - if (pci_tbl[i].vendor == 0) | |
564 | - return -ENODEV; | |
565 | - | |
566 | - ioat_dev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN); | |
567 | - if (!ioat_dev) | |
568 | - return -ENODEV; | |
569 | - | |
570 | - for (i = 0; fbd_ioat_list[i].vendor != 0; i++) { | |
571 | - if (ioat_dev->vendor == fbd_ioat_list[i].vendor && | |
572 | - ioat_dev->device == fbd_ioat_list[i].ioat_dev) { | |
573 | - return 0; | |
574 | - } | |
575 | - } | |
576 | - return -ENODEV; | |
577 | -} | |
578 | - | |
579 | 511 | int stats_open_generic(struct inode *inode, struct file *fp) |
580 | 512 | { |
581 | 513 | fp->private_data = inode->i_private; |
... | ... | @@ -617,7 +549,7 @@ |
617 | 549 | cpus_clear(idle_cpumask); |
618 | 550 | total_us = 0; |
619 | 551 | |
620 | - if (i7300_idle_platform_probe()) | |
552 | + if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev)) | |
621 | 553 | return -ENODEV; |
622 | 554 | |
623 | 555 | if (i7300_idle_thrt_save()) |
include/linux/i7300_idle.h
1 | + | |
2 | +#ifndef I7300_IDLE_H | |
3 | +#define I7300_IDLE_H | |
4 | + | |
5 | +#include <linux/pci.h> | |
6 | + | |
7 | +/* | |
8 | + * I/O AT controls (PCI bus 0 device 8 function 0) | |
9 | + * DIMM controls (PCI bus 0 device 16 function 1) | |
10 | + */ | |
11 | +#define IOAT_BUS 0 | |
12 | +#define IOAT_DEVFN PCI_DEVFN(8, 0) | |
13 | +#define MEMCTL_BUS 0 | |
14 | +#define MEMCTL_DEVFN PCI_DEVFN(16, 1) | |
15 | + | |
16 | +struct fbd_ioat { | |
17 | + unsigned int vendor; | |
18 | + unsigned int ioat_dev; | |
19 | +}; | |
20 | + | |
21 | +/* | |
22 | + * The i5000 chip-set has the same hooks as the i7300 | |
23 | + * but support is disabled by default because this driver | |
24 | + * has not been validated on that platform. | |
25 | + */ | |
26 | +#define SUPPORT_I5000 0 | |
27 | + | |
28 | +static const struct fbd_ioat fbd_ioat_list[] = { | |
29 | + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB}, | |
30 | +#if SUPPORT_I5000 | |
31 | + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT}, | |
32 | +#endif | |
33 | + {0, 0} | |
34 | +}; | |
35 | + | |
36 | +/* table of devices that work with this driver */ | |
37 | +static const struct pci_device_id pci_tbl[] = { | |
38 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_FBD_CNB) }, | |
39 | +#if SUPPORT_I5000 | |
40 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, | |
41 | +#endif | |
42 | + { } /* Terminating entry */ | |
43 | +}; | |
44 | + | |
45 | +/* Check for known platforms with I/O-AT */ | |
46 | +static inline int i7300_idle_platform_probe(struct pci_dev **fbd_dev, | |
47 | + struct pci_dev **ioat_dev) | |
48 | +{ | |
49 | + int i; | |
50 | + struct pci_dev *memdev, *dmadev; | |
51 | + | |
52 | + memdev = pci_get_bus_and_slot(MEMCTL_BUS, MEMCTL_DEVFN); | |
53 | + if (!memdev) | |
54 | + return -ENODEV; | |
55 | + | |
56 | + for (i = 0; pci_tbl[i].vendor != 0; i++) { | |
57 | + if (memdev->vendor == pci_tbl[i].vendor && | |
58 | + memdev->device == pci_tbl[i].device) { | |
59 | + break; | |
60 | + } | |
61 | + } | |
62 | + if (pci_tbl[i].vendor == 0) | |
63 | + return -ENODEV; | |
64 | + | |
65 | + dmadev = pci_get_bus_and_slot(IOAT_BUS, IOAT_DEVFN); | |
66 | + if (!dmadev) | |
67 | + return -ENODEV; | |
68 | + | |
69 | + for (i = 0; fbd_ioat_list[i].vendor != 0; i++) { | |
70 | + if (dmadev->vendor == fbd_ioat_list[i].vendor && | |
71 | + dmadev->device == fbd_ioat_list[i].ioat_dev) { | |
72 | + if (fbd_dev) | |
73 | + *fbd_dev = memdev; | |
74 | + if (ioat_dev) | |
75 | + *ioat_dev = dmadev; | |
76 | + | |
77 | + return 0; | |
78 | + } | |
79 | + } | |
80 | + return -ENODEV; | |
81 | +} | |
82 | + | |
83 | +#endif |