Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3067747imu; Sun, 9 Dec 2018 16:32:15 -0800 (PST) X-Google-Smtp-Source: AFSGD/URYqCv1iIxcYOSXAaQZfwd4ncAXGyCJlBrFhZLS14Paj1+TUdsxbBv3FadaRrEadJh36JE X-Received: by 2002:a17:902:442:: with SMTP id 60mr9602903ple.73.1544401935515; Sun, 09 Dec 2018 16:32:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544401935; cv=none; d=google.com; s=arc-20160816; b=r4VlrQsWXRuI/LNNtfcyyjuovmlzJTH3jNTHYcfeSiY/38ZxfA0bNxqAG0dASc7b7k CezOgjO/OmCubHRGrJ2SezTSKTayHjdNhIjwvVU+vmGVOCPTcfHed+4pF6I+x+yhPqD2 MJmGIwD6czcYcSYzdVbRk5HUIzs4aZsF4PlC8J/UERDuI+SHLejVZY71XtCNU3QziY2U YrsCl3BD6MjWIYQebo99RjA5pAZu2HS34W1XpRWO8S/9OnTSB46shSd7XeX2NmX8or7f byooFIQlYIGIOeMlMJANTtxJkuC+mA7OIA5kNxdH5wetU0AkKS2kkCqstN9tmUZsPYL+ Yx3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=thU91shrExb1S+gbwS53HT8pesFTUgR2dueDmiOWZI0=; b=uPW3DxvG3p1Oucy3ntFDYPh++E+gHoghs+zJJZ4jaylhGKuQVOdiydz9LbOdEBfv3C YN5VdkgT6DYusmfM+vMeY07B5Sj3FJCg346UrUATU6uhlkDr5r8E1jhWfko7W/xLPLG8 /lHq1r43EzHSQ/ZS7NYLPX73pXvVnJtvXYdnUQP6hTno5bX0oRpOVApyv6BLHut1Lxiz GKGdL91+05EveP34uyrUeQ8TZB/ccncjVYGhjGqXnq9ah5TQbTYqoQ4c1zPtJXWsBue4 dezHtwNCh8JG2gHePOKsBuAtaoY95ctzCe56gVicfoPnYFVxrjYMovfO1D0Gby9IZ1go HTgw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d9si7892281pgb.105.2018.12.09.16.31.59; Sun, 09 Dec 2018 16:32:15 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728561AbeLIWP1 (ORCPT + 99 others); Sun, 9 Dec 2018 17:15:27 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:38190 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727187AbeLIWP0 (ORCPT ); Sun, 9 Dec 2018 17:15:26 -0500 Received: from pub.yeoldevic.com ([81.174.156.145] helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gW738-0002io-7C; Sun, 09 Dec 2018 21:55:42 +0000 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1gW72f-0003Ti-OE; Sun, 09 Dec 2018 21:55:13 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Roland Dreier" , "Steve Wise" Date: Sun, 09 Dec 2018 21:50:33 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) X-Patchwork-Hint: ignore Subject: [PATCH 3.16 192/328] RDMA/cxgb4: Only call CQ completion handler if it is armed In-Reply-To: X-SA-Exim-Connect-IP: 81.174.156.145 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.62-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Steve Wise commit 678ea9b5baab6800692b249bdba77c3c07261d61 upstream. The function __flush_qp() always calls the ULP's CQ completion handler functions even if the CQ was not armed. This can crash the system if the function pointer is NULL. The iSER ULP behaves this way: no completion handler and never arm the CQ for notification. So now we track whether the CQ is armed at flush time and only call the completion handlers if their CQs were armed. Also, if the RCQ and SCQ are the same CQ, the completion handler is getting called twice. It should only be called once after all SQ and RQ WRs are flushed from the QP. So rearrange the logic to fix this. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings --- drivers/infiniband/hw/cxgb4/ev.c | 1 + drivers/infiniband/hw/cxgb4/qp.c | 37 +++++++++++++++++++++----------- drivers/infiniband/hw/cxgb4/t4.h | 11 ++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) --- a/drivers/infiniband/hw/cxgb4/ev.c +++ b/drivers/infiniband/hw/cxgb4/ev.c @@ -182,6 +182,7 @@ int c4iw_ev_handler(struct c4iw_dev *dev chp = get_chp(dev, qid); if (chp) { + t4_clear_cq_armed(&chp->cq); spin_lock_irqsave(&chp->comp_handler_lock, flag); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); spin_unlock_irqrestore(&chp->comp_handler_lock, flag); --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1066,7 +1066,7 @@ static void __flush_qp(struct c4iw_qp *q struct c4iw_cq *schp) { int count; - int flushed; + int rq_flushed, sq_flushed; unsigned long flag; PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp); @@ -1084,27 +1084,40 @@ static void __flush_qp(struct c4iw_qp *q c4iw_flush_hw_cq(rchp, qhp); c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count); - flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); + rq_flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); spin_unlock(&qhp->lock); spin_unlock_irqrestore(&rchp->lock, flag); - if (flushed) { - spin_lock_irqsave(&rchp->comp_handler_lock, flag); - (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); - spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); - } /* locking hierarchy: cq lock first, then qp lock. */ spin_lock_irqsave(&schp->lock, flag); spin_lock(&qhp->lock); if (schp != rchp) c4iw_flush_hw_cq(schp, qhp); - flushed = c4iw_flush_sq(qhp); + sq_flushed = c4iw_flush_sq(qhp); spin_unlock(&qhp->lock); spin_unlock_irqrestore(&schp->lock, flag); - if (flushed) { - spin_lock_irqsave(&schp->comp_handler_lock, flag); - (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); - spin_unlock_irqrestore(&schp->comp_handler_lock, flag); + + if (schp == rchp) { + if (t4_clear_cq_armed(&rchp->cq) && + (rq_flushed || sq_flushed)) { + spin_lock_irqsave(&rchp->comp_handler_lock, flag); + (*rchp->ibcq.comp_handler)(&rchp->ibcq, + rchp->ibcq.cq_context); + spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); + } + } else { + if (t4_clear_cq_armed(&rchp->cq) && rq_flushed) { + spin_lock_irqsave(&rchp->comp_handler_lock, flag); + (*rchp->ibcq.comp_handler)(&rchp->ibcq, + rchp->ibcq.cq_context); + spin_unlock_irqrestore(&rchp->comp_handler_lock, flag); + } + if (t4_clear_cq_armed(&schp->cq) && sq_flushed) { + spin_lock_irqsave(&schp->comp_handler_lock, flag); + (*schp->ibcq.comp_handler)(&schp->ibcq, + schp->ibcq.cq_context); + spin_unlock_irqrestore(&schp->comp_handler_lock, flag); + } } } --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -531,6 +531,10 @@ static inline int t4_wq_db_enabled(struc return !wq->rq.queue[wq->rq.size].status.db_off; } +enum t4_cq_flags { + CQ_ARMED = 1, +}; + struct t4_cq { struct t4_cqe *queue; dma_addr_t dma_addr; @@ -551,12 +555,19 @@ struct t4_cq { u16 cidx_inc; u8 gen; u8 error; + unsigned long flags; }; +static inline int t4_clear_cq_armed(struct t4_cq *cq) +{ + return test_and_clear_bit(CQ_ARMED, &cq->flags); +} + static inline int t4_arm_cq(struct t4_cq *cq, int se) { u32 val; + set_bit(CQ_ARMED, &cq->flags); while (cq->cidx_inc > CIDXINC_MASK) { val = SEINTARM(0) | CIDXINC(CIDXINC_MASK) | TIMERREG(7) | INGRESSQID(cq->cqid);