linux/drivers/crypto/qat/qat_common/adf_init.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/mutex.h>
  48#include <linux/list.h>
  49#include <linux/bitops.h>
  50#include <linux/delay.h>
  51#include "adf_accel_devices.h"
  52#include "adf_cfg.h"
  53#include "adf_common_drv.h"
  54
  55static LIST_HEAD(service_table);
  56static DEFINE_MUTEX(service_lock);
  57
  58static void adf_service_add(struct service_hndl *service)
  59{
  60        mutex_lock(&service_lock);
  61        list_add(&service->list, &service_table);
  62        mutex_unlock(&service_lock);
  63}
  64
  65/**
  66 * adf_service_register() - Register acceleration service in the accel framework
  67 * @service:    Pointer to the service
  68 *
  69 * Function adds the acceleration service to the acceleration framework.
  70 * To be used by QAT device specific drivers.
  71 *
  72 * Return: 0 on success, error code otherwise.
  73 */
  74int adf_service_register(struct service_hndl *service)
  75{
  76        service->init_status = 0;
  77        service->start_status = 0;
  78        adf_service_add(service);
  79        return 0;
  80}
  81EXPORT_SYMBOL_GPL(adf_service_register);
  82
  83static void adf_service_remove(struct service_hndl *service)
  84{
  85        mutex_lock(&service_lock);
  86        list_del(&service->list);
  87        mutex_unlock(&service_lock);
  88}
  89
  90/**
  91 * adf_service_unregister() - Unregister acceleration service from the framework
  92 * @service:    Pointer to the service
  93 *
  94 * Function remove the acceleration service from the acceleration framework.
  95 * To be used by QAT device specific drivers.
  96 *
  97 * Return: 0 on success, error code otherwise.
  98 */
  99int adf_service_unregister(struct service_hndl *service)
 100{
 101        if (service->init_status || service->start_status) {
 102                pr_err("QAT: Could not remove active service\n");
 103                return -EFAULT;
 104        }
 105        adf_service_remove(service);
 106        return 0;
 107}
 108EXPORT_SYMBOL_GPL(adf_service_unregister);
 109
 110/**
 111 * adf_dev_init() - Init data structures and services for the given accel device
 112 * @accel_dev: Pointer to acceleration device.
 113 *
 114 * Initialize the ring data structures and the admin comms and arbitration
 115 * services.
 116 *
 117 * Return: 0 on success, error code otherwise.
 118 */
 119int adf_dev_init(struct adf_accel_dev *accel_dev)
 120{
 121        struct service_hndl *service;
 122        struct list_head *list_itr;
 123        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
 124
 125        if (!hw_data) {
 126                dev_err(&GET_DEV(accel_dev),
 127                        "Failed to init device - hw_data not set\n");
 128                return -EFAULT;
 129        }
 130
 131        if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
 132                dev_err(&GET_DEV(accel_dev), "Device not configured\n");
 133                return -EFAULT;
 134        }
 135
 136        if (adf_init_etr_data(accel_dev)) {
 137                dev_err(&GET_DEV(accel_dev), "Failed initialize etr\n");
 138                return -EFAULT;
 139        }
 140
 141        if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
 142                dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n");
 143                return -EFAULT;
 144        }
 145
 146        if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
 147                dev_err(&GET_DEV(accel_dev), "Failed initialize hw arbiter\n");
 148                return -EFAULT;
 149        }
 150
 151        hw_data->enable_ints(accel_dev);
 152
 153        if (adf_ae_init(accel_dev)) {
 154                dev_err(&GET_DEV(accel_dev),
 155                        "Failed to initialise Acceleration Engine\n");
 156                return -EFAULT;
 157        }
 158        set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
 159
 160        if (adf_ae_fw_load(accel_dev)) {
 161                dev_err(&GET_DEV(accel_dev),
 162                        "Failed to load acceleration FW\n");
 163                return -EFAULT;
 164        }
 165        set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
 166
 167        if (hw_data->alloc_irq(accel_dev)) {
 168                dev_err(&GET_DEV(accel_dev), "Failed to allocate interrupts\n");
 169                return -EFAULT;
 170        }
 171        set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
 172
 173        /*
 174         * Subservice initialisation is divided into two stages: init and start.
 175         * This is to facilitate any ordering dependencies between services
 176         * prior to starting any of the accelerators.
 177         */
 178        list_for_each(list_itr, &service_table) {
 179                service = list_entry(list_itr, struct service_hndl, list);
 180                if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
 181                        dev_err(&GET_DEV(accel_dev),
 182                                "Failed to initialise service %s\n",
 183                                service->name);
 184                        return -EFAULT;
 185                }
 186                set_bit(accel_dev->accel_id, &service->init_status);
 187        }
 188
 189        hw_data->enable_error_correction(accel_dev);
 190        hw_data->enable_vf2pf_comms(accel_dev);
 191
 192        return 0;
 193}
 194EXPORT_SYMBOL_GPL(adf_dev_init);
 195
 196/**
 197 * adf_dev_start() - Start acceleration service for the given accel device
 198 * @accel_dev:    Pointer to acceleration device.
 199 *
 200 * Function notifies all the registered services that the acceleration device
 201 * is ready to be used.
 202 * To be used by QAT device specific drivers.
 203 *
 204 * Return: 0 on success, error code otherwise.
 205 */
 206int adf_dev_start(struct adf_accel_dev *accel_dev)
 207{
 208        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
 209        struct service_hndl *service;
 210        struct list_head *list_itr;
 211
 212        set_bit(ADF_STATUS_STARTING, &accel_dev->status);
 213
 214        if (adf_ae_start(accel_dev)) {
 215                dev_err(&GET_DEV(accel_dev), "AE Start Failed\n");
 216                return -EFAULT;
 217        }
 218        set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
 219
 220        if (hw_data->send_admin_init(accel_dev)) {
 221                dev_err(&GET_DEV(accel_dev), "Failed to send init message\n");
 222                return -EFAULT;
 223        }
 224
 225        list_for_each(list_itr, &service_table) {
 226                service = list_entry(list_itr, struct service_hndl, list);
 227                if (service->event_hld(accel_dev, ADF_EVENT_START)) {
 228                        dev_err(&GET_DEV(accel_dev),
 229                                "Failed to start service %s\n",
 230                                service->name);
 231                        return -EFAULT;
 232                }
 233                set_bit(accel_dev->accel_id, &service->start_status);
 234        }
 235
 236        clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
 237        set_bit(ADF_STATUS_STARTED, &accel_dev->status);
 238
 239        if (!list_empty(&accel_dev->crypto_list) &&
 240            (qat_algs_register() || qat_asym_algs_register())) {
 241                dev_err(&GET_DEV(accel_dev),
 242                        "Failed to register crypto algs\n");
 243                set_bit(ADF_STATUS_STARTING, &accel_dev->status);
 244                clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
 245                return -EFAULT;
 246        }
 247        return 0;
 248}
 249EXPORT_SYMBOL_GPL(adf_dev_start);
 250
 251/**
 252 * adf_dev_stop() - Stop acceleration service for the given accel device
 253 * @accel_dev:    Pointer to acceleration device.
 254 *
 255 * Function notifies all the registered services that the acceleration device
 256 * is shuting down.
 257 * To be used by QAT device specific drivers.
 258 *
 259 * Return: 0 on success, error code otherwise.
 260 */
 261int adf_dev_stop(struct adf_accel_dev *accel_dev)
 262{
 263        struct service_hndl *service;
 264        struct list_head *list_itr;
 265        bool wait = false;
 266        int ret;
 267
 268        if (!adf_dev_started(accel_dev) &&
 269            !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
 270                return 0;
 271        }
 272        clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
 273        clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
 274
 275        if (!list_empty(&accel_dev->crypto_list)) {
 276                qat_algs_unregister();
 277                qat_asym_algs_unregister();
 278        }
 279
 280        list_for_each(list_itr, &service_table) {
 281                service = list_entry(list_itr, struct service_hndl, list);
 282                if (!test_bit(accel_dev->accel_id, &service->start_status))
 283                        continue;
 284                ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
 285                if (!ret) {
 286                        clear_bit(accel_dev->accel_id, &service->start_status);
 287                } else if (ret == -EAGAIN) {
 288                        wait = true;
 289                        clear_bit(accel_dev->accel_id, &service->start_status);
 290                }
 291        }
 292
 293        if (wait)
 294                msleep(100);
 295
 296        if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
 297                if (adf_ae_stop(accel_dev))
 298                        dev_err(&GET_DEV(accel_dev), "failed to stop AE\n");
 299                else
 300                        clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
 301        }
 302
 303        return 0;
 304}
 305EXPORT_SYMBOL_GPL(adf_dev_stop);
 306
 307/**
 308 * adf_dev_shutdown() - shutdown acceleration services and data strucutures
 309 * @accel_dev: Pointer to acceleration device
 310 *
 311 * Cleanup the ring data structures and the admin comms and arbitration
 312 * services.
 313 */
 314void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
 315{
 316        struct adf_hw_device_data *hw_data = accel_dev->hw_device;
 317        struct service_hndl *service;
 318        struct list_head *list_itr;
 319
 320        if (!hw_data) {
 321                dev_err(&GET_DEV(accel_dev),
 322                        "QAT: Failed to shutdown device - hw_data not set\n");
 323                return;
 324        }
 325
 326        if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
 327                adf_ae_fw_release(accel_dev);
 328                clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
 329        }
 330
 331        if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
 332                if (adf_ae_shutdown(accel_dev))
 333                        dev_err(&GET_DEV(accel_dev),
 334                                "Failed to shutdown Accel Engine\n");
 335                else
 336                        clear_bit(ADF_STATUS_AE_INITIALISED,
 337                                  &accel_dev->status);
 338        }
 339
 340        list_for_each(list_itr, &service_table) {
 341                service = list_entry(list_itr, struct service_hndl, list);
 342                if (!test_bit(accel_dev->accel_id, &service->init_status))
 343                        continue;
 344                if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
 345                        dev_err(&GET_DEV(accel_dev),
 346                                "Failed to shutdown service %s\n",
 347                                service->name);
 348                else
 349                        clear_bit(accel_dev->accel_id, &service->init_status);
 350        }
 351
 352        if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
 353                hw_data->free_irq(accel_dev);
 354                clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
 355        }
 356
 357        /* Delete configuration only if not restarting */
 358        if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
 359                adf_cfg_del_all(accel_dev);
 360
 361        if (hw_data->exit_arb)
 362                hw_data->exit_arb(accel_dev);
 363
 364        if (hw_data->exit_admin_comms)
 365                hw_data->exit_admin_comms(accel_dev);
 366
 367        hw_data->disable_iov(accel_dev);
 368        adf_cleanup_etr_data(accel_dev);
 369}
 370EXPORT_SYMBOL_GPL(adf_dev_shutdown);
 371
 372int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
 373{
 374        struct service_hndl *service;
 375        struct list_head *list_itr;
 376
 377        list_for_each(list_itr, &service_table) {
 378                service = list_entry(list_itr, struct service_hndl, list);
 379                if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
 380                        dev_err(&GET_DEV(accel_dev),
 381                                "Failed to restart service %s.\n",
 382                                service->name);
 383        }
 384        return 0;
 385}
 386
 387int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
 388{
 389        struct service_hndl *service;
 390        struct list_head *list_itr;
 391
 392        list_for_each(list_itr, &service_table) {
 393                service = list_entry(list_itr, struct service_hndl, list);
 394                if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
 395                        dev_err(&GET_DEV(accel_dev),
 396                                "Failed to restart service %s.\n",
 397                                service->name);
 398        }
 399        return 0;
 400}
 401