diff options
Diffstat (limited to 'drivers/dma/ioat/pci.c')
-rw-r--r-- | drivers/dma/ioat/pci.c | 278 |
1 files changed, 0 insertions, 278 deletions
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c deleted file mode 100644 index 0ee610224ecd..000000000000 --- a/drivers/dma/ioat/pci.c +++ /dev/null | |||
@@ -1,278 +0,0 @@ | |||
1 | /* | ||
2 | * Intel I/OAT DMA Linux driver | ||
3 | * Copyright(c) 2007 - 2009 Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * The full GNU General Public License is included in this distribution in | ||
15 | * the file called "COPYING". | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * This driver supports an Intel I/OAT DMA engine, which does asynchronous | ||
21 | * copy operations. | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/dca.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/acpi.h> | ||
31 | #include "dma.h" | ||
32 | #include "registers.h" | ||
33 | #include "hw.h" | ||
34 | |||
35 | MODULE_VERSION(IOAT_DMA_VERSION); | ||
36 | MODULE_LICENSE("Dual BSD/GPL"); | ||
37 | MODULE_AUTHOR("Intel Corporation"); | ||
38 | |||
39 | static struct pci_device_id ioat_pci_tbl[] = { | ||
40 | /* I/OAT v3 platforms */ | ||
41 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) }, | ||
42 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) }, | ||
43 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) }, | ||
44 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) }, | ||
45 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) }, | ||
46 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) }, | ||
47 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) }, | ||
48 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) }, | ||
49 | |||
50 | /* I/OAT v3.2 platforms */ | ||
51 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF0) }, | ||
52 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF1) }, | ||
53 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF2) }, | ||
54 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF3) }, | ||
55 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF4) }, | ||
56 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF5) }, | ||
57 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF6) }, | ||
58 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF7) }, | ||
59 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF8) }, | ||
60 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF9) }, | ||
61 | |||
62 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB0) }, | ||
63 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB1) }, | ||
64 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB2) }, | ||
65 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB3) }, | ||
66 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB4) }, | ||
67 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB5) }, | ||
68 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB6) }, | ||
69 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB7) }, | ||
70 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB8) }, | ||
71 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB9) }, | ||
72 | |||
73 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB0) }, | ||
74 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB1) }, | ||
75 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB2) }, | ||
76 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB3) }, | ||
77 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB4) }, | ||
78 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB5) }, | ||
79 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB6) }, | ||
80 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB7) }, | ||
81 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB8) }, | ||
82 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB9) }, | ||
83 | |||
84 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW0) }, | ||
85 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW1) }, | ||
86 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW2) }, | ||
87 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW3) }, | ||
88 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW4) }, | ||
89 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW5) }, | ||
90 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW6) }, | ||
91 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW7) }, | ||
92 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW8) }, | ||
93 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_HSW9) }, | ||
94 | |||
95 | /* I/OAT v3.3 platforms */ | ||
96 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) }, | ||
97 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) }, | ||
98 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD2) }, | ||
99 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD3) }, | ||
100 | |||
101 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDXDE0) }, | ||
102 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDXDE1) }, | ||
103 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDXDE2) }, | ||
104 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDXDE3) }, | ||
105 | |||
106 | { 0, } | ||
107 | }; | ||
108 | MODULE_DEVICE_TABLE(pci, ioat_pci_tbl); | ||
109 | |||
110 | static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id); | ||
111 | static void ioat_remove(struct pci_dev *pdev); | ||
112 | |||
113 | static int ioat_dca_enabled = 1; | ||
114 | module_param(ioat_dca_enabled, int, 0644); | ||
115 | MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); | ||
116 | |||
117 | struct kmem_cache *ioat_cache; | ||
118 | struct kmem_cache *ioat3_sed_cache; | ||
119 | |||
120 | #define DRV_NAME "ioatdma" | ||
121 | |||
122 | static struct pci_driver ioat_pci_driver = { | ||
123 | .name = DRV_NAME, | ||
124 | .id_table = ioat_pci_tbl, | ||
125 | .probe = ioat_pci_probe, | ||
126 | .remove = ioat_remove, | ||
127 | }; | ||
128 | |||
129 | static struct ioatdma_device * | ||
130 | alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase) | ||
131 | { | ||
132 | struct device *dev = &pdev->dev; | ||
133 | struct ioatdma_device *d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); | ||
134 | |||
135 | if (!d) | ||
136 | return NULL; | ||
137 | d->pdev = pdev; | ||
138 | d->reg_base = iobase; | ||
139 | return d; | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * The dmaengine core assumes that async DMA devices will only be removed | ||
144 | * when they not used anymore, or it assumes dma_async_device_unregister() | ||
145 | * will only be called by dma driver exit routines. But this assumption is | ||
146 | * not true for the IOAT driver, which calls dma_async_device_unregister() | ||
147 | * from ioat_remove(). So current IOAT driver doesn't support device | ||
148 | * hot-removal because it may cause system crash to hot-remove inuse IOAT | ||
149 | * devices. | ||
150 | * | ||
151 | * This is a hack to disable IOAT devices under ejectable PCI host bridge | ||
152 | * so it won't break PCI host bridge hot-removal. | ||
153 | */ | ||
154 | static bool ioat_pci_has_ejectable_acpi_ancestor(struct pci_dev *pdev) | ||
155 | { | ||
156 | #ifdef CONFIG_ACPI | ||
157 | struct pci_bus *bus = pdev->bus; | ||
158 | struct acpi_device *adev; | ||
159 | |||
160 | while (bus->parent) | ||
161 | bus = bus->parent; | ||
162 | for (adev = ACPI_COMPANION(bus->bridge); adev; adev = adev->parent) | ||
163 | if (adev->flags.ejectable) | ||
164 | return true; | ||
165 | #endif | ||
166 | |||
167 | return false; | ||
168 | } | ||
169 | |||
170 | static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
171 | { | ||
172 | void __iomem * const *iomap; | ||
173 | struct device *dev = &pdev->dev; | ||
174 | struct ioatdma_device *device; | ||
175 | int err; | ||
176 | |||
177 | if (ioat_pci_has_ejectable_acpi_ancestor(pdev)) { | ||
178 | dev_dbg(&pdev->dev, "ignore ejectable IOAT device.\n"); | ||
179 | return -ENODEV; | ||
180 | } | ||
181 | |||
182 | err = pcim_enable_device(pdev); | ||
183 | if (err) | ||
184 | return err; | ||
185 | |||
186 | err = pcim_iomap_regions(pdev, 1 << IOAT_MMIO_BAR, DRV_NAME); | ||
187 | if (err) | ||
188 | return err; | ||
189 | iomap = pcim_iomap_table(pdev); | ||
190 | if (!iomap) | ||
191 | return -ENOMEM; | ||
192 | |||
193 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
194 | if (err) | ||
195 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
196 | if (err) | ||
197 | return err; | ||
198 | |||
199 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
200 | if (err) | ||
201 | err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
202 | if (err) | ||
203 | return err; | ||
204 | |||
205 | device = alloc_ioatdma(pdev, iomap[IOAT_MMIO_BAR]); | ||
206 | if (!device) | ||
207 | return -ENOMEM; | ||
208 | pci_set_master(pdev); | ||
209 | pci_set_drvdata(pdev, device); | ||
210 | |||
211 | device->version = readb(device->reg_base + IOAT_VER_OFFSET); | ||
212 | if (device->version >= IOAT_VER_3_0) | ||
213 | err = ioat3_dma_probe(device, ioat_dca_enabled); | ||
214 | else | ||
215 | return -ENODEV; | ||
216 | |||
217 | if (err) { | ||
218 | dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n"); | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static void ioat_remove(struct pci_dev *pdev) | ||
226 | { | ||
227 | struct ioatdma_device *device = pci_get_drvdata(pdev); | ||
228 | |||
229 | if (!device) | ||
230 | return; | ||
231 | |||
232 | dev_err(&pdev->dev, "Removing dma and dca services\n"); | ||
233 | if (device->dca) { | ||
234 | unregister_dca_provider(device->dca, &pdev->dev); | ||
235 | free_dca_provider(device->dca); | ||
236 | device->dca = NULL; | ||
237 | } | ||
238 | ioat_dma_remove(device); | ||
239 | } | ||
240 | |||
241 | static int __init ioat_init_module(void) | ||
242 | { | ||
243 | int err = -ENOMEM; | ||
244 | |||
245 | pr_info("%s: Intel(R) QuickData Technology Driver %s\n", | ||
246 | DRV_NAME, IOAT_DMA_VERSION); | ||
247 | |||
248 | ioat_cache = kmem_cache_create("ioat", sizeof(struct ioat_ring_ent), | ||
249 | 0, SLAB_HWCACHE_ALIGN, NULL); | ||
250 | if (!ioat_cache) | ||
251 | return -ENOMEM; | ||
252 | |||
253 | ioat3_sed_cache = KMEM_CACHE(ioat_sed_ent, 0); | ||
254 | if (!ioat3_sed_cache) | ||
255 | goto err_ioat_cache; | ||
256 | |||
257 | err = pci_register_driver(&ioat_pci_driver); | ||
258 | if (err) | ||
259 | goto err_ioat3_cache; | ||
260 | |||
261 | return 0; | ||
262 | |||
263 | err_ioat3_cache: | ||
264 | kmem_cache_destroy(ioat3_sed_cache); | ||
265 | |||
266 | err_ioat_cache: | ||
267 | kmem_cache_destroy(ioat_cache); | ||
268 | |||
269 | return err; | ||
270 | } | ||
271 | module_init(ioat_init_module); | ||
272 | |||
273 | static void __exit ioat_exit_module(void) | ||
274 | { | ||
275 | pci_unregister_driver(&ioat_pci_driver); | ||
276 | kmem_cache_destroy(ioat_cache); | ||
277 | } | ||
278 | module_exit(ioat_exit_module); | ||