linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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).