diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2015-07-08 03:41:42 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-07-16 08:58:28 -0400 |
commit | b6c52c634506d52b3a2dc18503980d717e478739 (patch) | |
tree | 751c0c1fd2b536507355bc4ed5f85c5e005e8e21 /drivers/dma/ioat | |
parent | 7618d0359c167d89d7e904a00487be4945c10a65 (diff) |
dmaengine: ioatdma: Ignore IOAT devices under hotplug-capable PCI host bridge
The dmaengine core assumes that async DMA devices will only be removed
when they not used anymore, or it assumes dma_async_device_unregister()
will only be called by dma driver exit routines. But this assumption is
not true for the IOAT driver, which calls dma_async_device_unregister()
from ioat_remove(). So current IOAT driver doesn't support device
hot-removal because it may cause system crash to hot-remove an inuse
IOAT device.
To support CPU socket hot-removal, all PCI devices, including IOAT
devices embedded in the socket, will be hot-removed. The idea solution
is to enhance the dmaengine core and IOAT driver to support hot-removal,
but that's too hard.
This patch implements a hack to disable IOAT devices under hotplug-capable
CPU socket so it won't break socket hot-removal.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/ioat')
-rw-r--r-- | drivers/dma/ioat/pci.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c index 76f0dc688a19..3b8c9b03f4b3 100644 --- a/drivers/dma/ioat/pci.c +++ b/drivers/dma/ioat/pci.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/dca.h> | 28 | #include <linux/dca.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/acpi.h> | ||
30 | #include "dma.h" | 31 | #include "dma.h" |
31 | #include "dma_v2.h" | 32 | #include "dma_v2.h" |
32 | #include "registers.h" | 33 | #include "registers.h" |
@@ -148,6 +149,34 @@ alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase) | |||
148 | return d; | 149 | return d; |
149 | } | 150 | } |
150 | 151 | ||
152 | /* | ||
153 | * The dmaengine core assumes that async DMA devices will only be removed | ||
154 | * when they not used anymore, or it assumes dma_async_device_unregister() | ||
155 | * will only be called by dma driver exit routines. But this assumption is | ||
156 | * not true for the IOAT driver, which calls dma_async_device_unregister() | ||
157 | * from ioat_remove(). So current IOAT driver doesn't support device | ||
158 | * hot-removal because it may cause system crash to hot-remove inuse IOAT | ||
159 | * devices. | ||
160 | * | ||
161 | * This is a hack to disable IOAT devices under ejectable PCI host bridge | ||
162 | * so it won't break PCI host bridge hot-removal. | ||
163 | */ | ||
164 | static bool ioat_pci_has_ejectable_acpi_ancestor(struct pci_dev *pdev) | ||
165 | { | ||
166 | #ifdef CONFIG_ACPI | ||
167 | struct pci_bus *bus = pdev->bus; | ||
168 | struct acpi_device *adev; | ||
169 | |||
170 | while (bus->parent) | ||
171 | bus = bus->parent; | ||
172 | for (adev = ACPI_COMPANION(bus->bridge); adev; adev = adev->parent) | ||
173 | if (adev->flags.ejectable) | ||
174 | return true; | ||
175 | #endif | ||
176 | |||
177 | return false; | ||
178 | } | ||
179 | |||
151 | static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 180 | static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
152 | { | 181 | { |
153 | void __iomem * const *iomap; | 182 | void __iomem * const *iomap; |
@@ -155,6 +184,11 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
155 | struct ioatdma_device *device; | 184 | struct ioatdma_device *device; |
156 | int err; | 185 | int err; |
157 | 186 | ||
187 | if (ioat_pci_has_ejectable_acpi_ancestor(pdev)) { | ||
188 | dev_dbg(&pdev->dev, "ignore ejectable IOAT device.\n"); | ||
189 | return -ENODEV; | ||
190 | } | ||
191 | |||
158 | err = pcim_enable_device(pdev); | 192 | err = pcim_enable_device(pdev); |
159 | if (err) | 193 | if (err) |
160 | return err; | 194 | return err; |