aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ioat.c
diff options
context:
space:
mode:
authorShannon Nelson <shannon.nelson@intel.com>2007-10-16 04:27:39 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:09 -0400
commit8ab89567da0cea9bae2c1b5dad47b51c424479e4 (patch)
tree95ac8bc77b2e8d9f1dec97f6fd7128760e27561f /drivers/dma/ioat.c
parent43d6e369d43ff175e1e0e80caaedb1e53829247c (diff)
I/OAT: Split PCI startup from DMA handling code
Split the general PCI startup from the DMA handling code in order to prepare for adding support for DCA services and future versions of the ioatdma device. [Rusty Russell] Removal of __unsafe() usage. Signed-off-by: Shannon Nelson <shannon.nelson@intel.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/dma/ioat.c')
-rw-r--r--drivers/dma/ioat.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
new file mode 100644
index 000000000000..ae5817bfc015
--- /dev/null
+++ b/drivers/dma/ioat.c
@@ -0,0 +1,196 @@
1/*
2 * Intel I/OAT DMA Linux driver
3 * Copyright(c) 2004 - 2007 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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
20 *
21 */
22
23/*
24 * This driver supports an Intel I/OAT DMA engine, which does asynchronous
25 * copy operations.
26 */
27
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/pci.h>
31#include <linux/interrupt.h>
32#include "ioatdma.h"
33#include "ioatdma_registers.h"
34#include "ioatdma_hw.h"
35
36MODULE_VERSION("1.24");
37MODULE_LICENSE("GPL");
38MODULE_AUTHOR("Intel Corporation");
39
40static struct pci_device_id ioat_pci_tbl[] = {
41 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
42 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
43 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
44 { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
45 { 0, }
46};
47
48struct ioat_device {
49 struct pci_dev *pdev;
50 void __iomem *iobase;
51 struct ioatdma_device *dma;
52};
53
54static int __devinit ioat_probe(struct pci_dev *pdev,
55 const struct pci_device_id *id);
56#ifdef IOAT_DMA_REMOVE
57static void __devexit ioat_remove(struct pci_dev *pdev);
58#endif
59
60static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
61{
62 struct ioat_device *device = pci_get_drvdata(pdev);
63 u8 version;
64 int err = 0;
65
66 version = readb(iobase + IOAT_VER_OFFSET);
67 switch (version) {
68 case IOAT_VER_1_2:
69 device->dma = ioat_dma_probe(pdev, iobase);
70 break;
71 default:
72 err = -ENODEV;
73 break;
74 }
75 return err;
76}
77
78static void ioat_shutdown_functionality(struct pci_dev *pdev)
79{
80 struct ioat_device *device = pci_get_drvdata(pdev);
81
82 if (device->dma) {
83 ioat_dma_remove(device->dma);
84 device->dma = NULL;
85 }
86}
87
88static struct pci_driver ioat_pci_drv = {
89 .name = "ioatdma",
90 .id_table = ioat_pci_tbl,
91 .probe = ioat_probe,
92 .shutdown = ioat_shutdown_functionality,
93#ifdef IOAT_DMA_REMOVE
94 .remove = __devexit_p(ioat_remove),
95#endif
96};
97
98static int __devinit ioat_probe(struct pci_dev *pdev,
99 const struct pci_device_id *id)
100{
101 void __iomem *iobase;
102 struct ioat_device *device;
103 unsigned long mmio_start, mmio_len;
104 int err;
105
106 err = pci_enable_device(pdev);
107 if (err)
108 goto err_enable_device;
109
110 err = pci_request_regions(pdev, ioat_pci_drv.name);
111 if (err)
112 goto err_request_regions;
113
114 err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
115 if (err)
116 err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
117 if (err)
118 goto err_set_dma_mask;
119
120 err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
121 if (err)
122 err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
123 if (err)
124 goto err_set_dma_mask;
125
126 mmio_start = pci_resource_start(pdev, 0);
127 mmio_len = pci_resource_len(pdev, 0);
128 iobase = ioremap(mmio_start, mmio_len);
129 if (!iobase) {
130 err = -ENOMEM;
131 goto err_ioremap;
132 }
133
134 device = kzalloc(sizeof(*device), GFP_KERNEL);
135 if (!device) {
136 err = -ENOMEM;
137 goto err_kzalloc;
138 }
139 device->pdev = pdev;
140 pci_set_drvdata(pdev, device);
141 device->iobase = iobase;
142
143 pci_set_master(pdev);
144
145 err = ioat_setup_functionality(pdev, iobase);
146 if (err)
147 goto err_version;
148
149 return 0;
150
151err_version:
152 kfree(device);
153err_kzalloc:
154 iounmap(iobase);
155err_ioremap:
156err_set_dma_mask:
157 pci_release_regions(pdev);
158 pci_disable_device(pdev);
159err_request_regions:
160err_enable_device:
161 return err;
162}
163
164#ifdef IOAT_DMA_REMOVE
165/*
166 * It is unsafe to remove this module: if removed while a requested
167 * dma is outstanding, esp. from tcp, it is possible to hang while
168 * waiting for something that will never finish, thus hanging at
169 * least one cpu. However, if you're feeling lucky and need to do
170 * some testing, this usually works just fine.
171 */
172static void __devexit ioat_remove(struct pci_dev *pdev)
173{
174 struct ioat_device *device = pci_get_drvdata(pdev);
175
176 ioat_shutdown_functionality(pdev);
177
178 kfree(device);
179
180 iounmap(device->iobase);
181 pci_release_regions(pdev);
182 pci_disable_device(pdev);
183}
184#endif
185
186static int __init ioat_init_module(void)
187{
188 return pci_register_driver(&ioat_pci_drv);
189}
190module_init(ioat_init_module);
191
192static void __exit ioat_exit_module(void)
193{
194 pci_unregister_driver(&ioat_pci_drv);
195}
196module_exit(ioat_exit_module);