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