Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.27 226 lines 6.1 kB view raw
1/* 2 * Intel I/OAT DMA Linux driver 3 * Copyright(c) 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 <linux/dca.h> 33#include "ioatdma.h" 34#include "ioatdma_registers.h" 35#include "ioatdma_hw.h" 36 37MODULE_VERSION(IOAT_DMA_VERSION); 38MODULE_LICENSE("GPL"); 39MODULE_AUTHOR("Intel Corporation"); 40 41static struct pci_device_id ioat_pci_tbl[] = { 42 /* I/OAT v1 platforms */ 43 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, 44 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) }, 45 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) }, 46 { PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) }, 47 48 /* I/OAT v2 platforms */ 49 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) }, 50 51 /* I/OAT v3 platforms */ 52 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) }, 53 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) }, 54 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) }, 55 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) }, 56 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) }, 57 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) }, 58 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) }, 59 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) }, 60 { 0, } 61}; 62 63struct ioat_device { 64 struct pci_dev *pdev; 65 void __iomem *iobase; 66 struct ioatdma_device *dma; 67 struct dca_provider *dca; 68}; 69 70static int __devinit ioat_probe(struct pci_dev *pdev, 71 const struct pci_device_id *id); 72static void __devexit ioat_remove(struct pci_dev *pdev); 73 74static int ioat_dca_enabled = 1; 75module_param(ioat_dca_enabled, int, 0644); 76MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)"); 77 78static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase) 79{ 80 struct ioat_device *device = pci_get_drvdata(pdev); 81 u8 version; 82 int err = 0; 83 84 version = readb(iobase + IOAT_VER_OFFSET); 85 switch (version) { 86 case IOAT_VER_1_2: 87 device->dma = ioat_dma_probe(pdev, iobase); 88 if (device->dma && ioat_dca_enabled) 89 device->dca = ioat_dca_init(pdev, iobase); 90 break; 91 case IOAT_VER_2_0: 92 device->dma = ioat_dma_probe(pdev, iobase); 93 if (device->dma && ioat_dca_enabled) 94 device->dca = ioat2_dca_init(pdev, iobase); 95 break; 96 case IOAT_VER_3_0: 97 device->dma = ioat_dma_probe(pdev, iobase); 98 if (device->dma && ioat_dca_enabled) 99 device->dca = ioat3_dca_init(pdev, iobase); 100 break; 101 default: 102 err = -ENODEV; 103 break; 104 } 105 if (!device->dma) 106 err = -ENODEV; 107 return err; 108} 109 110static void ioat_shutdown_functionality(struct pci_dev *pdev) 111{ 112 struct ioat_device *device = pci_get_drvdata(pdev); 113 114 dev_err(&pdev->dev, "Removing dma and dca services\n"); 115 if (device->dca) { 116 unregister_dca_provider(device->dca); 117 free_dca_provider(device->dca); 118 device->dca = NULL; 119 } 120 121 if (device->dma) { 122 ioat_dma_remove(device->dma); 123 device->dma = NULL; 124 } 125} 126 127static struct pci_driver ioat_pci_driver = { 128 .name = "ioatdma", 129 .id_table = ioat_pci_tbl, 130 .probe = ioat_probe, 131 .shutdown = ioat_shutdown_functionality, 132 .remove = __devexit_p(ioat_remove), 133}; 134 135static int __devinit ioat_probe(struct pci_dev *pdev, 136 const struct pci_device_id *id) 137{ 138 void __iomem *iobase; 139 struct ioat_device *device; 140 unsigned long mmio_start, mmio_len; 141 int err; 142 143 err = pci_enable_device(pdev); 144 if (err) 145 goto err_enable_device; 146 147 err = pci_request_regions(pdev, ioat_pci_driver.name); 148 if (err) 149 goto err_request_regions; 150 151 err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); 152 if (err) 153 err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 154 if (err) 155 goto err_set_dma_mask; 156 157 err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 158 if (err) 159 err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 160 if (err) 161 goto err_set_dma_mask; 162 163 mmio_start = pci_resource_start(pdev, 0); 164 mmio_len = pci_resource_len(pdev, 0); 165 iobase = ioremap(mmio_start, mmio_len); 166 if (!iobase) { 167 err = -ENOMEM; 168 goto err_ioremap; 169 } 170 171 device = kzalloc(sizeof(*device), GFP_KERNEL); 172 if (!device) { 173 err = -ENOMEM; 174 goto err_kzalloc; 175 } 176 device->pdev = pdev; 177 pci_set_drvdata(pdev, device); 178 device->iobase = iobase; 179 180 pci_set_master(pdev); 181 182 err = ioat_setup_functionality(pdev, iobase); 183 if (err) 184 goto err_version; 185 186 return 0; 187 188err_version: 189 kfree(device); 190err_kzalloc: 191 iounmap(iobase); 192err_ioremap: 193err_set_dma_mask: 194 pci_release_regions(pdev); 195 pci_disable_device(pdev); 196err_request_regions: 197err_enable_device: 198 return err; 199} 200 201/* 202 * It is unsafe to remove this module: if removed while a requested 203 * dma is outstanding, esp. from tcp, it is possible to hang while 204 * waiting for something that will never finish. However, if you're 205 * feeling lucky, this usually works just fine. 206 */ 207static void __devexit ioat_remove(struct pci_dev *pdev) 208{ 209 struct ioat_device *device = pci_get_drvdata(pdev); 210 211 ioat_shutdown_functionality(pdev); 212 213 kfree(device); 214} 215 216static int __init ioat_init_module(void) 217{ 218 return pci_register_driver(&ioat_pci_driver); 219} 220module_init(ioat_init_module); 221 222static void __exit ioat_exit_module(void) 223{ 224 pci_unregister_driver(&ioat_pci_driver); 225} 226module_exit(ioat_exit_module);