linux/drivers/crypto/qat/qat_c62xvf/adf_drv.c
<<
>>
Prefs
   1/*
   2  This file is provided under a dual BSD/GPLv2 license.  When using or
   3  redistributing this file, you may do so under either license.
   4
   5  GPL LICENSE SUMMARY
   6  Copyright(c) 2014 Intel Corporation.
   7  This program is free software; you can redistribute it and/or modify
   8  it under the terms of version 2 of the GNU General Public License as
   9  published by the Free Software Foundation.
  10
  11  This program is distributed in the hope that it will be useful, but
  12  WITHOUT ANY WARRANTY; without even the implied warranty of
  13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14  General Public License for more details.
  15
  16  Contact Information:
  17  qat-linux@intel.com
  18
  19  BSD LICENSE
  20  Copyright(c) 2014 Intel Corporation.
  21  Redistribution and use in source and binary forms, with or without
  22  modification, are permitted provided that the following conditions
  23  are met:
  24
  25    * Redistributions of source code must retain the above copyright
  26      notice, this list of conditions and the following disclaimer.
  27    * Redistributions in binary form must reproduce the above copyright
  28      notice, this list of conditions and the following disclaimer in
  29      the documentation and/or other materials provided with the
  30      distribution.
  31    * Neither the name of Intel Corporation nor the names of its
  32      contributors may be used to endorse or promote products derived
  33      from this software without specific prior written permission.
  34
  35  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  36  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  37  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  38  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  39  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  42  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  43  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  44  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  45  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  46*/
  47#include <linux/kernel.h>
  48#include <linux/module.h>
  49#include <linux/pci.h>
  50#include <linux/init.h>
  51#include <linux/types.h>
  52#include <linux/fs.h>
  53#include <linux/slab.h>
  54#include <linux/errno.h>
  55#include <linux/device.h>
  56#include <linux/dma-mapping.h>
  57#include <linux/platform_device.h>
  58#include <linux/workqueue.h>
  59#include <linux/io.h>
  60#include <adf_accel_devices.h>
  61#include <adf_common_drv.h>
  62#include <adf_cfg.h>
  63#include "adf_c62xvf_hw_data.h"
  64
  65#define ADF_SYSTEM_DEVICE(device_id) \
  66        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  67
  68static const struct pci_device_id adf_pci_tbl[] = {
  69        ADF_SYSTEM_DEVICE(ADF_C62XIOV_PCI_DEVICE_ID),
  70        {0,}
  71};
  72MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
  73
  74static int adf_probe(struct pci_dev *dev, const struct pci_device_id *ent);
  75static void adf_remove(struct pci_dev *dev);
  76
  77static struct pci_driver adf_driver = {
  78        .id_table = adf_pci_tbl,
  79        .name = ADF_C62XVF_DEVICE_NAME,
  80        .probe = adf_probe,
  81        .remove = adf_remove,
  82};
  83
  84static void adf_cleanup_pci_dev(struct adf_accel_dev *accel_dev)
  85{
  86        pci_release_regions(accel_dev->accel_pci_dev.pci_dev);
  87        pci_disable_device(accel_dev->accel_pci_dev.pci_dev);
  88}
  89
  90static void adf_cleanup_accel(struct adf_accel_dev *accel_dev)
  91{
  92        struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
  93        struct adf_accel_dev *pf;
  94        int i;
  95
  96        for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
  97                struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
  98
  99                if (bar->virt_addr)
 100                        pci_iounmap(accel_pci_dev->pci_dev, bar->virt_addr);
 101        }
 102
 103        if (accel_dev->hw_device) {
 104                switch (accel_pci_dev->pci_dev->device) {
 105                case ADF_C62XIOV_PCI_DEVICE_ID:
 106                        adf_clean_hw_data_c62xiov(accel_dev->hw_device);
 107                        break;
 108                default:
 109                        break;
 110                }
 111                kfree(accel_dev->hw_device);
 112                accel_dev->hw_device = NULL;
 113        }
 114        adf_cfg_dev_remove(accel_dev);
 115        debugfs_remove(accel_dev->debugfs_dir);
 116        pf = adf_devmgr_pci_to_accel_dev(accel_pci_dev->pci_dev->physfn);
 117        adf_devmgr_rm_dev(accel_dev, pf);
 118}
 119
 120static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 121{
 122        struct adf_accel_dev *accel_dev;
 123        struct adf_accel_dev *pf;
 124        struct adf_accel_pci *accel_pci_dev;
 125        struct adf_hw_device_data *hw_data;
 126        char name[ADF_DEVICE_NAME_LENGTH];
 127        unsigned int i, bar_nr;
 128        int ret, bar_mask;
 129
 130        switch (ent->device) {
 131        case ADF_C62XIOV_PCI_DEVICE_ID:
 132                break;
 133        default:
 134                dev_err(&pdev->dev, "Invalid device 0x%x.\n", ent->device);
 135                return -ENODEV;
 136        }
 137
 138        accel_dev = kzalloc_node(sizeof(*accel_dev), GFP_KERNEL,
 139                                 dev_to_node(&pdev->dev));
 140        if (!accel_dev)
 141                return -ENOMEM;
 142
 143        accel_dev->is_vf = true;
 144        pf = adf_devmgr_pci_to_accel_dev(pdev->physfn);
 145        accel_pci_dev = &accel_dev->accel_pci_dev;
 146        accel_pci_dev->pci_dev = pdev;
 147
 148        /* Add accel device to accel table */
 149        if (adf_devmgr_add_dev(accel_dev, pf)) {
 150                dev_err(&pdev->dev, "Failed to add new accelerator device.\n");
 151                kfree(accel_dev);
 152                return -EFAULT;
 153        }
 154        INIT_LIST_HEAD(&accel_dev->crypto_list);
 155
 156        accel_dev->owner = THIS_MODULE;
 157        /* Allocate and configure device configuration structure */
 158        hw_data = kzalloc_node(sizeof(*hw_data), GFP_KERNEL,
 159                               dev_to_node(&pdev->dev));
 160        if (!hw_data) {
 161                ret = -ENOMEM;
 162                goto out_err;
 163        }
 164        accel_dev->hw_device = hw_data;
 165        adf_init_hw_data_c62xiov(accel_dev->hw_device);
 166
 167        /* Get Accelerators and Accelerators Engines masks */
 168        hw_data->accel_mask = hw_data->get_accel_mask(hw_data->fuses);
 169        hw_data->ae_mask = hw_data->get_ae_mask(hw_data->fuses);
 170        accel_pci_dev->sku = hw_data->get_sku(hw_data);
 171
 172        /* Create dev top level debugfs entry */
 173        snprintf(name, sizeof(name), "%s%s_%02x:%02d.%02d",
 174                 ADF_DEVICE_NAME_PREFIX, hw_data->dev_class->name,
 175                 pdev->bus->number, PCI_SLOT(pdev->devfn),
 176                 PCI_FUNC(pdev->devfn));
 177
 178        accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
 179        if (!accel_dev->debugfs_dir) {
 180                dev_err(&pdev->dev, "Could not create debugfs dir %s\n", name);
 181                ret = -EINVAL;
 182                goto out_err;
 183        }
 184
 185        /* Create device configuration table */
 186        ret = adf_cfg_dev_add(accel_dev);
 187        if (ret)
 188                goto out_err;
 189
 190        /* enable PCI device */
 191        if (pci_enable_device(pdev)) {
 192                ret = -EFAULT;
 193                goto out_err;
 194        }
 195
 196        /* set dma identifier */
 197        if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
 198                if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
 199                        dev_err(&pdev->dev, "No usable DMA configuration\n");
 200                        ret = -EFAULT;
 201                        goto out_err_disable;
 202                } else {
 203                        pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
 204                }
 205
 206        } else {
 207                pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
 208        }
 209
 210        if (pci_request_regions(pdev, ADF_C62XVF_DEVICE_NAME)) {
 211                ret = -EFAULT;
 212                goto out_err_disable;
 213        }
 214
 215        /* Find and map all the device's BARS */
 216        i = 0;
 217        bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
 218        for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
 219                         ADF_PCI_MAX_BARS * 2) {
 220                struct adf_bar *bar = &accel_pci_dev->pci_bars[i++];
 221
 222                bar->base_addr = pci_resource_start(pdev, bar_nr);
 223                if (!bar->base_addr)
 224                        break;
 225                bar->size = pci_resource_len(pdev, bar_nr);
 226                bar->virt_addr = pci_iomap(accel_pci_dev->pci_dev, bar_nr, 0);
 227                if (!bar->virt_addr) {
 228                        dev_err(&pdev->dev, "Failed to map BAR %d\n", bar_nr);
 229                        ret = -EFAULT;
 230                        goto out_err_free_reg;
 231                }
 232        }
 233        pci_set_master(pdev);
 234        /* Completion for VF2PF request/response message exchange */
 235        init_completion(&accel_dev->vf.iov_msg_completion);
 236
 237        ret = qat_crypto_dev_config(accel_dev);
 238        if (ret)
 239                goto out_err_free_reg;
 240
 241        ret = adf_dev_init(accel_dev);
 242        if (ret)
 243                goto out_err_dev_shutdown;
 244
 245        ret = adf_dev_start(accel_dev);
 246        if (ret)
 247                goto out_err_dev_stop;
 248
 249        return ret;
 250
 251out_err_dev_stop:
 252        adf_dev_stop(accel_dev);
 253out_err_dev_shutdown:
 254        adf_dev_shutdown(accel_dev);
 255out_err_free_reg:
 256        pci_release_regions(accel_pci_dev->pci_dev);
 257out_err_disable:
 258        pci_disable_device(accel_pci_dev->pci_dev);
 259out_err:
 260        adf_cleanup_accel(accel_dev);
 261        kfree(accel_dev);
 262        return ret;
 263}
 264
 265static void adf_remove(struct pci_dev *pdev)
 266{
 267        struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
 268
 269        if (!accel_dev) {
 270                pr_err("QAT: Driver removal failed\n");
 271                return;
 272        }
 273        if (adf_dev_stop(accel_dev))
 274                dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
 275
 276        adf_dev_shutdown(accel_dev);
 277        adf_cleanup_accel(accel_dev);
 278        adf_cleanup_pci_dev(accel_dev);
 279        kfree(accel_dev);
 280}
 281
 282static int __init adfdrv_init(void)
 283{
 284        request_module("intel_qat");
 285
 286        if (pci_register_driver(&adf_driver)) {
 287                pr_err("QAT: Driver initialization failed\n");
 288                return -EFAULT;
 289        }
 290        return 0;
 291}
 292
 293static void __exit adfdrv_release(void)
 294{
 295        pci_unregister_driver(&adf_driver);
 296        adf_clean_vf_map(true);
 297}
 298
 299module_init(adfdrv_init);
 300module_exit(adfdrv_release);
 301
 302MODULE_LICENSE("Dual BSD/GPL");
 303MODULE_AUTHOR("Intel");
 304MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
 305MODULE_VERSION(ADF_DRV_VERSION);
 306