root/drivers/crypto/qat/qat_common/adf_init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adf_service_add
  2. adf_service_register
  3. adf_service_remove
  4. adf_service_unregister
  5. adf_dev_init
  6. adf_dev_start
  7. adf_dev_stop
  8. adf_dev_shutdown
  9. adf_dev_restarting_notify
  10. adf_dev_restarted_notify

   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 
  55 static LIST_HEAD(service_table);
  56 static DEFINE_MUTEX(service_lock);
  57 
  58 static 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 int 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 
  73 static 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 
  80 int 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  */
 103 int 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 }
 178 EXPORT_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  */
 190 int 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 }
 233 EXPORT_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  */
 245 void 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 }
 287 EXPORT_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  */
 296 void 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 }
 354 EXPORT_SYMBOL_GPL(adf_dev_shutdown);
 355 
 356 int 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 
 371 int 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 }

/* [<][>][^][v][top][bottom][index][help] */