diff options
Diffstat (limited to 'drivers/crypto')
| -rw-r--r-- | drivers/crypto/ccp/ccp-crypto-main.c | 164 |
1 files changed, 48 insertions, 116 deletions
diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c index b3f22b07b5bd..010fded5d46b 100644 --- a/drivers/crypto/ccp/ccp-crypto-main.c +++ b/drivers/crypto/ccp/ccp-crypto-main.c | |||
| @@ -38,23 +38,20 @@ MODULE_PARM_DESC(sha_disable, "Disable use of SHA - any non-zero value"); | |||
| 38 | static LIST_HEAD(hash_algs); | 38 | static LIST_HEAD(hash_algs); |
| 39 | static LIST_HEAD(cipher_algs); | 39 | static LIST_HEAD(cipher_algs); |
| 40 | 40 | ||
| 41 | /* For any tfm, requests for that tfm on the same CPU must be returned | 41 | /* For any tfm, requests for that tfm must be returned on the order |
| 42 | * in the order received. With multiple queues available, the CCP can | 42 | * received. With multiple queues available, the CCP can process more |
| 43 | * process more than one cmd at a time. Therefore we must maintain | 43 | * than one cmd at a time. Therefore we must maintain a cmd list to insure |
| 44 | * a cmd list to insure the proper ordering of requests on a given tfm/cpu | 44 | * the proper ordering of requests on a given tfm. |
| 45 | * combination. | ||
| 46 | */ | 45 | */ |
| 47 | struct ccp_crypto_cpu_queue { | 46 | struct ccp_crypto_queue { |
| 48 | struct list_head cmds; | 47 | struct list_head cmds; |
| 49 | struct list_head *backlog; | 48 | struct list_head *backlog; |
| 50 | unsigned int cmd_count; | 49 | unsigned int cmd_count; |
| 51 | }; | 50 | }; |
| 52 | #define CCP_CRYPTO_MAX_QLEN 50 | 51 | #define CCP_CRYPTO_MAX_QLEN 100 |
| 53 | 52 | ||
| 54 | struct ccp_crypto_percpu_queue { | 53 | static struct ccp_crypto_queue req_queue; |
| 55 | struct ccp_crypto_cpu_queue __percpu *cpu_queue; | 54 | static spinlock_t req_queue_lock; |
| 56 | }; | ||
| 57 | static struct ccp_crypto_percpu_queue req_queue; | ||
| 58 | 55 | ||
| 59 | struct ccp_crypto_cmd { | 56 | struct ccp_crypto_cmd { |
| 60 | struct list_head entry; | 57 | struct list_head entry; |
| @@ -71,8 +68,6 @@ struct ccp_crypto_cmd { | |||
| 71 | 68 | ||
| 72 | /* Used for held command processing to determine state */ | 69 | /* Used for held command processing to determine state */ |
| 73 | int ret; | 70 | int ret; |
| 74 | |||
| 75 | int cpu; | ||
| 76 | }; | 71 | }; |
| 77 | 72 | ||
| 78 | struct ccp_crypto_cpu { | 73 | struct ccp_crypto_cpu { |
| @@ -91,25 +86,21 @@ static inline bool ccp_crypto_success(int err) | |||
| 91 | return true; | 86 | return true; |
| 92 | } | 87 | } |
| 93 | 88 | ||
| 94 | /* | ||
| 95 | * ccp_crypto_cmd_complete must be called while running on the appropriate | ||
| 96 | * cpu and the caller must have done a get_cpu to disable preemption | ||
| 97 | */ | ||
| 98 | static struct ccp_crypto_cmd *ccp_crypto_cmd_complete( | 89 | static struct ccp_crypto_cmd *ccp_crypto_cmd_complete( |
| 99 | struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog) | 90 | struct ccp_crypto_cmd *crypto_cmd, struct ccp_crypto_cmd **backlog) |
| 100 | { | 91 | { |
| 101 | struct ccp_crypto_cpu_queue *cpu_queue; | ||
| 102 | struct ccp_crypto_cmd *held = NULL, *tmp; | 92 | struct ccp_crypto_cmd *held = NULL, *tmp; |
| 93 | unsigned long flags; | ||
| 103 | 94 | ||
| 104 | *backlog = NULL; | 95 | *backlog = NULL; |
| 105 | 96 | ||
| 106 | cpu_queue = this_cpu_ptr(req_queue.cpu_queue); | 97 | spin_lock_irqsave(&req_queue_lock, flags); |
| 107 | 98 | ||
| 108 | /* Held cmds will be after the current cmd in the queue so start | 99 | /* Held cmds will be after the current cmd in the queue so start |
| 109 | * searching for a cmd with a matching tfm for submission. | 100 | * searching for a cmd with a matching tfm for submission. |
| 110 | */ | 101 | */ |
| 111 | tmp = crypto_cmd; | 102 | tmp = crypto_cmd; |
| 112 | list_for_each_entry_continue(tmp, &cpu_queue->cmds, entry) { | 103 | list_for_each_entry_continue(tmp, &req_queue.cmds, entry) { |
| 113 | if (crypto_cmd->tfm != tmp->tfm) | 104 | if (crypto_cmd->tfm != tmp->tfm) |
| 114 | continue; | 105 | continue; |
| 115 | held = tmp; | 106 | held = tmp; |
| @@ -120,47 +111,45 @@ static struct ccp_crypto_cmd *ccp_crypto_cmd_complete( | |||
| 120 | * Because cmds can be executed from any point in the cmd list | 111 | * Because cmds can be executed from any point in the cmd list |
| 121 | * special precautions have to be taken when handling the backlog. | 112 | * special precautions have to be taken when handling the backlog. |
| 122 | */ | 113 | */ |
| 123 | if (cpu_queue->backlog != &cpu_queue->cmds) { | 114 | if (req_queue.backlog != &req_queue.cmds) { |
| 124 | /* Skip over this cmd if it is the next backlog cmd */ | 115 | /* Skip over this cmd if it is the next backlog cmd */ |
| 125 | if (cpu_queue->backlog == &crypto_cmd->entry) | 116 | if (req_queue.backlog == &crypto_cmd->entry) |
| 126 | cpu_queue->backlog = crypto_cmd->entry.next; | 117 | req_queue.backlog = crypto_cmd->entry.next; |
| 127 | 118 | ||
| 128 | *backlog = container_of(cpu_queue->backlog, | 119 | *backlog = container_of(req_queue.backlog, |
| 129 | struct ccp_crypto_cmd, entry); | 120 | struct ccp_crypto_cmd, entry); |
| 130 | cpu_queue->backlog = cpu_queue->backlog->next; | 121 | req_queue.backlog = req_queue.backlog->next; |
| 131 | 122 | ||
| 132 | /* Skip over this cmd if it is now the next backlog cmd */ | 123 | /* Skip over this cmd if it is now the next backlog cmd */ |
| 133 | if (cpu_queue->backlog == &crypto_cmd->entry) | 124 | if (req_queue.backlog == &crypto_cmd->entry) |
| 134 | cpu_queue->backlog = crypto_cmd->entry.next; | 125 | req_queue.backlog = crypto_cmd->entry.next; |
| 135 | } | 126 | } |
| 136 | 127 | ||
| 137 | /* Remove the cmd entry from the list of cmds */ | 128 | /* Remove the cmd entry from the list of cmds */ |
| 138 | cpu_queue->cmd_count--; | 129 | req_queue.cmd_count--; |
| 139 | list_del(&crypto_cmd->entry); | 130 | list_del(&crypto_cmd->entry); |
| 140 | 131 | ||
| 132 | spin_unlock_irqrestore(&req_queue_lock, flags); | ||
| 133 | |||
| 141 | return held; | 134 | return held; |
| 142 | } | 135 | } |
| 143 | 136 | ||
| 144 | static void ccp_crypto_complete_on_cpu(struct work_struct *work) | 137 | static void ccp_crypto_complete(void *data, int err) |
| 145 | { | 138 | { |
| 146 | struct ccp_crypto_cpu *cpu_work = | 139 | struct ccp_crypto_cmd *crypto_cmd = data; |
| 147 | container_of(work, struct ccp_crypto_cpu, work); | ||
| 148 | struct ccp_crypto_cmd *crypto_cmd = cpu_work->crypto_cmd; | ||
| 149 | struct ccp_crypto_cmd *held, *next, *backlog; | 140 | struct ccp_crypto_cmd *held, *next, *backlog; |
| 150 | struct crypto_async_request *req = crypto_cmd->req; | 141 | struct crypto_async_request *req = crypto_cmd->req; |
| 151 | struct ccp_ctx *ctx = crypto_tfm_ctx(req->tfm); | 142 | struct ccp_ctx *ctx = crypto_tfm_ctx(req->tfm); |
| 152 | int cpu, ret; | 143 | int ret; |
| 153 | |||
| 154 | cpu = get_cpu(); | ||
| 155 | 144 | ||
| 156 | if (cpu_work->err == -EINPROGRESS) { | 145 | if (err == -EINPROGRESS) { |
| 157 | /* Only propogate the -EINPROGRESS if necessary */ | 146 | /* Only propogate the -EINPROGRESS if necessary */ |
| 158 | if (crypto_cmd->ret == -EBUSY) { | 147 | if (crypto_cmd->ret == -EBUSY) { |
| 159 | crypto_cmd->ret = -EINPROGRESS; | 148 | crypto_cmd->ret = -EINPROGRESS; |
| 160 | req->complete(req, -EINPROGRESS); | 149 | req->complete(req, -EINPROGRESS); |
| 161 | } | 150 | } |
| 162 | 151 | ||
| 163 | goto e_cpu; | 152 | return; |
| 164 | } | 153 | } |
| 165 | 154 | ||
| 166 | /* Operation has completed - update the queue before invoking | 155 | /* Operation has completed - update the queue before invoking |
| @@ -178,7 +167,7 @@ static void ccp_crypto_complete_on_cpu(struct work_struct *work) | |||
| 178 | req->complete(req, -EINPROGRESS); | 167 | req->complete(req, -EINPROGRESS); |
| 179 | 168 | ||
| 180 | /* Completion callbacks */ | 169 | /* Completion callbacks */ |
| 181 | ret = cpu_work->err; | 170 | ret = err; |
| 182 | if (ctx->complete) | 171 | if (ctx->complete) |
| 183 | ret = ctx->complete(req, ret); | 172 | ret = ctx->complete(req, ret); |
| 184 | req->complete(req, ret); | 173 | req->complete(req, ret); |
| @@ -203,52 +192,28 @@ static void ccp_crypto_complete_on_cpu(struct work_struct *work) | |||
| 203 | } | 192 | } |
| 204 | 193 | ||
| 205 | kfree(crypto_cmd); | 194 | kfree(crypto_cmd); |
| 206 | |||
| 207 | e_cpu: | ||
| 208 | put_cpu(); | ||
| 209 | |||
| 210 | complete(&cpu_work->completion); | ||
| 211 | } | ||
| 212 | |||
| 213 | static void ccp_crypto_complete(void *data, int err) | ||
| 214 | |||
