123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /*
- * Intel I/OAT DMA Linux driver
- * Copyright(c) 2007 - 2009 Intel Corporation.
- *
- * 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>
- #include <linux/dca.h>
- #include <linux/slab.h>
- #include "dma.h"
- #include "dma_v2.h"
- #include "registers.h"
- #include "hw.h"
- MODULE_VERSION(IOAT_DMA_VERSION);
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_AUTHOR("Intel Corporation");
- static struct pci_device_id ioat_pci_tbl[] = {
- /* I/OAT v1 platforms */
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_CNB) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SCNB) },
- { PCI_VDEVICE(UNISYS, PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
- /* I/OAT v2 platforms */
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB) },
- /* I/OAT v3 platforms */
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG0) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG1) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG2) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG3) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG4) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG5) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG6) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_TBG7) },
- /* I/OAT v3.2 platforms */
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF0) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF1) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF2) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF3) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF4) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF5) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF6) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF7) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF8) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_JSF9) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB0) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB1) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB2) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB3) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB4) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB5) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB6) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB7) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB8) },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB9) },
- { 0, }
- };
- MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
- static int __devinit ioat_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
- static void __devexit ioat_remove(struct pci_dev *pdev);
- 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)");
- struct kmem_cache *ioat2_cache;
- #define DRV_NAME "ioatdma"
- static struct pci_driver ioat_pci_driver = {
- .name = DRV_NAME,
- .id_table = ioat_pci_tbl,
- .probe = ioat_pci_probe,
- .remove = __devexit_p(ioat_remove),
- };
- static struct ioatdma_device *
- alloc_ioatdma(struct pci_dev *pdev, void __iomem *iobase)
- {
- struct device *dev = &pdev->dev;
- struct ioatdma_device *d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
- if (!d)
- return NULL;
- d->pdev = pdev;
- d->reg_base = iobase;
- return d;
- }
- static int __devinit ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
- {
- void __iomem * const *iomap;
- struct device *dev = &pdev->dev;
- struct ioatdma_device *device;
- int err;
- err = pcim_enable_device(pdev);
- if (err)
- return err;
- err = pcim_iomap_regions(pdev, 1 << IOAT_MMIO_BAR, DRV_NAME);
- if (err)
- return err;
- iomap = pcim_iomap_table(pdev);
- if (!iomap)
- return -ENOMEM;
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err)
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err)
- return err;
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
- if (err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
- if (err)
- return err;
- device = alloc_ioatdma(pdev, iomap[IOAT_MMIO_BAR]);
- if (!device)
- return -ENOMEM;
- pci_set_master(pdev);
- pci_set_drvdata(pdev, device);
- device->version = readb(device->reg_base + IOAT_VER_OFFSET);
- if (device->version == IOAT_VER_1_2)
- err = ioat1_dma_probe(device, ioat_dca_enabled);
- else if (device->version == IOAT_VER_2_0)
- err = ioat2_dma_probe(device, ioat_dca_enabled);
- else if (device->version >= IOAT_VER_3_0)
- err = ioat3_dma_probe(device, ioat_dca_enabled);
- else
- return -ENODEV;
- if (err) {
- dev_err(dev, "Intel(R) I/OAT DMA Engine init failed\n");
- return -ENODEV;
- }
- return 0;
- }
- static void __devexit ioat_remove(struct pci_dev *pdev)
- {
- struct ioatdma_device *device = pci_get_drvdata(pdev);
- if (!device)
- return;
- dev_err(&pdev->dev, "Removing dma and dca services\n");
- if (device->dca) {
- unregister_dca_provider(device->dca, &pdev->dev);
- free_dca_provider(device->dca);
- device->dca = NULL;
- }
- ioat_dma_remove(device);
- }
- static int __init ioat_init_module(void)
- {
- int err;
- pr_info("%s: Intel(R) QuickData Technology Driver %s\n",
- DRV_NAME, IOAT_DMA_VERSION);
- ioat2_cache = kmem_cache_create("ioat2", sizeof(struct ioat_ring_ent),
- 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!ioat2_cache)
- return -ENOMEM;
- err = pci_register_driver(&ioat_pci_driver);
- if (err)
- kmem_cache_destroy(ioat2_cache);
- return err;
- }
- module_init(ioat_init_module);
- static void __exit ioat_exit_module(void)
- {
- pci_unregister_driver(&ioat_pci_driver);
- kmem_cache_destroy(ioat2_cache);
- }
- module_exit(ioat_exit_module);
|