Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/dma/ioat/pci.c
15109 views
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
* 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 <linux/dca.h>
33
#include <linux/slab.h>
34
#include "dma.h"
35
#include "dma_v2.h"
36
#include "registers.h"
37
#include "hw.h"
38
39
MODULE_VERSION(IOAT_DMA_VERSION);
40
MODULE_LICENSE("Dual BSD/GPL");
41
MODULE_AUTHOR("Intel Corporation");
42
43
static struct pci_device_id ioat_pci_tbl[] = {
44
/* I/OAT v1 platforms */
45
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
46
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
47
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
48
{ PCI_VDEVICE(UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
49
50
/* I/OAT v2 platforms */
51
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
52
53
/* I/OAT v3 platforms */
54
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },
55
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },
56
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },
57
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },
58
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },
59
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },
60
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },
61
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },
62
63
/* I/OAT v3.2 platforms */
64
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF0) },
65
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF1) },
66
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF2) },
67
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF3) },
68
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF4) },
69
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF5) },
70
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF6) },
71
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF7) },
72
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF8) },
73
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF9) },
74
75
{ 0, }
76
};
77
MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
78
79
static int __devinit ioat_pci_probe(struct pci_dev *pdev,
80
const struct pci_device_id *id);
81
static void __devexit ioat_remove(struct pci_dev *pdev);
82
83
static int ioat_dca_enabled = 1;
84
module_param(ioat_dca_enabled, int, 0644);
85
MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");
86
87
struct kmem_cache *ioat2_cache;
88
89
#define DRV_NAME "ioatdma"
90
91
static struct pci_driver ioat_pci_driver = {
92
.name = DRV_NAME,
93
.id_table = ioat_pci_tbl,
94
.probe = ioat_pci_probe,
95
.remove = __devexit_p(ioat_remove),
96
};
97
98
static struct ioatdma_device *
99
alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase)
100
{
101
struct device *dev = &pdev->dev;
102
struct ioatdma_device *d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
103
104
if (!d)
105
return NULL;
106
d->pdev = pdev;
107
d->reg_base = iobase;
108
return d;
109
}
110
111
static int __devinit ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
112
{
113
void __iomem * const *iomap;
114
struct device *dev = &pdev->dev;
115
struct ioatdma_device *device;
116
int err;
117
118
err = pcim_enable_device(pdev);
119
if (err)
120
return err;
121
122
err = pcim_iomap_regions(pdev, 1 << IOAT_MMIO_BAR, DRV_NAME);
123
if (err)
124
return err;
125
iomap = pcim_iomap_table(pdev);
126
if (!iomap)
127
return -ENOMEM;
128
129
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
130
if (err)
131
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
132
if (err)
133
return err;
134
135
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
136
if (err)
137
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
138
if (err)
139
return err;
140
141
device = alloc_ioatdma(pdev, iomap[IOAT_MMIO_BAR]);
142
if (!device)
143
return -ENOMEM;
144
pci_set_master(pdev);
145
pci_set_drvdata(pdev, device);
146
147
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
148
if (device->version == IOAT_VER_1_2)
149
err = ioat1_dma_probe(device, ioat_dca_enabled);
150
else if (device->version == IOAT_VER_2_0)
151
err = ioat2_dma_probe(device, ioat_dca_enabled);
152
else if (device->version >= IOAT_VER_3_0)
153
err = ioat3_dma_probe(device, ioat_dca_enabled);
154
else
155
return -ENODEV;
156
157
if (err) {
158
dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");
159
return -ENODEV;
160
}
161
162
return 0;
163
}
164
165
static void __devexit ioat_remove(struct pci_dev *pdev)
166
{
167
struct ioatdma_device *device = pci_get_drvdata(pdev);
168
169
if (!device)
170
return;
171
172
dev_err(&pdev->dev, "Removing dma and dca services\n");
173
if (device->dca) {
174
unregister_dca_provider(device->dca, &pdev->dev);
175
free_dca_provider(device->dca);
176
device->dca = NULL;
177
}
178
ioat_dma_remove(device);
179
}
180
181
static int __init ioat_init_module(void)
182
{
183
int err;
184
185
pr_info("%s: Intel(R) QuickData Technology Driver %s\n",
186
DRV_NAME, IOAT_DMA_VERSION);
187
188
ioat2_cache = kmem_cache_create("ioat2", sizeof(struct ioat_ring_ent),
189
0, SLAB_HWCACHE_ALIGN, NULL);
190
if (!ioat2_cache)
191
return -ENOMEM;
192
193
err = pci_register_driver(&ioat_pci_driver);
194
if (err)
195
kmem_cache_destroy(ioat2_cache);
196
197
return err;
198
}
199
module_init(ioat_init_module);
200
201
static void __exit ioat_exit_module(void)
202
{
203
pci_unregister_driver(&ioat_pci_driver);
204
kmem_cache_destroy(ioat2_cache);
205
}
206
module_exit(ioat_exit_module);
207
208