162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD Cryptographic Coprocessor (CCP) crypto API support 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2013,2017 Advanced Micro Devices, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author: Tom Lendacky <thomas.lendacky@amd.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/moduleparam.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/list.h> 1462306a36Sopenharmony_ci#include <linux/ccp.h> 1562306a36Sopenharmony_ci#include <linux/scatterlist.h> 1662306a36Sopenharmony_ci#include <crypto/internal/hash.h> 1762306a36Sopenharmony_ci#include <crypto/internal/akcipher.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "ccp-crypto.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciMODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>"); 2262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2362306a36Sopenharmony_ciMODULE_VERSION("1.0.0"); 2462306a36Sopenharmony_ciMODULE_DESCRIPTION("AMD Cryptographic Coprocessor crypto API support"); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic unsigned int aes_disable; 2762306a36Sopenharmony_cimodule_param(aes_disable, uint, 0444); 2862306a36Sopenharmony_ciMODULE_PARM_DESC(aes_disable, "Disable use of AES - any non-zero value"); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic unsigned int sha_disable; 3162306a36Sopenharmony_cimodule_param(sha_disable, uint, 0444); 3262306a36Sopenharmony_ciMODULE_PARM_DESC(sha_disable, "Disable use of SHA - any non-zero value"); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic unsigned int des3_disable; 3562306a36Sopenharmony_cimodule_param(des3_disable, uint, 0444); 3662306a36Sopenharmony_ciMODULE_PARM_DESC(des3_disable, "Disable use of 3DES - any non-zero value"); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic unsigned int rsa_disable; 3962306a36Sopenharmony_cimodule_param(rsa_disable, uint, 0444); 4062306a36Sopenharmony_ciMODULE_PARM_DESC(rsa_disable, "Disable use of RSA - any non-zero value"); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* List heads for the supported algorithms */ 4362306a36Sopenharmony_cistatic LIST_HEAD(hash_algs); 4462306a36Sopenharmony_cistatic LIST_HEAD(skcipher_algs); 4562306a36Sopenharmony_cistatic LIST_HEAD(aead_algs); 4662306a36Sopenharmony_cistatic LIST_HEAD(akcipher_algs); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* For any tfm, requests for that tfm must be returned on the order 4962306a36Sopenharmony_ci * received. With multiple queues available, the CCP can process more 5062306a36Sopenharmony_ci * than one cmd at a time. Therefore we must maintain a cmd list to insure 5162306a36Sopenharmony_ci * the proper ordering of requests on a given tfm. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistruct ccp_crypto_queue { 5462306a36Sopenharmony_ci struct list_head cmds; 5562306a36Sopenharmony_ci struct list_head *backlog; 5662306a36Sopenharmony_ci unsigned int cmd_count; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define CCP_CRYPTO_MAX_QLEN 100 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic struct ccp_crypto_queue req_queue; 6262306a36Sopenharmony_cistatic DEFINE_SPINLOCK(req_queue_lock); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct ccp_crypto_cmd { 6562306a36Sopenharmony_ci struct list_head entry; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci struct ccp_cmd *cmd; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* Save the crypto_tfm and crypto_async_request addresses 7062306a36Sopenharmony_ci * separately to avoid any reference to a possibly invalid 7162306a36Sopenharmony_ci * crypto_async_request structure after invoking the request 7262306a36Sopenharmony_ci * callback 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci struct crypto_async_request *req; 7562306a36Sopenharmony_ci struct crypto_tfm *tfm; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Used for held command processing to determine state */ 7862306a36Sopenharmony_ci int ret; 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline bool ccp_crypto_success(int err) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci if (err && (err != -EINPROGRESS) && (err != -EBUSY)) 8462306a36Sopenharmony_ci return false; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return true; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic struct ccp_crypto_cmd *ccp_crypto_cmd_complete( 9062306a36Sopenharmony_ci struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct ccp_crypto_cmd *held = NULL, *tmp; 9362306a36Sopenharmony_ci unsigned long flags; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci *backlog = NULL; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci spin_lock_irqsave(&req_queue_lock, flags); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Held cmds will be after the current cmd in the queue so start 10062306a36Sopenharmony_ci * searching for a cmd with a matching tfm for submission. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci tmp = crypto_cmd; 10362306a36Sopenharmony_ci list_for_each_entry_continue(tmp, &req_queue.cmds, entry) { 10462306a36Sopenharmony_ci if (crypto_cmd->tfm != tmp->tfm) 10562306a36Sopenharmony_ci continue; 10662306a36Sopenharmony_ci held = tmp; 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Process the backlog: 11162306a36Sopenharmony_ci * Because cmds can be executed from any point in the cmd list 11262306a36Sopenharmony_ci * special precautions have to be taken when handling the backlog. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci if (req_queue.backlog != &req_queue.cmds) { 11562306a36Sopenharmony_ci /* Skip over this cmd if it is the next backlog cmd */ 11662306a36Sopenharmony_ci if (req_queue.backlog == &crypto_cmd->entry) 11762306a36Sopenharmony_ci req_queue.backlog = crypto_cmd->entry.next; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci *backlog = container_of(req_queue.backlog, 12062306a36Sopenharmony_ci struct ccp_crypto_cmd, entry); 12162306a36Sopenharmony_ci req_queue.backlog = req_queue.backlog->next; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* Skip over this cmd if it is now the next backlog cmd */ 12462306a36Sopenharmony_ci if (req_queue.backlog == &crypto_cmd->entry) 12562306a36Sopenharmony_ci req_queue.backlog = crypto_cmd->entry.next; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Remove the cmd entry from the list of cmds */ 12962306a36Sopenharmony_ci req_queue.cmd_count--; 13062306a36Sopenharmony_ci list_del(&crypto_cmd->entry); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci spin_unlock_irqrestore(&req_queue_lock, flags); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return held; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic void ccp_crypto_complete(void *data, int err) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci struct ccp_crypto_cmd *crypto_cmd = data; 14062306a36Sopenharmony_ci struct ccp_crypto_cmd *held, *next, *backlog; 14162306a36Sopenharmony_ci struct crypto_async_request *req = crypto_cmd->req; 14262306a36Sopenharmony_ci struct ccp_ctx *ctx = crypto_tfm_ctx_dma(req->tfm); 14362306a36Sopenharmony_ci int ret; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (err == -EINPROGRESS) { 14662306a36Sopenharmony_ci /* Only propagate the -EINPROGRESS if necessary */ 14762306a36Sopenharmony_ci if (crypto_cmd->ret == -EBUSY) { 14862306a36Sopenharmony_ci crypto_cmd->ret = -EINPROGRESS; 14962306a36Sopenharmony_ci crypto_request_complete(req, -EINPROGRESS); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci return; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Operation has completed - update the queue before invoking 15662306a36Sopenharmony_ci * the completion callbacks and retrieve the next cmd (cmd with 15762306a36Sopenharmony_ci * a matching tfm) that can be submitted to the CCP. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci held = ccp_crypto_cmd_complete(crypto_cmd, &backlog); 16062306a36Sopenharmony_ci if (backlog) { 16162306a36Sopenharmony_ci backlog->ret = -EINPROGRESS; 16262306a36Sopenharmony_ci crypto_request_complete(backlog->req, -EINPROGRESS); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Transition the state from -EBUSY to -EINPROGRESS first */ 16662306a36Sopenharmony_ci if (crypto_cmd->ret == -EBUSY) 16762306a36Sopenharmony_ci crypto_request_complete(req, -EINPROGRESS); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* Completion callbacks */ 17062306a36Sopenharmony_ci ret = err; 17162306a36Sopenharmony_ci if (ctx->complete) 17262306a36Sopenharmony_ci ret = ctx->complete(req, ret); 17362306a36Sopenharmony_ci crypto_request_complete(req, ret); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Submit the next cmd */ 17662306a36Sopenharmony_ci while (held) { 17762306a36Sopenharmony_ci /* Since we have already queued the cmd, we must indicate that 17862306a36Sopenharmony_ci * we can backlog so as not to "lose" this request. 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci held->cmd->flags |= CCP_CMD_MAY_BACKLOG; 18162306a36Sopenharmony_ci ret = ccp_enqueue_cmd(held->cmd); 18262306a36Sopenharmony_ci if (ccp_crypto_success(ret)) 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Error occurred, report it and get the next entry */ 18662306a36Sopenharmony_ci ctx = crypto_tfm_ctx_dma(held->req->tfm); 18762306a36Sopenharmony_ci if (ctx->complete) 18862306a36Sopenharmony_ci ret = ctx->complete(held->req, ret); 18962306a36Sopenharmony_ci crypto_request_complete(held->req, ret); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci next = ccp_crypto_cmd_complete(held, &backlog); 19262306a36Sopenharmony_ci if (backlog) { 19362306a36Sopenharmony_ci backlog->ret = -EINPROGRESS; 19462306a36Sopenharmony_ci crypto_request_complete(backlog->req, -EINPROGRESS); 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci kfree(held); 19862306a36Sopenharmony_ci held = next; 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci kfree(crypto_cmd); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic int ccp_crypto_enqueue_cmd(struct ccp_crypto_cmd *crypto_cmd) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct ccp_crypto_cmd *active = NULL, *tmp; 20762306a36Sopenharmony_ci unsigned long flags; 20862306a36Sopenharmony_ci bool free_cmd = true; 20962306a36Sopenharmony_ci int ret; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci spin_lock_irqsave(&req_queue_lock, flags); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* Check if the cmd can/should be queued */ 21462306a36Sopenharmony_ci if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) { 21562306a36Sopenharmony_ci if (!(crypto_cmd->cmd->flags & CCP_CMD_MAY_BACKLOG)) { 21662306a36Sopenharmony_ci ret = -ENOSPC; 21762306a36Sopenharmony_ci goto e_lock; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Look for an entry with the same tfm. If there is a cmd 22262306a36Sopenharmony_ci * with the same tfm in the list then the current cmd cannot 22362306a36Sopenharmony_ci * be submitted to the CCP yet. 22462306a36Sopenharmony_ci */ 22562306a36Sopenharmony_ci list_for_each_entry(tmp, &req_queue.cmds, entry) { 22662306a36Sopenharmony_ci if (crypto_cmd->tfm != tmp->tfm) 22762306a36Sopenharmony_ci continue; 22862306a36Sopenharmony_ci active = tmp; 22962306a36Sopenharmony_ci break; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ret = -EINPROGRESS; 23362306a36Sopenharmony_ci if (!active) { 23462306a36Sopenharmony_ci ret = ccp_enqueue_cmd(crypto_cmd->cmd); 23562306a36Sopenharmony_ci if (!ccp_crypto_success(ret)) 23662306a36Sopenharmony_ci goto e_lock; /* Error, don't queue it */ 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (req_queue.cmd_count >= CCP_CRYPTO_MAX_QLEN) { 24062306a36Sopenharmony_ci ret = -EBUSY; 24162306a36Sopenharmony_ci if (req_queue.backlog == &req_queue.cmds) 24262306a36Sopenharmony_ci req_queue.backlog = &crypto_cmd->entry; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci crypto_cmd->ret = ret; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci req_queue.cmd_count++; 24762306a36Sopenharmony_ci list_add_tail(&crypto_cmd->entry, &req_queue.cmds); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci free_cmd = false; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cie_lock: 25262306a36Sopenharmony_ci spin_unlock_irqrestore(&req_queue_lock, flags); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (free_cmd) 25562306a36Sopenharmony_ci kfree(crypto_cmd); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci return ret; 25862306a36Sopenharmony_ci} 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/** 26162306a36Sopenharmony_ci * ccp_crypto_enqueue_request - queue an crypto async request for processing 26262306a36Sopenharmony_ci * by the CCP 26362306a36Sopenharmony_ci * 26462306a36Sopenharmony_ci * @req: crypto_async_request struct to be processed 26562306a36Sopenharmony_ci * @cmd: ccp_cmd struct to be sent to the CCP 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ciint ccp_crypto_enqueue_request(struct crypto_async_request *req, 26862306a36Sopenharmony_ci struct ccp_cmd *cmd) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct ccp_crypto_cmd *crypto_cmd; 27162306a36Sopenharmony_ci gfp_t gfp; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci gfp = req->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci crypto_cmd = kzalloc(sizeof(*crypto_cmd), gfp); 27662306a36Sopenharmony_ci if (!crypto_cmd) 27762306a36Sopenharmony_ci return -ENOMEM; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* The tfm pointer must be saved and not referenced from the 28062306a36Sopenharmony_ci * crypto_async_request (req) pointer because it is used after 28162306a36Sopenharmony_ci * completion callback for the request and the req pointer 28262306a36Sopenharmony_ci * might not be valid anymore. 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci crypto_cmd->cmd = cmd; 28562306a36Sopenharmony_ci crypto_cmd->req = req; 28662306a36Sopenharmony_ci crypto_cmd->tfm = req->tfm; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci cmd->callback = ccp_crypto_complete; 28962306a36Sopenharmony_ci cmd->data = crypto_cmd; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG) 29262306a36Sopenharmony_ci cmd->flags |= CCP_CMD_MAY_BACKLOG; 29362306a36Sopenharmony_ci else 29462306a36Sopenharmony_ci cmd->flags &= ~CCP_CMD_MAY_BACKLOG; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci return ccp_crypto_enqueue_cmd(crypto_cmd); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistruct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table, 30062306a36Sopenharmony_ci struct scatterlist *sg_add) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct scatterlist *sg, *sg_last = NULL; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci for (sg = table->sgl; sg; sg = sg_next(sg)) 30562306a36Sopenharmony_ci if (!sg_page(sg)) 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci if (WARN_ON(!sg)) 30862306a36Sopenharmony_ci return NULL; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci for (; sg && sg_add; sg = sg_next(sg), sg_add = sg_next(sg_add)) { 31162306a36Sopenharmony_ci sg_set_page(sg, sg_page(sg_add), sg_add->length, 31262306a36Sopenharmony_ci sg_add->offset); 31362306a36Sopenharmony_ci sg_last = sg; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci if (WARN_ON(sg_add)) 31662306a36Sopenharmony_ci return NULL; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return sg_last; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic int ccp_register_algs(void) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci int ret; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (!aes_disable) { 32662306a36Sopenharmony_ci ret = ccp_register_aes_algs(&skcipher_algs); 32762306a36Sopenharmony_ci if (ret) 32862306a36Sopenharmony_ci return ret; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci ret = ccp_register_aes_cmac_algs(&hash_algs); 33162306a36Sopenharmony_ci if (ret) 33262306a36Sopenharmony_ci return ret; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci ret = ccp_register_aes_xts_algs(&skcipher_algs); 33562306a36Sopenharmony_ci if (ret) 33662306a36Sopenharmony_ci return ret; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci ret = ccp_register_aes_aeads(&aead_algs); 33962306a36Sopenharmony_ci if (ret) 34062306a36Sopenharmony_ci return ret; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if (!des3_disable) { 34462306a36Sopenharmony_ci ret = ccp_register_des3_algs(&skcipher_algs); 34562306a36Sopenharmony_ci if (ret) 34662306a36Sopenharmony_ci return ret; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (!sha_disable) { 35062306a36Sopenharmony_ci ret = ccp_register_sha_algs(&hash_algs); 35162306a36Sopenharmony_ci if (ret) 35262306a36Sopenharmony_ci return ret; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (!rsa_disable) { 35662306a36Sopenharmony_ci ret = ccp_register_rsa_algs(&akcipher_algs); 35762306a36Sopenharmony_ci if (ret) 35862306a36Sopenharmony_ci return ret; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci return 0; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic void ccp_unregister_algs(void) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp; 36762306a36Sopenharmony_ci struct ccp_crypto_skcipher_alg *ablk_alg, *ablk_tmp; 36862306a36Sopenharmony_ci struct ccp_crypto_aead *aead_alg, *aead_tmp; 36962306a36Sopenharmony_ci struct ccp_crypto_akcipher_alg *akc_alg, *akc_tmp; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) { 37262306a36Sopenharmony_ci crypto_unregister_ahash(&ahash_alg->alg); 37362306a36Sopenharmony_ci list_del(&ahash_alg->entry); 37462306a36Sopenharmony_ci kfree(ahash_alg); 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci list_for_each_entry_safe(ablk_alg, ablk_tmp, &skcipher_algs, entry) { 37862306a36Sopenharmony_ci crypto_unregister_skcipher(&ablk_alg->alg); 37962306a36Sopenharmony_ci list_del(&ablk_alg->entry); 38062306a36Sopenharmony_ci kfree(ablk_alg); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci list_for_each_entry_safe(aead_alg, aead_tmp, &aead_algs, entry) { 38462306a36Sopenharmony_ci crypto_unregister_aead(&aead_alg->alg); 38562306a36Sopenharmony_ci list_del(&aead_alg->entry); 38662306a36Sopenharmony_ci kfree(aead_alg); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci list_for_each_entry_safe(akc_alg, akc_tmp, &akcipher_algs, entry) { 39062306a36Sopenharmony_ci crypto_unregister_akcipher(&akc_alg->alg); 39162306a36Sopenharmony_ci list_del(&akc_alg->entry); 39262306a36Sopenharmony_ci kfree(akc_alg); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int __init ccp_crypto_init(void) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci int ret; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci ret = ccp_present(); 40162306a36Sopenharmony_ci if (ret) { 40262306a36Sopenharmony_ci pr_err("Cannot load: there are no available CCPs\n"); 40362306a36Sopenharmony_ci return ret; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci INIT_LIST_HEAD(&req_queue.cmds); 40762306a36Sopenharmony_ci req_queue.backlog = &req_queue.cmds; 40862306a36Sopenharmony_ci req_queue.cmd_count = 0; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci ret = ccp_register_algs(); 41162306a36Sopenharmony_ci if (ret) 41262306a36Sopenharmony_ci ccp_unregister_algs(); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci return ret; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic void __exit ccp_crypto_exit(void) 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci ccp_unregister_algs(); 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cimodule_init(ccp_crypto_init); 42362306a36Sopenharmony_cimodule_exit(ccp_crypto_exit); 424