lkml.org 
[lkml]   [2018]   [Oct]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 111/113] crypto: mxs-dcp - Fix wait logic on chan threads
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Leonard Crestez <leonard.crestez@nxp.com>

    commit d80771c08363ad7fbf0f56f5301e7ca65065c582 upstream.

    When compiling with CONFIG_DEBUG_ATOMIC_SLEEP=y the mxs-dcp driver
    prints warnings such as:

    WARNING: CPU: 0 PID: 120 at kernel/sched/core.c:7736 __might_sleep+0x98/0x9c
    do not call blocking ops when !TASK_RUNNING; state=1 set at [<8081978c>] dcp_chan_thread_sha+0x3c/0x2ec

    The problem is that blocking ops will manipulate current->state
    themselves so it is not allowed to call them between
    set_current_state(TASK_INTERRUPTIBLE) and schedule().

    Fix this by converting the per-chan mutex to a spinlock (it only
    protects tiny list ops anyway) and rearranging the wait logic so that
    callbacks are called current->state as TASK_RUNNING. Those callbacks
    will indeed call blocking ops themselves so this is required.

    Cc: <stable@vger.kernel.org>
    Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
    Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/crypto/mxs-dcp.c | 53 ++++++++++++++++++++++++++---------------------
    1 file changed, 30 insertions(+), 23 deletions(-)

    --- a/drivers/crypto/mxs-dcp.c
    +++ b/drivers/crypto/mxs-dcp.c
    @@ -63,7 +63,7 @@ struct dcp {
    struct dcp_coherent_block *coh;

    struct completion completion[DCP_MAX_CHANS];
    - struct mutex mutex[DCP_MAX_CHANS];
    + spinlock_t lock[DCP_MAX_CHANS];
    struct task_struct *thread[DCP_MAX_CHANS];
    struct crypto_queue queue[DCP_MAX_CHANS];
    };
    @@ -349,13 +349,20 @@ static int dcp_chan_thread_aes(void *dat

    int ret;

    - do {
    - __set_current_state(TASK_INTERRUPTIBLE);
    + while (!kthread_should_stop()) {
    + set_current_state(TASK_INTERRUPTIBLE);

    - mutex_lock(&sdcp->mutex[chan]);
    + spin_lock(&sdcp->lock[chan]);
    backlog = crypto_get_backlog(&sdcp->queue[chan]);
    arq = crypto_dequeue_request(&sdcp->queue[chan]);
    - mutex_unlock(&sdcp->mutex[chan]);
    + spin_unlock(&sdcp->lock[chan]);
    +
    + if (!backlog && !arq) {
    + schedule();
    + continue;
    + }
    +
    + set_current_state(TASK_RUNNING);

    if (backlog)
    backlog->complete(backlog, -EINPROGRESS);
    @@ -363,11 +370,8 @@ static int dcp_chan_thread_aes(void *dat
    if (arq) {
    ret = mxs_dcp_aes_block_crypt(arq);
    arq->complete(arq, ret);
    - continue;
    }
    -
    - schedule();
    - } while (!kthread_should_stop());
    + }

    return 0;
    }
    @@ -407,9 +411,9 @@ static int mxs_dcp_aes_enqueue(struct ab
    rctx->ecb = ecb;
    actx->chan = DCP_CHAN_CRYPTO;

    - mutex_lock(&sdcp->mutex[actx->chan]);
    + spin_lock(&sdcp->lock[actx->chan]);
    ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
    - mutex_unlock(&sdcp->mutex[actx->chan]);
    + spin_unlock(&sdcp->lock[actx->chan]);

    wake_up_process(sdcp->thread[actx->chan]);

    @@ -645,13 +649,20 @@ static int dcp_chan_thread_sha(void *dat
    struct ahash_request *req;
    int ret, fini;

    - do {
    - __set_current_state(TASK_INTERRUPTIBLE);
    + while (!kthread_should_stop()) {
    + set_current_state(TASK_INTERRUPTIBLE);

    - mutex_lock(&sdcp->mutex[chan]);
    + spin_lock(&sdcp->lock[chan]);
    backlog = crypto_get_backlog(&sdcp->queue[chan]);
    arq = crypto_dequeue_request(&sdcp->queue[chan]);
    - mutex_unlock(&sdcp->mutex[chan]);
    + spin_unlock(&sdcp->lock[chan]);
    +
    + if (!backlog && !arq) {
    + schedule();
    + continue;
    + }
    +
    + set_current_state(TASK_RUNNING);

    if (backlog)
    backlog->complete(backlog, -EINPROGRESS);
    @@ -663,12 +674,8 @@ static int dcp_chan_thread_sha(void *dat
    ret = dcp_sha_req_to_buf(arq);
    fini = rctx->fini;
    arq->complete(arq, ret);
    - if (!fini)
    - continue;
    }
    -
    - schedule();
    - } while (!kthread_should_stop());
    + }

    return 0;
    }
    @@ -726,9 +733,9 @@ static int dcp_sha_update_fx(struct ahas
    rctx->init = 1;
    }

    - mutex_lock(&sdcp->mutex[actx->chan]);
    + spin_lock(&sdcp->lock[actx->chan]);
    ret = crypto_enqueue_request(&sdcp->queue[actx->chan], &req->base);
    - mutex_unlock(&sdcp->mutex[actx->chan]);
    + spin_unlock(&sdcp->lock[actx->chan]);

    wake_up_process(sdcp->thread[actx->chan]);
    mutex_unlock(&actx->mutex);
    @@ -984,7 +991,7 @@ static int mxs_dcp_probe(struct platform
    platform_set_drvdata(pdev, sdcp);

    for (i = 0; i < DCP_MAX_CHANS; i++) {
    - mutex_init(&sdcp->mutex[i]);
    + spin_lock_init(&sdcp->lock[i]);
    init_completion(&sdcp->completion[i]);
    crypto_init_queue(&sdcp->queue[i], 50);
    }

    \
     
     \ /
      Last update: 2018-10-08 21:14    [W:4.027 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site