On Thu, 2018-07-26 at 18:58 +0200, Sebastian Andrzej Siewior wrote: > On 2018-07-11 17:19:59 [+0200], Mike Galbraith wrote: > > Note: patch is the result of code inspection... > > > > cryptod disables preemption to provide request enqueue/dequeue exclusion, > > use a LOCAL_IRQ_LOCK to do the same for RT, keeping preemption enabled. > > What about this: Looks fine to me, I'll ask my arm-thing box for its opinion. > -------- >8 > > From: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> > Date: Thu, 26 Jul 2018 18:52:00 +0200 > Subject: [PATCH] crypto: cryptd - add a lock instead > preempt_disable/local_bh_disable > > cryptd has a per-CPU lock which protected with local_bh_disable() and > preempt_disable(). > Add an explicit spin_lock to make the locking context more obvious and > visible to lockdep. Since it is a per-CPU lock, there should be no lock > contention on the actual spinlock. > There is a small race-window where we could be migrated to another CPU > after the cpu_queue has been obtain. This is not a problem because the > actual ressource is protected by the spinlock. > > Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> > --- > crypto/cryptd.c | 19 +++++++++---------- > 1 file changed, 9 insertions(+), 10 deletions(-) > > diff --git a/crypto/cryptd.c b/crypto/cryptd.c > index addca7bae33f..8ad657cddc0a 100644 > --- a/crypto/cryptd.c > +++ b/crypto/cryptd.c > @@ -39,6 +39,7 @@ MODULE_PARM_DESC(cryptd_max_cpu_qlen, "Set cryptd Max queue depth"); > struct cryptd_cpu_queue { > struct crypto_queue queue; > struct work_struct work; > + spinlock_t qlock; > }; > > struct cryptd_queue { > @@ -117,6 +118,7 @@ static int cryptd_init_queue(struct cryptd_queue *queue, > cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu); > crypto_init_queue(&cpu_queue->queue, max_cpu_qlen); > INIT_WORK(&cpu_queue->work, cryptd_queue_worker); > + spin_lock_init(&cpu_queue->qlock); > } > pr_info("cryptd: max_cpu_qlen set to %d\n", max_cpu_qlen); > return 0; > @@ -141,8 +143,10 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue, > struct cryptd_cpu_queue *cpu_queue; > atomic_t *refcnt; > > - cpu = get_cpu(); > - cpu_queue = this_cpu_ptr(queue->cpu_queue); > + cpu_queue = raw_cpu_ptr(queue->cpu_queue); > + spin_lock_bh(&cpu_queue->qlock); > + cpu = smp_processor_id(); > + > err = crypto_enqueue_request(&cpu_queue->queue, request); > > refcnt = crypto_tfm_ctx(request->tfm); > @@ -158,7 +162,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue, > atomic_inc(refcnt); > > out_put_cpu: > - put_cpu(); > + spin_unlock_bh(&cpu_queue->qlock); > > return err; > } > @@ -174,16 +178,11 @@ static void cryptd_queue_worker(struct work_struct *work) > cpu_queue = container_of(work, struct cryptd_cpu_queue, work); > /* > * Only handle one request at a time to avoid hogging crypto workqueue. > - * preempt_disable/enable is used to prevent being preempted by > - * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent > - * cryptd_enqueue_request() being accessed from software interrupts. > */ > - local_bh_disable(); > - preempt_disable(); > + spin_lock_bh(&cpu_queue->qlock); > backlog = crypto_get_backlog(&cpu_queue->queue); > req = crypto_dequeue_request(&cpu_queue->queue); > - preempt_enable(); > - local_bh_enable(); > + spin_unlock_bh(&cpu_queue->qlock); > > if (!req) > return; -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html