linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
To: Hemant Kumar <hemantk@codeaurora.org>
Cc: Dan Carpenter <dan.carpenter@oracle.com>,
	linux-arm-msm@vger.kernel.org, kernel-janitors@vger.kernel.org
Subject: Re: [bug report] bus: mhi: core: Add support for data transfer
Date: Fri, 17 Apr 2020 15:44:28 +0530	[thread overview]
Message-ID: <20200417101428.GA10295@Mani-XPS-13-9360> (raw)
In-Reply-To: <d30c7648-b657-d8b2-ba64-71f1178b4a68@codeaurora.org>

Hi Hemant,

On Thu, Apr 16, 2020 at 08:37:16PM -0700, Hemant Kumar wrote:
> 
> On 4/7/20 7:33 AM, Manivannan Sadhasivam wrote:
> > Hi Dan,
> > 
> > On Tue, Apr 07, 2020 at 04:55:59PM +0300, Dan Carpenter wrote:
> > > Hello Manivannan Sadhasivam,
> > > 
> > > The patch 189ff97cca53: "bus: mhi: core: Add support for data
> > > transfer" from Feb 20, 2020, leads to the following static checker
> > > warning:
> > > 
> > > 	drivers/bus/mhi/core/main.c:1153 mhi_queue_buf()
> > > 	error: double locked 'mhi_chan->lock' (orig line 1110)
> > > 
> > > drivers/bus/mhi/core/main.c
> > >    1142          }
> > >    1143
> > >    1144          /* Toggle wake to exit out of M2 */
> > >    1145          mhi_cntrl->wake_toggle(mhi_cntrl);
> > >    1146
> > >    1147          if (mhi_chan->dir == DMA_TO_DEVICE)
> > >    1148                  atomic_inc(&mhi_cntrl->pending_pkts);
> > >    1149
> > >    1150          if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) {
> > >    1151                  unsigned long flags;
> > >    1152
> > >    1153                  read_lock_irqsave(&mhi_chan->lock, flags);
> 
> parse_xfer_event is taking read lock : read_lock_bh(&mhi_chan->lock); first
> and later
> 
> mhi_queue_buf takes read lock: read_lock_irqsave(&mhi_chan->lock, flags);
> 
> Both are read locks which are recursive, is this problematic ?
> 

read_locks are recursive but I wanted to make the static checker happy. But
looking into it further (and after having a chat with Arnd), we might need to
refactor the locking here.

Since 'chan->lock' only prevents 'mhi_chan->ch_state', how about doing something
like below?

diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c
index 3e9aa3b2da77..904f9be7a142 100644
--- a/drivers/bus/mhi/core/main.c
+++ b/drivers/bus/mhi/core/main.c
@@ -474,19 +474,12 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
        result.transaction_status = (ev_code == MHI_EV_CC_OVERFLOW) ?
                -EOVERFLOW : 0;
 
-       /*
-        * If it's a DB Event then we need to grab the lock
-        * with preemption disabled and as a write because we
-        * have to update db register and there are chances that
-        * another thread could be doing the same.
-        */
-       if (ev_code >= MHI_EV_CC_OOB)
-               write_lock_irqsave(&mhi_chan->lock, flags);
-       else
-               read_lock_bh(&mhi_chan->lock);
-
-       if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED)
-               goto end_process_tx_event;
+       read_lock_bh(&mhi_chan->lock);
+       if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) {
+               read_unlock_bh(&mhi_chan->lock);
+               return 0;
+       }
+       read_unlock_bh(&mhi_chan->lock);
 
        switch (ev_code) {
        case MHI_EV_CC_OVERFLOW:
@@ -559,10 +552,12 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
 
                mhi_chan->db_cfg.db_mode = 1;
                read_lock_irqsave(&mhi_cntrl->pm_lock, flags);
+               write_lock_irqsave(&mhi_chan->lock, flags);
                if (tre_ring->wp != tre_ring->rp &&
                    MHI_DB_ACCESS_VALID(mhi_cntrl)) {
                        mhi_ring_chan_db(mhi_cntrl, mhi_chan);
                }
+               write_unlock_irqrestore(&mhi_chan->lock, flags);
                read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags);
                break;
        }
@@ -572,12 +567,6 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
                break;
        } /* switch(MHI_EV_READ_CODE(EV_TRB_CODE,event)) */
 
-end_process_tx_event:
-       if (ev_code >= MHI_EV_CC_OOB)
-               write_unlock_irqrestore(&mhi_chan->lock, flags);
-       else
-               read_unlock_bh(&mhi_chan->lock);
-
        return 0;
 }

Moreover, I do have couple of concerns:

1. 'mhi_chan->db_cfg.db_mode = 1' needs to be added to the critical section
above.

2. Why we have {write/read}_lock_irq variants for chan->lock? I don't see where
the db or ch_state got shared with hardirq handler. Maybe we should only have
*_bh (softirq) variants all over the place?

Thanks,
Mani 

> > >                                            ^^^^^^^^^^^^^^^
> > > The caller is already holding this lock.
> > > 
> > Hmm. We have one internal user of this function and that's where the locking
> > has gone wrong. Will fix it.
> > 
> > Thanks for reporting!
> > 
> > Regards,
> > Mani
> > 
> > >    1154                  mhi_ring_chan_db(mhi_cntrl, mhi_chan);
> > >    1155                  read_unlock_irqrestore(&mhi_chan->lock, flags);
> > >    1156          }
> > >    1157
> > >    1158          read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags);
> > >    1159
> > >    1160          return 0;
> > >    1161  }
> > >    1162  EXPORT_SYMBOL_GPL(mhi_queue_buf);
> > > 
> > > regards,
> > > dan carpenter
> 
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project

  reply	other threads:[~2020-04-17 10:14 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-07 13:55 [bug report] bus: mhi: core: Add support for data transfer Dan Carpenter
2020-04-07 14:33 ` Manivannan Sadhasivam
2020-04-17  3:37   ` Hemant Kumar
2020-04-17 10:14     ` Manivannan Sadhasivam [this message]
2020-04-17 10:24       ` Dan Carpenter
2020-04-18  7:10       ` Hemant Kumar
2020-04-18 19:19         ` Manivannan Sadhasivam
2020-04-20 22:57           ` Hemant Kumar
2020-04-21  5:52             ` Manivannan Sadhasivam
2020-04-21  6:03 ` Manivannan Sadhasivam
2020-04-07 13:56 Dan Carpenter
2020-04-07 14:31 ` Manivannan Sadhasivam

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200417101428.GA10295@Mani-XPS-13-9360 \
    --to=manivannan.sadhasivam@linaro.org \
    --cc=dan.carpenter@oracle.com \
    --cc=hemantk@codeaurora.org \
    --cc=kernel-janitors@vger.kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).