All of lore.kernel.org
 help / color / mirror / Atom feed
From: Javi Merino <javi.merino@arm.com>
To: Jassi Brar <jaswinder.singh@linaro.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>,
	Boojin Kim <boojin.kim@samsung.com>,
	"vinod.koul@intel.com" <vinod.koul@intel.com>,
	"jassisinghbrar@gmail.com" <jassisinghbrar@gmail.com>,
	linux-samsung-soc <linux-samsung-soc@vger.kernel.org>,
	Thomas Abraham <thomas.abraham@linaro.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v2] ARM: pl330: Fix a race condition
Date: Fri, 9 Dec 2011 13:41:05 +0000	[thread overview]
Message-ID: <4EE20FF1.5070702@arm.com> (raw)
In-Reply-To: <CAJe_Zhcj_j+r+T5N_BdS-ENds1SmJs7-Pfyf8vrFkB75BGBaYg@mail.gmail.com>

On 09/12/11 13:04, Jassi Brar wrote:
> Hi Javi,
>
> On 9 December 2011 17:28, Javi Merino <javi.merino@arm.com> wrote:
>>
>>>>>> Javi, could you please check if you too get the memcpy failure with
>>>>>> dmatest ?
>>>>>
>>> Ok, I think I've just reproduced it in my end with the kernel's dmatest
>>> module.  After the first transaction it looks like the dma test wasn't
>>> able to issue any more transactions.
>>>
>> If you submit a transaction, it finishes and there's nothing else to run,
>> pl330_update() calls _start() but there is nothing to send.  This is all
>> right.  Then, if another transaction is submitted, pl330_submit_req() will
>> put it in buffer 0 again.  This time, the PC of the DMA is in the last
>> instruction of buffer 0 (the DMAEND of the *previous* transaction that
>> finished long ago) so _thrd_active() thinks that this buffer is active,
>>
> Many thanks for the in-depth analysis.
>
> Though before the PC check, the IS_FREE() should return true since
> pl330_update() does MARK_FREE()
>
> Could you please check if the client's callback function called
> successfully for the
> first submitted transfer ?

Yes, it calls MARK_FREE() and indeed in pl330_update(), _thrd_active()
returns 0.  The problem comes when, afterwards, pl330_submit_req()
introduces a new request and chooses the same buffer. Then, IS_FREE()
returns false (obviously) but the PC of the DMA is at the end of the
buffer, so _thrd_active() claims that it is active so pl330_chan_ctrl()
doesn't start it.

> Then we can decide upon one of the following 2 options (I *think*
> either should fix the issue)
>
> diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
> index 97912fa..f550d46 100644
> --- a/arch/arm/common/pl330.c
> +++ b/arch/arm/common/pl330.c
> @@ -846,7 +846,7 @@ static inline bool _req_active(struct pl330_thread *thrd,
>       if (IS_FREE(req))
>               return false;
>
> -     return (pc >= buf && pc <= buf + req->mc_len) ? true : false;
> +     return (pc >= buf && pc < buf + req->mc_len) ? true : false;
>  }

This reintroduces the race condition.  The DMA thread finishes and sends
the IRQ just after pl330_chan_ctrl() disables interrupts.  With this
patch, _thrd_active() returns false and _start() reissues the
just-finished transaction.

> diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
> index 97912fa..ad85a75 100644
> --- a/arch/arm/common/pl330.c
> +++ b/arch/arm/common/pl330.c
> @@ -233,7 +233,7 @@
>                       } while (0)
>
>  /* If the _pl330_req is available to the client */
> -#define IS_FREE(req) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
> +#define IS_FREE(req) ((req)->mc_len == 0)

No, this doesn't fix it.  pl330_submit_req() introduces a valid request,
IS_FREE() returns false as it should.  The problem is that the DMA pc is
pointing at buf + req->mc_len .

>> The problem is that pl330_submit_req() always puts the request in buffer 0 if
>> > both buffers are free.
>> >
> There should be nothing wrong in that.
> It is but natural to prefer 0 if both 0 and 1 are available.

On second thoughts, with the solution I proposed in the previous email
the DMA will freeze if you call pl330_submit_req() twice before calling
pl330_chan_ctrl().  Can that happen?  I'd assume that each call to
pl330_submit_req() is always followed by a pl330_chan_ctrl(PL330_OP_START)

Another way of solving this would be to revert
ee3f615819404a9438b2dd01b7a39f276d2737f2 and go back to my original
patch (in the beginning of this thread):

http://article.gmane.org/gmane.linux.ports.arm.kernel/133110

Cheers,
Javi

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

WARNING: multiple messages have this Message-ID (diff)
From: javi.merino@arm.com (Javi Merino)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2] ARM: pl330: Fix a race condition
Date: Fri, 9 Dec 2011 13:41:05 +0000	[thread overview]
Message-ID: <4EE20FF1.5070702@arm.com> (raw)
In-Reply-To: <CAJe_Zhcj_j+r+T5N_BdS-ENds1SmJs7-Pfyf8vrFkB75BGBaYg@mail.gmail.com>

On 09/12/11 13:04, Jassi Brar wrote:
> Hi Javi,
>
> On 9 December 2011 17:28, Javi Merino <javi.merino@arm.com> wrote:
>>
>>>>>> Javi, could you please check if you too get the memcpy failure with
>>>>>> dmatest ?
>>>>>
>>> Ok, I think I've just reproduced it in my end with the kernel's dmatest
>>> module.  After the first transaction it looks like the dma test wasn't
>>> able to issue any more transactions.
>>>
>> If you submit a transaction, it finishes and there's nothing else to run,
>> pl330_update() calls _start() but there is nothing to send.  This is all
>> right.  Then, if another transaction is submitted, pl330_submit_req() will
>> put it in buffer 0 again.  This time, the PC of the DMA is in the last
>> instruction of buffer 0 (the DMAEND of the *previous* transaction that
>> finished long ago) so _thrd_active() thinks that this buffer is active,
>>
> Many thanks for the in-depth analysis.
>
> Though before the PC check, the IS_FREE() should return true since
> pl330_update() does MARK_FREE()
>
> Could you please check if the client's callback function called
> successfully for the
> first submitted transfer ?

Yes, it calls MARK_FREE() and indeed in pl330_update(), _thrd_active()
returns 0.  The problem comes when, afterwards, pl330_submit_req()
introduces a new request and chooses the same buffer. Then, IS_FREE()
returns false (obviously) but the PC of the DMA is at the end of the
buffer, so _thrd_active() claims that it is active so pl330_chan_ctrl()
doesn't start it.

> Then we can decide upon one of the following 2 options (I *think*
> either should fix the issue)
>
> diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
> index 97912fa..f550d46 100644
> --- a/arch/arm/common/pl330.c
> +++ b/arch/arm/common/pl330.c
> @@ -846,7 +846,7 @@ static inline bool _req_active(struct pl330_thread *thrd,
>       if (IS_FREE(req))
>               return false;
>
> -     return (pc >= buf && pc <= buf + req->mc_len) ? true : false;
> +     return (pc >= buf && pc < buf + req->mc_len) ? true : false;
>  }

This reintroduces the race condition.  The DMA thread finishes and sends
the IRQ just after pl330_chan_ctrl() disables interrupts.  With this
patch, _thrd_active() returns false and _start() reissues the
just-finished transaction.

> diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
> index 97912fa..ad85a75 100644
> --- a/arch/arm/common/pl330.c
> +++ b/arch/arm/common/pl330.c
> @@ -233,7 +233,7 @@
>                       } while (0)
>
>  /* If the _pl330_req is available to the client */
> -#define IS_FREE(req) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
> +#define IS_FREE(req) ((req)->mc_len == 0)

No, this doesn't fix it.  pl330_submit_req() introduces a valid request,
IS_FREE() returns false as it should.  The problem is that the DMA pc is
pointing at buf + req->mc_len .

>> The problem is that pl330_submit_req() always puts the request in buffer 0 if
>> > both buffers are free.
>> >
> There should be nothing wrong in that.
> It is but natural to prefer 0 if both 0 and 1 are available.

On second thoughts, with the solution I proposed in the previous email
the DMA will freeze if you call pl330_submit_req() twice before calling
pl330_chan_ctrl().  Can that happen?  I'd assume that each call to
pl330_submit_req() is always followed by a pl330_chan_ctrl(PL330_OP_START)

Another way of solving this would be to revert
ee3f615819404a9438b2dd01b7a39f276d2737f2 and go back to my original
patch (in the beginning of this thread):

http://article.gmane.org/gmane.linux.ports.arm.kernel/133110

Cheers,
Javi

-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

  reply	other threads:[~2011-12-09 13:41 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-19 17:11 [PATCH] ARM: pl330: Fix a race condition Javi Merino
2011-09-19 18:07 ` Jassi Brar
2011-09-20 13:36   ` Javi Merino
2011-10-05 12:57     ` Javi Merino
2011-10-06  9:10       ` [PATCH v2] " Javi Merino
2011-11-05 19:05         ` Thomas Abraham
2011-11-05 19:05           ` Thomas Abraham
2011-11-07 10:48           ` Javi Merino
2011-11-07 10:48             ` Javi Merino
2011-11-07 11:03             ` Thomas Abraham
2011-11-07 11:03               ` Thomas Abraham
2011-11-28  8:23             ` Boojin Kim
2011-11-28  8:23               ` Boojin Kim
2011-11-28 16:36               ` Javi Merino
2011-11-28 16:36                 ` Javi Merino
2011-11-29  3:41                 ` Boojin Kim
2011-11-29  3:41                   ` Boojin Kim
2011-11-29  9:53                   ` Javi Merino
2011-11-29  9:53                     ` Javi Merino
2011-11-29 10:37                     ` Jassi Brar
2011-11-29 10:37                       ` Jassi Brar
2011-12-07  7:52                       ` Kukjin Kim
2011-12-07  7:52                         ` Kukjin Kim
2011-12-07 10:01                         ` Javi Merino
2011-12-07 10:01                           ` Javi Merino
2011-12-07 20:54                           ` Javi Merino
2011-12-07 20:54                             ` Javi Merino
2011-12-09 11:58                             ` Javi Merino
2011-12-09 11:58                               ` Javi Merino
2011-12-09 13:04                               ` Jassi Brar
2011-12-09 13:04                                 ` Jassi Brar
2011-12-09 13:41                                 ` Javi Merino [this message]
2011-12-09 13:41                                   ` Javi Merino
2011-12-09 14:15                                   ` Jassi Brar
2011-12-09 14:15                                     ` Jassi Brar
2011-12-09 14:52                                     ` Javi Merino
2011-12-09 14:52                                       ` Javi Merino
2011-12-09 16:50                                       ` Jassi Brar
2011-12-09 16:50                                         ` Jassi Brar
2011-12-09 19:50                                         ` Javi Merino
2011-12-09 19:50                                           ` Javi Merino
2011-12-11 10:51                                           ` Jassi Brar
2011-12-11 10:51                                             ` Jassi Brar
2011-12-11 15:09                                             ` Javi Merino
2011-12-11 15:09                                               ` Javi Merino
2011-12-11 17:10                                               ` Jassi Brar
2011-12-11 17:10                                                 ` Jassi Brar
2011-12-11 17:42                                                 ` Javi Merino
2011-12-11 17:42                                                   ` Javi Merino
2011-12-11 19:27                                                   ` [PATCH] ARM: PL330: Fix driver freeze Javi Merino
2011-12-11 19:27                                                     ` Javi Merino
2011-12-15 17:48                                                     ` Javi Merino
2011-12-15 17:48                                                       ` Javi Merino
2011-12-16  9:01                                                       ` Tushar Behera
2011-12-16  9:01                                                         ` Tushar Behera
2011-12-16  6:27                                                     ` Jassi Brar
2011-12-16  6:27                                                       ` Jassi Brar

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=4EE20FF1.5070702@arm.com \
    --to=javi.merino@arm.com \
    --cc=boojin.kim@samsung.com \
    --cc=jassisinghbrar@gmail.com \
    --cc=jaswinder.singh@linaro.org \
    --cc=kgene.kim@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=thomas.abraham@linaro.org \
    --cc=vinod.koul@intel.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.