Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: qce - switch to using a mutex

Having switched to workqueue from tasklet, we are no longer limited to
atomic APIs and can now convert the spinlock to a mutex. This, along
with the conversion from tasklet to workqueue grants us ~15% improvement
in cryptsetup benchmarks for AES encryption.

While at it: use guards to simplify locking code.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Bartosz Golaszewski and committed by
Herbert Xu
3382c44f eb7986e5

+23 -26
+21 -25
drivers/crypto/qce/core.c
··· 3 3 * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 4 4 */ 5 5 6 + #include <linux/cleanup.h> 6 7 #include <linux/clk.h> 7 8 #include <linux/device.h> 8 9 #include <linux/dma-mapping.h> ··· 12 11 #include <linux/module.h> 13 12 #include <linux/mod_devicetable.h> 14 13 #include <linux/platform_device.h> 15 - #include <linux/spinlock.h> 16 14 #include <linux/types.h> 17 15 #include <crypto/algapi.h> 18 16 #include <crypto/internal/hash.h> ··· 89 89 struct crypto_async_request *req) 90 90 { 91 91 struct crypto_async_request *async_req, *backlog; 92 - unsigned long flags; 93 92 int ret = 0, err; 94 93 95 - spin_lock_irqsave(&qce->lock, flags); 94 + scoped_guard(mutex, &qce->lock) { 95 + if (req) 96 + ret = crypto_enqueue_request(&qce->queue, req); 96 97 97 - if (req) 98 - ret = crypto_enqueue_request(&qce->queue, req); 98 + /* busy, do not dequeue request */ 99 + if (qce->req) 100 + return ret; 99 101 100 - /* busy, do not dequeue request */ 101 - if (qce->req) { 102 - spin_unlock_irqrestore(&qce->lock, flags); 103 - return ret; 102 + backlog = crypto_get_backlog(&qce->queue); 103 + async_req = crypto_dequeue_request(&qce->queue); 104 + if (async_req) 105 + qce->req = async_req; 104 106 } 105 - 106 - backlog = crypto_get_backlog(&qce->queue); 107 - async_req = crypto_dequeue_request(&qce->queue); 108 - if (async_req) 109 - qce->req = async_req; 110 - 111 - spin_unlock_irqrestore(&qce->lock, flags); 112 107 113 108 if (!async_req) 114 109 return ret; 115 110 116 111 if (backlog) { 117 - spin_lock_bh(&qce->lock); 118 - crypto_request_complete(backlog, -EINPROGRESS); 119 - spin_unlock_bh(&qce->lock); 112 + scoped_guard(mutex, &qce->lock) 113 + crypto_request_complete(backlog, -EINPROGRESS); 120 114 } 121 115 122 116 err = qce_handle_request(async_req); ··· 127 133 struct qce_device *qce = container_of(work, struct qce_device, 128 134 done_work); 129 135 struct crypto_async_request *req; 130 - unsigned long flags; 131 136 132 - spin_lock_irqsave(&qce->lock, flags); 133 - req = qce->req; 134 - qce->req = NULL; 135 - spin_unlock_irqrestore(&qce->lock, flags); 137 + scoped_guard(mutex, &qce->lock) { 138 + req = qce->req; 139 + qce->req = NULL; 140 + } 136 141 137 142 if (req) 138 143 crypto_request_complete(req, qce->result); ··· 236 243 if (ret) 237 244 return ret; 238 245 239 - spin_lock_init(&qce->lock); 246 + ret = devm_mutex_init(qce->dev, &qce->lock); 247 + if (ret) 248 + return ret; 249 + 240 250 INIT_WORK(&qce->done_work, qce_req_done_work); 241 251 crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH); 242 252
+2 -1
drivers/crypto/qce/core.h
··· 6 6 #ifndef _CORE_H_ 7 7 #define _CORE_H_ 8 8 9 + #include <linux/mutex.h> 9 10 #include <linux/workqueue.h> 10 11 11 12 #include "dma.h" ··· 31 30 */ 32 31 struct qce_device { 33 32 struct crypto_queue queue; 34 - spinlock_t lock; 33 + struct mutex lock; 35 34 struct work_struct done_work; 36 35 struct crypto_async_request *req; 37 36 int result;