Blame view
drivers/dma/ioat.c
5.97 KB
8ab89567d I/OAT: Split PCI ... |
1 2 |
/* * Intel I/OAT DMA Linux driver |
2ed6dc34f I/OAT: Add DCA se... |
3 |
* Copyright(c) 2007 Intel Corporation. |
8ab89567d I/OAT: Split PCI ... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
* * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * The full GNU General Public License is included in this distribution in * the file called "COPYING". * */ /* * This driver supports an Intel I/OAT DMA engine, which does asynchronous * copy operations. */ #include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/interrupt.h> |
2ed6dc34f I/OAT: Add DCA se... |
32 |
#include <linux/dca.h> |
8ab89567d I/OAT: Split PCI ... |
33 34 35 |
#include "ioatdma.h" #include "ioatdma_registers.h" #include "ioatdma_hw.h" |
5149fd010 I/OAT: clean up e... |
36 |
MODULE_VERSION(IOAT_DMA_VERSION); |
8ab89567d I/OAT: Split PCI ... |
37 38 39 40 |
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Intel Corporation"); static struct pci_device_id ioat_pci_tbl[] = { |
7bb67c14f I/OAT: Add suppor... |
41 |
/* I/OAT v1 platforms */ |
8ab89567d I/OAT: Split PCI ... |
42 43 44 45 |
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) }, { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, |
7bb67c14f I/OAT: Add suppor... |
46 47 48 |
/* I/OAT v2 platforms */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) }, |
7f1b358a2 I/OAT: I/OAT vers... |
49 50 51 52 53 54 55 56 57 58 |
/* I/OAT v3 platforms */ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) }, |
8ab89567d I/OAT: Split PCI ... |
59 60 61 62 63 64 65 |
{ 0, } }; struct ioat_device { struct pci_dev *pdev; void __iomem *iobase; struct ioatdma_device *dma; |
2ed6dc34f I/OAT: Add DCA se... |
66 |
struct dca_provider *dca; |
8ab89567d I/OAT: Split PCI ... |
67 68 69 70 |
}; static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *id); |
8ab89567d I/OAT: Split PCI ... |
71 |
static void __devexit ioat_remove(struct pci_dev *pdev); |
8ab89567d I/OAT: Split PCI ... |
72 |
|
2ed6dc34f I/OAT: Add DCA se... |
73 74 75 |
static int ioat_dca_enabled = 1; module_param(ioat_dca_enabled, int, 0644); MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); |
8ab89567d I/OAT: Split PCI ... |
76 77 78 79 80 81 82 83 84 85 |
static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) { struct ioat_device *device = pci_get_drvdata(pdev); u8 version; int err = 0; version = readb(iobase + IOAT_VER_OFFSET); switch (version) { case IOAT_VER_1_2: device->dma = ioat_dma_probe(pdev, iobase); |
dfe2299e7 I/OAT: clean up o... |
86 |
if (device->dma && ioat_dca_enabled) |
2ed6dc34f I/OAT: Add DCA se... |
87 |
device->dca = ioat_dca_init(pdev, iobase); |
8ab89567d I/OAT: Split PCI ... |
88 |
break; |
7bb67c14f I/OAT: Add suppor... |
89 90 91 92 93 |
case IOAT_VER_2_0: device->dma = ioat_dma_probe(pdev, iobase); if (device->dma && ioat_dca_enabled) device->dca = ioat2_dca_init(pdev, iobase); break; |
7f1b358a2 I/OAT: I/OAT vers... |
94 95 96 97 98 |
case IOAT_VER_3_0: device->dma = ioat_dma_probe(pdev, iobase); if (device->dma && ioat_dca_enabled) device->dca = ioat3_dca_init(pdev, iobase); break; |
8ab89567d I/OAT: Split PCI ... |
99 100 101 102 |
default: err = -ENODEV; break; } |
7bb67c14f I/OAT: Add suppor... |
103 104 |
if (!device->dma) err = -ENODEV; |
8ab89567d I/OAT: Split PCI ... |
105 106 107 108 109 110 |
return err; } static void ioat_shutdown_functionality(struct pci_dev *pdev) { struct ioat_device *device = pci_get_drvdata(pdev); |
5149fd010 I/OAT: clean up e... |
111 112 |
dev_err(&pdev->dev, "Removing dma and dca services "); |
2ed6dc34f I/OAT: Add DCA se... |
113 114 115 116 117 |
if (device->dca) { unregister_dca_provider(device->dca); free_dca_provider(device->dca); device->dca = NULL; } |
dfe2299e7 I/OAT: clean up o... |
118 119 120 121 |
if (device->dma) { ioat_dma_remove(device->dma); device->dma = NULL; } |
8ab89567d I/OAT: Split PCI ... |
122 |
} |
7df7cf067 I/OAT: cleanup pc... |
123 |
static struct pci_driver ioat_pci_driver = { |
8ab89567d I/OAT: Split PCI ... |
124 125 126 127 |
.name = "ioatdma", .id_table = ioat_pci_tbl, .probe = ioat_probe, .shutdown = ioat_shutdown_functionality, |
8ab89567d I/OAT: Split PCI ... |
128 |
.remove = __devexit_p(ioat_remove), |
8ab89567d I/OAT: Split PCI ... |
129 130 131 132 133 134 135 136 137 138 139 140 141 |
}; static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *iobase; struct ioat_device *device; unsigned long mmio_start, mmio_len; int err; err = pci_enable_device(pdev); if (err) goto err_enable_device; |
7df7cf067 I/OAT: cleanup pc... |
142 |
err = pci_request_regions(pdev, ioat_pci_driver.name); |
8ab89567d I/OAT: Split PCI ... |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
if (err) goto err_request_regions; err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); if (err) err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (err) goto err_set_dma_mask; err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); if (err) err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); if (err) goto err_set_dma_mask; mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); iobase = ioremap(mmio_start, mmio_len); if (!iobase) { err = -ENOMEM; goto err_ioremap; } device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) { err = -ENOMEM; goto err_kzalloc; } device->pdev = pdev; pci_set_drvdata(pdev, device); device->iobase = iobase; pci_set_master(pdev); err = ioat_setup_functionality(pdev, iobase); if (err) goto err_version; return 0; err_version: kfree(device); err_kzalloc: iounmap(iobase); err_ioremap: err_set_dma_mask: pci_release_regions(pdev); pci_disable_device(pdev); err_request_regions: err_enable_device: return err; } |
8ab89567d I/OAT: Split PCI ... |
195 196 197 |
/* * It is unsafe to remove this module: if removed while a requested * dma is outstanding, esp. from tcp, it is possible to hang while |
7df7cf067 I/OAT: cleanup pc... |
198 199 |
* waiting for something that will never finish. However, if you're * feeling lucky, this usually works just fine. |
8ab89567d I/OAT: Split PCI ... |
200 201 202 203 204 205 206 207 |
*/ static void __devexit ioat_remove(struct pci_dev *pdev) { struct ioat_device *device = pci_get_drvdata(pdev); ioat_shutdown_functionality(pdev); kfree(device); |
8ab89567d I/OAT: Split PCI ... |
208 |
} |
8ab89567d I/OAT: Split PCI ... |
209 210 211 |
static int __init ioat_init_module(void) { |
7df7cf067 I/OAT: cleanup pc... |
212 |
return pci_register_driver(&ioat_pci_driver); |
8ab89567d I/OAT: Split PCI ... |
213 214 215 216 217 |
} module_init(ioat_init_module); static void __exit ioat_exit_module(void) { |
7df7cf067 I/OAT: cleanup pc... |
218 |
pci_unregister_driver(&ioat_pci_driver); |
8ab89567d I/OAT: Split PCI ... |
219 220 |
} module_exit(ioat_exit_module); |