From: Sujit Reddy Thumma <sthumma@codeaurora.org>
To: Seungwon Jeon <tgih.jun@samsung.com>
Cc: 'Vinayak Holikatti' <vinholikatti@gmail.com>,
'Santosh Y' <santoshsy@gmail.com>,
"'James E.J. Bottomley'" <JBottomley@parallels.com>,
linux-scsi@vger.kernel.org, linux-arm-msm@vger.kernel.org,
'Dolev Raviv' <draviv@codeaurora.org>
Subject: Re: [PATCH V3 1/2] scsi: ufs: Add support for sending NOP OUT UPIU
Date: Fri, 19 Jul 2013 23:56:27 +0530 [thread overview]
Message-ID: <51E984D3.80502@codeaurora.org> (raw)
In-Reply-To: <001c01ce8486$9357c510$ba074f30$%jun@samsung.com>
On 7/19/2013 7:17 PM, Seungwon Jeon wrote:
> On Thu, July 18, 2013, Sujit Reddy Thumma wrote:
>>>>>> + * ufshcd_wait_for_register - wait for register value to change
>>>>>> + * @hba - per-adapter interface
>>>>>> + * @reg - mmio register offset
>>>>>> + * @mask - mask to apply to read register value
>>>>>> + * @val - wait condition
>>>>>> + * @interval_us - polling interval in microsecs
>>>>>> + * @timeout_ms - timeout in millisecs
>>>>>> + *
>>>>>> + * Returns final register value after iteration
>>>>>> + */
>>>>>> +static u32 ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
>>>>>> + u32 val, unsigned long interval_us, unsigned long timeout_ms)
>>>>> I feel like this function's role is to wait for clearing register (specially, doorbells).
>>>>> If you really don't intend to apply other all register, I think it would better to change the
>>>> function name.
>>>>> ex> ufshcd_wait_for_clear_doorbell or ufshcd_wait_for_clear_reg?
>>>>
>>>> Although, this API is introduced in this patch and used only for
>>>> clearing the doorbell, I have intentionally made it generic to avoid
>>>> duplication of wait condition code in future (not just clearing but
>>>> also for setting a bit). For example, when we write to HCE.ENABLE we
>>>> wait for it turn to 1.
>>>>
>>>>
>>>>> And if you like it, it could be more simple like below
>>>>>
>>>>> static bool ufshcd_wait_for_clear_reg(struct ufs_hba *hba, u32 reg, u32 mask,
>>>>> unsigned long interval_us,
>>>>> unsigned int timeout_ms)
>>>>> {
>>>>> unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
>>>>
>>>> Jiffies on 100Hz systems have minimum granularity of 10ms. So we really
>>>> wait for more 10ms even though the timeout_ms < 10ms.
>>> Yes. Real timeout depends on system.
>>> But normally actual wait will be maintained until 'ufshcd_readl' is done.
>>> Timeout is valid for failure case. If we don't need to apply a strict timeout value, it's not bad.
>>
>> Hmm.. make sense. Will take care in the next patchset.
>>
>>>
>>>>
>>>>> /* wakeup within 50us of expiry */
>>>>> const unsigned int expiry = 50;
>>>>>
>>>>> while (ufshcd_readl(hba, reg) & mask) {
>>>>> usleep_range(interval_us, interval_us + expiry);
>>>>> if (time_after(jiffies, timeout)) {
>>>>> if (ufshcd_readl(hba, reg) & mask)
>>>>> return false;
>>>>
>>>> I really want the caller to decide on what to do after the timeout.
>>>> This helps in error handling cases where we try to clear off the entire
>>>> door-bell register but only a few of the bits are cleared after timeout.
>>> I don't know what we can do with the report of the partial success on clearing bit.
>>> It's just failure case. Isn't enough with false/true?
>>
>> The point is, if a bit can't be cleared it can be regarded as a
>> permanent failure (only for that request), otherwise, it can be
>> retried with the same tag value.
>>
>>>
>>>>
>>>>> else
>>>>> return true;
>>>>> }
>>>>> }
>>>>>
>>>>> return true;
>>>>> }
>>>>>> +{
>>>>>> + u32 tmp;
>>>>>> + ktime_t start;
>>>>>> + unsigned long diff;
>>>>>> +
>>>>>> + tmp = ufshcd_readl(hba, reg);
>>>>>> +
>>>>>> + if ((val & mask) != val) {
>>>>>> + dev_err(hba->dev, "%s: Invalid wait condition 0x%x\n",
>>>>>> + __func__, val);
>>>>>> + goto out;
>>>>>> + }
>>>>>> +
>>>>>> + start = ktime_get();
>>>>>> + while ((tmp & mask) != val) {
>>>>>> + /* wakeup within 50us of expiry */
>>>>>> + usleep_range(interval_us, interval_us + 50);
>>>>>> + tmp = ufshcd_readl(hba, reg);
>>>>>> + diff = ktime_to_ms(ktime_sub(ktime_get(), start));
>>>>>> + if (diff > timeout_ms) {
>>>>>> + tmp = ufshcd_readl(hba, reg);
>>>>>> + break;
>>>>>> + }
>>>>>> + }
>>>>>> +out:
>>>>>> + return tmp;
>>>>>> +}
>>>>>> +
>> ..
>>>>>> +static int
>>>>>> +ufshcd_clear_cmd(struct ufs_hba *hba, int tag)
>>>>>> +{
>>>>>> + int err = 0;
>>>>>> + unsigned long flags;
>>>>>> + u32 reg;
>>>>>> + u32 mask = 1 << tag;
>>>>>> +
>>>>>> + /* clear outstanding transaction before retry */
>>>>>> + spin_lock_irqsave(hba->host->host_lock, flags);
>>>>>> + ufshcd_utrl_clear(hba, tag);
>>>>>> + spin_unlock_irqrestore(hba->host->host_lock, flags);
>>>>>> +
>>>>>> + /*
>>>>>> + * wait for for h/w to clear corresponding bit in door-bell.
>>>>>> + * max. wait is 1 sec.
>>>>>> + */
>>>>>> + reg = ufshcd_wait_for_register(hba,
>>>>>> + REG_UTP_TRANSFER_REQ_DOOR_BELL,
>>>>>> + mask, 0, 1000, 1000);
>>>>> 4th argument should be (~mask) instead of '0', right?
>>>>
>>>> True, but not really for this implementation. It breaks the check in
>>>> in wait_for_register -
>>>> if ((val & mask) != val)
>>>> dev_err(...);
>>> Hmm, it seems complicated to use.
>>> Ok. Is right the following about val as 4th argument?
>>> - clear: val should be '0' regardless corresponding bit.
>>> - set: val should be same with mask.
>>> If the related comment is added, it will be helpful.
>>
>> Thinking again it looks like it is complicated. How about changing
>> the check to -
>>
>> val = val & mask; /* ignore the bits we don't intend to wait on */
>> while (ufshcd_readl() & mask != val) {
>> sleep
>> }
>>
>> Usage will be ~mask for clearing the bits, mask for setting the bits
>> in the fourth argument.
> Ok.
> It's better for the caller.
>
>>
>>>
>>>>
>>>>> Actually, mask value involves the corresponding bit to be cleared.
>>>>> So, 4th argument may be unnecessary.
>>>>
>>>> As I described above, the wait_for_register can also be used to
>>>> check if the value is set or not. In which case, we need 4th argument.
>>>>
>>>>>
>>>>>> + if ((reg & mask) == mask)
>>>>>> + err = -ETIMEDOUT;
>>>>> Also, checking the result can be involved in ufshcd_wait_for_register.
>>> Any comment?
>>
>> Sorry I missed this. But the point was the same. To make
>> wait_for_register() just to wait a definite time and not return any
>> error condition when the bits don't turn as expected.
> Comparing reg with mask can be done in 'ufshcd_wait_for_register' commonly.
> Currently the caller do the same.
Hmm.. you don't seem to agree to my point earlier mentioned
">>>> I really want the caller to decide on what to do after the timeout.
>>>> This helps in error handling cases where we try to clear off the
entire
>>>> door-bell register but only a few of the bits are cleared after
timeout.
>>> I don't know what we can do with the report of the partial success
on clearing bit.
>>> It's just failure case. Isn't enough with false/true?
>>
>> The point is, if a bit can't be cleared it can be regarded as a
>> permanent failure (only for that request), otherwise, it can be
>> retried with the same tag value."
Since there is no real use case as of now. I will move the error check
to the wait_for_register.
--
Regards,
Sujit
next prev parent reply other threads:[~2013-07-19 18:26 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-09 9:15 [PATCH V3 0/2] Add suport for internal request (NOP and Query Request) Sujit Reddy Thumma
2013-07-09 9:15 ` [PATCH V3 1/2] scsi: ufs: Add support for sending NOP OUT UPIU Sujit Reddy Thumma
2013-07-09 10:40 ` merez
2013-07-10 13:28 ` Seungwon Jeon
2013-07-11 9:38 ` Sujit Reddy Thumma
2013-07-17 8:13 ` Seungwon Jeon
2013-07-18 3:48 ` Sujit Reddy Thumma
2013-07-19 13:47 ` Seungwon Jeon
2013-07-19 18:26 ` Sujit Reddy Thumma [this message]
2013-07-09 9:15 ` [PATCH V3 2/2] scsi: ufs: Set fDeviceInit flag to initiate device initialization Sujit Reddy Thumma
2013-07-09 10:40 ` merez
2013-07-10 13:29 ` Seungwon Jeon
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=51E984D3.80502@codeaurora.org \
--to=sthumma@codeaurora.org \
--cc=JBottomley@parallels.com \
--cc=draviv@codeaurora.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=santoshsy@gmail.com \
--cc=tgih.jun@samsung.com \
--cc=vinholikatti@gmail.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 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).