summaryrefslogtreecommitdiff
path: root/net/tls/tls_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tls/tls_device.c')
-rw-r--r--net/tls/tls_device.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index b3e2a30041c6..5150b3939b1f 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -96,19 +96,29 @@ static void tls_device_gc_task(struct work_struct *work)
static void tls_device_queue_ctx_destruction(struct tls_context *ctx)
{
unsigned long flags;
+ bool async_cleanup;
spin_lock_irqsave(&tls_device_lock, flags);
- if (unlikely(!refcount_dec_and_test(&ctx->refcount)))
- goto unlock;
+ if (unlikely(!refcount_dec_and_test(&ctx->refcount))) {
+ spin_unlock_irqrestore(&tls_device_lock, flags);
+ return;
+ }
- list_move_tail(&ctx->list, &tls_device_gc_list);
+ async_cleanup = ctx->netdev && ctx->tx_conf == TLS_HW;
+ if (async_cleanup) {
+ list_move_tail(&ctx->list, &tls_device_gc_list);
- /* schedule_work inside the spinlock
- * to make sure tls_device_down waits for that work.
- */
- schedule_work(&tls_device_gc_work);
-unlock:
+ /* schedule_work inside the spinlock
+ * to make sure tls_device_down waits for that work.
+ */
+ schedule_work(&tls_device_gc_work);
+ } else {
+ list_del(&ctx->list);
+ }
spin_unlock_irqrestore(&tls_device_lock, flags);
+
+ if (!async_cleanup)
+ tls_device_free_ctx(ctx);
}
/* We assume that the socket is already connected */