Re: [PATCH] perf auxtrace: Fix potential null pointer dereference

2021-04-20 Thread Adrian Hunter
On 20/04/21 6:15 pm, Leo Yan wrote:
> In the function auxtrace_parse_snapshot_options(), the callback pointer
> "itr->parse_snapshot_options" can be NULL if it has not been set during
> the AUX record initialization.  This can cause tool crashing if the
> callback pointer "itr->parse_snapshot_options" is dereferenced without
> performing NULL check.
> 
> Add a NULL check for the pointer "itr->parse_snapshot_options" before
> invoke the callback.
> 
> Fixes: d20031bb63dd ("perf tools: Add AUX area tracing Snapshot Mode")
> Signed-off-by: Leo Yan 

Acked-by: Adrian Hunter 

> ---
>  tools/perf/util/auxtrace.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
> index 953f4afacd3b..320b47f133d3 100644
> --- a/tools/perf/util/auxtrace.c
> +++ b/tools/perf/util/auxtrace.c
> @@ -638,7 +638,7 @@ int auxtrace_parse_snapshot_options(struct 
> auxtrace_record *itr,
>   break;
>   }
>  
> - if (itr)
> + if (itr && itr->parse_snapshot_options)
>   return itr->parse_snapshot_options(itr, opts, str);
>  
>   pr_err("No AUX area tracing to snapshot\n");
> 



Re: [PATCH v4 1/2] mmc: block: Issue flush only if allowed

2021-04-20 Thread Adrian Hunter
On 20/04/21 4:46 pm, Avri Altman wrote:
> The cache may be flushed to the nonvolatile storage by writing to
> FLUSH_CACHE byte (EXT_CSD byte [32]). When in command queueing mode, the
> cache may be flushed by issuing a CMDQ_TASK_ DEV_MGMT (CMD48) with a
> FLUSH_CACHE op-code.  Either way, verify that The cache function is
> turned ON before doing so.
> 
> fixes: 1e8e55b67030 (mmc: block: Add CQE support)
> 
> Reported-by: Brendan Peter 
> Tested-by: Brendan Peter 
> Signed-off-by: Avri Altman 

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/core/block.c   | 9 +
>  drivers/mmc/core/mmc.c | 2 +-
>  drivers/mmc/core/mmc_ops.h | 5 +
>  3 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 8bfd4d95b386..24e1ecbdd510 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -2186,6 +2186,11 @@ static int mmc_blk_wait_for_idle(struct mmc_queue *mq, 
> struct mmc_host *host)
>   return mmc_blk_rw_wait(mq, NULL);
>  }
>  
> +static bool mmc_blk_cache_disabled(struct mmc_card *card)
> +{
> + return mmc_card_mmc(card) && !mmc_flush_allowed(card);
> +}
> +
>  enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request 
> *req)
>  {
>   struct mmc_blk_data *md = mq->blkdata;
> @@ -2225,6 +2230,10 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue 
> *mq, struct request *req)
>   case MMC_ISSUE_ASYNC:
>   switch (req_op(req)) {
>   case REQ_OP_FLUSH:
> + if (mmc_blk_cache_disabled(mq->card)) {
> + blk_mq_end_request(req, BLK_STS_OK);
> + return MMC_REQ_FINISHED;
> + }
>   ret = mmc_blk_cqe_issue_flush(mq, req);
>   break;
>   case REQ_OP_READ:
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 9ad4aa537867..e3da62ffcb5e 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -2037,7 +2037,7 @@ static int _mmc_flush_cache(struct mmc_card *card)
>  {
>   int err = 0;
>  
> - if (card->ext_csd.cache_size > 0 && card->ext_csd.cache_ctrl & 1) {
> + if (mmc_flush_allowed(card)) {
>   err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>EXT_CSD_FLUSH_CACHE, 1,
>CACHE_FLUSH_TIMEOUT_MS);
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 5782fdf4e8e9..2682bf66708a 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -19,6 +19,11 @@ enum mmc_busy_cmd {
>  struct mmc_host;
>  struct mmc_card;
>  
> +static inline bool mmc_flush_allowed(struct mmc_card *card)
> +{
> + return card->ext_csd.cache_size > 0 && card->ext_csd.cache_ctrl & 1;
> +}
> +
>  int mmc_select_card(struct mmc_card *card);
>  int mmc_deselect_cards(struct mmc_host *host);
>  int mmc_set_dsr(struct mmc_host *host);
> 



Re: [PATCH v3 2/2] mmc: block: Update ext_csd.cache_ctrl if it was written

2021-04-20 Thread Adrian Hunter
On 20/04/21 8:53 am, Avri Altman wrote:
> The cache function can be turned ON and OFF by writing to the CACHE_CTRL
> byte (EXT_CSD byte [33]).  However,  card->ext_csd.cache_ctrl is only
> set on init if cache size > 0.
> 
> Fix that by explicitly setting ext_csd.cache_ctrl on ext-csd write.
> 
> Signed-off-by: Avri Altman 

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/core/block.c | 12 
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 5b6501fc9fb7..8b07ed5e08de 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -572,6 +572,18 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
> struct mmc_blk_data *md,
>   main_md->part_curr = value & EXT_CSD_PART_CONFIG_ACC_MASK;
>   }
>  
> + /*
> +  * Make sure to update CACHE_CTRL in case it was changed. The cache
> +  * will get turned back on if the card is re-initialized, e.g.
> +  * suspend/resume or hw reset in recovery.
> +  */
> + if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) &&
> + (cmd.opcode == MMC_SWITCH)) {
> + u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1;
> +
> + card->ext_csd.cache_ctrl = value;
> + }
> +
>   /*
>* According to the SD specs, some commands require a delay after
>* issuing the command.
> 



Re: [PATCH v3 1/2] mmc: block: Issue flush only if allowed

2021-04-20 Thread Adrian Hunter
On 20/04/21 8:53 am, Avri Altman wrote:
> The cache may be flushed to the nonvolatile storage by writing to
> FLUSH_CACHE byte (EXT_CSD byte [32]). When in command queueing mode, the
> cache may be flushed by issuing a CMDQ_TASK_ DEV_MGMT (CMD48) with a
> FLUSH_CACHE op-code.  Either way, verify that The cache function is
> turned ON before doing so.
> 
> fixes: 1e8e55b67030 (mmc: block: Add CQE support)
> 
> Reported-by: Brendan Peter 
> Tested-by: Brendan Peter 
> Signed-off-by: Avri Altman 
> ---
>  drivers/mmc/core/block.c   | 7 +++
>  drivers/mmc/core/mmc.c | 2 +-
>  drivers/mmc/core/mmc_ops.h | 5 +
>  3 files changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 8bfd4d95b386..5b6501fc9fb7 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -1476,6 +1476,11 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue 
> *mq, struct request *req)
>   struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
>   struct mmc_request *mrq = mmc_blk_cqe_prep_dcmd(mqrq, req);
>  
> + if (mmc_card_mmc(mq->card) && !mmc_flush_allowed(mq->card)) {
> + blk_mq_end_request(req, BLK_STS_OK);
> + return -EPERM;
> + }
> +
>   mrq->cmd->opcode = MMC_SWITCH;
>   mrq->cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
>   (EXT_CSD_FLUSH_CACHE << 16) |
> @@ -2226,6 +2231,8 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue 
> *mq, struct request *req)
>   switch (req_op(req)) {
>   case REQ_OP_FLUSH:
>   ret = mmc_blk_cqe_issue_flush(mq, req);
> + if (ret == -EPERM)
> + return MMC_REQ_FINISHED;

Using an error code for this case seems a little fragile.

How about something like:

case REQ_OP_FLUSH:
if (mmc_blk_cache_disabled(mq->card)) {
blk_mq_end_request(req, BLK_STS_OK);
return MMC_REQ_FINISHED;
}
ret = mmc_blk_cqe_issue_flush(mq, req);


static bool mmc_blk_cache_disabled(struct mmc_card *card)
{
return mmc_card_mmc(mq->card) && !mmc_flush_allowed(card);
}

>   break;
>   case REQ_OP_READ:
>   case REQ_OP_WRITE:
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 9ad4aa537867..e3da62ffcb5e 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -2037,7 +2037,7 @@ static int _mmc_flush_cache(struct mmc_card *card)
>  {
>   int err = 0;
>  
> - if (card->ext_csd.cache_size > 0 && card->ext_csd.cache_ctrl & 1) {
> + if (mmc_flush_allowed(card)) {
>   err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>EXT_CSD_FLUSH_CACHE, 1,
>CACHE_FLUSH_TIMEOUT_MS);
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 5782fdf4e8e9..2682bf66708a 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -19,6 +19,11 @@ enum mmc_busy_cmd {
>  struct mmc_host;
>  struct mmc_card;
>  
> +static inline bool mmc_flush_allowed(struct mmc_card *card)
> +{
> + return card->ext_csd.cache_size > 0 && card->ext_csd.cache_ctrl & 1;
> +}
> +
>  int mmc_select_card(struct mmc_card *card);
>  int mmc_deselect_cards(struct mmc_host *host);
>  int mmc_set_dsr(struct mmc_host *host);
> 



Re: [PATCH v20 1/2] scsi: ufs: Enable power management for wlun

2021-04-20 Thread Adrian Hunter
On 20/04/21 7:15 am, Adrian Hunter wrote:
> On 20/04/21 12:53 am, Asutosh Das (asd) wrote:
>> On 4/19/2021 11:37 AM, Adrian Hunter wrote:
>>> On 16/04/21 10:49 pm, Asutosh Das wrote:
>>>>
>>>> Co-developed-by: Can Guo 
>>>> Signed-off-by: Can Guo 
>>>> Signed-off-by: Asutosh Das 
>>>> ---
>>>
>>> I came across 3 issues while testing.  See comments below.
>>>
>> Hi Adrian
>> Thanks for the comments.
>>> 
>>>
>>>> @@ -5794,7 +5839,7 @@ static void ufshcd_err_handling_unprepare(struct 
>>>> ufs_hba *hba)
>>>>   if (ufshcd_is_clkscaling_supported(hba))
>>>>   ufshcd_clk_scaling_suspend(hba, false);
>>>>   ufshcd_clear_ua_wluns(hba);
>>>
>>> ufshcd_clear_ua_wluns() deadlocks trying to clear UFS_UPIU_RPMB_WLUN
>>> if sdev_rpmb is suspended and sdev_ufs_device is suspending.
>>> e.g. ufshcd_wl_suspend() is waiting on host_sem while ufshcd_err_handler()
>>> is running, at which point sdev_rpmb has already suspended.
>>>
>> Umm, I didn't understand this deadlock.
>> When you say, sdev_rpmb is suspended, does it mean runtime_suspended?
>> sdev_ufs_device is suspending - this can't be runtime_suspending, while 
>> ufshcd_err_handling_unprepare is running.
>>
>> If you've a call-stack of this deadlock, please can you share it with me. 
>> I'll also try to reproduce this.
> 
> Yes it is system suspend. sdev_rpmb has suspended, sdev_ufs_device is waiting 
> on host_sem.
> ufshcd_err_handler() holds host_sem. ufshcd_clear_ua_wlun(UFS_UPIU_RPMB_WLUN) 
> gets stuck.
> I will get some call-stacks.

Here are the call stacks

[   34.094321] Workqueue: ufs_eh_wq_0 ufshcd_err_handler
[   34.094788] Call Trace:
[   34.095281]  __schedule+0x275/0x6c0
[   34.095743]  schedule+0x41/0xa0
[   34.096240]  blk_queue_enter+0x10d/0x230
[   34.096693]  ? wait_woken+0x70/0x70
[   34.097167]  blk_mq_alloc_request+0x53/0xc0
[   34.097610]  blk_get_request+0x1e/0x60
[   34.098053]  __scsi_execute+0x3c/0x260
[   34.098529]  ufshcd_clear_ua_wlun.cold+0xa6/0x14b
[   34.098977]  ufshcd_clear_ua_wluns.part.0+0x4d/0x92
[   34.099456]  ufshcd_err_handler+0x97a/0x9ff
[   34.099902]  process_one_work+0x1cc/0x360
[   34.100384]  worker_thread+0x45/0x3b0
[   34.100851]  ? process_one_work+0x360/0x360
[   34.101308]  kthread+0xf6/0x130
[   34.101728]  ? kthread_park+0x80/0x80
[   34.102186]  ret_from_fork+0x1f/0x30

[   34.640751] task:kworker/u10:9   state:D stack:14528 pid:  255 ppid: 2 
flags:0x4000
[   34.641253] Workqueue: events_unbound async_run_entry_fn
[   34.641722] Call Trace:
[   34.642217]  __schedule+0x275/0x6c0
[   34.642683]  schedule+0x41/0xa0
[   34.643179]  schedule_timeout+0x18b/0x290
[   34.643645]  ? del_timer_sync+0x30/0x30
[   34.644131]  __down_timeout+0x6b/0xc0
[   34.644568]  ? ufshcd_clkscale_enable_show+0x20/0x20
[   34.645014]  ? async_schedule_node_domain+0x17d/0x190
[   34.645496]  down_timeout+0x42/0x50
[   34.645947]  ufshcd_wl_suspend+0x79/0xa0
[   34.646432]  ? scmd_printk+0x100/0x100
[   34.646917]  scsi_bus_suspend_common+0x56/0xc0
[   34.647405]  ? scsi_bus_freeze+0x10/0x10
[   34.647858]  dpm_run_callback+0x45/0x110
[   34.648347]  __device_suspend+0x117/0x460
[   34.648788]  async_suspend+0x16/0x90
[   34.649251]  async_run_entry_fn+0x26/0x110
[   34.649676]  process_one_work+0x1cc/0x360
[   34.650137]  worker_thread+0x45/0x3b0
[   34.650563]  ? process_one_work+0x360/0x360
[   34.650994]  kthread+0xf6/0x130
[   34.651455]  ? kthread_park+0x80/0x80
[   34.651882]  ret_from_fork+0x1f/0x30



> 
>>
>> I'll address the other comments in the next version.
>>
>>
>> Thank you!
>>
>>>> -    pm_runtime_put(hba->dev);
>>>> +    ufshcd_rpm_put(hba);
>>>>   }
>>>
>>> 
>>>
>>>> +void ufshcd_resume_complete(struct device *dev)
>>>> +{
>>
> 



Re: [PATCH v20 1/2] scsi: ufs: Enable power management for wlun

2021-04-19 Thread Adrian Hunter
On 20/04/21 12:53 am, Asutosh Das (asd) wrote:
> On 4/19/2021 11:37 AM, Adrian Hunter wrote:
>> On 16/04/21 10:49 pm, Asutosh Das wrote:
>>>
>>> Co-developed-by: Can Guo 
>>> Signed-off-by: Can Guo 
>>> Signed-off-by: Asutosh Das 
>>> ---
>>
>> I came across 3 issues while testing.  See comments below.
>>
> Hi Adrian
> Thanks for the comments.
>> 
>>
>>> @@ -5794,7 +5839,7 @@ static void ufshcd_err_handling_unprepare(struct 
>>> ufs_hba *hba)
>>>   if (ufshcd_is_clkscaling_supported(hba))
>>>   ufshcd_clk_scaling_suspend(hba, false);
>>>   ufshcd_clear_ua_wluns(hba);
>>
>> ufshcd_clear_ua_wluns() deadlocks trying to clear UFS_UPIU_RPMB_WLUN
>> if sdev_rpmb is suspended and sdev_ufs_device is suspending.
>> e.g. ufshcd_wl_suspend() is waiting on host_sem while ufshcd_err_handler()
>> is running, at which point sdev_rpmb has already suspended.
>>
> Umm, I didn't understand this deadlock.
> When you say, sdev_rpmb is suspended, does it mean runtime_suspended?
> sdev_ufs_device is suspending - this can't be runtime_suspending, while 
> ufshcd_err_handling_unprepare is running.
> 
> If you've a call-stack of this deadlock, please can you share it with me. 
> I'll also try to reproduce this.

Yes it is system suspend. sdev_rpmb has suspended, sdev_ufs_device is waiting 
on host_sem.
ufshcd_err_handler() holds host_sem. ufshcd_clear_ua_wlun(UFS_UPIU_RPMB_WLUN) 
gets stuck.
I will get some call-stacks.

> 
> I'll address the other comments in the next version.
> 
> 
> Thank you!
> 
>>> -    pm_runtime_put(hba->dev);
>>> +    ufshcd_rpm_put(hba);
>>>   }
>>
>> 
>>
>>> +void ufshcd_resume_complete(struct device *dev)
>>> +{
> 



Re: [PATCH v20 1/2] scsi: ufs: Enable power management for wlun

2021-04-19 Thread Adrian Hunter
On 16/04/21 10:49 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes. This also registers a new scsi driver for rpmb wlun.
> This new driver is mostly used to clear rpmb uac.
> 
> Fixed smatch warnings:
> Reported-by: kernel test robot 
> Reported-by: Dan Carpenter 
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---

I came across 3 issues while testing.  See comments below.



> @@ -5753,12 +5797,13 @@ static void ufshcd_clk_scaling_suspend(struct ufs_hba 
> *hba, bool suspend)
>  
>  static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
>  {
> - pm_runtime_get_sync(hba->dev);
> - if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) {
> + ufshcd_rpm_get_sync(hba);

hba->sdev_ufs_device could be NULL.
Need to add a check for that in ufshcd_err_handling_should_stop()

> + if (pm_runtime_status_suspended(>sdev_ufs_device->sdev_gendev) ||
> + hba->is_sys_suspended) {
>   enum ufs_pm_op pm_op;
>  
>   /*
> -  * Don't assume anything of pm_runtime_get_sync(), if
> +  * Don't assume anything of resume, if
>* resume fails, irq and clocks can be OFF, and powers
>* can be OFF or in LPM.
>*/
> @@ -5794,7 +5839,7 @@ static void ufshcd_err_handling_unprepare(struct 
> ufs_hba *hba)
>   if (ufshcd_is_clkscaling_supported(hba))
>   ufshcd_clk_scaling_suspend(hba, false);
>   ufshcd_clear_ua_wluns(hba);

ufshcd_clear_ua_wluns() deadlocks trying to clear UFS_UPIU_RPMB_WLUN
if sdev_rpmb is suspended and sdev_ufs_device is suspending.
e.g. ufshcd_wl_suspend() is waiting on host_sem while ufshcd_err_handler()
is running, at which point sdev_rpmb has already suspended.

> - pm_runtime_put(hba->dev);
> + ufshcd_rpm_put(hba);
>  }



> +void ufshcd_resume_complete(struct device *dev)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> +
> + ufshcd_rpm_put(hba);
> +}
> +EXPORT_SYMBOL_GPL(ufshcd_resume_complete);
> +
> +int ufshcd_suspend_prepare(struct device *dev)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> + struct device *ufs_dev = >sdev_ufs_device->sdev_gendev;
> + enum ufs_dev_pwr_mode spm_pwr_mode;
> + enum uic_link_state spm_link_state;
> + unsigned long flags;
> + bool rpm_state_ok;
> +
> + /*
> +  * SCSI assumes that runtime-pm and system-pm for scsi drivers
> +  * are same. And it doesn't wake up the device for system-suspend
> +  * if it's runtime suspended. But ufs doesn't follow that.
> +  * The rpm-lvl and spm-lvl can be different in ufs.
> +  * However, if the current_{pwr_mode, link_state} is same as the
> +  * desired_{pwr_mode, link_state}, there's no need to rpm resume
> +  * the device.
> +  * Refer ufshcd_resume_complete()
> +  */
> + pm_runtime_get_noresume(ufs_dev);
> +
> + spin_lock_irqsave(_dev->power.lock, flags);
> +
> + spm_pwr_mode = ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl);
> + spm_link_state = ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl);
> +
> + rpm_state_ok = pm_runtime_suspended(ufs_dev) &&
> + hba->curr_dev_pwr_mode == spm_pwr_mode &&
> + hba->uic_link_state == spm_link_state &&
> + !hba->dev_info.b_rpm_dev_flush_capable;
> +
> + spin_unlock_irqrestore(_dev->power.lock, flags);
> +
> + if (!rpm_state_ok) {
> + int ret = pm_runtime_resume(ufs_dev);
> +
> + if (ret < 0 && ret != -EACCES) {
> + pm_runtime_put(ufs_dev);
> + return 

Re: [PATCH] scsi: ufs: Check for bkops in runtime suspend

2021-04-18 Thread Adrian Hunter
On 18/04/21 10:21 am, Avri Altman wrote:
> The UFS driver allowed BKOPS and WB Flush operations to be completed on
> Runtime suspend. Adding the DeepSleep support, this is no longer true:
> the driver will ignore BKOPS and WB Flush states, and force a link state
> transition to UIC_LINK_OFF_STATE.
> 
> Do not ignore BKOPS and WB Flush on runtme suspend flow.
> 
> fixes: fe1d4c2ebcae (scsi: ufs: Add DeepSleep feature)
> 
> Suggested-by: Alex Lemberg 
> Signed-off-by: Avri Altman 
> ---
>  drivers/scsi/ufs/ufshcd.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 58d7f264c664..1a0cac670aba 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -8755,7 +8755,8 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>* In the case of DeepSleep, the device is expected to remain powered
>* with the link off, so do not check for bkops.
>*/
> - check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
> + check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba) ||
> +   hba->dev_info.b_rpm_dev_flush_capable;

Can you explain this some more? If hba->dev_info.b_rpm_dev_flush_capable
is true, then ufshcd_set_dev_pwr_mode() was not called, so
ufshcd_is_ufs_dev_deepsleep() is false i.e. the same result for the
condition above.

However, it is assumed DeepSleep has the link off so that a full reset
and restore is done upon resume, which is necessary to exit DeepSleep.
So if you wanted to have DeepSleep with the link on, then the resume
logic would also need changes.

>   ret = ufshcd_link_state_transition(hba, req_link_state, 
> check_for_bkops);
>   if (ret)
>   goto set_dev_active;
> 



Re: [PATCH v19 1/2] scsi: ufs: Enable power management for wlun

2021-04-16 Thread Adrian Hunter
On 16/04/21 12:22 pm, Adrian Hunter wrote:
> On 16/04/21 2:36 am, Asutosh Das wrote:
>> During runtime-suspend of ufs host, the scsi devices are
>> already suspended and so are the queues associated with them.
>> But the ufs host sends SSU (START_STOP_UNIT) to wlun
>> during its runtime-suspend.
>> During the process blk_queue_enter checks if the queue is not in
>> suspended state. If so, it waits for the queue to resume, and never
>> comes out of it.
>> The commit
>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>> adds the check if the queue is in suspended state in blk_queue_enter().
>>
>> Call trace:
>>  __switch_to+0x174/0x2c4
>>  __schedule+0x478/0x764
>>  schedule+0x9c/0xe0
>>  blk_queue_enter+0x158/0x228
>>  blk_mq_alloc_request+0x40/0xa4
>>  blk_get_request+0x2c/0x70
>>  __scsi_execute+0x60/0x1c4
>>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>  ufshcd_suspend+0x208/0x83c
>>  ufshcd_runtime_suspend+0x40/0x154
>>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>  pm_generic_runtime_suspend+0x28/0x3c
>>  __rpm_callback+0x80/0x2a4
>>  rpm_suspend+0x308/0x614
>>  rpm_idle+0x158/0x228
>>  pm_runtime_work+0x84/0xac
>>  process_one_work+0x1f0/0x470
>>  worker_thread+0x26c/0x4c8
>>  kthread+0x13c/0x320
>>  ret_from_fork+0x10/0x18
>>
>> Fix this by registering ufs device wlun as a scsi driver and
>> registering it for block runtime-pm. Also make this as a
>> supplier for all other luns. That way, this device wlun
>> suspends after all the consumers and resumes after
>> hba resumes.
>> This also registers a new scsi driver for rpmb wlun.
>> This new driver is mostly used to clear rpmb uac.
>> With this design, the driver would always be runtime resumed
>> before system suspend.
> 
> I thought some more about that and I think we can still support
> allowing runtime suspend to work with system suspend, without
> too much difficulty. See ufshcd_suspend_prepare() below.
> 
>>
>> Fixed smatch warnings:
>> Reported-by: kernel test robot 
>> Reported-by: Dan Carpenter 
>>
>> Co-developed-by: Can Guo 
>> Signed-off-by: Can Guo 
>> Signed-off-by: Asutosh Das 
>> ---
> 
> 
> 
>> -static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>> +static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>>  {
>>  int ret;
>> -enum uic_link_state old_link_state;
>> +enum uic_link_state old_link_state = hba->uic_link_state;
>>  
>> -hba->pm_op_in_progress = 1;
>> -old_link_state = hba->uic_link_state;
>> -
>> -ufshcd_hba_vreg_set_hpm(hba);
>> -ret = ufshcd_vreg_set_hpm(hba);
>> -if (ret)
>> -goto out;
>> -
>> -/* Make sure clocks are enabled before accessing controller */
>> -ret = ufshcd_setup_clocks(hba, true);
>> -if (ret)
>> -goto disable_vreg;
>> -
>> -/* enable the host irq as host controller would be active soon */
>> -ufshcd_enable_irq(hba);
>> +hba->pm_op_in_progress = true;
>>  
>>  /*
>>   * Call vendor specific resume callback. As these callbacks may access
>> @@ -8868,7 +8858,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
>> ufs_pm_op pm_op)
>>   */
>>  ret = ufshcd_vops_resume(hba, pm_op);
>>  if (ret)
>> -goto disable_irq_and_vops_clks;
>> +goto out;
>>  
>>  /* For DeepSleep, the only supported option is to have the link off */
>>  WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba));
>> @@ -8916,42 +8906,219 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
>> ufs_pm_op pm_op)
>>  if (hba->ee_usr_mask)
>>  ufshcd_write_ee_control(hba);
>>  
>> -hba->clk_gating.is_suspended = false;
>> -
>>  if (ufshcd_is_clkscaling_supported(hba))
>> -ufshcd_clk_scaling_suspend(hba, false);
>> -
>> -/* Enable Auto-Hibernate if configured */
>> -ufshcd_auto_hibern8_enable(hba);
>> +ufshcd_resume_clkscaling(hba);
> 
> This still doesn't look right. ufshcd_resume_clkscaling()
> doesn't update hba->clk_scaling.is_allowed whereas
> ufshcd_clk_scaling_suspend() does.
> 
>>  
>>  if (hba->dev_info.b_rpm_dev_flush_capable) {
>>  hba->dev_info.b_rpm_dev_flush_capable = false;
>>  cancel_delayed_work(>rpm_dev_flush_recheck_work);
>>  }
>>  
>>

Re: [PATCH v19 1/2] scsi: ufs: Enable power management for wlun

2021-04-16 Thread Adrian Hunter
On 16/04/21 2:36 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> This also registers a new scsi driver for rpmb wlun.
> This new driver is mostly used to clear rpmb uac.
> With this design, the driver would always be runtime resumed
> before system suspend.

I thought some more about that and I think we can still support
allowing runtime suspend to work with system suspend, without
too much difficulty. See ufshcd_suspend_prepare() below.

> 
> Fixed smatch warnings:
> Reported-by: kernel test robot 
> Reported-by: Dan Carpenter 
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---



> -static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
> +static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
>   int ret;
> - enum uic_link_state old_link_state;
> + enum uic_link_state old_link_state = hba->uic_link_state;
>  
> - hba->pm_op_in_progress = 1;
> - old_link_state = hba->uic_link_state;
> -
> - ufshcd_hba_vreg_set_hpm(hba);
> - ret = ufshcd_vreg_set_hpm(hba);
> - if (ret)
> - goto out;
> -
> - /* Make sure clocks are enabled before accessing controller */
> - ret = ufshcd_setup_clocks(hba, true);
> - if (ret)
> - goto disable_vreg;
> -
> - /* enable the host irq as host controller would be active soon */
> - ufshcd_enable_irq(hba);
> + hba->pm_op_in_progress = true;
>  
>   /*
>* Call vendor specific resume callback. As these callbacks may access
> @@ -8868,7 +8858,7 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>*/
>   ret = ufshcd_vops_resume(hba, pm_op);
>   if (ret)
> - goto disable_irq_and_vops_clks;
> + goto out;
>  
>   /* For DeepSleep, the only supported option is to have the link off */
>   WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba));
> @@ -8916,42 +8906,219 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>   if (hba->ee_usr_mask)
>   ufshcd_write_ee_control(hba);
>  
> - hba->clk_gating.is_suspended = false;
> -
>   if (ufshcd_is_clkscaling_supported(hba))
> - ufshcd_clk_scaling_suspend(hba, false);
> -
> - /* Enable Auto-Hibernate if configured */
> - ufshcd_auto_hibern8_enable(hba);
> + ufshcd_resume_clkscaling(hba);

This still doesn't look right. ufshcd_resume_clkscaling()
doesn't update hba->clk_scaling.is_allowed whereas
ufshcd_clk_scaling_suspend() does.

>  
>   if (hba->dev_info.b_rpm_dev_flush_capable) {
>   hba->dev_info.b_rpm_dev_flush_capable = false;
>   cancel_delayed_work(>rpm_dev_flush_recheck_work);
>   }
>  
> - ufshcd_clear_ua_wluns(hba);
> -
> - /* Schedule clock gating in case of no access to UFS device yet */
> - ufshcd_release(hba);
> -
> + /* Enable Auto-Hibernate if configured */
> + ufshcd_auto_hibern8_enable(hba);
>   goto out;
>  
>  set_old_link_state:
>   ufshcd_link_state_transition(hba, old_link_state, 0);
>  vendor_suspend:
>   ufshcd_vops_suspend(hba, pm_op);
> -disable_irq_and_vops_clks:
> +out:
> + if (ret)
> + ufshcd_update_evt_hist(hba, UFS_EVT_WL_RES_ERR, (u32)ret);
> + hba->clk_gating.is_suspended = false;
> + ufshcd_release(hba);
> + hba->pm_op_in_progress = false;
> + return ret;
> +}



> +void ufshcd_resume_complete(struct device *dev)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> +
> + ufshcd_rpm_put(hba);
> +}
> 

Re: [PATCH v18 1/2] scsi: ufs: Enable power management for wlun

2021-04-15 Thread Adrian Hunter
On 14/04/21 9:58 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.

Can you also explain the new driver for RPMB WLUN and UAC changes here?

And also mention that the driver will now always be runtime
resumed before system suspend.

> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---



> +static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
> +{
> + struct device_link *link;
> +
> + /*
> +  * device wlun is the supplier & rest of the luns are consumers
> +  * This ensures that device wlun suspends after all other luns.
> +  */
> + if (hba->sdev_ufs_device) {
> + link = device_link_add(>sdev_gendev,
> +>sdev_ufs_device->sdev_gendev,
> +DL_FLAG_PM_RUNTIME|DL_FLAG_RPM_ACTIVE);

"|" could be surrounded by spaces i.e.
   DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);

> + if (!link) {
> + dev_err(>sdev_gendev, "Failed establishing link - 
> %s\n",
> + dev_name(>sdev_ufs_device->sdev_gendev));
> + return;
> + }
> + hba->luns_avail--;
> + /* Ignore REPORT_LUN wlun probing */
> + if (hba->luns_avail == 1) {
> + ufshcd_rpm_put(hba);
> + return;
> + }
> + } else {
> + /* device wlun is probed */
> + hba->luns_avail--;
> + }
> +}



> @@ -8916,42 +8906,214 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>   if (hba->ee_usr_mask)
>   ufshcd_write_ee_control(hba);
>  
> - hba->clk_gating.is_suspended = false;
> -
> - if (ufshcd_is_clkscaling_supported(hba))
> - ufshcd_clk_scaling_suspend(hba, false);
> -
> - /* Enable Auto-Hibernate if configured */
> - ufshcd_auto_hibern8_enable(hba);
> + if (hba->clk_scaling.is_allowed)
> + ufshcd_resume_clkscaling(hba);

We don't use clks, regulators, clk gating, clk scaling, but the
original code looks more correct because hba->clk_scaling.is_allowed
will have been set to false by ufshcd_clk_scaling_suspend(hba, true)
in __ufshcd_wl_suspend().



> +#ifdef CONFIG_PM_SLEEP
> +static int ufshcd_wl_suspend(struct device *dev)
> +{
> + struct scsi_device *sdev = to_scsi_device(dev);
> + struct ufs_hba *hba;
> + int ret;

For below:
int ret = 0;

> + ktime_t start = ktime_get();
> +
> + hba = shost_priv(sdev->host);
> + down(>host_sem);

If we get here with dev runtime suspended, then skip
__ufshcd_wl_suspend() i.e.

if (pm_runtime_suspended(dev))
goto out;

> + ret = __ufshcd_wl_suspend(hba, UFS_SYSTEM_PM);
> + if (ret) {
> + dev_err(>sdev_gendev, "%s failed: %d\n", __func__,  ret);
> + up(>host_sem);
> + } else {
> + hba->is_sys_suspended = true;
> + }

out:
if (!ret)
hba->is_sys_suspended = true;

> +
> + trace_ufshcd_wl_suspend(dev_name(dev), ret,
> + ktime_to_us(ktime_sub(ktime_get(), start)),
> + hba->curr_dev_pwr_mode, hba->uic_link_state);
> +
> + return ret;
> +}




Re: [PATCH v18 2/2] ufs: sysfs: Resume the proper scsi device

2021-04-15 Thread Adrian Hunter
On 14/04/21 9:58 pm, Asutosh Das wrote:
> Resumes the actual scsi device the unit descriptor of which
> is being accessed instead of the hba alone.
> 
> Reviewed-by: Can Guo 
> Signed-off-by: Asutosh Das 

Reviewed-by: Adrian Hunter 

> ---
>  drivers/scsi/ufs/ufs-sysfs.c | 24 
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index d7c3cff..4d9d4d8 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -245,9 +245,9 @@ static ssize_t wb_on_store(struct device *dev, struct 
> device_attribute *attr,
>   goto out;
>   }
>  
> - pm_runtime_get_sync(hba->dev);
> + ufshcd_rpm_get_sync(hba);
>   res = ufshcd_wb_toggle(hba, wb_enable);
> - pm_runtime_put_sync(hba->dev);
> + ufshcd_rpm_put_sync(hba);
>  out:
>   up(>host_sem);
>   return res < 0 ? res : count;
> @@ -297,10 +297,10 @@ static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba 
> *hba,
>   goto out;
>   }
>  
> - pm_runtime_get_sync(hba->dev);
> + ufshcd_rpm_get_sync(hba);
>   ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
>   param_offset, desc_buf, param_size);
> - pm_runtime_put_sync(hba->dev);
> + ufshcd_rpm_put_sync(hba);
>   if (ret) {
>   ret = -EINVAL;
>   goto out;
> @@ -678,7 +678,7 @@ static ssize_t _name##_show(struct device *dev,   
> \
>   up(>host_sem); \
>   return -ENOMEM; \
>   }   \
> - pm_runtime_get_sync(hba->dev);  \
> + ufshcd_rpm_get_sync(hba);   \
>   ret = ufshcd_query_descriptor_retry(hba,\
>   UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
>   0, 0, desc_buf, _len); \
> @@ -695,7 +695,7 @@ static ssize_t _name##_show(struct device *dev,   
> \
>   goto out;   \
>   ret = sysfs_emit(buf, "%s\n", desc_buf);\
>  out: \
> - pm_runtime_put_sync(hba->dev);  \
> + ufshcd_rpm_put_sync(hba);   \
>   kfree(desc_buf);\
>   up(>host_sem); \
>   return ret; \
> @@ -744,10 +744,10 @@ static ssize_t _name##_show(struct device *dev, 
> \
>   }   \
>   if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname)) \
>   index = ufshcd_wb_get_query_index(hba); \
> - pm_runtime_get_sync(hba->dev);  \
> + ufshcd_rpm_get_sync(hba);   \
>   ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,   \
>   QUERY_FLAG_IDN##_uname, index, );  \
> - pm_runtime_put_sync(hba->dev);  \
> + ufshcd_rpm_put_sync(hba);   \
>   if (ret) {  \
>   ret = -EINVAL;  \
>   goto out;   \
> @@ -813,10 +813,10 @@ static ssize_t _name##_show(struct device *dev, 
> \
>   }   \
>   if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname)) \
>   index = ufshcd_wb_get_query_index(hba); \
> - pm_runtime_get_sync(hba->dev);  \
> + ufshcd_rpm_get_sync(hba);   \
>   ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,   \
>   QUERY_ATTR_IDN##_uname, index, 0, );  \
> - pm_runtime_put_sync(hba->dev);  \
> + ufshcd_rpm_put_sync(hba);   \
>   if (ret) {  \
>   ret = -EINVAL; 

Re: [PATCH 2/2] perf intel-pt: Use aux_watermark

2021-04-14 Thread Adrian Hunter
On 8/04/21 6:31 pm, Alexander Shishkin wrote:
> Turns out, the default setting of attr.aux_watermark to half of the total
> buffer size is not very useful, especially with smaller buffers. The
> problem is that, after half of the buffer is filled up, the kernel updates
> ->aux_head and sets up the next "transaction", while observing that
> ->aux_tail is still zero (as userspace haven't had the chance to update
> it), meaning that the trace will have to stop at the end of this second
> "transaction". This means, for example, that the second PERF_RECORD_AUX in
> every trace comes with TRUNCATED flag set.
> 
> Setting attr.aux_watermark to quarter of the buffer gives enough space for
> the ->aux_tail update to be observed and prevents the data loss.
> 
> The obligatory before/after showcase:
> 
>> # perf_before record -e intel_pt//u -m,8 uname
>> Linux
>> [ perf record: Woken up 6 times to write data ]
>> Warning:
>> AUX data lost 4 times out of 10!
>>
>> [ perf record: Captured and wrote 0.099 MB perf.data ]
>> # perf record -e intel_pt//u -m,8 uname
>> Linux
>> [ perf record: Woken up 4 times to write data ]
>> [ perf record: Captured and wrote 0.039 MB perf.data ]
> 
> The effect is still visible with large workloads and large buffers,
> although less pronounced.
> 
> Signed-off-by: Alexander Shishkin 
> ---
>  tools/perf/arch/x86/util/intel-pt.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/tools/perf/arch/x86/util/intel-pt.c 
> b/tools/perf/arch/x86/util/intel-pt.c
> index a6420c647959..d00707faf547 100644
> --- a/tools/perf/arch/x86/util/intel-pt.c
> +++ b/tools/perf/arch/x86/util/intel-pt.c
> @@ -776,6 +776,10 @@ static int intel_pt_recording_options(struct 
> auxtrace_record *itr,
>   }
>   }
>  
> + if (opts->full_auxtrace)
> + intel_pt_evsel->core.attr.aux_watermark =
> +opts->auxtrace_mmap_pages / 4 * page_size;
> +

I would be explicit about the mode and put "/ 4" at the end
for the case auxtrace_mmap_pages is not a multiple of 4 (e.g. 2).
i.e.

if (!opts->auxtrace_snapshot_mode && !opts->auxtrace_sample_mode) {
u32 aux_watermark = opts->auxtrace_mmap_pages * page_size / 4;

intel_pt_evsel->core.attr.aux_watermark = aux_watermark;
}


>   intel_pt_parse_terms(intel_pt_pmu->name, _pt_pmu->format,
>"tsc", _bit);
>  
> 



Re: [PATCH v17 1/2] scsi: ufs: Enable power management for wlun

2021-04-11 Thread Adrian Hunter
On 8/04/21 5:49 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---



> @@ -5815,14 +5857,14 @@ static void ufshcd_recover_pm_error(struct ufs_hba 
> *hba)
>  
>   hba->is_sys_suspended = false;
>   /*
> -  * Set RPM status of hba device to RPM_ACTIVE,
> +  * Set RPM status of wlun device to RPM_ACTIVE,
>* this also clears its runtime error.
>*/
> - ret = pm_runtime_set_active(hba->dev);
> + ret = pm_runtime_set_active(>sdev_ufs_device->sdev_gendev);

It may be that it was hba->dev with a runtime error. So,
also need here:

if (ret)
ret = pm_runtime_set_active(hba->dev);


> @@ -8671,7 +8701,7 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>   enum ufs_dev_pwr_mode req_dev_pwr_mode;
>   enum uic_link_state req_link_state;
>  
> - hba->pm_op_in_progress = 1;
> + hba->pm_op_in_progress = true;
>   if (!ufshcd_is_shutdown_pm(pm_op)) {
>   pm_lvl = ufshcd_is_runtime_pm(pm_op) ?
>hba->rpm_lvl : hba->spm_lvl;
> @@ -8694,17 +8724,17 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>  
>   if (req_dev_pwr_mode == UFS_ACTIVE_PWR_MODE &&
>   req_link_state == UIC_LINK_ACTIVE_STATE) {
> - goto disable_clks;
> + goto enable_scaling;

Previously "goto disable_clks" would go to the vendor callback
ufshcd_vops_suspend(), but now it is skipped.


>   }
>  
>   if ((req_dev_pwr_mode == hba->curr_dev_pwr_mode) &&
>   (req_link_state == hba->uic_link_state))
> - goto enable_gating;
> + goto enable_scaling;
>  
>   /* UFS device & link must be active before we enter in this function */
>   if (!ufshcd_is_ufs_dev_active(hba) || !ufshcd_is_link_active(hba)) {
>   ret = -EINVAL;
> - goto enable_gating;
> + goto enable_scaling;
>   }



> +/**
> + * ufshcd_suspend - helper function for suspend operations
> + * @hba: per adapter instance
> + *
> + * This function will put disable irqs, turn off clocks
> + * and set vreg and hba-vreg in lpm mode.
> + * Also check the description of __ufshcd_wl_suspend().
> + */
> +static void ufshcd_suspend(struct ufs_hba *hba)
> +{
> + hba->pm_op_in_progress = 1;

Seems like pm_op_in_progress wouldn't be needed in this function,
nor ufshcd_resume().

You could probably simplify the callers slighly by
putting the "if (!hbs->is_powered) return" check here and in
ufshcd_resume().

> +
> + /*
> +  * Disable the host irq as host controller as there won't be any
> +  * host controller transaction expected till resume.
> +  */
>   ufshcd_disable_irq(hba);
>   ufshcd_setup_clocks(hba, false);
>   if (ufshcd_is_clkgating_allowed(hba)) {
> @@ -8948,6 +9054,43 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
> ufs_pm_op pm_op)
>   trace_ufshcd_clk_gating(dev_name(hba->dev),
>   hba->clk_gating.state);
>   }
> +
> + ufshcd_vreg_set_lpm(hba);
> + /* Put the host controller in low power mode if possible */
> + ufshcd_hba_vreg_set_lpm(hba);
> + hba->pm_op_in_progress = 0;
> +}
> +
> +/**
> + * ufshcd_resume - helper function for resume operations
> + * @hba: per adapter instance
> + *
> + * This function basically turns on the regulators, clocks and
> + * irqs of the hba.
> + * Also check the description of __ufshcd_wl_resume().
> + *
> + * Returns 0 for success and 

Re: [PATCH v17 2/2] ufs: sysfs: Resume the proper scsi device

2021-04-10 Thread Adrian Hunter
On 8/04/21 5:49 pm, Asutosh Das wrote:
> Resumes the actual scsi device the unit descriptor of which
> is being accessed instead of the hba alone.
> 
> Reviewed-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufs-sysfs.c | 30 +-
>  1 file changed, 17 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index d7c3cff..fa57bac 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c



> @@ -899,11 +899,15 @@ static ssize_t _pname##_show(struct device *dev,
> \
>   struct scsi_device *sdev = to_scsi_device(dev); \
>   struct ufs_hba *hba = shost_priv(sdev->host);   \
>   u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);\
> + int ret;\
>   if (!ufs_is_valid_unit_desc_lun(>dev_info, lun,\
>   _duname##_DESC_PARAM##_puname)) \
>   return -EINVAL; \
> - return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
> + scsi_autopm_get_device(sdev);   \
> + ret = ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname,  \
>   lun, _duname##_DESC_PARAM##_puname, buf, _size);\
> + scsi_autopm_put_device(sdev);   \
> + return ret; \

I am not sure why this change is needed.  It it is needed, please add
a comment explaining.



Re: [PATCH] perf session: Dump PERF_RECORD_TIME_CONV event

2021-04-10 Thread Adrian Hunter
On 10/04/21 6:19 am, Leo Yan wrote:
> Now perf tool uses the common stub function process_event_op2_stub() for
> dumping TIME_CONV event, thus it doesn't output the clock parameters
> contained in the event.
> 
> This patch adds the callback function for dumping the hardware clock
> parameters in TIME_CONV event.
> 
> Before:
> 
>   # perf report -D
> 
>   0x978 [0x38]: event: 79
>   .
>   . ... raw event: size 56 bytes
>   .  :  4f 00 00 00 00 00 38 00 15 00 00 00 00 00 00 00  O.8.
>   .  0010:  00 00 40 01 00 00 00 00 86 89 0b bf df ff ff ff  
> ..@
>   .  0020:  d1 c1 b2 39 03 00 00 00 ff ff ff ff ff ff ff 00  
> 9.
>   .  0030:  01 01 00 00 00 00 00 00  
> 
>   0 0 0x978 [0x38]: PERF_RECORD_TIME_CONV
>   : unhandled!
> 
>   [...]
> 
> After:
> 
>   # perf report -D
> 
>   0x978 [0x38]: event: 79
>   .
>   . ... raw event: size 56 bytes
>   .  :  4f 00 00 00 00 00 38 00 15 00 00 00 00 00 00 00  O.8.
>   .  0010:  00 00 40 01 00 00 00 00 86 89 0b bf df ff ff ff  
> ..@
>   .  0020:  d1 c1 b2 39 03 00 00 00 ff ff ff ff ff ff ff 00  
> 9.
>   .  0030:  01 01 00 00 00 00 00 00  
> 
>   0 0 0x978 [0x38]: PERF_RECORD_TIME_CONV
>   ... Time Shift  21
>   ... Time Muliplier  20971520
>   ... Time Zero   18446743935180835206
>   ... Time Cycles 13852918225
>   ... Time Mask   0xff
>   ... Cap Time Zero   1
>   ... Cap Time Short  1
>   : unhandled!
> 
>   [...]
> 
> Signed-off-by: Leo Yan 
> ---
>  tools/perf/util/session.c | 13 -
>  tools/perf/util/tsc.c | 18 ++
>  tools/perf/util/tsc.h |  4 
>  3 files changed, 34 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 9a8808507bd9..75931c8054aa 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -29,6 +29,7 @@
>  #include "thread-stack.h"
>  #include "sample-raw.h"
>  #include "stat.h"
> +#include "tsc.h"
>  #include "ui/progress.h"
>  #include "../perf.h"
>  #include "arch/common.h"
> @@ -451,6 +452,16 @@ static int process_stat_round_stub(struct perf_session 
> *perf_session __maybe_unu
>   return 0;
>  }
>  
> +static int process_event_time_conv_stub(struct perf_session *perf_session 
> __maybe_unused,
> + union perf_event *event)
> +{
> + if (dump_trace)
> + perf_event__fprintf_time_conv(event, stdout);
> +
> + dump_printf(": unhandled!\n");
> + return 0;
> +}
> +
>  static int perf_session__process_compressed_event_stub(struct perf_session 
> *session __maybe_unused,
>  union perf_event *event 
> __maybe_unused,
>  u64 file_offset 
> __maybe_unused)
> @@ -532,7 +543,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
>   if (tool->stat_round == NULL)
>   tool->stat_round = process_stat_round_stub;
>   if (tool->time_conv == NULL)
> - tool->time_conv = process_event_op2_stub;
> + tool->time_conv = process_event_time_conv_stub;
>   if (tool->feature == NULL)
>   tool->feature = process_event_op2_stub;
>   if (tool->compressed == NULL)
> diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c
> index 62b4c75c966c..4ac3cc72f3e1 100644
> --- a/tools/perf/util/tsc.c
> +++ b/tools/perf/util/tsc.c
> @@ -1,5 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0
>  #include 
> +#include 
> +#include 
>  
>  #include 
>  #include 
> @@ -110,3 +112,19 @@ u64 __weak rdtsc(void)
>  {
>   return 0;
>  }
> +
> +size_t perf_event__fprintf_time_conv(union perf_event *event, FILE *fp)
> +{
> + struct perf_record_time_conv *tc = (struct perf_record_time_conv 
> *)event;
> + size_t ret;
> +
> + ret  = fprintf(fp, "\n... Time Shift  %" PRI_lu64 "\n", 
> tc->time_shift);
> + ret += fprintf(fp, "... Time Muliplier  %" PRI_lu64 "\n", 
> tc->time_mult);
> + ret += fprintf(fp, "... Time Zero   %" PRI_lu64 "\n", 
> tc->time_zero);
> + ret += fprintf(fp, "... Time Cycles %" PRI_lu64 "\n", 
> tc->time_cycles);
> + ret += fprintf(fp, "... Time Mask   %#" PRI_lx64 "\n", 
> tc->time_mask);
> + ret += fprintf(fp, "... Cap Time Zero   %" PRId32 "\n", 
> tc->cap_user_time_zero);
> + ret += fprintf(fp, "... Cap Time Short  %" PRId32 "\n", 
> tc->cap_user_time_short);

Hi Leo

I think there might be some more work related to this.

Pedantically, shouldn't you cater for backward compatibility and
not assume the following were in the perf.data file:

   
   __u64time_cycles;
  

Re: [PATCH v17 1/2] scsi: ufs: Enable power management for wlun

2021-04-09 Thread Adrian Hunter
On 9/04/21 8:15 pm, Asutosh Das (asd) wrote:
> On 4/9/2021 3:07 AM, Adrian Hunter wrote:
>> On 9/04/21 5:27 am, Daejun Park wrote:
>>> Hi Asutosh Das,
>>>
>>>> During runtime-suspend of ufs host, the scsi devices are
>>>> already suspended and so are the queues associated with them.
>>>> But the ufs host sends SSU (START_STOP_UNIT) to wlun
>>>> during its runtime-suspend.
>>>> During the process blk_queue_enter checks if the queue is not in
>>>> suspended state. If so, it waits for the queue to resume, and never
>>>> comes out of it.
>>>> The commit
>>>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>>>> adds the check if the queue is in suspended state in blk_queue_enter().
>>>>
>>>> Call trace:
>>>> __switch_to+0x174/0x2c4
>>>> __schedule+0x478/0x764
>>>> schedule+0x9c/0xe0
>>>> blk_queue_enter+0x158/0x228
>>>> blk_mq_alloc_request+0x40/0xa4
>>>> blk_get_request+0x2c/0x70
>>>> __scsi_execute+0x60/0x1c4
>>>> ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>>> ufshcd_suspend+0x208/0x83c
>>>> ufshcd_runtime_suspend+0x40/0x154
>>>> ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>>> pm_generic_runtime_suspend+0x28/0x3c
>>>> __rpm_callback+0x80/0x2a4
>>>> rpm_suspend+0x308/0x614
>>>> rpm_idle+0x158/0x228
>>>> pm_runtime_work+0x84/0xac
>>>> process_one_work+0x1f0/0x470
>>>> worker_thread+0x26c/0x4c8
>>>> kthread+0x13c/0x320
>>>> ret_from_fork+0x10/0x18
>>>>
>>>> Fix this by registering ufs device wlun as a scsi driver and
>>>> registering it for block runtime-pm. Also make this as a
>>>> supplier for all other luns. That way, this device wlun
>>>> suspends after all the consumers and resumes after
>>>> hba resumes.
>>>>
>>>> Co-developed-by: Can Guo 
>>>> Signed-off-by: Can Guo 
>>>> Signed-off-by: Asutosh Das 
>>>> ---
>>>> drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>>>> drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>>>> drivers/scsi/ufs/ufs-debugfs.c |   6 +-
>>>> drivers/scsi/ufs/ufs-debugfs.h |   2 +-
>>>> drivers/scsi/ufs/ufs-exynos.c  |   2 +
>>>> drivers/scsi/ufs/ufs-hisi.c    |   2 +
>>>> drivers/scsi/ufs/ufs-mediatek.c    |  12 +-
>>>> drivers/scsi/ufs/ufs-qcom.c    |   2 +
>>>> drivers/scsi/ufs/ufs_bsg.c |   6 +-
>>>> drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>>>> drivers/scsi/ufs/ufshcd.c  | 642 
>>>> ++---
>>>> drivers/scsi/ufs/ufshcd.h  |   6 +
>>>> include/trace/events/ufs.h |  20 ++
>>>> 13 files changed, 509 insertions(+), 231 deletions(-)
>>>
>>> In this patch, you changed pm_runtime_{get, put}_sync to scsi_autopm_{get, 
>>> put}_device.
>>> But, scsi_autopm_get_device() calls pm_runtime_put_sync() in case of error
>>> of pm_runtime_get_sync(). So, pm_runtime_put_sync() can be called twice if
>>> scsi_autopm_get_device has error.
>>
>> Also it might be tidy to make wrappers e.g.
>>
>> static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba)
>> {
>>  return pm_runtime_get_sync(>sdev_ufs_device->sdev_gendev);
>> }
>>     static inline int ufshcd_rpm_put(struct ufs_hba *hba)
>> {
>>  return pm_runtime_put(>sdev_ufs_device->sdev_gendev);
>> }
>>
>> static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
>> {
>>  return pm_runtime_put_sync(>sdev_ufs_device->sdev_gendev);
>> }
>>
>> And also consider matching: e.g.
>>
>> pm_runtime_put(hba->dev)    to    ufshcd_rpm_put(hba)
>> pm_runtime_put_sync(hba->dev)    to    ufshcd_rpm_put_sync(hba)
>>
>>
>>
> 
> Ok, I'll push the changes shortly.
> 

I think I will have some more comments, so you could wait if you want.



Re: [PATCH v17 1/2] scsi: ufs: Enable power management for wlun

2021-04-09 Thread Adrian Hunter
On 9/04/21 5:27 am, Daejun Park wrote:
> Hi Asutosh Das,
> 
>> During runtime-suspend of ufs host, the scsi devices are
>> already suspended and so are the queues associated with them.
>> But the ufs host sends SSU (START_STOP_UNIT) to wlun
>> during its runtime-suspend.
>> During the process blk_queue_enter checks if the queue is not in
>> suspended state. If so, it waits for the queue to resume, and never
>> comes out of it.
>> The commit
>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>> adds the check if the queue is in suspended state in blk_queue_enter().
>>
>> Call trace:
>> __switch_to+0x174/0x2c4
>> __schedule+0x478/0x764
>> schedule+0x9c/0xe0
>> blk_queue_enter+0x158/0x228
>> blk_mq_alloc_request+0x40/0xa4
>> blk_get_request+0x2c/0x70
>> __scsi_execute+0x60/0x1c4
>> ufshcd_set_dev_pwr_mode+0x124/0x1e4
>> ufshcd_suspend+0x208/0x83c
>> ufshcd_runtime_suspend+0x40/0x154
>> ufshcd_pltfrm_runtime_suspend+0x14/0x20
>> pm_generic_runtime_suspend+0x28/0x3c
>> __rpm_callback+0x80/0x2a4
>> rpm_suspend+0x308/0x614
>> rpm_idle+0x158/0x228
>> pm_runtime_work+0x84/0xac
>> process_one_work+0x1f0/0x470
>> worker_thread+0x26c/0x4c8
>> kthread+0x13c/0x320
>> ret_from_fork+0x10/0x18
>>
>> Fix this by registering ufs device wlun as a scsi driver and
>> registering it for block runtime-pm. Also make this as a
>> supplier for all other luns. That way, this device wlun
>> suspends after all the consumers and resumes after
>> hba resumes.
>>
>> Co-developed-by: Can Guo 
>> Signed-off-by: Can Guo 
>> Signed-off-by: Asutosh Das 
>> ---
>> drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>> drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>> drivers/scsi/ufs/ufs-debugfs.c |   6 +-
>> drivers/scsi/ufs/ufs-debugfs.h |   2 +-
>> drivers/scsi/ufs/ufs-exynos.c  |   2 +
>> drivers/scsi/ufs/ufs-hisi.c|   2 +
>> drivers/scsi/ufs/ufs-mediatek.c|  12 +-
>> drivers/scsi/ufs/ufs-qcom.c|   2 +
>> drivers/scsi/ufs/ufs_bsg.c |   6 +-
>> drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>> drivers/scsi/ufs/ufshcd.c  | 642 
>> ++---
>> drivers/scsi/ufs/ufshcd.h  |   6 +
>> include/trace/events/ufs.h |  20 ++
>> 13 files changed, 509 insertions(+), 231 deletions(-)
> 
> In this patch, you changed pm_runtime_{get, put}_sync to scsi_autopm_{get, 
> put}_device.
> But, scsi_autopm_get_device() calls pm_runtime_put_sync() in case of error
> of pm_runtime_get_sync(). So, pm_runtime_put_sync() can be called twice if
> scsi_autopm_get_device has error.

Also it might be tidy to make wrappers e.g.

static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba)
{
return pm_runtime_get_sync(>sdev_ufs_device->sdev_gendev);
}
   
static inline int ufshcd_rpm_put(struct ufs_hba *hba)
{
return pm_runtime_put(>sdev_ufs_device->sdev_gendev);
}

static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
{
return pm_runtime_put_sync(>sdev_ufs_device->sdev_gendev);
} 

And also consider matching: e.g.

pm_runtime_put(hba->dev)to  ufshcd_rpm_put(hba)
pm_runtime_put_sync(hba->dev)   to  ufshcd_rpm_put_sync(hba)





Re: [PATCH v16 1/2] scsi: ufs: Enable power management for wlun

2021-04-08 Thread Adrian Hunter
On 7/04/21 9:08 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---



> +#ifdef CONFIG_PM_SLEEP
> +static int ufshcd_wl_poweroff(struct device *dev)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);

Should be:

struct scsi_device *sdev = to_scsi_device(dev);
struct ufs_hba *hba = shost_priv(sdev->host);

> +
> + __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);
> + return 0;
> +}
> +#endif


Re: [PATCH v2 0/7] perf arm-spe: Enable timestamp

2021-04-07 Thread Adrian Hunter
On 7/04/21 4:15 pm, Leo Yan wrote:
> Hi Al,
> 
> On Tue, Apr 06, 2021 at 09:38:32AM +, Al Grant wrote:
> 
> [...]
> 
>>> This patch set is to enable timestamp for Arm SPE trace.  It reads out TSC
>>> parameters from mmap page and stores into auxtrace info structure;
>>
>> Why not synthesize a PERF_RECORD_TIME_CONV - isn't that specifically to
>> capture the TSC parameters from the mmap page? If a generic mechanism
>> exists it would be better to use it, otherwise we'll have to do this again 
>> for
>> future trace formats.
> 
> Good point!  Actually "perf record" tool has synthesized event
> PERF_RECORD_TIME_CONV.  This patch series is studying the
> implementation from Intel-PT, so the question is why the existed
> implementations (like Intel-PT, Intel-BTS) don't directly use
> PERF_RECORD_TIME_CONV for retriving TSC parameters.

PERF_RECORD_TIME_CONV was added later because the TSC information is
needed by jitdump.



Re: [PATCH v15 1/2] scsi: ufs: Enable power management for wlun

2021-04-07 Thread Adrian Hunter
On 6/04/21 8:52 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---

v15 seems to be missing the updates to ufs_debugfs_get/put_user_access
that were in v14:


@@ -60,14 +60,14 @@ __acquires(>host_sem)
up(>host_sem);
return -EBUSY;
}
-   pm_runtime_get_sync(hba->dev);
+   scsi_autopm_get_device(hba->sdev_ufs_device);
return 0;
 }
 
 static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
 __releases(>host_sem)
 {
-   pm_runtime_put_sync(hba->dev);
+   scsi_autopm_put_device(hba->sdev_ufs_device);
up(>host_sem);
 }
 

Also from last comments, the issue below:



> +#ifdef CONFIG_PM_SLEEP
> +static int ufshcd_wl_poweroff(struct device *dev)
> +{
> + ufshcd_wl_shutdown(dev);

This turned out to be wrong.  This is a PM op and SCSI has already
quiesced the sdev's.  All that is needed is:

__ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);




[PATCH] perf inject: Fix repipe usage

2021-04-01 Thread Adrian Hunter
Since commit 14d3d5405253 ("perf session: Try to read pipe data from file")
perf inject has started printing "PERFILE2h" when not processing pipes.

The commit exposed perf to the possiblity that the input is not a pipe but
the 'repipe' parameter gets used. That causes the printing because perf
inject sets 'repipe' to true always.

The 'repipe' parameter of perf_session__new() is used by 2 functions:
- perf_file_header__read_pipe()
- trace_report()
In both cases, the functions copy data to STDOUT_FILENO when 'repipe' is
true.

Fix by setting 'repipe' to true only if the output is a pipe.

Fixes: e558a5bd8b74 ("perf inject: Work with files")
Signed-off-by: Adrian Hunter 
---
 tools/perf/builtin-inject.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6fe44d97fde5..ddccc0eb7390 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -906,7 +906,7 @@ int cmd_inject(int argc, const char **argv)
}
 
data.path = inject.input_name;
-   inject.session = perf_session__new(, true, );
+   inject.session = perf_session__new(, inject.output.is_pipe, 
);
if (IS_ERR(inject.session))
return PTR_ERR(inject.session);
 
-- 
2.17.1



Re: [PATCH v14 1/2] scsi: ufs: Enable power management for wlun

2021-04-01 Thread Adrian Hunter
On 1/04/21 4:40 am, Asutosh Das (asd) wrote:
> On 3/31/2021 11:19 AM, Adrian Hunter wrote:
>> On 31/03/21 1:31 am, Asutosh Das wrote:
>>> During runtime-suspend of ufs host, the scsi devices are
>>> already suspended and so are the queues associated with them.
>>> But the ufs host sends SSU (START_STOP_UNIT) to wlun
>>> during its runtime-suspend.
>>> During the process blk_queue_enter checks if the queue is not in
>>> suspended state. If so, it waits for the queue to resume, and never
>>> comes out of it.
>>> The commit
>>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>>> adds the check if the queue is in suspended state in blk_queue_enter().
>>>
>>> Call trace:
>>>   __switch_to+0x174/0x2c4
>>>   __schedule+0x478/0x764
>>>   schedule+0x9c/0xe0
>>>   blk_queue_enter+0x158/0x228
>>>   blk_mq_alloc_request+0x40/0xa4
>>>   blk_get_request+0x2c/0x70
>>>   __scsi_execute+0x60/0x1c4
>>>   ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>>   ufshcd_suspend+0x208/0x83c
>>>   ufshcd_runtime_suspend+0x40/0x154
>>>   ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>>   pm_generic_runtime_suspend+0x28/0x3c
>>>   __rpm_callback+0x80/0x2a4
>>>   rpm_suspend+0x308/0x614
>>>   rpm_idle+0x158/0x228
>>>   pm_runtime_work+0x84/0xac
>>>   process_one_work+0x1f0/0x470
>>>   worker_thread+0x26c/0x4c8
>>>   kthread+0x13c/0x320
>>>   ret_from_fork+0x10/0x18
>>>
>>> Fix this by registering ufs device wlun as a scsi driver and
>>> registering it for block runtime-pm. Also make this as a
>>> supplier for all other luns. That way, this device wlun
>>> suspends after all the consumers and resumes after
>>> hba resumes.
>>>
>>> Co-developed-by: Can Guo 
>>> Signed-off-by: Can Guo 
>>> Signed-off-by: Asutosh Das 
>>> ---
>>
> Hi Adrian
> Thanks for the comments.
>> Looks good but still doesn't seem to based on the latest tree.
>>
> Umm, it's based on the below:
> git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
> Branch: refs/heads/for-next
> 
> The top most change is e27f3c8 on 27th March'21.
> Which tree are you referring to that'd be latest?

Dunno, but that seems to be missing:

  commit aa53f580e67b49ec5f4d9bd1de81eb9eb0dc079f
  Author: Can Guo 
  Date:   Tue Feb 23 21:36:47 2021 -0800

scsi: ufs: Minor adjustments to error handling

which is in v5.12-rc3

> 
>> Also came across the issue below:
>>
>> 
>>
>>> +#ifdef CONFIG_PM_SLEEP
>>> +static int ufshcd_wl_poweroff(struct device *dev)
>>> +{
>>> +    ufshcd_wl_shutdown(dev);
>>
>> This turned out to be wrong.  This is a PM op and SCSI has already
>> quiesced the sdev's.  All that is needed isOk. I'll fix it in the next 
>> version.
> 
>>
>> __ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);
>>
>>> +    return 0;
>>> +}
>>> +#endif
> 
> 



Re: [PATCH v14 1/2] scsi: ufs: Enable power management for wlun

2021-03-31 Thread Adrian Hunter
On 31/03/21 1:31 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---

Looks good but still doesn't seem to based on the latest tree.

Also came across the issue below:



> +#ifdef CONFIG_PM_SLEEP
> +static int ufshcd_wl_poweroff(struct device *dev)
> +{
> + ufshcd_wl_shutdown(dev);

This turned out to be wrong.  This is a PM op and SCSI has already
quiesced the sdev's.  All that is needed is:

__ufshcd_wl_suspend(hba, UFS_SHUTDOWN_PM);

> + return 0;
> +}
> +#endif


Re: [PATCH v13 1/2] scsi: ufs: Enable power management for wlun

2021-03-30 Thread Adrian Hunter
On 25/03/21 3:39 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU (START_STOP_UNIT) to wlun
> during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 

A few comments below, but also:
- re-base
- change ufs_debugfs_get/put_user_access() to use
scsi_autopm_get/put_device(hba->sdev_ufs_device);

> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-debugfs.c |   2 +-
>  drivers/scsi/ufs/ufs-debugfs.h |   2 +-
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|  12 +-
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>  drivers/scsi/ufs/ufshcd.c  | 627 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   6 +
>  include/trace/events/ufs.h |  20 ++
>  13 files changed, 496 insertions(+), 225 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
> index dee98dc..06457d5 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.c
> +++ b/drivers/scsi/ufs/ufs-debugfs.c
> @@ -13,7 +13,7 @@ void __init ufs_debugfs_init(void)
>   ufs_debugfs_root = debugfs_create_dir("ufshcd", NULL);
>  }
>  
> -void __exit ufs_debugfs_exit(void)
> +void ufs_debugfs_exit(void)
>  {
>   debugfs_remove_recursive(ufs_debugfs_root);
>  }
> diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
> index f35b39c..12c2730 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.h
> +++ b/drivers/scsi/ufs/ufs-debugfs.h
> @@ -9,7 +9,7 @@ struct ufs_hba;
>  
>  #ifdef CONFIG_DEBUG_FS
>  void __init ufs_debugfs_init(void);
> -void __exit ufs_debugfs_exit(void);
> +void ufs_debugfs_exit(void);
>  void ufs_debugfs_hba_init(struct ufs_hba *hba);
>  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
>  #else
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= 

Re: [PATCH v12 1/2] scsi: ufs: Enable power management for wlun

2021-03-25 Thread Adrian Hunter
On 25/03/21 4:14 am, Asutosh Das (asd) wrote:
> On 3/23/2021 12:19 PM, Adrian Hunter wrote:
>> On 23/03/21 5:13 pm, Asutosh Das (asd) wrote:
>>> On 3/22/2021 11:12 PM, Adrian Hunter wrote:
>>>> On 22/03/21 9:53 pm, Asutosh Das (asd) wrote:
>>>>> On 3/19/2021 10:47 AM, Adrian Hunter wrote:
>>>>>> On 19/03/21 2:35 am, Asutosh Das wrote:
>>>>>>> During runtime-suspend of ufs host, the scsi devices are
>>>>>>> already suspended and so are the queues associated with them.
>>>>>>> But the ufs host sends SSU to wlun during its runtime-suspend.
>>>>>>> During the process blk_queue_enter checks if the queue is not in
>>>>>>> suspended state. If so, it waits for the queue to resume, and never
>>>>>>> comes out of it.
>>>>>>> The commit
>>>>>>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>>>>>>> adds the check if the queue is in suspended state in blk_queue_enter().
>>>>>>>
>>>>>>> Call trace:
>>>>>>>     __switch_to+0x174/0x2c4
>>>>>>>     __schedule+0x478/0x764
>>>>>>>     schedule+0x9c/0xe0
>>>>>>>     blk_queue_enter+0x158/0x228
>>>>>>>     blk_mq_alloc_request+0x40/0xa4
>>>>>>>     blk_get_request+0x2c/0x70
>>>>>>>     __scsi_execute+0x60/0x1c4
>>>>>>>     ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>>>>>>     ufshcd_suspend+0x208/0x83c
>>>>>>>     ufshcd_runtime_suspend+0x40/0x154
>>>>>>>     ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>>>>>>     pm_generic_runtime_suspend+0x28/0x3c
>>>>>>>     __rpm_callback+0x80/0x2a4
>>>>>>>     rpm_suspend+0x308/0x614
>>>>>>>     rpm_idle+0x158/0x228
>>>>>>>     pm_runtime_work+0x84/0xac
>>>>>>>     process_one_work+0x1f0/0x470
>>>>>>>     worker_thread+0x26c/0x4c8
>>>>>>>     kthread+0x13c/0x320
>>>>>>>     ret_from_fork+0x10/0x18
>>>>>>>
>>>>>>> Fix this by registering ufs device wlun as a scsi driver and
>>>>>>> registering it for block runtime-pm. Also make this as a
>>>>>>> supplier for all other luns. That way, this device wlun
>>>>>>> suspends after all the consumers and resumes after
>>>>>>> hba resumes.
>>>>>>>
>>>>>>> Co-developed-by: Can Guo 
>>>>>>> Signed-off-by: Can Guo 
>>>>>>> Signed-off-by: Asutosh Das 
>>>>>>
>>>>>> I have some more comments that may help straighten things out.
>>>>>>
>>>>>> Also please look at ufs_debugfs_get_user_access() and
>>>>>> ufs_debugfs_put_user_access() that now need to scsi_autopm_get/put_device
>>>>>> sdev_ufs_device.
>>>>>>
>>>>>> It would also be good if you could re-base on linux-next.
>>>>>>
>>>>>
>>>>> Hi Adrian
>>>>> Thanks for the comments.
>>>>>
>>>>> I agree moving the code to wlun probe and other changes.
>>>>> But it looks to me that it may not fully solve the issue.
>>>>>
>>>>> Please let me explain my understanding on this:
>>>>>
>>>>> (Please refer to the logs in v10)
>>>>> scsi_autopm_*() are invoked on a sdev.
>>>>> pm_runtime_get_suppliers()/rpm_put_suppliers() are on the supplier device.
>>>>>
>>>>> For the device wlun:
>>>>>   slave_configure():
>>>>>   - doesn't set the rpm_autosuspend
>>>>>   - pm_runtime_getnoresume()
>>>>>   scsi_sysfs_add_sdev():
>>>>>   - pm_runtime_forbid()
>>>>>   - scsi_autopm_get_device()
>>>>>   - device_add()
>>>>>   - ufshcd_wl_probe()
>>>>>   - scsi_autopm_put_device()
>>>>>
>>>>> For all other scsi devices:
>>>>>   slave_alloc():
>>>>>   - ufshcd_setup_links()
>>>>> Say all link_add: pm_runtime_put(>sdev_ufs_device->sdev_gendev);
>>>>
>>>> With DL_FLAG_RPM_A

Re: [PATCH v12 1/2] scsi: ufs: Enable power management for wlun

2021-03-23 Thread Adrian Hunter
On 23/03/21 5:13 pm, Asutosh Das (asd) wrote:
> On 3/22/2021 11:12 PM, Adrian Hunter wrote:
>> On 22/03/21 9:53 pm, Asutosh Das (asd) wrote:
>>> On 3/19/2021 10:47 AM, Adrian Hunter wrote:
>>>> On 19/03/21 2:35 am, Asutosh Das wrote:
>>>>> During runtime-suspend of ufs host, the scsi devices are
>>>>> already suspended and so are the queues associated with them.
>>>>> But the ufs host sends SSU to wlun during its runtime-suspend.
>>>>> During the process blk_queue_enter checks if the queue is not in
>>>>> suspended state. If so, it waits for the queue to resume, and never
>>>>> comes out of it.
>>>>> The commit
>>>>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>>>>> adds the check if the queue is in suspended state in blk_queue_enter().
>>>>>
>>>>> Call trace:
>>>>>    __switch_to+0x174/0x2c4
>>>>>    __schedule+0x478/0x764
>>>>>    schedule+0x9c/0xe0
>>>>>    blk_queue_enter+0x158/0x228
>>>>>    blk_mq_alloc_request+0x40/0xa4
>>>>>    blk_get_request+0x2c/0x70
>>>>>    __scsi_execute+0x60/0x1c4
>>>>>    ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>>>>    ufshcd_suspend+0x208/0x83c
>>>>>    ufshcd_runtime_suspend+0x40/0x154
>>>>>    ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>>>>    pm_generic_runtime_suspend+0x28/0x3c
>>>>>    __rpm_callback+0x80/0x2a4
>>>>>    rpm_suspend+0x308/0x614
>>>>>    rpm_idle+0x158/0x228
>>>>>    pm_runtime_work+0x84/0xac
>>>>>    process_one_work+0x1f0/0x470
>>>>>    worker_thread+0x26c/0x4c8
>>>>>    kthread+0x13c/0x320
>>>>>    ret_from_fork+0x10/0x18
>>>>>
>>>>> Fix this by registering ufs device wlun as a scsi driver and
>>>>> registering it for block runtime-pm. Also make this as a
>>>>> supplier for all other luns. That way, this device wlun
>>>>> suspends after all the consumers and resumes after
>>>>> hba resumes.
>>>>>
>>>>> Co-developed-by: Can Guo 
>>>>> Signed-off-by: Can Guo 
>>>>> Signed-off-by: Asutosh Das 
>>>>
>>>> I have some more comments that may help straighten things out.
>>>>
>>>> Also please look at ufs_debugfs_get_user_access() and
>>>> ufs_debugfs_put_user_access() that now need to scsi_autopm_get/put_device
>>>> sdev_ufs_device.
>>>>
>>>> It would also be good if you could re-base on linux-next.
>>>>
>>>
>>> Hi Adrian
>>> Thanks for the comments.
>>>
>>> I agree moving the code to wlun probe and other changes.
>>> But it looks to me that it may not fully solve the issue.
>>>
>>> Please let me explain my understanding on this:
>>>
>>> (Please refer to the logs in v10)
>>> scsi_autopm_*() are invoked on a sdev.
>>> pm_runtime_get_suppliers()/rpm_put_suppliers() are on the supplier device.
>>>
>>> For the device wlun:
>>>  slave_configure():
>>>  - doesn't set the rpm_autosuspend
>>>  - pm_runtime_getnoresume()
>>>  scsi_sysfs_add_sdev():
>>>  - pm_runtime_forbid()
>>>  - scsi_autopm_get_device()
>>>  - device_add()
>>>  - ufshcd_wl_probe()
>>>  - scsi_autopm_put_device()
>>>
>>> For all other scsi devices:
>>>  slave_alloc():
>>>  - ufshcd_setup_links()
>>> Say all link_add: pm_runtime_put(>sdev_ufs_device->sdev_gendev);
>>
>> With DL_FLAG_RPM_ACTIVE, links will 'get' not 'put'
>>
> I'm referring to the pm_runtime_put(sdev_ufs_device) after all the links are 
> setup, that you suggested to add.

Ok

>>>  slave_configure():
>>>  - set rpm_autosuspend
>>>  scsi_sysfs_add_sdev():
>>>  - scsi_autopm_get_device()
>>>  - device_add() -> schedules an async probe()
>>>  - scsi_autopm_put_device() - (1)
>>>
>>> Now the rpm_put_suppliers() can be invoked *after* 
>>> pm_runtime_get_suppliers() of the async probe(), since both are running in 
>>> different contexts.
>>
>> Only if the sd device suspends.
>>
> Correct. What'd stop the sd device from suspending?
> We should be stopping the sd 

Re: [PATCH v12 1/2] scsi: ufs: Enable power management for wlun

2021-03-23 Thread Adrian Hunter
On 22/03/21 9:53 pm, Asutosh Das (asd) wrote:
> On 3/19/2021 10:47 AM, Adrian Hunter wrote:
>> On 19/03/21 2:35 am, Asutosh Das wrote:
>>> During runtime-suspend of ufs host, the scsi devices are
>>> already suspended and so are the queues associated with them.
>>> But the ufs host sends SSU to wlun during its runtime-suspend.
>>> During the process blk_queue_enter checks if the queue is not in
>>> suspended state. If so, it waits for the queue to resume, and never
>>> comes out of it.
>>> The commit
>>> (d55d15a33: scsi: block: Do not accept any requests while suspended)
>>> adds the check if the queue is in suspended state in blk_queue_enter().
>>>
>>> Call trace:
>>>   __switch_to+0x174/0x2c4
>>>   __schedule+0x478/0x764
>>>   schedule+0x9c/0xe0
>>>   blk_queue_enter+0x158/0x228
>>>   blk_mq_alloc_request+0x40/0xa4
>>>   blk_get_request+0x2c/0x70
>>>   __scsi_execute+0x60/0x1c4
>>>   ufshcd_set_dev_pwr_mode+0x124/0x1e4
>>>   ufshcd_suspend+0x208/0x83c
>>>   ufshcd_runtime_suspend+0x40/0x154
>>>   ufshcd_pltfrm_runtime_suspend+0x14/0x20
>>>   pm_generic_runtime_suspend+0x28/0x3c
>>>   __rpm_callback+0x80/0x2a4
>>>   rpm_suspend+0x308/0x614
>>>   rpm_idle+0x158/0x228
>>>   pm_runtime_work+0x84/0xac
>>>   process_one_work+0x1f0/0x470
>>>   worker_thread+0x26c/0x4c8
>>>   kthread+0x13c/0x320
>>>   ret_from_fork+0x10/0x18
>>>
>>> Fix this by registering ufs device wlun as a scsi driver and
>>> registering it for block runtime-pm. Also make this as a
>>> supplier for all other luns. That way, this device wlun
>>> suspends after all the consumers and resumes after
>>> hba resumes.
>>>
>>> Co-developed-by: Can Guo 
>>> Signed-off-by: Can Guo 
>>> Signed-off-by: Asutosh Das 
>>
>> I have some more comments that may help straighten things out.
>>
>> Also please look at ufs_debugfs_get_user_access() and
>> ufs_debugfs_put_user_access() that now need to scsi_autopm_get/put_device
>> sdev_ufs_device.
>>
>> It would also be good if you could re-base on linux-next.
>>
> 
> Hi Adrian
> Thanks for the comments.
> 
> I agree moving the code to wlun probe and other changes.
> But it looks to me that it may not fully solve the issue.
> 
> Please let me explain my understanding on this:
> 
> (Please refer to the logs in v10)
> scsi_autopm_*() are invoked on a sdev.
> pm_runtime_get_suppliers()/rpm_put_suppliers() are on the supplier device.
> 
> For the device wlun:
> slave_configure():
>     - doesn't set the rpm_autosuspend
>     - pm_runtime_getnoresume()
> scsi_sysfs_add_sdev():
>     - pm_runtime_forbid()
>     - scsi_autopm_get_device()
>     - device_add()
>     - ufshcd_wl_probe()
>     - scsi_autopm_put_device()
> 
> For all other scsi devices:
> slave_alloc():
>     - ufshcd_setup_links()
> Say all link_add: pm_runtime_put(>sdev_ufs_device->sdev_gendev);

With DL_FLAG_RPM_ACTIVE, links will 'get' not 'put'

> slave_configure():
>     - set rpm_autosuspend
> scsi_sysfs_add_sdev():
>     - scsi_autopm_get_device()
>     - device_add() -> schedules an async probe()
>     - scsi_autopm_put_device() - (1)
> 
> Now the rpm_put_suppliers() can be invoked *after* pm_runtime_get_suppliers() 
> of the async probe(), since both are running in different contexts.

Only if the sd device suspends.

> In that case, the usage_count of supplier would be decremented until 
> rpm_active of this link becomes 1.

Right, because the sd device suspended.

> Now the pm_runtime_get_suppliers() expects the link_active to be more than 1.

Not sure what you mean here. pm_runtime_*put*_suppliers() won't do anything if 
the link count is 1.

> Now then, there comes a time, that when sd_probe() schedules a suspend, the 
> supplier usage_count becomes 0 and the link_active becomes 1.
> And the supplier suspends before the consumer.

sd probe first resumes the sd device which will resume the supplier.

> 
> So I was wondering, what'd make sure that the pm_runtime_get_suppliers() from 
> driver_probe_device() is invoked after scsi_autopm_put_device() (1) finishes 
> the rpm_put_suppliers().
> 
> Am not sure if I'm missing something in this.
> Do you think, the current changes alone can fix the above issue?

Yes, but let's see.

> 
> -asd
> 
>>> ---
>>>   drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>>>   drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>>>   d

Re: [PATCH 2/2] mmc: block: Update ext_csd.cache_ctrl if it was written

2021-03-22 Thread Adrian Hunter
On 22/03/21 3:36 pm, Avri Altman wrote:
> The cache function can be turned ON and OFF by writing to the CACHE_CTRL
> byte (EXT_CSD byte [33]).  However,  card->ext_csd.cache_ctrl is only
> set on init if cache size > 0.
> 
> Fix that by explicitly setting ext_csd.cache_ctrl on ext-csd write.
> 
> Signed-off-by: Avri Altman 
> ---
>  drivers/mmc/core/block.c | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index a93c66aa91db..4c816d001ac1 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -571,6 +571,14 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, 
> struct mmc_blk_data *md,
>   main_md->part_curr = value & EXT_CSD_PART_CONFIG_ACC_MASK;
>   }
>  
> + /* Make sure to update CACHE_CTRL in case it was changed */

It might be worth noting that the cache will get turned back
on if the card is re-initialized, for example suspend/resume or
hw reset in recovery.

> + if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) &&
> + (cmd.opcode == MMC_SWITCH)) {
> + u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1;
> +
> + card->ext_csd.cache_ctrl = value;
> + }
> +
>   /*
>* According to the SD specs, some commands require a delay after
>* issuing the command.
> 



Re: [PATCH 1/2] mmc: block: Issue flush only if allowed

2021-03-22 Thread Adrian Hunter
On 22/03/21 3:36 pm, Avri Altman wrote:
> The cache may be flushed to the nonvolatile storage by writing to
> FLUSH_CACHE byte (EXT_CSD byte [32]). When in command queueing mode, the
> cache may be flushed by issuing a CMDQ_TASK_ DEV_MGMT (CMD48) with a
> FLUSH_CACHE op-code.  Either way, verify that The cache function is
> turned ON before doing so.
> 
> fixes: 1e8e55b67030 (mmc: block: Add CQE support)
> 
> Reported-by: Brendan Peter 
> Tested-by: Brendan Peter 
> Signed-off-by: Avri Altman 
> ---
>  drivers/mmc/core/block.c   | 3 +++
>  drivers/mmc/core/mmc_ops.c | 4 +---
>  drivers/mmc/core/mmc_ops.h | 5 +
>  3 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 42e27a298218..a93c66aa91db 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -1473,6 +1473,9 @@ static int mmc_blk_cqe_issue_flush(struct mmc_queue 
> *mq, struct request *req)
>   struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
>   struct mmc_request *mrq = mmc_blk_cqe_prep_dcmd(mqrq, req);
>  
> + if (mmc_card_mmc(mq->card) && !mmc_flush_allowed(mq->card))
> + return 0;

Returning 0 means the flush was issued successfully. i.e. it is in
flight.

Instead, a call to blk_mq_end_request(req, BLK_STS_OK) is needed,
and mmc_blk_mq_issue_rq() must be amended so that it will return
MMC_REQ_DONE for this case.

> +
>   mrq->cmd->opcode = MMC_SWITCH;
>   mrq->cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
>   (EXT_CSD_FLUSH_CACHE << 16) |
> diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
> index baa6314f69b4..b8a0c9ac8a20 100644
> --- a/drivers/mmc/core/mmc_ops.c
> +++ b/drivers/mmc/core/mmc_ops.c
> @@ -988,9 +988,7 @@ int mmc_flush_cache(struct mmc_card *card)
>  {
>   int err = 0;
>  
> - if (mmc_card_mmc(card) &&
> - (card->ext_csd.cache_size > 0) &&
> - (card->ext_csd.cache_ctrl & 1)) {
> + if (mmc_card_mmc(card) && mmc_flush_allowed(card)) {
>   err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>EXT_CSD_FLUSH_CACHE, 1,
>MMC_CACHE_FLUSH_TIMEOUT_MS);
> diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
> index 632009260e51..bf2b315addd7 100644
> --- a/drivers/mmc/core/mmc_ops.h
> +++ b/drivers/mmc/core/mmc_ops.h
> @@ -19,6 +19,11 @@ enum mmc_busy_cmd {
>  struct mmc_host;
>  struct mmc_card;
>  
> +static inline bool mmc_flush_allowed(struct mmc_card *card)
> +{
> + return card->ext_csd.cache_size > 0 && (card->ext_csd.cache_ctrl & 1);
> +}
> +
>  int mmc_select_card(struct mmc_card *card);
>  int mmc_deselect_cards(struct mmc_host *host);
>  int mmc_set_dsr(struct mmc_host *host);
> 



Re: [PATCH v12 1/2] scsi: ufs: Enable power management for wlun

2021-03-19 Thread Adrian Hunter
On 19/03/21 2:35 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 

I have some more comments that may help straighten things out.

Also please look at ufs_debugfs_get_user_access() and
ufs_debugfs_put_user_access() that now need to scsi_autopm_get/put_device
sdev_ufs_device.

It would also be good if you could re-base on linux-next.

> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-debugfs.c |   2 +-
>  drivers/scsi/ufs/ufs-debugfs.h |   2 +-
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|  12 +-
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>  drivers/scsi/ufs/ufshcd.c  | 622 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   6 +
>  include/trace/events/ufs.h |  20 ++
>  13 files changed, 491 insertions(+), 225 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
> index dee98dc..06457d5 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.c
> +++ b/drivers/scsi/ufs/ufs-debugfs.c
> @@ -13,7 +13,7 @@ void __init ufs_debugfs_init(void)
>   ufs_debugfs_root = debugfs_create_dir("ufshcd", NULL);
>  }
>  
> -void __exit ufs_debugfs_exit(void)
> +void ufs_debugfs_exit(void)
>  {
>   debugfs_remove_recursive(ufs_debugfs_root);
>  }
> diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
> index f35b39c..12c2730 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.h
> +++ b/drivers/scsi/ufs/ufs-debugfs.h
> @@ -9,7 +9,7 @@ struct ufs_hba;
>  
>  #ifdef CONFIG_DEBUG_FS
>  void __init ufs_debugfs_init(void);
> -void __exit ufs_debugfs_exit(void);
> +void ufs_debugfs_exit(void);
>  void ufs_debugfs_hba_init(struct ufs_hba *hba);
>  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
>  #else
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = 

Re: [PATCH v10 1/2] scsi: ufs: Enable power management for wlun

2021-03-18 Thread Adrian Hunter
On 18/03/21 7:58 pm, Asutosh Das (asd) wrote:
> On 3/18/2021 10:54 AM, Rafael J. Wysocki wrote:
>> On Thu, Mar 18, 2021 at 6:33 PM Asutosh Das (asd)
>>  wrote:
>>>
>>> On 3/18/2021 7:00 AM, Rafael J. Wysocki wrote:
>>>> On Wed, Mar 17, 2021 at 7:37 AM Adrian Hunter  
>>>> wrote:
>>>>>
>>>>> On 16/03/21 10:35 pm, Asutosh Das (asd) wrote:
>>>>>> On 3/16/2021 12:48 AM, Adrian Hunter wrote:
>>>>>>> On 16/03/21 12:22 am, Asutosh Das (asd) wrote:
>>>>>>>> On 3/14/2021 1:11 AM, Adrian Hunter wrote:
>>>>>>>>> On 10/03/21 5:04 am, Asutosh Das (asd) wrote:
>>>>>>>>>> On 3/9/2021 7:56 AM, Asutosh Das (asd) wrote:
>>>>>>>>>>> On 3/8/2021 9:17 AM, Rafael J. Wysocki wrote:
>>>>>>>>>>>> On Mon, Mar 8, 2021 at 5:21 PM Rafael J. Wysocki 
>>>>>>>>>>>>  wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Sat, Mar 6, 2021 at 5:17 PM Alan Stern 
>>>>>>>>>>>>>  wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Fri, Mar 05, 2021 at 06:54:24PM -0800, Asutosh Das (asd) 
>>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Now during my testing I see a weird issue sometimes (1 in 7).
>>>>>>>>>>>>>>> Scenario - bootups
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Issue:
>>>>>>>>>>>>>>> The supplier 'ufs_device_wlun 0:0:0:49488' goes into runtime 
>>>>>>>>>>>>>>> suspend even
>>>>>>>>>>>>>>> when one/more of its consumers are in RPM_ACTIVE state.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> *Log:
>>>>>>>>>>>>>>> [   10.056379][  T206] sd 0:0:0:1: [sdb] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.062497][  T113] sd 0:0:0:5: [sdf] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.356600][   T32] sd 0:0:0:7: [sdh] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.362944][  T174] sd 0:0:0:3: [sdd] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.696627][   T83] sd 0:0:0:2: [sdc] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.704562][  T170] sd 0:0:0:6: [sdg] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>> [   10.980602][    T5] sd 0:0:0:0: [sda] Synchronizing SCSI 
>>>>>>>>>>>>>>> cache
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> /** Printing all the consumer nodes of supplier **/
>>>>>>>>>>>>>>> [   10.987327][    T5] ufs_device_wlun 0:0:0:49488: usage-count 
>>>>>>>>>>>>>>> @ suspend: 0
>>>>>>>>>>>>>>> <-- this is the usage_count
>>>>>>>>>>>>>>> [   10.994440][    T5] ufs_rpmb_wlun 0:0:0:49476: PM state - 2
>>>>>>>>>>>>>>> [   11.000402][    T5] scsi 0:0:0:49456: PM state - 2
>>>>>>>>>>>>>>> [   11.005453][    T5] sd 0:0:0:0: PM state - 2
>>>>>>>>>>>>>>> [   11.009958][    T5] sd 0:0:0:1: PM state - 2
>>>>>>>>>>>>>>> [   11.014469][    T5] sd 0:0:0:2: PM state - 2
>>>>>>>>>>>>>>> [   11.019072][    T5] sd 0:0:0:3: PM state - 2
>>>>>>>>>>>>>>> [   11.023595][    T5] sd 0:0:0:4: PM state - 0 << RPM_ACTIVE
>>>>>>>>>>&

Re: [PATCH v10 1/2] scsi: ufs: Enable power management for wlun

2021-03-17 Thread Adrian Hunter
On 16/03/21 10:35 pm, Asutosh Das (asd) wrote:
> On 3/16/2021 12:48 AM, Adrian Hunter wrote:
>> On 16/03/21 12:22 am, Asutosh Das (asd) wrote:
>>> On 3/14/2021 1:11 AM, Adrian Hunter wrote:
>>>> On 10/03/21 5:04 am, Asutosh Das (asd) wrote:
>>>>> On 3/9/2021 7:56 AM, Asutosh Das (asd) wrote:
>>>>>> On 3/8/2021 9:17 AM, Rafael J. Wysocki wrote:
>>>>>>> On Mon, Mar 8, 2021 at 5:21 PM Rafael J. Wysocki  
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> On Sat, Mar 6, 2021 at 5:17 PM Alan Stern  
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> On Fri, Mar 05, 2021 at 06:54:24PM -0800, Asutosh Das (asd) wrote:
>>>>>>>>>
>>>>>>>>>> Now during my testing I see a weird issue sometimes (1 in 7).
>>>>>>>>>> Scenario - bootups
>>>>>>>>>>
>>>>>>>>>> Issue:
>>>>>>>>>> The supplier 'ufs_device_wlun 0:0:0:49488' goes into runtime suspend 
>>>>>>>>>> even
>>>>>>>>>> when one/more of its consumers are in RPM_ACTIVE state.
>>>>>>>>>>
>>>>>>>>>> *Log:
>>>>>>>>>> [   10.056379][  T206] sd 0:0:0:1: [sdb] Synchronizing SCSI cache
>>>>>>>>>> [   10.062497][  T113] sd 0:0:0:5: [sdf] Synchronizing SCSI cache
>>>>>>>>>> [   10.356600][   T32] sd 0:0:0:7: [sdh] Synchronizing SCSI cache
>>>>>>>>>> [   10.362944][  T174] sd 0:0:0:3: [sdd] Synchronizing SCSI cache
>>>>>>>>>> [   10.696627][   T83] sd 0:0:0:2: [sdc] Synchronizing SCSI cache
>>>>>>>>>> [   10.704562][  T170] sd 0:0:0:6: [sdg] Synchronizing SCSI cache
>>>>>>>>>> [   10.980602][T5] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>>>>>>>>>
>>>>>>>>>> /** Printing all the consumer nodes of supplier **/
>>>>>>>>>> [   10.987327][T5] ufs_device_wlun 0:0:0:49488: usage-count @ 
>>>>>>>>>> suspend: 0
>>>>>>>>>> <-- this is the usage_count
>>>>>>>>>> [   10.994440][T5] ufs_rpmb_wlun 0:0:0:49476: PM state - 2
>>>>>>>>>> [   11.000402][T5] scsi 0:0:0:49456: PM state - 2
>>>>>>>>>> [   11.005453][T5] sd 0:0:0:0: PM state - 2
>>>>>>>>>> [   11.009958][T5] sd 0:0:0:1: PM state - 2
>>>>>>>>>> [   11.014469][T5] sd 0:0:0:2: PM state - 2
>>>>>>>>>> [   11.019072][T5] sd 0:0:0:3: PM state - 2
>>>>>>>>>> [   11.023595][T5] sd 0:0:0:4: PM state - 0 << RPM_ACTIVE
>>>>>>>>>> [   11.353298][T5] sd 0:0:0:5: PM state - 2
>>>>>>>>>> [   11.357726][T5] sd 0:0:0:6: PM state - 2
>>>>>>>>>> [   11.362155][T5] sd 0:0:0:7: PM state - 2
>>>>>>>>>> [   11.366584][T5] ufshcd-qcom 1d84000.ufshc: 
>>>>>>>>>> __ufshcd_wl_suspend - 8709
>>>>>>>>>> [   11.374366][T5] ufs_device_wlun 0:0:0:49488: 
>>>>>>>>>> __ufshcd_wl_suspend -
>>>>>>>>>> (0) has rpm_active flags
>>>>>>>>
>>>>>>>> Do you mean that rpm_active of the link between the consumer and the
>>>>>>>> supplier is greater than 0 at this point and the consumer is
>>>>>>>
>>>>>>> I mean is rpm_active of the link greater than 1 (because 1 means "no
>>>>>>> active references to the supplier")?
>>>>>> Hi Rafael:
>>>>>> No - it is not greater than 1.
>>>>>>
>>>>>> I'm trying to understand what's going on in it; will update when I've 
>>>>>> something.
>>>>>>
>>>>>>>
>>>>>>>> RPM_ACTIVE, but the supplier suspends successfully nevertheless?
>>>>>>>>
>>>>>>>>>> [   11.383376][T5] ufs_device_wlun 0:0:0:49488:
>>>>>>>>>> ufshcd_wl_runtime_suspend <-- Supplier suspends fine.
>>>>>>>>>> [   12.977318][  T174

Re: [PATCH v10 1/2] scsi: ufs: Enable power management for wlun

2021-03-16 Thread Adrian Hunter
On 16/03/21 12:22 am, Asutosh Das (asd) wrote:
> On 3/14/2021 1:11 AM, Adrian Hunter wrote:
>> On 10/03/21 5:04 am, Asutosh Das (asd) wrote:
>>> On 3/9/2021 7:56 AM, Asutosh Das (asd) wrote:
>>>> On 3/8/2021 9:17 AM, Rafael J. Wysocki wrote:
>>>>> On Mon, Mar 8, 2021 at 5:21 PM Rafael J. Wysocki  
>>>>> wrote:
>>>>>>
>>>>>> On Sat, Mar 6, 2021 at 5:17 PM Alan Stern  
>>>>>> wrote:
>>>>>>>
>>>>>>> On Fri, Mar 05, 2021 at 06:54:24PM -0800, Asutosh Das (asd) wrote:
>>>>>>>
>>>>>>>> Now during my testing I see a weird issue sometimes (1 in 7).
>>>>>>>> Scenario - bootups
>>>>>>>>
>>>>>>>> Issue:
>>>>>>>> The supplier 'ufs_device_wlun 0:0:0:49488' goes into runtime suspend 
>>>>>>>> even
>>>>>>>> when one/more of its consumers are in RPM_ACTIVE state.
>>>>>>>>
>>>>>>>> *Log:
>>>>>>>> [   10.056379][  T206] sd 0:0:0:1: [sdb] Synchronizing SCSI cache
>>>>>>>> [   10.062497][  T113] sd 0:0:0:5: [sdf] Synchronizing SCSI cache
>>>>>>>> [   10.356600][   T32] sd 0:0:0:7: [sdh] Synchronizing SCSI cache
>>>>>>>> [   10.362944][  T174] sd 0:0:0:3: [sdd] Synchronizing SCSI cache
>>>>>>>> [   10.696627][   T83] sd 0:0:0:2: [sdc] Synchronizing SCSI cache
>>>>>>>> [   10.704562][  T170] sd 0:0:0:6: [sdg] Synchronizing SCSI cache
>>>>>>>> [   10.980602][    T5] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>>>>>>>
>>>>>>>> /** Printing all the consumer nodes of supplier **/
>>>>>>>> [   10.987327][    T5] ufs_device_wlun 0:0:0:49488: usage-count @ 
>>>>>>>> suspend: 0
>>>>>>>> <-- this is the usage_count
>>>>>>>> [   10.994440][    T5] ufs_rpmb_wlun 0:0:0:49476: PM state - 2
>>>>>>>> [   11.000402][    T5] scsi 0:0:0:49456: PM state - 2
>>>>>>>> [   11.005453][    T5] sd 0:0:0:0: PM state - 2
>>>>>>>> [   11.009958][    T5] sd 0:0:0:1: PM state - 2
>>>>>>>> [   11.014469][    T5] sd 0:0:0:2: PM state - 2
>>>>>>>> [   11.019072][    T5] sd 0:0:0:3: PM state - 2
>>>>>>>> [   11.023595][    T5] sd 0:0:0:4: PM state - 0 << RPM_ACTIVE
>>>>>>>> [   11.353298][    T5] sd 0:0:0:5: PM state - 2
>>>>>>>> [   11.357726][    T5] sd 0:0:0:6: PM state - 2
>>>>>>>> [   11.362155][    T5] sd 0:0:0:7: PM state - 2
>>>>>>>> [   11.366584][    T5] ufshcd-qcom 1d84000.ufshc: __ufshcd_wl_suspend 
>>>>>>>> - 8709
>>>>>>>> [   11.374366][    T5] ufs_device_wlun 0:0:0:49488: 
>>>>>>>> __ufshcd_wl_suspend -
>>>>>>>> (0) has rpm_active flags
>>>>>>
>>>>>> Do you mean that rpm_active of the link between the consumer and the
>>>>>> supplier is greater than 0 at this point and the consumer is
>>>>>
>>>>> I mean is rpm_active of the link greater than 1 (because 1 means "no
>>>>> active references to the supplier")?
>>>> Hi Rafael:
>>>> No - it is not greater than 1.
>>>>
>>>> I'm trying to understand what's going on in it; will update when I've 
>>>> something.
>>>>
>>>>>
>>>>>> RPM_ACTIVE, but the supplier suspends successfully nevertheless?
>>>>>>
>>>>>>>> [   11.383376][    T5] ufs_device_wlun 0:0:0:49488:
>>>>>>>> ufshcd_wl_runtime_suspend <-- Supplier suspends fine.
>>>>>>>> [   12.977318][  T174] sd 0:0:0:4: [sde] Synchronizing SCSI cache
>>>>>>>>
>>>>>>>> And the the suspend of sde is stuck now:
>>>>>>>> schedule+0x9c/0xe0
>>>>>>>> schedule_timeout+0x40/0x128
>>>>>>>> io_schedule_timeout+0x44/0x68
>>>>>>>> wait_for_common_io+0x7c/0x100
>>>>>>>> wait_for_completion_io+0x14/0x20
>>>>>>>> blk_execute_rq+0x90/0xcc
>>>>>>>> __scsi_execute+0x104/0x1c4
>>>>>>>> sd_sync_cache+0xf8/0x2a0
&

Re: [PATCH v1 1/1] mmc: sdhci-acpi: Add support for NVIDIA BlueField-3 SoC

2021-03-15 Thread Adrian Hunter
On 15/03/21 7:00 pm, Liming Sun wrote:
> Thanks Adrian. Yes, I did consider adding this ACPI support into 
> sdhci-of-dwcmshc.c, but not sure which one is the preferred way.
> Is this (sdhci-of-dwcmshc.c) what you recommend? I'll post the revised 
> changes in patch v2.

Yes, that is generally preferred I think.

> 
>> -Original Message-
>> From: Adrian Hunter 
>> Sent: Monday, March 15, 2021 4:34 AM
>> To: Liming Sun ; Ulf Hansson ;
>> Khalil Blaiech 
>> Cc: linux-...@vger.kernel.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v1 1/1] mmc: sdhci-acpi: Add support for NVIDIA
>> BlueField-3 SoC
>>
>> On 12/03/21 3:48 pm, Liming Sun wrote:
>>> This commit adds ACPI support for the BlueField-3 SoC which uses
>>> the DWC_mshc eMMC controller. The boundary check logic in static
>>> function dwcmshc_adma_write_desc() comes from sdhci-of-dwcmshc.c.
>>
>> Did you consider adding ACPI support to sdhci-of-dwcmshc.c ?
>> Other drivers have taken that approach, see sdhci-xenon.c or sdhci-iproc.c
>>
>>>
>>> Signed-off-by: Liming Sun 
>>> Reviewed-by: Khalil Blaiech 
>>> ---
>>>  drivers/mmc/host/sdhci-acpi.c | 64
>> +++
>>>  1 file changed, 64 insertions(+)
>>>
>>> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
>>> index 54205e3..6448e94e 100644
>>> --- a/drivers/mmc/host/sdhci-acpi.c
>>> +++ b/drivers/mmc/host/sdhci-acpi.c
>>> @@ -716,6 +716,68 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct
>> platform_device *pdev,
>>> .priv_size  = sizeof(struct amd_sdhci_host),
>>>  };
>>>
>>> +/* Check DMA address/length boundary. */
>>> +static inline bool dwcmshc_adma_boundary_ok(dma_addr_t addr, int len)
>>> +{
>>> +   return (addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1));
>>> +}
>>> +
>>> +/*
>>> + * If DMA addr spans 128MB boundary, we split the DMA transfer into two
>>> + * so that each DMA transfer doesn't exceed the boundary.
>>> + */
>>> +static void dwcmshc_adma_write_desc(struct sdhci_host *host, void
>> **desc,
>>> +   dma_addr_t addr, int len, unsigned int cmd)
>>> +{
>>> +   int tmplen, offset;
>>> +
>>> +   if (likely(!len || dwcmshc_adma_boundary_ok(addr, len))) {
>>> +   sdhci_adma_write_desc(host, desc, addr, len, cmd);
>>> +   return;
>>> +   }
>>> +
>>> +   offset = addr & (SZ_128M - 1);
>>> +   tmplen = SZ_128M - offset;
>>> +   sdhci_adma_write_desc(host, desc, addr, tmplen, cmd);
>>> +
>>> +   addr += tmplen;
>>> +   len -= tmplen;
>>> +   sdhci_adma_write_desc(host, desc, addr, len, cmd);
>>> +}
>>> +
>>> +static int sdhci_acpi_emmc_nvda_bf_probe_slot(struct platform_device
>> *pdev,
>>> + struct acpi_device *adev)
>>> +{
>>> +   struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
>>> +   struct sdhci_host *host = c->host;
>>> +   u32 extra;
>>> +
>>> +   /* Extra adma table cnt for cross 128M boundary handling. */
>>> +   extra = DIV_ROUND_UP_ULL(dma_get_required_mask(>dev),
>> SZ_128M);
>>> +   extra = min(extra, (u32)SDHCI_MAX_SEGS);
>>> +   host->adma_table_cnt += extra;
>>> +
>>> +   return 0;
>>> +}
>>> +
>>> +static const struct sdhci_ops sdhci_acpi_ops_nvda_bf = {
>>> +   .set_clock  = sdhci_set_clock,
>>> +   .set_bus_width  = sdhci_set_bus_width,
>>> +   .set_uhs_signaling  = sdhci_set_uhs_signaling,
>>> +   .reset  = sdhci_reset,
>>> +   .adma_write_desc= dwcmshc_adma_write_desc,
>>> +};
>>> +
>>> +static const struct sdhci_acpi_chip sdhci_acpi_chip_nvda_bf = {
>>> +   .ops = _acpi_ops_nvda_bf,
>>> +};
>>> +
>>> +static const struct sdhci_acpi_slot sdhci_acpi_slot_nvda_bf_emmc = {
>>> +   .chip   = _acpi_chip_nvda_bf,
>>> +   .caps   = MMC_CAP_8_BIT_DATA |
>> MMC_CAP_NONREMOVABLE,
>>> +   .probe_slot = sdhci_acpi_emmc_nvda_bf_probe_slot,
>>> +};
>>> +
>>>  struct sdhci_acpi_uid_slot {
>>> const char *hid;
>>> const char *uid;
>>> @@ -740,6 +802,7 @@ struct sdhci_acpi_uid_slot {
>>> { "QCOM8051", NULL, _acpi_slot_qcom_sd_3v },
>>> { "QCOM8052", NULL, _acpi_slot_qcom_sd },
>>> { "AMDI0040", NULL, _acpi_slot_amd_emmc },
>>> +   { "MLNXBF30", NULL, _acpi_slot_nvda_bf_emmc },
>>> { },
>>>  };
>>>
>>> @@ -757,6 +820,7 @@ struct sdhci_acpi_uid_slot {
>>> { "QCOM8051" },
>>> { "QCOM8052" },
>>> { "AMDI0040" },
>>> +   { "MLNXBF30" },
>>> { },
>>>  };
>>>  MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
>>>
> 



Re: [PATCH v11 1/2] scsi: ufs: Enable power management for wlun

2021-03-15 Thread Adrian Hunter
On 12/03/21 12:19 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.

I haven't had time to try to reproduce the device-links issue, but
there are a couple of comments below, in addition to the suggestions
here:

https://lore.kernel.org/linux-scsi/b13086f3-eea1-51a7-2117-579d520f2...@intel.com/

Also, there are still ufshcd_err_handling_prepare()/unprepare()
and ufshcd_recover_pm_error(), that look like they need attention
e.g. to use scsi_autopm_get/put_device(hba->sdev_ufs_device)


> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-debugfs.c |   5 +
>  drivers/scsi/ufs/ufs-debugfs.h |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  36 +--
>  drivers/scsi/ufs/ufshcd.c  | 616 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  13 files changed, 498 insertions(+), 206 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
> index dee98dc..f8ce2eb 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.c
> +++ b/drivers/scsi/ufs/ufs-debugfs.c
> @@ -54,3 +54,8 @@ void ufs_debugfs_hba_exit(struct ufs_hba *hba)
>  {
>   debugfs_remove_recursive(hba->debugfs_root);
>  }
> +
> +void ufs_debugfs_eh_exit(void)
> +{
> + debugfs_remove_recursive(ufs_debugfs_root);
> +}

This is the same as ufs_debugfs_exit() without __exit so why not
remove __exit from ufs_debugfs_exit() and use that instead?

> diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
> index f35b39c..3fce5a0 100644
> --- a/drivers/scsi/ufs/ufs-debugfs.h
> +++ b/drivers/scsi/ufs/ufs-debugfs.h
> @@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
>  void __exit ufs_debugfs_exit(void);
>  void ufs_debugfs_hba_init(struct ufs_hba *hba);
>  void ufs_debugfs_hba_exit(struct ufs_hba *hba);
> +void ufs_debugfs_eh_exit(void);
>  #else
>  static inline void ufs_debugfs_init(void) {}
>  static inline void ufs_debugfs_exit(void) {}
>  static inline void 

Re: [PATCH v1 1/1] mmc: sdhci-acpi: Add support for NVIDIA BlueField-3 SoC

2021-03-15 Thread Adrian Hunter
On 12/03/21 3:48 pm, Liming Sun wrote:
> This commit adds ACPI support for the BlueField-3 SoC which uses
> the DWC_mshc eMMC controller. The boundary check logic in static
> function dwcmshc_adma_write_desc() comes from sdhci-of-dwcmshc.c.

Did you consider adding ACPI support to sdhci-of-dwcmshc.c ?
Other drivers have taken that approach, see sdhci-xenon.c or sdhci-iproc.c

> 
> Signed-off-by: Liming Sun 
> Reviewed-by: Khalil Blaiech 
> ---
>  drivers/mmc/host/sdhci-acpi.c | 64 
> +++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
> index 54205e3..6448e94e 100644
> --- a/drivers/mmc/host/sdhci-acpi.c
> +++ b/drivers/mmc/host/sdhci-acpi.c
> @@ -716,6 +716,68 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct 
> platform_device *pdev,
>   .priv_size  = sizeof(struct amd_sdhci_host),
>  };
>  
> +/* Check DMA address/length boundary. */
> +static inline bool dwcmshc_adma_boundary_ok(dma_addr_t addr, int len)
> +{
> + return (addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1));
> +}
> +
> +/*
> + * If DMA addr spans 128MB boundary, we split the DMA transfer into two
> + * so that each DMA transfer doesn't exceed the boundary.
> + */
> +static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc,
> + dma_addr_t addr, int len, unsigned int cmd)
> +{
> + int tmplen, offset;
> +
> + if (likely(!len || dwcmshc_adma_boundary_ok(addr, len))) {
> + sdhci_adma_write_desc(host, desc, addr, len, cmd);
> + return;
> + }
> +
> + offset = addr & (SZ_128M - 1);
> + tmplen = SZ_128M - offset;
> + sdhci_adma_write_desc(host, desc, addr, tmplen, cmd);
> +
> + addr += tmplen;
> + len -= tmplen;
> + sdhci_adma_write_desc(host, desc, addr, len, cmd);
> +}
> +
> +static int sdhci_acpi_emmc_nvda_bf_probe_slot(struct platform_device *pdev,
> +   struct acpi_device *adev)
> +{
> + struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
> + struct sdhci_host *host = c->host;
> + u32 extra;
> +
> + /* Extra adma table cnt for cross 128M boundary handling. */
> + extra = DIV_ROUND_UP_ULL(dma_get_required_mask(>dev), SZ_128M);
> + extra = min(extra, (u32)SDHCI_MAX_SEGS);
> + host->adma_table_cnt += extra;
> +
> + return 0;
> +}
> +
> +static const struct sdhci_ops sdhci_acpi_ops_nvda_bf = {
> + .set_clock  = sdhci_set_clock,
> + .set_bus_width  = sdhci_set_bus_width,
> + .set_uhs_signaling  = sdhci_set_uhs_signaling,
> + .reset  = sdhci_reset,
> + .adma_write_desc= dwcmshc_adma_write_desc,
> +};
> +
> +static const struct sdhci_acpi_chip sdhci_acpi_chip_nvda_bf = {
> + .ops = _acpi_ops_nvda_bf,
> +};
> +
> +static const struct sdhci_acpi_slot sdhci_acpi_slot_nvda_bf_emmc = {
> + .chip   = _acpi_chip_nvda_bf,
> + .caps   = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
> + .probe_slot = sdhci_acpi_emmc_nvda_bf_probe_slot,
> +};
> +
>  struct sdhci_acpi_uid_slot {
>   const char *hid;
>   const char *uid;
> @@ -740,6 +802,7 @@ struct sdhci_acpi_uid_slot {
>   { "QCOM8051", NULL, _acpi_slot_qcom_sd_3v },
>   { "QCOM8052", NULL, _acpi_slot_qcom_sd },
>   { "AMDI0040", NULL, _acpi_slot_amd_emmc },
> + { "MLNXBF30", NULL, _acpi_slot_nvda_bf_emmc },
>   { },
>  };
>  
> @@ -757,6 +820,7 @@ struct sdhci_acpi_uid_slot {
>   { "QCOM8051" },
>   { "QCOM8052" },
>   { "AMDI0040" },
> + { "MLNXBF30" },
>   { },
>  };
>  MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
> 



Re: [PATCH v10 1/2] scsi: ufs: Enable power management for wlun

2021-03-14 Thread Adrian Hunter
On 10/03/21 5:04 am, Asutosh Das (asd) wrote:
> On 3/9/2021 7:56 AM, Asutosh Das (asd) wrote:
>> On 3/8/2021 9:17 AM, Rafael J. Wysocki wrote:
>>> On Mon, Mar 8, 2021 at 5:21 PM Rafael J. Wysocki  wrote:

 On Sat, Mar 6, 2021 at 5:17 PM Alan Stern  
 wrote:
>
> On Fri, Mar 05, 2021 at 06:54:24PM -0800, Asutosh Das (asd) wrote:
>
>> Now during my testing I see a weird issue sometimes (1 in 7).
>> Scenario - bootups
>>
>> Issue:
>> The supplier 'ufs_device_wlun 0:0:0:49488' goes into runtime suspend even
>> when one/more of its consumers are in RPM_ACTIVE state.
>>
>> *Log:
>> [   10.056379][  T206] sd 0:0:0:1: [sdb] Synchronizing SCSI cache
>> [   10.062497][  T113] sd 0:0:0:5: [sdf] Synchronizing SCSI cache
>> [   10.356600][   T32] sd 0:0:0:7: [sdh] Synchronizing SCSI cache
>> [   10.362944][  T174] sd 0:0:0:3: [sdd] Synchronizing SCSI cache
>> [   10.696627][   T83] sd 0:0:0:2: [sdc] Synchronizing SCSI cache
>> [   10.704562][  T170] sd 0:0:0:6: [sdg] Synchronizing SCSI cache
>> [   10.980602][    T5] sd 0:0:0:0: [sda] Synchronizing SCSI cache
>>
>> /** Printing all the consumer nodes of supplier **/
>> [   10.987327][    T5] ufs_device_wlun 0:0:0:49488: usage-count @ 
>> suspend: 0
>> <-- this is the usage_count
>> [   10.994440][    T5] ufs_rpmb_wlun 0:0:0:49476: PM state - 2
>> [   11.000402][    T5] scsi 0:0:0:49456: PM state - 2
>> [   11.005453][    T5] sd 0:0:0:0: PM state - 2
>> [   11.009958][    T5] sd 0:0:0:1: PM state - 2
>> [   11.014469][    T5] sd 0:0:0:2: PM state - 2
>> [   11.019072][    T5] sd 0:0:0:3: PM state - 2
>> [   11.023595][    T5] sd 0:0:0:4: PM state - 0 << RPM_ACTIVE
>> [   11.353298][    T5] sd 0:0:0:5: PM state - 2
>> [   11.357726][    T5] sd 0:0:0:6: PM state - 2
>> [   11.362155][    T5] sd 0:0:0:7: PM state - 2
>> [   11.366584][    T5] ufshcd-qcom 1d84000.ufshc: __ufshcd_wl_suspend - 
>> 8709
>> [   11.374366][    T5] ufs_device_wlun 0:0:0:49488: __ufshcd_wl_suspend -
>> (0) has rpm_active flags

 Do you mean that rpm_active of the link between the consumer and the
 supplier is greater than 0 at this point and the consumer is
>>>
>>> I mean is rpm_active of the link greater than 1 (because 1 means "no
>>> active references to the supplier")?
>> Hi Rafael:
>> No - it is not greater than 1.
>>
>> I'm trying to understand what's going on in it; will update when I've 
>> something.
>>
>>>
 RPM_ACTIVE, but the supplier suspends successfully nevertheless?

>> [   11.383376][    T5] ufs_device_wlun 0:0:0:49488:
>> ufshcd_wl_runtime_suspend <-- Supplier suspends fine.
>> [   12.977318][  T174] sd 0:0:0:4: [sde] Synchronizing SCSI cache
>>
>> And the the suspend of sde is stuck now:
>> schedule+0x9c/0xe0
>> schedule_timeout+0x40/0x128
>> io_schedule_timeout+0x44/0x68
>> wait_for_common_io+0x7c/0x100
>> wait_for_completion_io+0x14/0x20
>> blk_execute_rq+0x90/0xcc
>> __scsi_execute+0x104/0x1c4
>> sd_sync_cache+0xf8/0x2a0
>> sd_suspend_common+0x74/0x11c
>> sd_suspend_runtime+0x14/0x20
>> scsi_runtime_suspend+0x64/0x94
>> __rpm_callback+0x80/0x2a4
>> rpm_suspend+0x308/0x614
>> pm_runtime_work+0x98/0xa8
>>
>> I added 'DL_FLAG_RPM_ACTIVE' while creating links.
>>    if (hba->sdev_ufs_device) {
>>    link = device_link_add(>sdev_gendev,
>>    >sdev_ufs_device->sdev_gendev,
>>   DL_FLAG_PM_RUNTIME|DL_FLAG_RPM_ACTIVE);
>> I didn't expect this to resolve the issue anyway and it didn't.
>>
>> Another interesting point here is when I resume any of the above 
>> suspended
>> consumers, it all goes back to normal, which is kind of expected. I tried
>> resuming the consumer and the supplier is resumed and the supplier is
>> suspended when all the consumers are suspended.
>>
>> Any pointers on this issue please?
>>
>> @Bart/@Alan - Do you've any pointers please?
>
> It's very noticeable that although you seem to have isolated a bug in
> the power management subsystem (supplier goes into runtime suspend
> even when one of its consumers is still active), you did not CC the
> power management maintainer or mailing list.
>
> I have added the appropriate CC's.

 Thanks Alan!
>>
>>
> 
> Hello
> I & Can (thanks CanG) debugged this further:
> 
> Looks like this issue can occur if the sd probe is asynchronous.
> 
> Essentially, the sd_probe() is done asynchronously and driver_probe_device() 
> invokes pm_runtime_get_suppliers() before invoking sd_probe().
> 
> But scsi_probe_and_add_lun() runs in a separate context.
> So the scsi_autopm_put_device() invoked from scsi_scan_host() context reduces 
> the link->rpm_active to 1. And sd_probe() invokes 

[PATCH] scsi: ufs-pci: Add support for Intel LKF

2021-03-12 Thread Adrian Hunter
Add PCI ID and callbacks to support Intel LKF.

This includes the ability to use an ACPI device-specific method (DSM) to
perform a UFS device reset.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufshcd-pci.c | 169 ++
 1 file changed, 169 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index fadd566025b8..23ee828747e2 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -15,13 +15,89 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+
+struct ufs_host {
+   void (*late_init)(struct ufs_hba *hba);
+};
+
+enum {
+   INTEL_DSM_FNS   =  0,
+   INTEL_DSM_RESET =  1,
+};
 
 struct intel_host {
+   struct ufs_host ufs_host;
+   u32 dsm_fns;
u32 active_ltr;
u32 idle_ltr;
struct dentry   *debugfs_root;
+   struct gpio_desc *reset_gpio;
 };
 
+static const guid_t intel_dsm_guid =
+   GUID_INIT(0x1A4832A0, 0x7D03, 0x43CA,
+ 0xB0, 0x20, 0xF6, 0xDC, 0xD1, 0x2A, 0x19, 0x50);
+
+static int __intel_dsm(struct intel_host *intel_host, struct device *dev,
+  unsigned int fn, u32 *result)
+{
+   union acpi_object *obj;
+   int err = 0;
+   size_t len;
+
+   obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), _dsm_guid, 0, fn, NULL);
+   if (!obj)
+   return -EOPNOTSUPP;
+
+   if (obj->type != ACPI_TYPE_BUFFER || obj->buffer.length < 1) {
+   err = -EINVAL;
+   goto out;
+   }
+
+   len = min_t(size_t, obj->buffer.length, 4);
+
+   *result = 0;
+   memcpy(result, obj->buffer.pointer, len);
+out:
+   ACPI_FREE(obj);
+
+   return err;
+}
+
+static int intel_dsm(struct intel_host *intel_host, struct device *dev,
+unsigned int fn, u32 *result)
+{
+   if (fn > 31 || !(intel_host->dsm_fns & (1 << fn)))
+   return -EOPNOTSUPP;
+
+   return __intel_dsm(intel_host, dev, fn, result);
+}
+
+static void intel_dsm_init(struct intel_host *intel_host, struct device *dev)
+{
+   int err;
+
+   err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, _host->dsm_fns);
+   dev_dbg(dev, "DSM fns %#x, error %d\n", intel_host->dsm_fns, err);
+}
+
+static int ufs_intel_hce_enable_notify(struct ufs_hba *hba,
+  enum ufs_notify_change_status status)
+{
+   /* Cannot enable ICE until after HC enable */
+   if (status == POST_CHANGE && hba->caps & UFSHCD_CAP_CRYPTO) {
+   u32 hce = ufshcd_readl(hba, REG_CONTROLLER_ENABLE);
+
+   hce |= CRYPTO_GENERAL_ENABLE;
+   ufshcd_writel(hba, hce, REG_CONTROLLER_ENABLE);
+   }
+
+   return 0;
+}
+
 static int ufs_intel_disable_lcc(struct ufs_hba *hba)
 {
u32 attr = UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE);
@@ -144,6 +220,41 @@ static void intel_remove_debugfs(struct ufs_hba *hba)
debugfs_remove_recursive(host->debugfs_root);
 }
 
+static int ufs_intel_device_reset(struct ufs_hba *hba)
+{
+   struct intel_host *host = ufshcd_get_variant(hba);
+
+   if (host->dsm_fns & INTEL_DSM_RESET) {
+   u32 result = 0;
+   int err;
+
+   err = intel_dsm(host, hba->dev, INTEL_DSM_RESET, );
+   if (!err && !result)
+   err = -EIO;
+   if (err)
+   dev_err(hba->dev, "%s: DSM error %d result %u\n",
+   __func__, err, result);
+   return err;
+   }
+
+   if (!host->reset_gpio)
+   return -EOPNOTSUPP;
+
+   gpiod_set_value_cansleep(host->reset_gpio, 1);
+   usleep_range(10, 15);
+
+   gpiod_set_value_cansleep(host->reset_gpio, 0);
+   usleep_range(10, 15);
+
+   return 0;
+}
+
+static struct gpio_desc *ufs_intel_get_reset_gpio(struct device *dev)
+{
+   /* GPIO in _DSD has active low setting */
+   return devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+}
+
 static int ufs_intel_common_init(struct ufs_hba *hba)
 {
struct intel_host *host;
@@ -154,6 +265,23 @@ static int ufs_intel_common_init(struct ufs_hba *hba)
if (!host)
return -ENOMEM;
ufshcd_set_variant(hba, host);
+   intel_dsm_init(host, hba->dev);
+   if (host->dsm_fns & INTEL_DSM_RESET) {
+   if (hba->vops->device_reset)
+   hba->caps |= UFSHCD_CAP_DEEPSLEEP;
+   } else {
+   if (hba->vops->device_reset)
+   host->reset_gpio = ufs_intel_get_reset_gpio(hba->dev);
+   if (IS_ERR(host->reset_gpio)) {
+   dev_err(hba->dev, "%s: failed to get reset GPIO, error 
%ld\n",
+  

Re: [PATCH] mmc: sdhci-pci: Avoid comma separated statements

2021-03-11 Thread Adrian Hunter
On 11/03/21 12:14 pm, Jisheng Zhang wrote:
> Use semicolons.
> 
> Signed-off-by: Jisheng Zhang 

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/host/sdhci-pci-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/sdhci-pci-core.c 
> b/drivers/mmc/host/sdhci-pci-core.c
> index 9552708846ca..62799c1d9c0c 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -958,7 +958,7 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot 
> *slot)
>   slot->host->mmc->caps2 |= MMC_CAP2_CQE;
>  
>   if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
> - slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
> + slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
>   slot->host->mmc_host_ops.hs400_enhanced_strobe =
>   intel_hs400_enhanced_strobe;
>   slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
> 



Re: [PATCH] mmc: sdhci: Use "mmc" directly rather than "host->mmc"

2021-03-11 Thread Adrian Hunter
On 11/03/21 11:40 am, Jisheng Zhang wrote:
> Clean up the code to use the "mmc" directly instead of "host->mmc".
> If the code sits in hot code path, this clean up also brings trvial
> performance improvement. Take the sdhci_post_req() for example:
> 
> before the patch:
>  ...
>  8d0: a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4: 910003fdmov x29, sp
>  8d8: f9000bf3str x19, [sp, #16]
>  8dc: f9400833ldr x19, [x1, #16]
>  8e0: b9404261ldr w1, [x19, #64]
>  8e4: 34000161cbz w1, 910 
>  8e8: f9424400ldr x0, [x0, #1160]
>  8ec: d284mov x4, #0x0// #0
>  8f0: b9401a61ldr w1, [x19, #24]
>  8f4: b9403262ldr w2, [x19, #48]
>  8f8: f940ldr x0, [x0]
>  8fc: f278003ftst x1, #0x100
>  900: f9401e61ldr x1, [x19, #56]
>  904: 1a9f17e3csetw3, eq  // eq = none
>  908: 11000463add w3, w3, #0x1
>  90c: 9400bl  0 
>  ...
> 
> After the patch:
>  ...
>  8d0: a9be7bfdstp x29, x30, [sp, #-32]!
>  8d4: 910003fdmov x29, sp
>  8d8: f9000bf3str x19, [sp, #16]
>  8dc: f9400833ldr x19, [x1, #16]
>  8e0: b9404261ldr w1, [x19, #64]
>  8e4: 34000141cbz w1, 90c 
>  8e8: b9401a61ldr w1, [x19, #24]
>  8ec: d284mov x4, #0x0// #0
>  8f0: b9403262ldr w2, [x19, #48]
>  8f4: f940ldr x0, [x0]
>  8f8: f278003ftst x1, #0x100
>  8fc: f9401e61ldr x1, [x19, #56]
>  900: 1a9f17e3csetw3, eq  // eq = none
>  904: 11000463add w3, w3, #0x1
>  908: 94000000bl  0 
>  ...
> 
> We saved one ldr instruction: "ldr x0, [x0, #1160]"
> 
> Signed-off-by: Jisheng Zhang 

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/host/sdhci.c | 33 -
>  1 file changed, 16 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 2d73407ee52e..b1afabab9cae 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -907,7 +907,7 @@ static void sdhci_calc_sw_timeout(struct sdhci_host *host,
>  
>   if (data) {
>   blksz = data->blksz;
> - freq = host->mmc->actual_clock ? : host->clock;
> + freq = mmc->actual_clock ? : host->clock;
>   transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width);
>   do_div(transfer_time, freq);
>   /* multiply by '2' to account for any unknowns */
> @@ -2269,14 +2269,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct 
> mmc_ios *ios)
>  
>   if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
>   host->clock) {
> - host->timeout_clk = host->mmc->actual_clock ?
> - host->mmc->actual_clock / 1000 :
> + host->timeout_clk = mmc->actual_clock ?
> + mmc->actual_clock / 1000 :
>   host->clock / 1000;
> - host->mmc->max_busy_timeout =
> + mmc->max_busy_timeout =
>   host->ops->get_max_timeout_count ?
>   host->ops->get_max_timeout_count(host) :
>   1 << 27;
> - host->mmc->max_busy_timeout /= host->timeout_clk;
> + mmc->max_busy_timeout /= host->timeout_clk;
>   }
>   }
>  
> @@ -2399,7 +2399,7 @@ static int sdhci_get_cd(struct mmc_host *mmc)
>   return 0;
>  
>   /* If nonremovable, assume that the card is always present. */
> - if (!mmc_card_is_removable(host->mmc))
> + if (!mmc_card_is_removable(mmc))
>   return 1;
>  
>   /*
> @@ -2489,14 +2489,14 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int 
> enable)
>   unsigned long flags;
>  
>   if (enable)
> - pm_runtime_get_noresume(host->mmc->parent);
> + pm_runtime_get_noresume(mmc->parent);
>  
>   spin_lock_irqsave(>loc

[PATCH] perf auxtrace: Fix auxtrace queue conflict

2021-03-08 Thread Adrian Hunter
The only requirement of an auxtrace queue is that the buffers are in
time order.  That is achieved by making separate queues for separate
perf buffer or AUX area buffer mmaps.

That generally means a separate queue per cpu for per-cpu contexts,
and a separate queue per thread for per-task contexts.

When buffers are added to a queue, perf checks that the buffer cpu
and thread id (tid) match the queue cpu and thread id.

However, generally, that need not be true, and perf will queue
buffers correctly anyway, so the check is not needed.

In addition, the check gets erroneously hit when using sample mode
to trace multiple threads.

Consequently, fix that case by removing the check.

Reported-by: Andi Kleen 
Fixes: e502789302a6 ("perf auxtrace: Add helpers for queuing AUX area tracing 
data")
Signed-off-by: Adrian Hunter 
---
 tools/perf/util/auxtrace.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 953f4afacd3b..5b6ccb90b397 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -298,10 +298,6 @@ static int auxtrace_queues__queue_buffer(struct 
auxtrace_queues *queues,
queue->set = true;
queue->tid = buffer->tid;
queue->cpu = buffer->cpu;
-   } else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) {
-   pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid 
%d\n",
-  queue->cpu, queue->tid, buffer->cpu, buffer->tid);
-   return -EINVAL;
}
 
buffer->buffer_nr = queues->next_buffer_nr++;
-- 
2.17.1



Re: [PATCH v10 1/2] scsi: ufs: Enable power management for wlun

2021-03-04 Thread Adrian Hunter
On 3/03/21 12:52 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 

It looks good, but still a few further comments below.

Also, do you think ufshcd_err_handling_prepare()/unprepare()
need changes?  And ufshcd_recover_pm_error()?

And maybe ufshcd_auto_hibern8_update() when it is called from ufs_sysfs.c?

> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufs_bsg.c |   6 +-
>  drivers/scsi/ufs/ufshcd-pci.c  |  32 +-
>  drivers/scsi/ufs/ufshcd.c  | 583 
> +++--
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  11 files changed, 478 insertions(+), 182 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver exynos_ufs_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
> index 0aa5813..d463b44 100644
> --- a/drivers/scsi/ufs/ufs-hisi.c
> +++ b/drivers/scsi/ufs/ufs-hisi.c
> @@ -574,6 +574,8 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver ufs_hisi_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
> index c55202b..df1eabb 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -1097,6 

Re: [PATCH v10 2/2] ufs: sysfs: Resume the proper scsi device

2021-03-03 Thread Adrian Hunter
On 3/03/21 12:52 am, Asutosh Das wrote:
> Resumes the actual scsi device the unit descriptor of which
> is being accessed instead of the hba alone.

Since "scsi: ufs: ufs-debugfs: Add user-defined exception_event_mask"
is now in linux-next, a similar change is needed for ufs-debugfs.c.
Probably best it is a separate patch though.


Re: [PATCH v2 1/1] mmc: cqhci: fix random crash when remove mmc module

2021-03-03 Thread Adrian Hunter
On 3/03/21 7:42 pm, Frank Li wrote:
> [ 6684.493350] Unable to handle kernel paging request at virtual address 
> 800011c5b0f0
> [ 6684.498531] mmc0: card 0001 removed
> [ 6684.501556] Mem abort info:
> [ 6684.509681]   ESR = 0x9647
> [ 6684.512786]   EC = 0x25: DABT (current EL), IL = 32 bits
> [ 6684.518394]   SET = 0, FnV = 0
> [ 6684.521707]   EA = 0, S1PTW = 0
> [ 6684.524998] Data abort info:
> [ 6684.528236]   ISV = 0, ISS = 0x0047
> [ 6684.532986]   CM = 0, WnR = 1
> [ 6684.536129] swapper pgtable: 4k pages, 48-bit VAs, pgdp=81b22000
> [ 6684.543923] [800011c5b0f0] pgd=b003, p4d=b003, 
> pud=bfffe003, pmd=900e1003, pte=
> [ 6684.557915] Internal error: Oops: 9647 [#1] PREEMPT SMP
> [ 6684.564240] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci cqhci 
> mmc_block mmc_core fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc 
> caamalg_desc crypto_engine rng_core authenc libdes crct10dif_ce flexcan 
> can_dev caam error [last unloaded: mmc_core]
> [ 6684.587281] CPU: 0 PID: 79138 Comm: kworker/0:3H Not tainted 
> 5.10.9-01410-g3ba33182767b-dirty #10
> [ 6684.596160] Hardware name: Freescale i.MX8DXL EVK (DT)
> [ 6684.601320] Workqueue: kblockd blk_mq_run_work_fn
> 
> [ 6684.606094] pstate: 4005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
> [ 6684.612286] pc : cqhci_request+0x148/0x4e8 [cqhci]
> ^GMessage from syslogd@  at Thu Jan  1 01:51:24 1970 ...[ 6684.617085] lr : 
> cqhci_request+0x314/0x4e8 [cqhci]
> [ 6684.626734] sp : 80001243b9f0
> [ 6684.630049] x29: 80001243b9f0 x28: 2c3dd000
> [ 6684.635367] x27: 0001 x26: 0001
> [ 6684.640690] x25: 2c451000 x24: 000f
> [ 6684.646007] x23: 17e71c80 x22: 2c451000
> [ 6684.651326] x21: 2c0f3550 x20: 2c0f3550
> [ 6684.656651] x19: 17d46880 x18: 2cea1500
> [ 6684.661977] x17:  x16: 
> [ 6684.667294] x15: 01ee628e3ed1 x14: 0278
> [ 6684.672610] x13: 0001 x12: 0001
> [ 6684.677927] x11:  x10: 
> [ 6684.683243] x9 : 002b x8 : 1000
> [ 6684.688560] x7 : 0010 x6 : 2c0f3678
> [ 6684.693886] x5 : 000f x4 : 800011c5b000
> [ 6684.699211] x3 : 0002d988 x2 : 0008
> [ 6684.704537] x1 : 00f0 x0 : 0002d9880008102f
> [ 6684.709854] Call trace:
> [ 6684.712313]  cqhci_request+0x148/0x4e8 [cqhci]
> [ 6684.716803]  mmc_cqe_start_req+0x58/0x68 [mmc_core]
> [ 6684.721698]  mmc_blk_mq_issue_rq+0x460/0x810 [mmc_block]
> [ 6684.727018]  mmc_mq_queue_rq+0x118/0x2b0 [mmc_block]
> 
> cqhci_request was called after cqhci_disable.
> 
> cqhci_disable cqhci_request
> { {
>   dmam_free_coherent();  (1) free
>   if(!cq_host->enable)
>return
>(2) pass check here
>   cq_host->enable = false;
> 
>   task_desc= 
> get_desc(cq_host,tag);
>  ^^^^ crash here
>  (3) access memory which is already 
> free
> 
> } }
> 
> Signed-off-by: Frank Li 

Acked-by: Adrian Hunter 

> ---
> 
> Change from v1 to v2
>  - use Adrian Hunter suggested method to fix this problem
> 
>  drivers/mmc/core/bus.c | 11 +--
>  1 file changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
> index c2e70b757dd1..4383c262b3f5 100644
> --- a/drivers/mmc/core/bus.c
> +++ b/drivers/mmc/core/bus.c
> @@ -399,11 +399,6 @@ void mmc_remove_card(struct mmc_card *card)
>   mmc_remove_card_debugfs(card);
>  #endif
>  
> - if (host->cqe_enabled) {
> - host->cqe_ops->cqe_disable(host);
> - host->cqe_enabled = false;
> - }
> -
>   if (mmc_card_present(card)) {
>   if (mmc_host_is_spi(card->host)) {
>   pr_info("%s: SPI card removed\n",
> @@ -416,6 +411,10 @@ void mmc_remove_card(struct mmc_card *card)
>   of_node_put(card->dev.of_node);
>   }
>  
> + if (host->cqe_enabled) {
> + host->cqe_ops->cqe_disable(host);
> + host->cqe_enabled = false;
> + }
> +
>   put_device(>dev);
>  }
> -
> 



Re: [PATCH V1] mmc: sdhci: Check for reset prior to DMA address unmap

2021-03-03 Thread Adrian Hunter
On 24/02/21 12:53 pm, Pradeep P V K wrote:
> For data read commands, SDHC may initiate data transfers even before it
> completely process the command response. In case command itself fails,
> driver un-maps the memory associated with data transfer but this memory
> can still be accessed by SDHC for the already initiated data transfer.
> This scenario can lead to un-mapped memory access error.
> 
> To avoid this scenario, reset SDHC (when command fails) prior to
> un-mapping memory. Resetting SDHC ensures that all in-flight data
> transfers are either aborted or completed. So we don't run into this
> scenario.
> 
> Swap the reset, un-map steps sequence in sdhci_request_done().
> 
> Suggested-by: Veerabhadrarao Badiganti 
> Signed-off-by: Pradeep P V K 

Seems like a good change to make.  A couple of cosmetic tweaks below,
but:

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/host/sdhci.c | 58 
> 
>  1 file changed, 29 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 646823d..e78d84c 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2996,6 +2996,35 @@ static bool sdhci_request_done(struct sdhci_host *host)
>   spin_unlock_irqrestore(>lock, flags);
>   return true;
>   }

Blank line here please.

> + /*
> +  * The controller needs a reset of internal state machines
> +  * upon error conditions.
> +  */
> + if (sdhci_needs_reset(host, mrq)) {
> + /*
> +  * Do not finish until command and data lines are available for
> +  * reset. Note there can only be one other mrq, so it cannot
> +  * also be in mrqs_done, otherwise host->cmd and host->data_cmd
> +  * would both be null.
> +  */
> + if (host->cmd || host->data_cmd) {
> + spin_unlock_irqrestore(>lock, flags);
> + return true;
> + }
> +
> + /* Some controllers need this kick or reset won't work here */
> + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
> + /* This is to force an update */
> + host->ops->set_clock(host, host->clock);
> +
> + /* Spec says we should do both at the same time, but Ricoh
> +  * controllers do not like that.
> +  */

Please change comment style:

/*
 * Spec says we should do both at the same time, but Ricoh
 * controllers do not like that.
 */

> + sdhci_do_reset(host, SDHCI_RESET_CMD);
> + sdhci_do_reset(host, SDHCI_RESET_DATA);
> +
> + host->pending_reset = false;
> + }
>  
>   /*
>* Always unmap the data buffers if they were mapped by
> @@ -3060,35 +3089,6 @@ static bool sdhci_request_done(struct sdhci_host *host)
>   }
>   }
>  
> - /*
> -  * The controller needs a reset of internal state machines
> -  * upon error conditions.
> -  */
> - if (sdhci_needs_reset(host, mrq)) {
> - /*
> -  * Do not finish until command and data lines are available for
> -  * reset. Note there can only be one other mrq, so it cannot
> -  * also be in mrqs_done, otherwise host->cmd and host->data_cmd
> -  * would both be null.
> -  */
> - if (host->cmd || host->data_cmd) {
> - spin_unlock_irqrestore(>lock, flags);
> - return true;
> - }
> -
> - /* Some controllers need this kick or reset won't work here */
> - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
> - /* This is to force an update */
> - host->ops->set_clock(host, host->clock);
> -
> - /* Spec says we should do both at the same time, but Ricoh
> -controllers do not like that. */
> - sdhci_do_reset(host, SDHCI_RESET_CMD);
> - sdhci_do_reset(host, SDHCI_RESET_DATA);
> -
> - host->pending_reset = false;
> - }
> -
>   host->mrqs_done[i] = NULL;
>  
>   spin_unlock_irqrestore(>lock, flags);
> 



Re: [PATCH 1/1] mmc: cqhci: fix random crash when remove mmc module

2021-03-02 Thread Adrian Hunter
On 2/03/21 5:12 pm, Zhi Li wrote:
> 
> 
> On Tue, Mar 2, 2021 at 1:03 AM Adrian Hunter  <mailto:adrian.hun...@intel.com>> wrote:
> 
> On 1/03/21 7:21 pm, Frank Li wrote:
> > [ 6684.493350] Unable to handle kernel paging request at virtual 
> address 800011c5b0f0
> > [ 6684.498531] mmc0: card 0001 removed
> > [ 6684.501556] Mem abort info:
> > [ 6684.509681]   ESR = 0x9647
> > [ 6684.512786]   EC = 0x25: DABT (current EL), IL = 32 bits
> > [ 6684.518394]   SET = 0, FnV = 0
> > [ 6684.521707]   EA = 0, S1PTW = 0
> > [ 6684.524998] Data abort info:
> > [ 6684.528236]   ISV = 0, ISS = 0x0047
> > [ 6684.532986]   CM = 0, WnR = 1
> > [ 6684.536129] swapper pgtable: 4k pages, 48-bit VAs, 
> pgdp=81b22000
> > [ 6684.543923] [800011c5b0f0] pgd=b003, 
> p4d=b003, pud=bfffe003, pmd=900e1003, 
> pte=
> > [ 6684.557915] Internal error: Oops: 9647 [#1] PREEMPT SMP
> > [ 6684.564240] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci 
> cqhci mmc_block mmc_core fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc 
> caamalg_desc crypto_engine rng_core authenc libdes crct10dif_ce flexcan 
> can_dev caam error [last unloaded: mmc_core]
> > [ 6684.587281] CPU: 0 PID: 79138 Comm: kworker/0:3H Not tainted 
> 5.10.9-01410-g3ba33182767b-dirty #10
> > [ 6684.596160] Hardware name: Freescale i.MX8DXL EVK (DT)
> > [ 6684.601320] Workqueue: kblockd blk_mq_run_work_fn
> >
> > [ 6684.606094] pstate: 4005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
> > [ 6684.612286] pc : cqhci_request+0x148/0x4e8 [cqhci]
> > ^GMessage from syslogd@  at Thu Jan  1 01:51:24 1970 ...[ 6684.617085] 
> lr : cqhci_request+0x314/0x4e8 [cqhci]
> > [ 6684.626734] sp : 80001243b9f0
> > [ 6684.630049] x29: 80001243b9f0 x28: 2c3dd000
> > [ 6684.635367] x27: 0001 x26: 0001
> > [ 6684.640690] x25: 2c451000 x24: 000f
> > [ 6684.646007] x23: 17e71c80 x22: 2c451000
> > [ 6684.651326] x21: 2c0f3550 x20: 2c0f3550
> > [ 6684.656651] x19: 17d46880 x18: 2cea1500
> > [ 6684.661977] x17:  x16: 
> > [ 6684.667294] x15: 01ee628e3ed1 x14: 0278
> > [ 6684.672610] x13: 0001 x12: 0001
> > [ 6684.677927] x11:  x10: 
> > [ 6684.683243] x9 : 002b x8 : 1000
> > [ 6684.688560] x7 : 0010 x6 : 2c0f3678
> > [ 6684.693886] x5 : 000f x4 : 800011c5b000
> > [ 6684.699211] x3 : 0002d988 x2 : 0008
> > [ 6684.704537] x1 : 00f0 x0 : 0002d9880008102f
> > [ 6684.709854] Call trace:
> > [ 6684.712313]  cqhci_request+0x148/0x4e8 [cqhci]
> > [ 6684.716803]  mmc_cqe_start_req+0x58/0x68 [mmc_core]
> > [ 6684.721698]  mmc_blk_mq_issue_rq+0x460/0x810 [mmc_block]
> > [ 6684.727018]  mmc_mq_queue_rq+0x118/0x2b0 [mmc_block]
> >
> > cqhci_request was called after cqhci_disable.
> >
> > cqhci_disable                                 cqhci_request
> > {                                             {
> >       dmam_free_coherent();  (1) free
> >                                                   if(!cq_host->enable)
> >                                                        return
> >                                        (2) pass check here
> >       cq_host->enable = false;
> >
> >                                                   task_desc= 
> get_desc(cq_host,tag);
> >                                                               crash 
> here
> >                                          (3) access memory which is 
> already free
> >
> > }                                             }
> >
> > Signed-off-by: Frank Li mailto:frank...@nxp.com>>
> > ---
> >  drivers/mmc/host/cqhci-core.c | 18 ++
> >  1 file changed, 14 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/mmc/host/cqhci-core.c 
> b/drivers/mmc/host/cqhci-core.c
> > index 93b0432bb601..36d292261e50 100644
> > --- a/drivers/mmc/host/cqhci-core.c
> > +++ b/drivers/mmc/host/cqhci-core.c
> > @@ -389,6 +389,7 @@ static void cqhci_off(struct mmc_host *mmc)
> >  static void cqhci_d

Re: [PATCH v9 1/2] scsi: ufs: Enable power management for wlun

2021-03-02 Thread Adrian Hunter
On 2/03/21 5:21 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---

Now we need either to move the suspend/resume vops from
ufshcd_suspend/resume to __ufshcd_wl_suspend/resume, assuming that
would work for existing implementations of those callbacks,
or otherwise create new vops ->wl_suspend() / ->wl_resume(), and
then split the existing implementations of those callbacks.

ufs_intel_resume() now needs to be invoked from __ufshcd_wl_resume().
I am not sure about the others:

exynos_ufs_suspend()
exynos_ufs_resume()
ufs_hisi_suspend()
ufs_hisi_resume()
ufs_mtk_suspend()
ufs_mtk_resume()
ufs_qcom_suspend()
ufs_qcom_resume()


Re: [PATCH] scsi: ufs: Fix incorrect ufshcd_state after ufshcd_reset_and_restore()

2021-03-02 Thread Adrian Hunter
On 2/03/21 9:01 am, Avri Altman wrote:
>  
>> If ufshcd_probe_hba() fails it sets ufshcd_state to UFSHCD_STATE_ERROR,
>> however, if it is called again, as it is within a loop in
>> ufshcd_reset_and_restore(), and succeeds, then it will not set the state
>> back to UFSHCD_STATE_OPERATIONAL unless the state was
>> UFSHCD_STATE_RESET.
>>
>> That can result in the state being UFSHCD_STATE_ERROR even though
>> ufshcd_reset_and_restore() is successful and returns zero.
>>
>> Fix by initializing the state to UFSHCD_STATE_RESET in the start of each
>> loop in ufshcd_reset_and_restore().  If there is an error,
>> ufshcd_reset_and_restore() will change the state to UFSHCD_STATE_ERROR,
>> otherwise ufshcd_probe_hba() will have set the state appropriately.
>>
>> Fixes: 4db7a2360597 ("scsi: ufs: Fix concurrency of error handler and other
>> error recovery paths")
>> Signed-off-by: Adrian Hunter 
> I think that CanG recent series addressed that issue as well, can you take a 
> look?
> https://lore.kernel.org/lkml/1614145010-36079-2-git-send-email-c...@codeaurora.org/

Yes, there it is mixed in with other changes.  However it is probably better
as a separate patch.  Can Guo, what do you think?

> 
> 
>> ---
>>  drivers/scsi/ufs/ufshcd.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 77161750c9fb..91a403afe038 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -7031,6 +7031,8 @@ static int ufshcd_reset_and_restore(struct ufs_hba
>> *hba)
>> spin_unlock_irqrestore(hba->host->host_lock, flags);
>>
>> do {
>> +   hba->ufshcd_state = UFSHCD_STATE_RESET;
>> +
>> /* Reset the attached device */
>> ufshcd_device_reset(hba);
>>
>> --
>> 2.17.1
> 



Re: [PATCH 1/1] mmc: cqhci: fix random crash when remove mmc module

2021-03-02 Thread Adrian Hunter
On 1/03/21 7:21 pm, Frank Li wrote:
> [ 6684.493350] Unable to handle kernel paging request at virtual address 
> 800011c5b0f0
> [ 6684.498531] mmc0: card 0001 removed
> [ 6684.501556] Mem abort info:
> [ 6684.509681]   ESR = 0x9647
> [ 6684.512786]   EC = 0x25: DABT (current EL), IL = 32 bits
> [ 6684.518394]   SET = 0, FnV = 0
> [ 6684.521707]   EA = 0, S1PTW = 0
> [ 6684.524998] Data abort info:
> [ 6684.528236]   ISV = 0, ISS = 0x0047
> [ 6684.532986]   CM = 0, WnR = 1
> [ 6684.536129] swapper pgtable: 4k pages, 48-bit VAs, pgdp=81b22000
> [ 6684.543923] [800011c5b0f0] pgd=b003, p4d=b003, 
> pud=bfffe003, pmd=900e1003, pte=
> [ 6684.557915] Internal error: Oops: 9647 [#1] PREEMPT SMP
> [ 6684.564240] Modules linked in: sdhci_esdhc_imx(-) sdhci_pltfm sdhci cqhci 
> mmc_block mmc_core fsl_jr_uio caam_jr caamkeyblob_desc caamhash_desc 
> caamalg_desc crypto_engine rng_core authenc libdes crct10dif_ce flexcan 
> can_dev caam error [last unloaded: mmc_core]
> [ 6684.587281] CPU: 0 PID: 79138 Comm: kworker/0:3H Not tainted 
> 5.10.9-01410-g3ba33182767b-dirty #10
> [ 6684.596160] Hardware name: Freescale i.MX8DXL EVK (DT)
> [ 6684.601320] Workqueue: kblockd blk_mq_run_work_fn
> 
> [ 6684.606094] pstate: 4005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
> [ 6684.612286] pc : cqhci_request+0x148/0x4e8 [cqhci]
> ^GMessage from syslogd@  at Thu Jan  1 01:51:24 1970 ...[ 6684.617085] lr : 
> cqhci_request+0x314/0x4e8 [cqhci]
> [ 6684.626734] sp : 80001243b9f0
> [ 6684.630049] x29: 80001243b9f0 x28: 2c3dd000
> [ 6684.635367] x27: 0001 x26: 0001
> [ 6684.640690] x25: 2c451000 x24: 000f
> [ 6684.646007] x23: 17e71c80 x22: 2c451000
> [ 6684.651326] x21: 2c0f3550 x20: 2c0f3550
> [ 6684.656651] x19: 17d46880 x18: 2cea1500
> [ 6684.661977] x17:  x16: 
> [ 6684.667294] x15: 01ee628e3ed1 x14: 0278
> [ 6684.672610] x13: 0001 x12: 0001
> [ 6684.677927] x11:  x10: 
> [ 6684.683243] x9 : 002b x8 : 1000
> [ 6684.688560] x7 : 0010 x6 : 2c0f3678
> [ 6684.693886] x5 : 000f x4 : 800011c5b000
> [ 6684.699211] x3 : 0002d988 x2 : 0008
> [ 6684.704537] x1 : 00f0 x0 : 0002d9880008102f
> [ 6684.709854] Call trace:
> [ 6684.712313]  cqhci_request+0x148/0x4e8 [cqhci]
> [ 6684.716803]  mmc_cqe_start_req+0x58/0x68 [mmc_core]
> [ 6684.721698]  mmc_blk_mq_issue_rq+0x460/0x810 [mmc_block]
> [ 6684.727018]  mmc_mq_queue_rq+0x118/0x2b0 [mmc_block]
> 
> cqhci_request was called after cqhci_disable.
> 
> cqhci_disable cqhci_request
> { {
>   dmam_free_coherent();  (1) free
>   if(!cq_host->enable)
>return
>(2) pass check here
>   cq_host->enable = false;
> 
>   task_desc= 
> get_desc(cq_host,tag);
>   crash here
>  (3) access memory which is already 
> free
> 
> } }
> 
> Signed-off-by: Frank Li 
> ---
>  drivers/mmc/host/cqhci-core.c | 18 ++
>  1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c
> index 93b0432bb601..36d292261e50 100644
> --- a/drivers/mmc/host/cqhci-core.c
> +++ b/drivers/mmc/host/cqhci-core.c
> @@ -389,6 +389,7 @@ static void cqhci_off(struct mmc_host *mmc)
>  static void cqhci_disable(struct mmc_host *mmc)
>  {
>   struct cqhci_host *cq_host = mmc->cqe_private;
> + unsigned long flags;
>  
>   if (!cq_host->enabled)
>   return;
> @@ -397,6 +398,11 @@ static void cqhci_disable(struct mmc_host *mmc)
>  
>   __cqhci_disable(cq_host);
>  
> + /* need wait for cqhci_request finish before free memory */
> + spin_lock_irqsave(_host->lock, flags);
> + cq_host->enabled = false;
> + spin_unlock_irqrestore(_host->lock, flags);
> +
>   dmam_free_coherent(mmc_dev(mmc), cq_host->data_size,
>  cq_host->trans_desc_base,
>  cq_host->trans_desc_dma_base);
> @@ -408,7 +414,6 @@ static void cqhci_disable(struct mmc_host *mmc)
>   cq_host->trans_desc_base = NULL;
>   cq_host->desc_base = NULL;
>  
> - cq_host->enabled = false;
>  }
>  
>  static void cqhci_prep_task_desc(struct mmc_request *mrq,
> @@ -612,6 +617,13 @@ static int cqhci_request(struct mmc_host *mmc, struct 
> mmc_request *mrq)
>   cq_host->ops->enable(mmc);
>   }
>  
> +  

[PATCH] scsi: ufs: Fix incorrect ufshcd_state after ufshcd_reset_and_restore()

2021-03-01 Thread Adrian Hunter
If ufshcd_probe_hba() fails it sets ufshcd_state to UFSHCD_STATE_ERROR,
however, if it is called again, as it is within a loop in
ufshcd_reset_and_restore(), and succeeds, then it will not set the state
back to UFSHCD_STATE_OPERATIONAL unless the state was
UFSHCD_STATE_RESET.

That can result in the state being UFSHCD_STATE_ERROR even though
ufshcd_reset_and_restore() is successful and returns zero.

Fix by initializing the state to UFSHCD_STATE_RESET in the start of each
loop in ufshcd_reset_and_restore().  If there is an error,
ufshcd_reset_and_restore() will change the state to UFSHCD_STATE_ERROR,
otherwise ufshcd_probe_hba() will have set the state appropriately.

Fixes: 4db7a2360597 ("scsi: ufs: Fix concurrency of error handler and other 
error recovery paths")
Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufshcd.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 77161750c9fb..91a403afe038 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7031,6 +7031,8 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
spin_unlock_irqrestore(hba->host->host_lock, flags);
 
do {
+   hba->ufshcd_state = UFSHCD_STATE_RESET;
+
/* Reset the attached device */
ufshcd_device_reset(hba);
 
-- 
2.17.1



Re: [PATCH v8 1/2] scsi: ufs: Enable power management for wlun

2021-03-01 Thread Adrian Hunter
On 1/03/21 8:10 pm, Asutosh Das wrote:
> On Mon, Mar 01 2021 at 05:23 -0800, Adrian Hunter wrote:
>> On 26/02/21 1:37 am, Asutosh Das wrote:
>>> @@ -8901,43 +9125,14 @@ static int ufshcd_resume(struct ufs_hba *hba, enum 
>>> ufs_pm_op pm_op)
>>>  goto vendor_suspend;
>>>  }
>>
>> The ufshcd_reset_and_restore() in ufshcd_resume() will also change the power
>> mode of the UFS device to active.  Until the UFS device is also resumed and
>> then suspended, it will not return to a low power mode.
>>
>>
> Umm, sorry, I didn't understand this comment.
> Say, the UFS device was reset in ufshcd_reset_and_restore() it'd be a hardware
> reset and the UFS device would move to Powered On mode and then to Active 
> power
> mode, when it is ready to begin initialization. And from this state it should
> move to all other legal states.
> Before entering system suspend ufshcd_system_suspend(), the ufs device is
> runtime resumed in ufshcd_suspend_prepare().
> 
> Please can you explain a bit more on this issue that you see?

Say you runtime resume the host controller, and
ufshcd_reset_and_restore() makes the UFS device active,
but the UFS device is still runtime suspended.


Example:

Add a debugfs file to show the current power mode:

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index dee98dc72d29..700b88df0866 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -48,6 +48,7 @@ void ufs_debugfs_hba_init(struct ufs_hba *hba)
 {
hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), 
ufs_debugfs_root);
debugfs_create_file("stats", 0400, hba->debugfs_root, hba, 
_debugfs_stats_fops);
+   debugfs_create_u32("curr_dev_pwr_mode", 0400, hba->debugfs_root, (u32 
*)>curr_dev_pwr_mode);
 }

 void ufs_debugfs_hba_exit(struct ufs_hba *hba)


# grep -H . /sys/bus/pci/drivers/ufshcd/\:00\:12.5/rpm*
/sys/bus/pci/drivers/ufshcd/:00:12.5/rpm_lvl:6
/sys/bus/pci/drivers/ufshcd/:00:12.5/rpm_target_dev_state:DEEPSLEEP
/sys/bus/pci/drivers/ufshcd/:00:12.5/rpm_target_link_state:OFF
# cat /sys/kernel/debug/ufshcd/\:00\:12.5/curr_dev_pwr_mode
4
# echo on > /sys/devices/pci:00/:00:12.5/power/control
# cat /sys/kernel/debug/ufshcd/\:00\:12.5/curr_dev_pwr_mode
1
# grep -H . 
/sys/bus/pci/drivers/ufshcd/\:00\:12.5/host*/target*/*/power/runtime_status
/sys/bus/pci/drivers/ufshcd/:00:12.5/host1/target1:0:0/1:0:0:0/power/runtime_status:suspended
/sys/bus/pci/drivers/ufshcd/:00:12.5/host1/target1:0:0/1:0:0:49456/power/runtime_status:suspended
/sys/bus/pci/drivers/ufshcd/:00:12.5/host1/target1:0:0/1:0:0:49476/power/runtime_status:suspended
/sys/bus/pci/drivers/ufshcd/:00:12.5/host1/target1:0:0/1:0:0:49488/power/runtime_status:suspended

So UFS devices is runtime suspended and should in DeepSleep, but it is active.


Re: [PATCH v8 1/2] scsi: ufs: Enable power management for wlun

2021-03-01 Thread Adrian Hunter
Hi

A couple of minor things, but also a potential issue with when link state
transitions are done.  Please see comments below.

On 26/02/21 1:37 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufshcd-pci.c  |  26 +-
>  drivers/scsi/ufs/ufshcd.c  | 540 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  10 files changed, 483 insertions(+), 122 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver exynos_ufs_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
> index 0aa5813..d463b44 100644
> --- a/drivers/scsi/ufs/ufs-hisi.c
> +++ b/drivers/scsi/ufs/ufs-hisi.c
> @@ -574,6 +574,8 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver ufs_hisi_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
> index c55202b..df1eabb 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -1097,6 +1097,8 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = 

Re: [PATCH] mmc: Try power cycling card if command request times out

2021-03-01 Thread Adrian Hunter
On 1/03/21 10:50 am, Ulf Hansson wrote:
> + Adrian
> 
> On Tue, 16 Feb 2021 at 23:43, Mårten Lindahl  wrote:
>>
>> Sometimes SD cards that has been run for a long time enters a state
>> where it cannot by itself be recovered, but needs a power cycle to be
>> operational again. Card status analysis has indicated that the card can
>> end up in a state where all external commands are ignored by the card
>> since it is halted by data timeouts.
>>
>> If the card has been heavily used for a long time it can be weared out,
>> and should typically be replaced. But on some tests, it shows that the
>> card can still be functional after a power cycle, but as it requires an
>> operator to do it, the card can remain in a non-operational state for a
>> long time until the problem has been observed by the operator.
>>
>> This patch adds function to power cycle the card in case it does not
>> respond to a command, and then resend the command if the power cycle
>> was successful. This procedure will be tested 1 time before giving up,
>> and resuming host operation as normal.
> 
> I assume the context above is all about the ioctl interface?
> 
> So, when the card enters this non functional state, have you tried
> just reading a block through the regular I/O interface. Does it
> trigger a power cycle of the card - and then makes it functional
> again?
> 
>>
>> Signed-off-by: Mårten Lindahl 
>> ---
>> Please note: This might not be the way we want to handle these cases,
>> but at least it lets us start the discussion. In which cases should the
>> mmc framework deal with error messages like ETIMEDOUT, and in which
>> cases should it be handled by userspace?
>> The mmc framework tries to recover a failed block request
>> (mmc_blk_mq_rw_recovery) which may end up in a HW reset of the card.
>> Would it be an idea to act in a similar way when an ioctl times out?
> 
> Maybe, it's a good idea to allow the similar reset for ioctls as we do
> for regular I/O requests. My concern with this though, is that we
> might allow user space to trigger a HW resets a bit too easily - and
> that could damage the card.
> 
> Did you consider this?
> 
>>
>>  drivers/mmc/core/block.c | 20 ++--
>>  1 file changed, 18 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
>> index 42e27a298218..d007b2af64d6 100644
>> --- a/drivers/mmc/core/block.c
>> +++ b/drivers/mmc/core/block.c
>> @@ -976,6 +976,7 @@ static inline void mmc_blk_reset_success(struct 
>> mmc_blk_data *md, int type)
>>   */
>>  static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
>>  {
>> +   int type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
>> struct mmc_queue_req *mq_rq;
>> struct mmc_card *card = mq->card;
>> struct mmc_blk_data *md = mq->blkdata;
>> @@ -983,7 +984,7 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, 
>> struct request *req)
>> bool rpmb_ioctl;
>> u8 **ext_csd;
>> u32 status;
>> -   int ret;
>> +   int ret, retry = 1;
>> int i;
>>
>> mq_rq = req_to_mmc_queue_req(req);
>> @@ -994,9 +995,24 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, 
>> struct request *req)
>> case MMC_DRV_OP_IOCTL_RPMB:

SD cards do not have RPMB.  Did you mean eMMC?


>> idata = mq_rq->drv_op_data;
>> for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
>> +cmd_do:
>> ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
>> -   if (ret)
>> +   if (ret == -ETIMEDOUT) {
>> +   dev_warn(mmc_dev(card->host),
>> +"error %d sending command\n", ret);
>> +cmd_reset:
>> +   mmc_blk_reset_success(md, type);

mmc_blk_reset_success() is called upon success, not failure.  The reset will
not be attempted twice in a row, for a given type, without a "success" in
between.

>> +   if (retry--) {
>> +   dev_warn(mmc_dev(card->host),
>> +"power cycling card\n");
>> +   if (mmc_blk_reset
>> +   (md, card->host, type))
>> +   goto cmd_reset;
>> +   mmc_blk_reset_success(md, type);
>> +   goto cmd_do;
>> +   }
>> break;
>> +   }
>> }
>> /* Always switch back to main area after RPMB access */
>> if (rpmb_ioctl)
>> --
>> 2.11.0
>>
> 
> Kind regards
> Uffe
> 



Re: [PATCH v7 1/2] scsi: ufs: Enable power management for wlun

2021-02-25 Thread Adrian Hunter
On 25/02/21 5:00 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/cdns-pltfrm.c |   2 +
>  drivers/scsi/ufs/tc-dwc-g210-pci.c |   2 +
>  drivers/scsi/ufs/ufs-exynos.c  |   2 +
>  drivers/scsi/ufs/ufs-hisi.c|   2 +
>  drivers/scsi/ufs/ufs-mediatek.c|   2 +
>  drivers/scsi/ufs/ufs-qcom.c|   2 +
>  drivers/scsi/ufs/ufshcd-pci.c  |  26 +-
>  drivers/scsi/ufs/ufshcd.c  | 532 
> ++---
>  drivers/scsi/ufs/ufshcd.h  |   7 +
>  include/trace/events/ufs.h |  20 ++
>  10 files changed, 476 insertions(+), 121 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
> index 149391f..3e70c23 100644
> --- a/drivers/scsi/ufs/cdns-pltfrm.c
> +++ b/drivers/scsi/ufs/cdns-pltfrm.c
> @@ -319,6 +319,8 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver cdns_ufs_pltfrm_driver = {
> diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c 
> b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> index 67a6a61..b01db12 100644
> --- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
> +++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
> @@ -148,6 +148,8 @@ static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
>   .runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
>   .runtime_resume  = tc_dwc_g210_pci_runtime_resume,
>   .runtime_idle= tc_dwc_g210_pci_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
> diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
> index 267943a1..45c0b02 100644
> --- a/drivers/scsi/ufs/ufs-exynos.c
> +++ b/drivers/scsi/ufs/ufs-exynos.c
> @@ -1268,6 +1268,8 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver exynos_ufs_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
> index 0aa5813..d463b44 100644
> --- a/drivers/scsi/ufs/ufs-hisi.c
> +++ b/drivers/scsi/ufs/ufs-hisi.c
> @@ -574,6 +574,8 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + .complete   = ufshcd_resume_complete,
>  };
>  
>  static struct platform_driver ufs_hisi_pltform = {
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
> index c55202b..df1eabb 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -1097,6 +1097,8 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare = ufshcd_suspend_prepare,
> + 

Re: [PATCH v5 1/2] scsi: ufs: Enable power management for wlun

2021-02-24 Thread Adrian Hunter
On 24/02/21 7:13 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.
> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufs-qcom.c  |   2 +
>  drivers/scsi/ufs/ufshcd-pci.c|  24 --
>  drivers/scsi/ufs/ufshcd-pltfrm.c |  29 +++
>  drivers/scsi/ufs/ufshcd-pltfrm.h |   4 +
>  drivers/scsi/ufs/ufshcd.c| 491 
> +++
>  drivers/scsi/ufs/ufshcd.h|   5 +
>  include/trace/events/ufs.h   |  20 ++
>  7 files changed, 454 insertions(+), 121 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index f97d7b0..8cd8cfd 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1546,6 +1546,8 @@ static const struct dev_pm_ops ufs_qcom_pm_ops = {
>   .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
>   .runtime_resume  = ufshcd_pltfrm_runtime_resume,
>   .runtime_idle= ufshcd_pltfrm_runtime_idle,
> + .prepare= ufshcd_pltfrm_prepare,
> + .resume_early   = ufshcd_pltfrm_resume_early,

The pair for the "prepare" callback is the "complete" callback rather than
"resume_early"

Presumably all drivers will need this kind of change.

>  };
>  
>  static struct platform_driver ufs_qcom_pltform = {
> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
> index fadd566..ab84d56 100644
> --- a/drivers/scsi/ufs/ufshcd-pci.c
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -247,29 +247,6 @@ static int ufshcd_pci_resume(struct device *dev)
>   return ufshcd_system_resume(dev_get_drvdata(dev));
>  }
>  
> -/**
> - * ufshcd_pci_poweroff - suspend-to-disk poweroff function
> - * @dev: pointer to PCI device handle
> - *
> - * Returns 0 if successful
> - * Returns non-zero otherwise
> - */
> -static int ufshcd_pci_poweroff(struct device *dev)
> -{
> - struct ufs_hba *hba = dev_get_drvdata(dev);
> - int spm_lvl = hba->spm_lvl;
> - int ret;
> -
> - /*
> -  * For poweroff we need to set the UFS device to PowerDown mode.
> -  * Force spm_lvl to ensure that.
> -  */
> - hba->spm_lvl = 5;
> - ret = ufshcd_system_suspend(hba);
> - hba->spm_lvl = spm_lvl;
> - return ret;
> -}
> -
>  #endif /* !CONFIG_PM_SLEEP */
>  
>  #ifdef CONFIG_PM
> @@ -370,7 +347,6 @@ static const struct dev_pm_ops ufshcd_pci_pm_ops = {
>   .resume = ufshcd_pci_resume,
>   .freeze = ufshcd_pci_suspend,
>   .thaw   = ufshcd_pci_resume,
> - .poweroff   = ufshcd_pci_poweroff,
>   .restore= ufshcd_pci_resume,
>  #endif
>   SET_RUNTIME_PM_OPS(ufshcd_pci_runtime_suspend,
> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c 
> b/drivers/scsi/ufs/ufshcd-pltfrm.c
> index 1a69949..84550dc 100644
> --- a/drivers/scsi/ufs/ufshcd-pltfrm.c
> +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
> @@ -217,6 +217,35 @@ int ufshcd_pltfrm_runtime_idle(struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle);
>  
> +int ufshcd_pltfrm_prepare(struct device *dev)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> +
> + /*
> +  * SCSI assumes that runtime-pm and system-pm for scsi drivers
> +  * are same. And it doesn't wake up the device for system-suspend
> +  * if it's runtime suspended. But ufs doesn't follow that.
> +  * The rpm-lvl and spm-lvl can be different in ufs.
> +  * Force it to honor system-suspend.

Presumably we could check whether the current power mode is different from
the spm_lvl target power mode, and only do this in that case?

> +  */
> + 

Re: [PATCH v4 1/2] scsi: ufs: Enable power management for wlun

2021-02-23 Thread Adrian Hunter
On 23/02/21 1:04 am, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.

Hi

I have a few more questions and comments.

At a glance it looked to me like the SCSI bus will leave a SCSI device
runtime suspended at system suspend, but UFS device spm_lvl and rpm_lvl need
not be the same.  Do you know how SCSI handles that case?

> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufshcd.c  | 455 
> +++--
>  drivers/scsi/ufs/ufshcd.h  |   4 +
>  include/trace/events/ufs.h |  20 ++
>  3 files changed, 382 insertions(+), 97 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 45624c7..1d8044a 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -16,6 +16,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "ufshcd.h"
>  #include "ufs_quirks.h"
>  #include "unipro.h"
> @@ -251,6 +252,11 @@ static int ufshcd_wb_toggle_flush_during_h8(struct 
> ufs_hba *hba, bool set);
>  static inline int ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);
>  static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
>  static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
> +static int ufshcd_wl_runtime_suspend(struct device *dev);
> +static int ufshcd_wl_runtime_resume(struct device *dev);
> +static int ufshcd_wl_suspend(struct device *dev);
> +static int ufshcd_wl_resume(struct device *dev);
> +static void ufshcd_wl_shutdown(struct device *dev);
>  
>  static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
>  {
> @@ -1556,7 +1562,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct 
> device *dev,
>   if (value == hba->clk_scaling.is_enabled)
>   goto out;
>  
> - pm_runtime_get_sync(hba->dev);
> + scsi_autopm_get_device(hba->sdev_ufs_device);
>   ufshcd_hold(hba, false);
>  
>   hba->clk_scaling.is_enabled = value;
> @@ -1572,7 +1578,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct 
> device *dev,
>   }
>  
>   ufshcd_release(hba);
> - pm_runtime_put_sync(hba->dev);
> + scsi_autopm_put_device(hba->sdev_ufs_device);
>  out:
>   up(>host_sem);
>   return err ? err : count;
> @@ -2572,6 +2578,17 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 
> upiu_wlun_id)
>   return (upiu_wlun_id & ~UFS_UPIU_WLUN_ID) | SCSI_W_LUN_BASE;
>  }
>  
> +static inline bool is_rpmb_wlun(struct scsi_device *sdev)
> +{
> + return (sdev->lun == ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN));
> +}
> +
> +static inline bool is_device_wlun(struct scsi_device *sdev)
> +{
> + return (sdev->lun ==
> + ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN));
> +}
> +
>  static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int 
> i)
>  {
>   struct utp_transfer_cmd_desc *cmd_descp = hba->ucdl_base_addr;
> @@ -4808,6 +4825,41 @@ static inline void 
> ufshcd_get_lu_power_on_wp_status(struct ufs_hba *hba,
>  }
>  
>  /**
> + * ufshcd_setup_links - associate link b/w device wlun and other luns
> + * @sdev: pointer to SCSI device
> + * @hba: pointer to ufs hba
> + */
> +static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
> +{
> + struct device_link *link;
> +
> + /*
> +  * device wlun is the supplier & rest of the luns are consumers
> +  * This ensures that device wlun suspends after all other luns.
> +  */
> + if (hba->sdev_ufs_device) {
> + link = device_link_add(>sdev_gendev,
> +>sdev_ufs_device->sdev_gendev,
> +  

Re: [RFC PATCH v3 1/1] scsi: ufs: Enable power management for wlun

2021-02-19 Thread Adrian Hunter
On 11/02/21 9:18 pm, Asutosh Das wrote:
> During runtime-suspend of ufs host, the scsi devices are
> already suspended and so are the queues associated with them.
> But the ufs host sends SSU to wlun during its runtime-suspend.
> During the process blk_queue_enter checks if the queue is not in
> suspended state. If so, it waits for the queue to resume, and never
> comes out of it.
> The commit
> (d55d15a33: scsi: block: Do not accept any requests while suspended)
> adds the check if the queue is in suspended state in blk_queue_enter().
> 
> Call trace:
>  __switch_to+0x174/0x2c4
>  __schedule+0x478/0x764
>  schedule+0x9c/0xe0
>  blk_queue_enter+0x158/0x228
>  blk_mq_alloc_request+0x40/0xa4
>  blk_get_request+0x2c/0x70
>  __scsi_execute+0x60/0x1c4
>  ufshcd_set_dev_pwr_mode+0x124/0x1e4
>  ufshcd_suspend+0x208/0x83c
>  ufshcd_runtime_suspend+0x40/0x154
>  ufshcd_pltfrm_runtime_suspend+0x14/0x20
>  pm_generic_runtime_suspend+0x28/0x3c
>  __rpm_callback+0x80/0x2a4
>  rpm_suspend+0x308/0x614
>  rpm_idle+0x158/0x228
>  pm_runtime_work+0x84/0xac
>  process_one_work+0x1f0/0x470
>  worker_thread+0x26c/0x4c8
>  kthread+0x13c/0x320
>  ret_from_fork+0x10/0x18
> 
> Fix this by registering ufs device wlun as a scsi driver and
> registering it for block runtime-pm. Also make this as a
> supplier for all other luns. That way, this device wlun
> suspends after all the consumers and resumes after
> hba resumes.

Sounds reasonable.  Thanks for doing this.  Some comments below.

> 
> Co-developed-by: Can Guo 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufshcd.c  | 415 
> +
>  drivers/scsi/ufs/ufshcd.h  |   4 +
>  include/trace/events/ufs.h |  20 +++
>  3 files changed, 364 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 45624c7..e92dbde 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -16,6 +16,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include "ufshcd.h"
>  #include "ufs_quirks.h"
>  #include "unipro.h"
> @@ -251,6 +252,13 @@ static int ufshcd_wb_toggle_flush_during_h8(struct 
> ufs_hba *hba, bool set);
>  static inline int ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);
>  static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba);
>  static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba);
> +static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op);
> +static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op);
> +static int ufshcd_wl_runtime_suspend(struct device *dev);
> +static int ufshcd_wl_runtime_resume(struct device *dev);
> +static int ufshcd_wl_suspend(struct device *dev);
> +static int ufshcd_wl_resume(struct device *dev);
> +static void ufshcd_wl_shutdown(struct device *dev);

Please try to reduce the number of forward declarations.

>  
>  static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
>  {
> @@ -2572,6 +2580,17 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 
> upiu_wlun_id)
>   return (upiu_wlun_id & ~UFS_UPIU_WLUN_ID) | SCSI_W_LUN_BASE;
>  }
>  
> +static inline bool is_rpmb_wlun(struct scsi_device *sdev)
> +{
> + return (sdev->lun == ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN));
> +}
> +
> +static inline bool is_device_wlun(struct scsi_device *sdev)
> +{
> + return (sdev->lun ==
> + ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN));
> +}
> +
>  static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int 
> i)
>  {
>   struct utp_transfer_cmd_desc *cmd_descp = hba->ucdl_base_addr;
> @@ -4808,6 +4827,43 @@ static inline void 
> ufshcd_get_lu_power_on_wp_status(struct ufs_hba *hba,
>  }
>  
>  /**
> + * ufshcd_setup_links - associate link b/w device wlun and other luns
> + * @sdev: pointer to SCSI device
> + * @hba: pointer to ufs hba
> + *
> + * Returns void
> + */
> +static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
> +{
> + struct device_link *link;
> +
> + /*
> +  * device wlun is the supplier & rest of the luns are consumers
> +  * This ensures that device wlun suspends after all other luns.
> +  */
> + if (hba->sdev_ufs_device) {
> + link = device_link_add(>sdev_gendev,
> +>sdev_ufs_device->sdev_gendev,
> +DL_FLAG_PM_RUNTIME);
> + if (!link) {
> + dev_err(>sdev_gendev, "Failed establishing link - 
> %s\n",
> + dev_name(>sdev_ufs_device->sdev_gendev));
> + return;
> + }
> + hba->luns_avail--;
> + /* Ignore REPORT_LUN wlun probing */
> + if (hba->luns_avail != 1)
> + return;
> +
> + pm_runtime_put_noidle(>sdev_ufs_device->sdev_gendev);
> + 

[PATCH 02/11] perf intel_pt: Add vmlaunch and vmresume as branches

2021-02-18 Thread Adrian Hunter
In preparation to support Intel PT decoding of virtual machine traces, add
vmlaunch and vmresume as branch instructions.

Note, sample flags will show "VMentry" even if the VM-Entry fails.

Signed-off-by: Adrian Hunter 
---
 tools/perf/arch/x86/tests/insn-x86.c  |  1 +
 .../util/intel-pt-decoder/intel-pt-insn-decoder.c | 15 +++
 .../util/intel-pt-decoder/intel-pt-insn-decoder.h |  1 +
 3 files changed, 17 insertions(+)

diff --git a/tools/perf/arch/x86/tests/insn-x86.c 
b/tools/perf/arch/x86/tests/insn-x86.c
index 745f29adb14b..f782ef8c5982 100644
--- a/tools/perf/arch/x86/tests/insn-x86.c
+++ b/tools/perf/arch/x86/tests/insn-x86.c
@@ -48,6 +48,7 @@ static int get_op(const char *op_str)
{"int", INTEL_PT_OP_INT},
{"syscall", INTEL_PT_OP_SYSCALL},
{"sysret",  INTEL_PT_OP_SYSRET},
+   {"vmentry",  INTEL_PT_OP_VMENTRY},
{NULL, 0},
};
struct val_data *val;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
index fb8a3558d3d5..2f6cc7eea251 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -43,6 +43,17 @@ static void intel_pt_insn_decoder(struct insn *insn,
switch (insn->opcode.bytes[0]) {
case 0xf:
switch (insn->opcode.bytes[1]) {
+   case 0x01:
+   switch (insn->modrm.bytes[0]) {
+   case 0xc2: /* vmlaunch */
+   case 0xc3: /* vmresume */
+   op = INTEL_PT_OP_VMENTRY;
+   branch = INTEL_PT_BR_INDIRECT;
+   break;
+   default:
+   break;
+   }
+   break;
case 0x05: /* syscall */
case 0x34: /* sysenter */
op = INTEL_PT_OP_SYSCALL;
@@ -213,6 +224,7 @@ const char *branch_name[] = {
[INTEL_PT_OP_INT]   = "Int",
[INTEL_PT_OP_SYSCALL]   = "Syscall",
[INTEL_PT_OP_SYSRET]= "Sysret",
+   [INTEL_PT_OP_VMENTRY]   = "VMentry",
 };
 
 const char *intel_pt_insn_name(enum intel_pt_insn_op op)
@@ -267,6 +279,9 @@ int intel_pt_insn_type(enum intel_pt_insn_op op)
case INTEL_PT_OP_SYSRET:
return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
   PERF_IP_FLAG_SYSCALLRET;
+   case INTEL_PT_OP_VMENTRY:
+   return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
+  PERF_IP_FLAG_VMENTRY;
default:
return 0;
}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h 
b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
index 95a1eb0141ff..c2861cfdd768 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -24,6 +24,7 @@ enum intel_pt_insn_op {
INTEL_PT_OP_INT,
INTEL_PT_OP_SYSCALL,
INTEL_PT_OP_SYSRET,
+   INTEL_PT_OP_VMENTRY,
 };
 
 enum intel_pt_insn_branch {
-- 
2.17.1



[PATCH 00/11] perf intel-pt: Add limited support for tracing guest kernels

2021-02-18 Thread Adrian Hunter
Hi

Currently, only kernel tracing is supported and only with "timeless" decoding
i.e. no TSC timestamps

Other limitations and caveats

 VMX controls may suppress packets needed for decoding resulting in decoding 
errors
 VMX controls may block the perf NMI to the host potentially resulting in lost 
trace data
 Guest kernel self-modifying code (e.g. jump labels or JIT-compiled eBPF) will 
result in decoding errors
 Guest thread information is unknown
 Guest VCPU is unknown but may be able to be inferred from the host thread
 Callchains are not supported

There is an example in the documentation of patch
"perf intel-pt: Add documentation for tracing virtual machines"

The patches are on top of the "Add PSB events" series.


Adrian Hunter (11):
  perf script: Add branch types for VM-Entry and VM-Exit
  perf intel_pt: Add vmlaunch and vmresume as branches
  perf intel-pt: Retain the last PIP packet payload as is
  perf intel-pt: Amend decoder to track the NR flag
  perf machine: Factor out machines__find_guest()
  perf machine: Factor out machine__idle_thread()
  perf intel-pt: Support decoding of guest kernel
  perf intel-pt: Allow for a guest kernel address filter
  perf intel-pt: Adjust sample flags for VM-Exit
  perf intel-pt: Split VM-Entry and VM-Exit branches
  perf intel-pt: Add documentation for tracing virtual machines

 tools/perf/Documentation/perf-intel-pt.txt |  82 ++
 tools/perf/arch/x86/tests/insn-x86.c   |   1 +
 .../arch/x86/tests/intel-pt-pkt-decoder-test.c |   4 +-
 tools/perf/builtin-script.c|   2 +
 tools/perf/util/db-export.c|   2 +
 tools/perf/util/event.h|   6 +-
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  |  61 +--
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |   3 +-
 .../util/intel-pt-decoder/intel-pt-insn-decoder.c  |  15 +++
 .../util/intel-pt-decoder/intel-pt-insn-decoder.h  |   1 +
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.c   |  12 +-
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.h   |   2 +
 tools/perf/util/intel-pt.c | 122 ++---
 tools/perf/util/machine.c  |  27 +
 tools/perf/util/machine.h  |   2 +
 tools/perf/util/session.c  |  32 +-
 16 files changed, 307 insertions(+), 67 deletions(-)


Regards
Adrian


[PATCH 01/11] perf script: Add branch types for VM-Entry and VM-Exit

2021-02-18 Thread Adrian Hunter
In preparation to support Intel PT decoding of virtual machine traces, add
branch types for VM-Entry and VM-Exit.

Note they are both treated as "calls" because the VM-Exit transfers control
to a different address.

Signed-off-by: Adrian Hunter 
---
 tools/perf/builtin-script.c | 2 ++
 tools/perf/util/db-export.c | 2 ++
 tools/perf/util/event.h | 6 +-
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 4143d3f6eb37..57958bb96082 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1537,6 +1537,8 @@ static struct {
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
+   {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, 
"vmentry"},
+   {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, 
"vmexit"},
{0, NULL}
 };
 
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index db7447154622..5cd189172525 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -438,6 +438,8 @@ static struct {
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
+   {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vm 
entry"},
+   {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vm 
exit"},
{0, NULL}
 };
 
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 4a3b5b6478d8..034526288e05 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -96,6 +96,8 @@ enum {
PERF_IP_FLAG_TRACE_BEGIN= 1ULL << 8,
PERF_IP_FLAG_TRACE_END  = 1ULL << 9,
PERF_IP_FLAG_IN_TX  = 1ULL << 10,
+   PERF_IP_FLAG_VMENTRY= 1ULL << 11,
+   PERF_IP_FLAG_VMEXIT = 1ULL << 12,
 };
 
 #define PERF_IP_FLAG_CHARS "bcrosyiABEx"
@@ -110,7 +112,9 @@ enum {
PERF_IP_FLAG_INTERRUPT  |\
PERF_IP_FLAG_TX_ABORT   |\
PERF_IP_FLAG_TRACE_BEGIN|\
-   PERF_IP_FLAG_TRACE_END)
+   PERF_IP_FLAG_TRACE_END  |\
+   PERF_IP_FLAG_VMENTRY|\
+   PERF_IP_FLAG_VMEXIT)
 
 #define MAX_INSN 16
 
-- 
2.17.1



[PATCH 09/11] perf intel-pt: Adjust sample flags for VM-Exit

2021-02-18 Thread Adrian Hunter
Use the change of NR to detect whether an asynchronous branch is a VM-Exit.

Note VM-Entry is determined from the vmlaunch or vmresume instruction,
in which case, sample flags will show "VMentry" even if the VM-Entry fails.

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/intel-pt.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 546d512b300a..cafb3943d5f6 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1201,13 +1201,16 @@ static void intel_pt_sample_flags(struct intel_pt_queue 
*ptq)
if (ptq->state->flags & INTEL_PT_ABORT_TX) {
ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT;
} else if (ptq->state->flags & INTEL_PT_ASYNC) {
-   if (ptq->state->to_ip)
+   if (!ptq->state->to_ip)
+   ptq->flags = PERF_IP_FLAG_BRANCH |
+PERF_IP_FLAG_TRACE_END;
+   else if (ptq->state->from_nr && !ptq->state->to_nr)
+   ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
+PERF_IP_FLAG_VMEXIT;
+   else
ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
 PERF_IP_FLAG_ASYNC |
 PERF_IP_FLAG_INTERRUPT;
-   else
-   ptq->flags = PERF_IP_FLAG_BRANCH |
-PERF_IP_FLAG_TRACE_END;
ptq->insn_len = 0;
} else {
if (ptq->state->from_ip)
-- 
2.17.1



[PATCH 08/11] perf intel-pt: Allow for a guest kernel address filter

2021-02-18 Thread Adrian Hunter
Handling TIP.PGD for an address filter for a guest kernel is the same as a
host kernel, but user space decoding, and hence address filters, are not
supported.

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/intel-pt.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 29d871718995..546d512b300a 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -792,8 +792,14 @@ static int __intel_pt_pgd_ip(uint64_t ip, void *data)
u8 cpumode;
u64 offset;
 
-   if (ip >= ptq->pt->kernel_start)
+   if (ptq->state->to_nr) {
+   if (intel_pt_guest_kernel_ip(ip))
+   return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
+   /* No support for decoding guest user space */
+   return -EINVAL;
+   } else if (ip >= ptq->pt->kernel_start) {
return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
+   }
 
cpumode = PERF_RECORD_MISC_USER;
 
-- 
2.17.1



[PATCH 11/11] perf intel-pt: Add documentation for tracing virtual machines

2021-02-18 Thread Adrian Hunter
Add documentation to the perf-intel-pt man page for tracing virtual
machines.

Signed-off-by: Adrian Hunter 
---
 tools/perf/Documentation/perf-intel-pt.txt | 82 ++
 1 file changed, 82 insertions(+)

diff --git a/tools/perf/Documentation/perf-intel-pt.txt 
b/tools/perf/Documentation/perf-intel-pt.txt
index 0b8a339803cb..18c91b7cd937 100644
--- a/tools/perf/Documentation/perf-intel-pt.txt
+++ b/tools/perf/Documentation/perf-intel-pt.txt
@@ -1146,6 +1146,88 @@ XED
 
 include::build-xed.txt[]
 
+
+Tracing Virtual Machines
+
+
+Currently, only kernel tracing is supported and only with "timeless" decoding
+i.e. no TSC timestamps
+
+Other limitations and caveats
+
+ VMX controls may suppress packets needed for decoding resulting in decoding 
errors
+ VMX controls may block the perf NMI to the host potentially resulting in lost 
trace data
+ Guest kernel self-modifying code (e.g. jump labels or JIT-compiled eBPF) will 
result in decoding errors
+ Guest thread information is unknown
+ Guest VCPU is unknown but may be able to be inferred from the host thread
+ Callchains are not supported
+
+Example
+
+Start VM
+
+ $ sudo virsh start kubuntu20.04
+ Domain kubuntu20.04 started
+
+Mount the guest file system.  Note sshfs needs -o direct_io to enable reading 
of proc files.  root access is needed to read /proc/kcore.
+
+ $ mkdir vm0
+ $ sshfs -o direct_io root@vm0:/ vm0
+
+Copy the guest /proc/kallsyms, /proc/modules and /proc/kcore
+
+ $ perf buildid-cache -v --kcore vm0/proc/kcore
+ kcore added to build-id cache directory 
/home/user/.debug/[kernel.kcore]/9600f316a53a0f54278885e8d9710538ec5f6a08/2021021807494306
+ $ 
KALLSYMS=/home/user/.debug/[kernel.kcore]/9600f316a53a0f54278885e8d9710538ec5f6a08/2021021807494306/kallsyms
+
+Find the VM process
+
+ $ ps -eLl | grep 'KVM\|PID'
+ F S   UID PIDPPID LWP  C PRI  NI ADDR SZ WCHAN  TTY  TIME 
CMD
+ 3 S 640551430   11440  1  80   0 - 1921718 -?00:02:47 
CPU 0/KVM
+ 3 S 640551430   11441  1  80   0 - 1921718 -?00:02:41 
CPU 1/KVM
+ 3 S 640551430   11442  1  80   0 - 1921718 -?00:02:38 
CPU 2/KVM
+ 3 S 640551430   11443  2  80   0 - 1921718 -?00:03:18 
CPU 3/KVM
+
+Start an open-ended perf record, tracing the VM process, do something on the 
VM, and then ctrl-C to stop.
+TSC is not supported and tsc=0 must be specified.  That means mtc is useless, 
so add mtc=0.
+However, IPC can still be determined, hence cyc=1 can be added.
+Only kernel decoding is supported, so 'k' must be specified.
+Intel PT traces both the host and the guest so --guest and --host need to be 
specified.
+Without timestamps, --per-thread must be specified to distinguish threads.
+
+ $ sudo perf kvm --guest --host --guestkallsyms $KALLSYMS record --kcore -e 
intel_pt/tsc=0,mtc=0,cyc=1/k -p 1430 --per-thread
+ ^C
+ [ perf record: Woken up 1 times to write data ]
+ [ perf record: Captured and wrote 5.829 MB ]
+
+perf script can be used to provide an instruction trace
+
+ $ perf script --guestkallsyms $KALLSYMS --insn-trace --xed -F+ipc | grep -C10 
vmresume | head -21
+   CPU 0/KVM  1440  82133cdd __vmx_vcpu_run+0x3d 
([kernel.kallsyms])movq  0x48(%rax), %r9
+   CPU 0/KVM  1440  82133ce1 __vmx_vcpu_run+0x41 
([kernel.kallsyms])movq  0x50(%rax), %r10
+   CPU 0/KVM  1440  82133ce5 __vmx_vcpu_run+0x45 
([kernel.kallsyms])movq  0x58(%rax), %r11
+   CPU 0/KVM  1440  82133ce9 __vmx_vcpu_run+0x49 
([kernel.kallsyms])movq  0x60(%rax), %r12
+   CPU 0/KVM  1440  82133ced __vmx_vcpu_run+0x4d 
([kernel.kallsyms])movq  0x68(%rax), %r13
+   CPU 0/KVM  1440  82133cf1 __vmx_vcpu_run+0x51 
([kernel.kallsyms])movq  0x70(%rax), %r14
+   CPU 0/KVM  1440  82133cf5 __vmx_vcpu_run+0x55 
([kernel.kallsyms])movq  0x78(%rax), %r15
+   CPU 0/KVM  1440  82133cf9 __vmx_vcpu_run+0x59 
([kernel.kallsyms])movq  (%rax), %rax
+   CPU 0/KVM  1440  82133cfc __vmx_vcpu_run+0x5c 
([kernel.kallsyms])callq  0x82133c40
+   CPU 0/KVM  1440  82133c40 vmx_vmenter+0x0 ([kernel.kallsyms])   
 jz 0x82133c46
+   CPU 0/KVM  1440  82133c42 vmx_vmenter+0x2 ([kernel.kallsyms])   
 vmresume IPC: 0.11 (50/445)
+   :1440  1440  bb678b06 native_write_msr+0x6 
([guest.kernel.kallsyms]) nopl  %eax, (%rax,%rax,1)
+   :1440  1440  bb678b0b native_write_msr+0xb 
([guest.kernel.kallsyms]) retq IPC: 0.04 (2/41)
+   :1440  1440  bb46 lapic_next_deadline+0x26 
([guest.kernel.kallsyms]) data16 nop
+   :1440  1440  bb48 lapic_next_deadline+0x28 
([guest.kernel.kallsyms])  

[PATCH 10/11] perf intel-pt: Split VM-Entry and VM-Exit branches

2021-02-18 Thread Adrian Hunter
Events record a single cpumode so the tools cannot handle a branch from
the host machine to a virtual machine, or vice versa. Split it in two so
that each branch can have a different cpumode.

  E.g.  host ip -> guest ip

  becomes:  host ip -> 0
  0 -> guest ip

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/intel-pt.c | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index cafb3943d5f6..f6e28ac231b7 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2171,7 +2171,27 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
}
 
if (pt->sample_branches) {
-   err = intel_pt_synth_branch_sample(ptq);
+   if (state->from_nr != state->to_nr &&
+   state->from_ip && state->to_ip) {
+   struct intel_pt_state *st = (struct intel_pt_state 
*)state;
+   u64 to_ip = st->to_ip;
+   u64 from_ip = st->from_ip;
+
+   /*
+* perf cannot handle having different machines for ip
+* and addr, so create 2 branches.
+*/
+   st->to_ip = 0;
+   err = intel_pt_synth_branch_sample(ptq);
+   if (err)
+   return err;
+   st->from_ip = 0;
+   st->to_ip = to_ip;
+   err = intel_pt_synth_branch_sample(ptq);
+   st->from_ip = from_ip;
+   } else {
+   err = intel_pt_synth_branch_sample(ptq);
+   }
if (err)
return err;
}
-- 
2.17.1



[PATCH 07/11] perf intel-pt: Support decoding of guest kernel

2021-02-18 Thread Adrian Hunter
The guest kernel can be found from any guest thread belonging to the guest
machine. The guest machine is associated with the current host process pid.
An idle thread (pid=tid=0) is created as a vehicle from which to find the
guest kernel map.

Decoding guest user space is not supported.

Synthesized samples just need the cpumode set for the guest.

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/intel-pt.c | 81 --
 1 file changed, 69 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index ddb8e6c3ffb0..29d871718995 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -163,6 +163,9 @@ struct intel_pt_queue {
int switch_state;
pid_t next_tid;
struct thread *thread;
+   struct machine *guest_machine;
+   struct thread *unknown_guest_thread;
+   pid_t guest_machine_pid;
bool exclude_kernel;
bool have_sample;
u64 time;
@@ -550,13 +553,59 @@ static void intel_pt_cache_invalidate(struct dso *dso, 
struct machine *machine,
auxtrace_cache__remove(dso->auxtrace_cache, offset);
 }
 
-static inline u8 intel_pt_cpumode(struct intel_pt *pt, uint64_t ip)
+static inline bool intel_pt_guest_kernel_ip(uint64_t ip)
 {
-   return ip >= pt->kernel_start ?
+   /* Assumes 64-bit kernel */
+   return ip & (1ULL << 63);
+}
+
+static inline u8 intel_pt_nr_cpumode(struct intel_pt_queue *ptq, uint64_t ip, 
bool nr)
+{
+   if (nr) {
+   return intel_pt_guest_kernel_ip(ip) ?
+  PERF_RECORD_MISC_GUEST_KERNEL :
+  PERF_RECORD_MISC_GUEST_USER;
+   }
+
+   return ip >= ptq->pt->kernel_start ?
   PERF_RECORD_MISC_KERNEL :
   PERF_RECORD_MISC_USER;
 }
 
+static inline u8 intel_pt_cpumode(struct intel_pt_queue *ptq, uint64_t 
from_ip, uint64_t to_ip)
+{
+   /* No support for non-zero CS base */
+   if (from_ip)
+   return intel_pt_nr_cpumode(ptq, from_ip, ptq->state->from_nr);
+   return intel_pt_nr_cpumode(ptq, to_ip, ptq->state->to_nr);
+}
+
+static int intel_pt_get_guest(struct intel_pt_queue *ptq)
+{
+   struct machines *machines = >pt->session->machines;
+   struct machine *machine;
+   pid_t pid = ptq->pid <= 0 ? DEFAULT_GUEST_KERNEL_ID : ptq->pid;
+
+   if (ptq->guest_machine && pid == ptq->guest_machine_pid)
+   return 0;
+
+   ptq->guest_machine = NULL;
+   thread__zput(ptq->unknown_guest_thread);
+
+   machine = machines__find_guest(machines, pid);
+   if (!machine)
+   return -1;
+
+   ptq->unknown_guest_thread = machine__idle_thread(machine);
+   if (!ptq->unknown_guest_thread)
+   return -1;
+
+   ptq->guest_machine = machine;
+   ptq->guest_machine_pid = pid;
+
+   return 0;
+}
+
 static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
   uint64_t *insn_cnt_ptr, uint64_t *ip,
   uint64_t to_ip, uint64_t max_insn_cnt,
@@ -573,19 +622,29 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn 
*intel_pt_insn,
u64 offset, start_offset, start_ip;
u64 insn_cnt = 0;
bool one_map = true;
+   bool nr;
 
intel_pt_insn->length = 0;
 
if (to_ip && *ip == to_ip)
goto out_no_cache;
 
-   cpumode = intel_pt_cpumode(ptq->pt, *ip);
+   nr = ptq->state->to_nr;
+   cpumode = intel_pt_nr_cpumode(ptq, *ip, nr);
 
-   thread = ptq->thread;
-   if (!thread) {
-   if (cpumode != PERF_RECORD_MISC_KERNEL)
+   if (nr) {
+   if (cpumode != PERF_RECORD_MISC_GUEST_KERNEL ||
+   intel_pt_get_guest(ptq))
return -EINVAL;
-   thread = ptq->pt->unknown_thread;
+   machine = ptq->guest_machine;
+   thread = ptq->unknown_guest_thread;
+   } else {
+   thread = ptq->thread;
+   if (!thread) {
+   if (cpumode != PERF_RECORD_MISC_KERNEL)
+   return -EINVAL;
+   thread = ptq->pt->unknown_thread;
+   }
}
 
while (1) {
@@ -1101,6 +1160,7 @@ static void intel_pt_free_queue(void *priv)
if (!ptq)
return;
thread__zput(ptq->thread);
+   thread__zput(ptq->unknown_guest_thread);
intel_pt_decoder_free(ptq->decoder);
zfree(>event_buf);
zfree(>last_branch);
@@ -1315,8 +1375,8 @@ static void intel_pt_prep_b_sample(struct intel_pt *pt,
sample->time = tsc_to_perf_time(ptq->timestamp, >tc);
 
sample->ip = ptq->state->from_ip;
-   sample->cpumode = intel_p

[PATCH 06/11] perf machine: Factor out machine__idle_thread()

2021-02-18 Thread Adrian Hunter
Factor out machine__idle_thread() so it can be re-used for guest machines.

A thread is needed to find executable code, even for the guest kernel. To
avoid possible future pid number conflicts, the idle thread can be used.

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/machine.c | 18 ++
 tools/perf/util/machine.h |  1 +
 tools/perf/util/session.c | 25 +++--
 3 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 90703b7ca6de..b5c2d8be4144 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -598,6 +598,24 @@ struct thread *machine__find_thread(struct machine 
*machine, pid_t pid,
return th;
 }
 
+/*
+ * Threads are identified by pid and tid, and the idle task has pid == tid == 
0.
+ * So here a single thread is created for that, but actually there is a 
separate
+ * idle task per cpu, so there should be one 'struct thread' per cpu, but there
+ * is only 1. That causes problems for some tools, requiring workarounds. For
+ * example get_idle_thread() in builtin-sched.c, or thread_stack__per_cpu().
+ */
+struct thread *machine__idle_thread(struct machine *machine)
+{
+   struct thread *thread = machine__findnew_thread(machine, 0, 0);
+
+   if (!thread || thread__set_comm(thread, "swapper", 0) ||
+   thread__set_namespaces(thread, 0, NULL))
+   pr_err("problem inserting idle task for machine pid %d\n", 
machine->pid);
+
+   return thread;
+}
+
 struct comm *machine__thread_exec_comm(struct machine *machine,
   struct thread *thread)
 {
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 022c19ecd287..7377ed6efdf1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -106,6 +106,7 @@ u8 machine__addr_cpumode(struct machine *machine, u8 
cpumode, u64 addr);
 
 struct thread *machine__find_thread(struct machine *machine, pid_t pid,
pid_t tid);
+struct thread *machine__idle_thread(struct machine *machine);
 struct comm *machine__thread_exec_comm(struct machine *machine,
   struct thread *thread);
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 7b0d0c9e3dd1..859832a82496 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1789,32 +1789,13 @@ struct thread *perf_session__findnew(struct 
perf_session *session, pid_t pid)
return machine__findnew_thread(>machines.host, -1, pid);
 }
 
-/*
- * Threads are identified by pid and tid, and the idle task has pid == tid == 
0.
- * So here a single thread is created for that, but actually there is a 
separate
- * idle task per cpu, so there should be one 'struct thread' per cpu, but there
- * is only 1. That causes problems for some tools, requiring workarounds. For
- * example get_idle_thread() in builtin-sched.c, or thread_stack__per_cpu().
- */
 int perf_session__register_idle_thread(struct perf_session *session)
 {
-   struct thread *thread;
-   int err = 0;
-
-   thread = machine__findnew_thread(>machines.host, 0, 0);
-   if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
-   pr_err("problem inserting idle task.\n");
-   err = -1;
-   }
+   struct thread *thread = machine__idle_thread(>machines.host);
 
-   if (thread == NULL || thread__set_namespaces(thread, 0, NULL)) {
-   pr_err("problem inserting idle task.\n");
-   err = -1;
-   }
-
-   /* machine__findnew_thread() got the thread, so put it */
+   /* machine__idle_thread() got the thread, so put it */
thread__put(thread);
-   return err;
+   return thread ? 0 : -1;
 }
 
 static void
-- 
2.17.1



[PATCH 04/11] perf intel-pt: Amend decoder to track the NR flag

2021-02-18 Thread Adrian Hunter
The PIP packet NR (non-root) flag indicates whether or not a virtual
machine is being traced (NR=1 => VM). Add support for tracking its value.

In particular note that the PIP packet (outside of PSB+) will be
associated with a TIP packet from which address the NR value takes
effect. At that point, there is a branch from_ip, to_ip with
corresponding from_nr and to_nr.

In the event of VM-Entry failure, there should still PIP and TIP packets
that can be followed in the same way.

Also note that this assumes that a host VMM is not employing VMX controls
that affect Intel PT, e.g. to hide the host from a guest using Intel PT.

Signed-off-by: Adrian Hunter 
---
 .../util/intel-pt-decoder/intel-pt-decoder.c  | 59 ---
 .../util/intel-pt-decoder/intel-pt-decoder.h  |  3 +-
 2 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index cfaa091c935c..8c59677bee13 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -122,6 +122,8 @@ struct intel_pt_decoder {
bool in_psb;
bool hop;
bool leap;
+   bool nr;
+   bool next_nr;
enum intel_pt_param_flags flags;
uint64_t pos;
uint64_t last_ip;
@@ -503,6 +505,28 @@ static inline void intel_pt_update_in_tx(struct 
intel_pt_decoder *decoder)
decoder->tx_flags = decoder->packet.payload & INTEL_PT_IN_TX;
 }
 
+static inline void intel_pt_update_pip(struct intel_pt_decoder *decoder)
+{
+   decoder->pip_payload = decoder->packet.payload;
+}
+
+static inline void intel_pt_update_nr(struct intel_pt_decoder *decoder)
+{
+   decoder->next_nr = decoder->pip_payload & 1;
+}
+
+static inline void intel_pt_set_nr(struct intel_pt_decoder *decoder)
+{
+   decoder->nr = decoder->pip_payload & 1;
+   decoder->next_nr = decoder->nr;
+}
+
+static inline void intel_pt_set_pip(struct intel_pt_decoder *decoder)
+{
+   intel_pt_update_pip(decoder);
+   intel_pt_set_nr(decoder);
+}
+
 static int intel_pt_bad_packet(struct intel_pt_decoder *decoder)
 {
intel_pt_clear_tx_flags(decoder);
@@ -1240,6 +1264,7 @@ static int intel_pt_walk_tip(struct intel_pt_decoder 
*decoder)
decoder->continuous_period = false;
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->state.type |= INTEL_PT_TRACE_END;
+   intel_pt_update_nr(decoder);
return 0;
}
if (err == INTEL_PT_RETURN)
@@ -1247,6 +1272,8 @@ static int intel_pt_walk_tip(struct intel_pt_decoder 
*decoder)
if (err)
return err;
 
+   intel_pt_update_nr(decoder);
+
if (intel_pt_insn.branch == INTEL_PT_BR_INDIRECT) {
if (decoder->pkt_state == INTEL_PT_STATE_TIP_PGD) {
decoder->pge = false;
@@ -1359,6 +1386,7 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder 
*decoder)
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = decoder->last_ip;
decoder->ip = decoder->last_ip;
+   intel_pt_update_nr(decoder);
return 0;
}
 
@@ -1483,6 +1511,7 @@ static int intel_pt_overflow(struct intel_pt_decoder 
*decoder)
 {
intel_pt_log("ERROR: Buffer overflow\n");
intel_pt_clear_tx_flags(decoder);
+   intel_pt_set_nr(decoder);
decoder->timestamp_insn_cnt = 0;
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
decoder->overflow = true;
@@ -1757,7 +1786,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder 
*decoder)
break;
 
case INTEL_PT_PIP:
-   decoder->pip_payload = decoder->packet.payload;
+   intel_pt_set_pip(decoder);
break;
 
case INTEL_PT_FUP:
@@ -1856,6 +1885,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder 
*decoder)
decoder->pge = false;
decoder->continuous_period = false;
decoder->state.type |= INTEL_PT_TRACE_END;
+   intel_pt_update_nr(decoder);
return 0;
 
case INTEL_PT_TIP_PGE:
@@ -1871,6 +1901,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder 
*decoder)
}
decoder->state.type |= INTEL_PT_TRACE_BEGIN;
intel_pt_mtc_cyc_cnt_pge(decoder);
+   intel_pt_set_nr(decoder);
return 0;
 
case INTEL_PT_TIP:
@@ -1881,10 +1912,11 @@ static int intel_pt_walk_fup_tip(struct 
intel_pt_decoder *decoder)
 

[PATCH 03/11] perf intel-pt: Retain the last PIP packet payload as is

2021-02-18 Thread Adrian Hunter
Retain the PIP packet payload as is, instead of just the CR3, because it
contains also the VMX NR flag which is needed to track VM-Entry.

Signed-off-by: Adrian Hunter 
---
 .../arch/x86/tests/intel-pt-pkt-decoder-test.c |  4 ++--
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 14 +++---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |  2 +-
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.c   | 12 
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.h   |  2 ++
 5 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c 
b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
index 901bf1f449c4..c933e3dcd0a8 100644
--- a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
+++ b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
@@ -66,8 +66,8 @@ struct test_data {
{7, {0x9d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 4, 0x60504030201}, 0, 0 
},
{9, {0xdd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_FUP, 6, 
0x807060504030201}, 0, 0 },
/* Paging Information Packet */
-   {8, {0x02, 0x43, 2, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 
0x60504030201}, 0, 0 },
-   {8, {0x02, 0x43, 3, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 
0x60504030201 | (1ULL << 63)}, 0, 0 },
+   {8, {0x02, 0x43, 2, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 
0xC0A08060402}, 0, 0 },
+   {8, {0x02, 0x43, 3, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 
0xC0A08060403}, 0, 0 },
/* Mode Exec Packet */
{2, {0x99, 0x00}, 0, {INTEL_PT_MODE_EXEC, 0, 16}, 0, 0 },
{2, {0x99, 0x01}, 0, {INTEL_PT_MODE_EXEC, 0, 64}, 0, 0 },
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 6df52d3c3f7e..cfaa091c935c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -126,7 +126,7 @@ struct intel_pt_decoder {
uint64_t pos;
uint64_t last_ip;
uint64_t ip;
-   uint64_t cr3;
+   uint64_t pip_payload;
uint64_t timestamp;
uint64_t tsc_timestamp;
uint64_t ref_timestamp;
@@ -1757,7 +1757,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder 
*decoder)
break;
 
case INTEL_PT_PIP:
-   decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
+   decoder->pip_payload = decoder->packet.payload;
break;
 
case INTEL_PT_FUP:
@@ -1884,7 +1884,7 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder 
*decoder)
return 0;
 
case INTEL_PT_PIP:
-   decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
+   decoder->pip_payload = decoder->packet.payload;
break;
 
case INTEL_PT_MTC:
@@ -2297,7 +2297,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder 
*decoder)
return err;
 
case INTEL_PT_PIP:
-   decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
+   decoder->pip_payload = decoder->packet.payload;
break;
 
case INTEL_PT_MTC:
@@ -2536,7 +2536,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder 
*decoder)
break;
 
case INTEL_PT_PIP:
-   decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
+   decoder->pip_payload = decoder->packet.payload;
break;
 
case INTEL_PT_MODE_EXEC:
@@ -2655,7 +2655,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder 
*decoder)
break;
 
case INTEL_PT_PIP:
-   decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
+   decoder->pip_payload = decoder->packet.payload;
break;
 
case INTEL_PT_MODE_EXEC:
@@ -2987,7 +2987,7 @@ const struct intel_pt_state *intel_pt_decode(struct 
intel_pt_decoder *decoder)
 
decoder->state.timestamp = decoder->sample_timestamp;
decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
-   decoder->state.cr3 = decoder->cr3;
+   decoder->state.pip_payload = decoder->pip_payload;
decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
decoder->state.tot_cyc_cnt = decoder->sample_tot_cyc_cnt;
 
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index ae13f3251536..b9564c93fca7 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -204,7 +204,7 @@ struct intel_pt_state {
int err;
uint

[PATCH 05/11] perf machine: Factor out machines__find_guest()

2021-02-18 Thread Adrian Hunter
Factor out machines__find_guest() so it can be re-used.

Signed-off-by: Adrian Hunter 
---
 tools/perf/util/machine.c | 9 +
 tools/perf/util/machine.h | 1 +
 tools/perf/util/session.c | 7 +--
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index ab8a6b3e801d..90703b7ca6de 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -369,6 +369,15 @@ struct machine *machines__findnew(struct machines 
*machines, pid_t pid)
return machine;
 }
 
+struct machine *machines__find_guest(struct machines *machines, pid_t pid)
+{
+   struct machine *machine = machines__find(machines, pid);
+
+   if (!machine)
+   machine = machines__findnew(machines, DEFAULT_GUEST_KERNEL_ID);
+   return machine;
+}
+
 void machines__process_guests(struct machines *machines,
  machine__process_t process, void *data)
 {
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 26368d3c1754..022c19ecd287 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -162,6 +162,7 @@ struct machine *machines__add(struct machines *machines, 
pid_t pid,
 struct machine *machines__find_host(struct machines *machines);
 struct machine *machines__find(struct machines *machines, pid_t pid);
 struct machine *machines__findnew(struct machines *machines, pid_t pid);
+struct machine *machines__find_guest(struct machines *machines, pid_t pid);
 
 void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
 void machines__set_comm_exec(struct machines *machines, bool comm_exec);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f4aeb1af05d8..7b0d0c9e3dd1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1356,8 +1356,6 @@ static struct machine *machines__find_for_cpumode(struct 
machines *machines,
   union perf_event *event,
   struct perf_sample *sample)
 {
-   struct machine *machine;
-
if (perf_guest &&
((sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
 (sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) {
@@ -1369,10 +1367,7 @@ static struct machine *machines__find_for_cpumode(struct 
machines *machines,
else
pid = sample->pid;
 
-   machine = machines__find(machines, pid);
-   if (!machine)
-   machine = machines__findnew(machines, 
DEFAULT_GUEST_KERNEL_ID);
-   return machine;
+   return machines__find_guest(machines, pid);
}
 
return >host;
-- 
2.17.1



Re: [PATCH 2/2] mmc: core: Add no single read retries

2021-02-16 Thread Adrian Hunter
On 17/02/21 7:46 am, Adrian Hunter wrote:
> On 17/02/21 7:22 am, DooHyun Hwang wrote:
>> This makes to handle read errors faster by not retrying
>> multiple block read(CMD18) errors with single block reads(CMD17).
>>
>> On some bad SD Cards that have problem with read operations,
>> it is not helpful to retry multiple block read errors with
>> several single block reads, and it is delayed to treat read
>> operations as I/O error as much as retrying single block reads.
> 
> If the issue is that it takes too long, then maybe it would be better to get
> mmc_blk_read_single() to give up after a certain amount of time.
> 

So that a device property would not be needed I mean.  Then everyone would
benefit.


Re: [PATCH 2/2] mmc: core: Add no single read retries

2021-02-16 Thread Adrian Hunter
On 17/02/21 7:22 am, DooHyun Hwang wrote:
> This makes to handle read errors faster by not retrying
> multiple block read(CMD18) errors with single block reads(CMD17).
> 
> On some bad SD Cards that have problem with read operations,
> it is not helpful to retry multiple block read errors with
> several single block reads, and it is delayed to treat read
> operations as I/O error as much as retrying single block reads.

If the issue is that it takes too long, then maybe it would be better to get
mmc_blk_read_single() to give up after a certain amount of time.

> 
> Signed-off-by: DooHyun Hwang 
> ---
>  drivers/mmc/core/block.c | 3 ++-
>  drivers/mmc/core/host.c  | 6 ++
>  include/linux/mmc/host.h | 3 +++
>  3 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index d666e24fbe0e..e25aaf8fca34 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -1809,7 +1809,8 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue 
> *mq, struct request *req)
>  
>   /* FIXME: Missing single sector read for large sector size */
>   if (!mmc_large_sector(card) && rq_data_dir(req) == READ &&
> - brq->data.blocks > 1) {
> + brq->data.blocks > 1 &&
> + !card->host->no_single_read_retry) {
>   /* Read one sector at a time */
>   mmc_blk_read_single(mq, req);
>   return;
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 9b89a91b6b47..3bf5b2fc111b 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -352,6 +352,12 @@ int mmc_of_parse(struct mmc_host *host)
>   if (device_property_read_bool(dev, "no-mmc"))
>   host->caps2 |= MMC_CAP2_NO_MMC;
>  
> + if (device_property_read_bool(dev, "no-single-read-retry")) {
> + dev_info(host->parent,
> + "Single block read retrying is not supported\n");
> + host->no_single_read_retry = true;
> + }
> +
>   /* Must be after "non-removable" check */
>   if (device_property_read_u32(dev, "fixed-emmc-driver-type", _type) 
> == 0) {
>   if (host->caps & MMC_CAP_NONREMOVABLE)
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 26a3c7bc29ae..faec55035a63 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -502,6 +502,9 @@ struct mmc_host {
>   /* Host Software Queue support */
>   boolhsq_enabled;
>  
> + /* Do not retry multi block read as single block read */
> + boolno_single_read_retry;
> +
>   unsigned long   private[] cacheline_aligned;
>  };
>  
> 



Re: [PATCH 2/2] mmc: core: Drop reference counting of the bus_ops

2021-02-16 Thread Adrian Hunter
On 12/02/21 3:16 pm, Ulf Hansson wrote:
> When the mmc_rescan work is enabled for execution (host->rescan_disable),
> it's the only instance per mmc host that is allowed to set/clear the
> host->bus_ops pointer.
> 
> Besides the mmc_rescan work, there are a couple of scenarios when the
> host->bus_ops pointer may be accessed. Typically, those can be described as
> as below:
> 
> *)
> Upper mmc driver layers (like the mmc block device driver or an SDIO
> functional driver) needs to execute a host->bus_ops callback. This can be
> considered as safe without having to use some special locking mechanism,
> because they operate on top of the struct mmc_card. As long as there is a
> card to operate upon, the mmc core guarantees that there is a host->bus_ops
> assigned as well. Note that, upper layer mmc drivers are of course
> responsible to clean up from themselves from their ->remove() callbacks,
> otherwise things would fall apart anyways.
> 
> **)
> Via the mmc host instance, we may need to force a removal of an inserted
> mmc card. This happens when a mmc host driver gets unbind, for example. In
> this case, we protect the host->bus_ops pointer from concurrent accesses,
> by disabling the mmc_rescan work upfront (host->rescan_disable). See
> mmc_stop_host() for example.
> 
> This said, it seems like the reference counting of the host->bus_ops
> pointer at some point have become superfluous. As this is an old mechanism
> of the mmc core, it a bit difficult to digest the history of when that
> could have happened. However, let's drop the reference counting to avoid
> unnecessary code-paths and lockings.
> 
> Cc: Pierre Ossman 
> Cc: Russell King 
> Signed-off-by: Ulf Hansson 

Reviewed-by: Adrian Hunter 

> ---
>  drivers/mmc/core/core.c  | 89 ++--
>  include/linux/mmc/host.h |  2 -
>  2 files changed, 4 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 2e41fa598bd6..860995eb548b 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1377,63 +1377,13 @@ void mmc_power_cycle(struct mmc_host *host, u32 ocr)
>   mmc_power_up(host, ocr);
>  }
>  
> -/*
> - * Cleanup when the last reference to the bus operator is dropped.
> - */
> -static void __mmc_release_bus(struct mmc_host *host)
> -{
> - WARN_ON(!host->bus_dead);
> -
> - host->bus_ops = NULL;
> -}
> -
> -/*
> - * Increase reference count of bus operator
> - */
> -static inline void mmc_bus_get(struct mmc_host *host)
> -{
> - unsigned long flags;
> -
> - spin_lock_irqsave(>lock, flags);
> - host->bus_refs++;
> - spin_unlock_irqrestore(>lock, flags);
> -}
> -
> -/*
> - * Decrease reference count of bus operator and free it if
> - * it is the last reference.
> - */
> -static inline void mmc_bus_put(struct mmc_host *host)
> -{
> - unsigned long flags;
> -
> - spin_lock_irqsave(>lock, flags);
> - host->bus_refs--;
> - if ((host->bus_refs == 0) && host->bus_ops)
> - __mmc_release_bus(host);
> - spin_unlock_irqrestore(>lock, flags);
> -}
> -
>  /*
>   * Assign a mmc bus handler to a host. Only one bus handler may control a
>   * host at any given time.
>   */
>  void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
>  {
> - unsigned long flags;
> -
> - WARN_ON(!host->claimed);
> -
> - spin_lock_irqsave(>lock, flags);
> -
> - WARN_ON(host->bus_ops);
> - WARN_ON(host->bus_refs);
> -
>   host->bus_ops = ops;
> - host->bus_refs = 1;
> - host->bus_dead = 0;
> -
> - spin_unlock_irqrestore(>lock, flags);
>  }
>  
>  /*
> @@ -1441,18 +1391,7 @@ void mmc_attach_bus(struct mmc_host *host, const 
> struct mmc_bus_ops *ops)
>   */
>  void mmc_detach_bus(struct mmc_host *host)
>  {
> - unsigned long flags;
> -
> - WARN_ON(!host->claimed);
> - WARN_ON(!host->bus_ops);
> -
> - spin_lock_irqsave(>lock, flags);
> -
> - host->bus_dead = 1;
> -
> - spin_unlock_irqrestore(>lock, flags);
> -
> - mmc_bus_put(host);
> + host->bus_ops = NULL;
>  }
>  
>  void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool 
> cd_irq)
> @@ -2244,32 +2183,15 @@ void mmc_rescan(struct work_struct *work)
>   host->trigger_card_event = false;
>   }
>  
> - mmc_bus_get(host);
> -
>   /* Verify a registered card to be functional, else remove it. */
> - if (host->

Re: [PATCH 1/2] mmc: core: Drop superfluous validations in mmc_hw|sw_reset()

2021-02-16 Thread Adrian Hunter
On 12/02/21 3:15 pm, Ulf Hansson wrote:
> The mmc_hw|sw_reset() APIs are designed to be called solely from upper
> layers, which means drivers that operates on top of the struct mmc_card,
> like the mmc block device driver and an SDIO functional driver.
> 
> Additionally, as long as the struct mmc_host has a valid pointer to a
> struct mmc_card, the corresponding host->bus_ops pointer stays valid and
> assigned.
> 
> For these reasons, let's drop the superfluous reference counting and the
> redundant validations in mmc_hw|sw_reset().
> 
> Signed-off-by: Ulf Hansson 

Reviewed-by: Adrian Hunter 

> ---
> 
> Note, ideally mmc_hw|sw_reset() shall be converted to take a struct mmc_card*
> as an in-parameter, rather than the current struct mmc_host*, but that is left
> to a future/separate change.
> 
> ---
>  drivers/mmc/core/block.c |  2 +-
>  drivers/mmc/core/core.c  | 21 +
>  2 files changed, 2 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index b877f62df366..b7d3f5a73388 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -947,7 +947,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct 
> mmc_host *host,
>   md->reset_done |= type;
>   err = mmc_hw_reset(host);
>   /* Ensure we switch back to the correct partition */
> - if (err != -EOPNOTSUPP) {
> + if (err) {
>   struct mmc_blk_data *main_md =
>   dev_get_drvdata(>card->dev);
>   int part_err;
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index 1136b859ddd8..2e41fa598bd6 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -2080,18 +2080,7 @@ int mmc_hw_reset(struct mmc_host *host)
>  {
>   int ret;
>  
> - if (!host->card)
> - return -EINVAL;
> -
> - mmc_bus_get(host);
> - if (!host->bus_ops || host->bus_dead || !host->bus_ops->hw_reset) {
> - mmc_bus_put(host);
> - return -EOPNOTSUPP;
> - }
> -
>   ret = host->bus_ops->hw_reset(host);
> - mmc_bus_put(host);
> -
>   if (ret < 0)
>   pr_warn("%s: tried to HW reset card, got error %d\n",
>   mmc_hostname(host), ret);
> @@ -2104,18 +2093,10 @@ int mmc_sw_reset(struct mmc_host *host)
>  {
>   int ret;
>  
> - if (!host->card)
> - return -EINVAL;
> -
> - mmc_bus_get(host);
> - if (!host->bus_ops || host->bus_dead || !host->bus_ops->sw_reset) {
> - mmc_bus_put(host);
> + if (!host->bus_ops->sw_reset)
>   return -EOPNOTSUPP;
> - }
>  
>   ret = host->bus_ops->sw_reset(host);
> - mmc_bus_put(host);
> -
>   if (ret)
>   pr_warn("%s: tried to SW reset card, got error %d\n",
>   mmc_hostname(host), ret);
> 



Re: [PATCH] perf test: Fix unaligned access in sample parsing test

2021-02-14 Thread Adrian Hunter
On 14/02/21 11:16 am, Namhyung Kim wrote:
> The ubsan reported the following error.  It was because sample's raw
> data missed u32 padding at the end.  So it broke the alignment of the
> array after it.
> 
> The raw data contains an u32 size prefix so the data size should have
> an u32 padding after 8-byte aligned data.
> 
> 27: Sample parsing  :util/synthetic-events.c:1539:4:
>   runtime error: store to misaligned address 0x6216b9bc for type
>   '__u64' (aka 'unsigned long long'), which requires 8 byte alignment
> 0x6216b9bc: note: pointer points here
>   00 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  
> ff ff ff ff ff ff ff ff
>   ^
> #0 0x561532a9fc96 in perf_event__synthesize_sample 
> util/synthetic-events.c:1539:13
> #1 0x5615327f4a4f in do_test tests/sample-parsing.c:284:8
> #2 0x5615327f3f50 in test__sample_parsing tests/sample-parsing.c:381:9
> #3 0x56153279d3a1 in run_test tests/builtin-test.c:424:9
> #4 0x56153279c836 in test_and_print tests/builtin-test.c:454:9
> #5 0x56153279b7eb in __cmd_test tests/builtin-test.c:675:4
> #6 0x56153279abf0 in cmd_test tests/builtin-test.c:821:9
> #7 0x56153264e796 in run_builtin perf.c:312:11
> #8 0x56153264cf03 in handle_internal_command perf.c:364:8
> #9 0x56153264e47d in run_argv perf.c:408:2
> #10 0x56153264c9a9 in main perf.c:538:3
> #11 0x7f137ab6fbbc in __libc_start_main (/lib64/libc.so.6+0x38bbc)
> #12 0x561532596828 in _start ...
> 
> SUMMARY: UndefinedBehaviorSanitizer: misaligned-pointer-use
>  util/synthetic-events.c:1539:4 in
> 
> Fixes: 045f8cd8542d ("perf tests: Add a sample parsing test")
> Cc: Adrian Hunter 
> Signed-off-by: Namhyung Kim 

Acked-by: Adrian Hunter 

> ---
>  tools/perf/tests/sample-parsing.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/perf/tests/sample-parsing.c 
> b/tools/perf/tests/sample-parsing.c
> index f506eabfc269..0dbe3aa99853 100644
> --- a/tools/perf/tests/sample-parsing.c
> +++ b/tools/perf/tests/sample-parsing.c
> @@ -202,7 +202,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 
> read_format)
>   .data = {1, -1ULL, 211, 212, 213},
>   };
>   u64 regs[64];
> - const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL};
> + const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 
> 0 };
>   const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
>   const u64 aux_data[] = {0xa55a, 0, 0xeeddee, 0x0282028202820282};
>   struct perf_sample sample = {
> 



[PATCH V2 3/4] scsi: ufs-debugfs: Add user-defined exception_event_mask

2021-02-08 Thread Adrian Hunter
Allow users to enable specific exception events via debugfs.

The bits enabled by the driver ee_drv_ctrl are separated from the bits
enabled by the user ee_usr_ctrl. The control mask ee_mask_ctrl is the
logical-or of those two. A mutex is needed to ensure that the masks match
what was written to the device.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufs-debugfs.c | 46 ++
 drivers/scsi/ufs/ufshcd.c  | 86 +-
 drivers/scsi/ufs/ufshcd.h  | 22 -
 3 files changed, 120 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index dee98dc72d29..59729073b569 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -44,10 +44,56 @@ static int ufs_debugfs_stats_show(struct seq_file *s, void 
*data)
 }
 DEFINE_SHOW_ATTRIBUTE(ufs_debugfs_stats);
 
+static int ee_usr_mask_get(void *data, u64 *val)
+{
+   struct ufs_hba *hba = data;
+
+   *val = hba->ee_usr_mask;
+   return 0;
+}
+
+static int ufs_debugfs_get_user_access(struct ufs_hba *hba)
+__acquires(>host_sem)
+{
+   down(>host_sem);
+   if (!ufshcd_is_user_access_allowed(hba)) {
+   up(>host_sem);
+   return -EBUSY;
+   }
+   pm_runtime_get_sync(hba->dev);
+   return 0;
+}
+
+static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
+__releases(>host_sem)
+{
+   pm_runtime_put_sync(hba->dev);
+   up(>host_sem);
+}
+
+static int ee_usr_mask_set(void *data, u64 val)
+{
+   struct ufs_hba *hba = data;
+   int err;
+
+   if (val & ~(u64)MASK_EE_STATUS)
+   return -EINVAL;
+   err = ufs_debugfs_get_user_access(hba);
+   if (err)
+   return err;
+   err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS);
+   ufs_debugfs_put_user_access(hba);
+   return err;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, 
"%#llx\n");
+
 void ufs_debugfs_hba_init(struct ufs_hba *hba)
 {
hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), 
ufs_debugfs_root);
debugfs_create_file("stats", 0400, hba->debugfs_root, hba, 
_debugfs_stats_fops);
+   debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
+   hba, _usr_mask_fops);
 }
 
 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d6fdce655388..065a662e7886 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5160,6 +5160,46 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
}
 }
 
+static int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
+{
+   return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+  QUERY_ATTR_IDN_EE_CONTROL, 0, 0,
+  _ctrl_mask);
+}
+
+static int ufshcd_write_ee_control(struct ufs_hba *hba)
+{
+   int err;
+
+   mutex_lock(>ee_ctrl_mutex);
+   err = __ufshcd_write_ee_control(hba, hba->ee_ctrl_mask);
+   mutex_unlock(>ee_ctrl_mutex);
+   if (err)
+   dev_err(hba->dev, "%s: failed to write ee control %d\n",
+   __func__, err);
+   return err;
+}
+
+int ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask, u16 *other_mask,
+u16 set, u16 clr)
+{
+   u16 new_mask, ee_ctrl_mask;
+   int err = 0;
+
+   mutex_lock(>ee_ctrl_mutex);
+   new_mask = (*mask & ~clr) | set;
+   ee_ctrl_mask = new_mask | *other_mask;
+   if (ee_ctrl_mask != hba->ee_ctrl_mask)
+   err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
+   /* Still need to update 'mask' even if 'ee_ctrl_mask' was unchanged */
+   if (!err) {
+   hba->ee_ctrl_mask = ee_ctrl_mask;
+   *mask = new_mask;
+   }
+   mutex_unlock(>ee_ctrl_mutex);
+   return err;
+}
+
 /**
  * ufshcd_disable_ee - disable exception event
  * @hba: per-adapter instance
@@ -5170,22 +5210,9 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
  *
  * Returns zero on success, non-zero error value on failure.
  */
-static int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)
+static inline int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)
 {
-   int err = 0;
-   u32 val;
-
-   if (!(hba->ee_ctrl_mask & mask))
-   goto out;
-
-   val = hba->ee_ctrl_mask & ~mask;
-   val &= MASK_EE_STATUS;
-   err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
-   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
-   if (!err)
-   hba->ee_ctrl_mask &= ~mask;
-out:
-   return err;
+   return ufshcd_update_ee_drv_mask(hba, 0, mask);
 }
 
 /*

[PATCH V2 4/4] scsi: ufs-debugfs: Add user-defined exception event rate limiting

2021-02-08 Thread Adrian Hunter
An enabled user-specified exception event that does not clear quickly will
repeatedly cause the handler to run. That could unduly disturb the driver
behaviour being tested or debugged. To prevent that add debugfs file
exception_event_rate_limit_ms. When a exception event happens, it is
disabled, and then after a period of time (default 20ms) the exception
event is enabled again.

Note that if the driver also has that exception event enabled, it will not
be disabled.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufs-debugfs.c | 44 ++
 drivers/scsi/ufs/ufs-debugfs.h |  2 ++
 drivers/scsi/ufs/ufshcd.c  |  5 ++--
 drivers/scsi/ufs/ufshcd.h  |  4 
 4 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 59729073b569..ced9ef4d7c78 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -88,15 +88,59 @@ static int ee_usr_mask_set(void *data, u64 val)
 
 DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, 
"%#llx\n");
 
+void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status)
+{
+   bool chgd = false;
+   u16 ee_ctrl_mask;
+   int err = 0;
+
+   if (!hba->debugfs_ee_rate_limit_ms || !status)
+   return;
+
+   mutex_lock(>ee_ctrl_mutex);
+   ee_ctrl_mask = hba->ee_drv_mask | (hba->ee_usr_mask & ~status);
+   chgd = ee_ctrl_mask != hba->ee_ctrl_mask;
+   if (chgd) {
+   err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
+   if (err)
+   dev_err(hba->dev, "%s: failed to write ee control %d\n",
+   __func__, err);
+   }
+   mutex_unlock(>ee_ctrl_mutex);
+
+   if (chgd && !err) {
+   unsigned long delay = 
msecs_to_jiffies(hba->debugfs_ee_rate_limit_ms);
+
+   queue_delayed_work(system_freezable_wq, >debugfs_ee_work, 
delay);
+   }
+}
+
+static void ufs_debugfs_restart_ee(struct work_struct *work)
+{
+   struct ufs_hba *hba = container_of(work, struct ufs_hba, 
debugfs_ee_work.work);
+
+   if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) ||
+   ufs_debugfs_get_user_access(hba))
+   return;
+   ufshcd_write_ee_control(hba);
+   ufs_debugfs_put_user_access(hba);
+}
+
 void ufs_debugfs_hba_init(struct ufs_hba *hba)
 {
+   /* Set default exception event rate limit period to 20ms */
+   hba->debugfs_ee_rate_limit_ms = 20;
+   INIT_DELAYED_WORK(>debugfs_ee_work, ufs_debugfs_restart_ee);
hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), 
ufs_debugfs_root);
debugfs_create_file("stats", 0400, hba->debugfs_root, hba, 
_debugfs_stats_fops);
debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
hba, _usr_mask_fops);
+   debugfs_create_u32("exception_event_rate_limit_ms", 0600, 
hba->debugfs_root,
+  >debugfs_ee_rate_limit_ms);
 }
 
 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
 {
debugfs_remove_recursive(hba->debugfs_root);
+   cancel_delayed_work_sync(>debugfs_ee_work);
 }
diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index f35b39c4b4f5..3ca29d30460a 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
 void __exit ufs_debugfs_exit(void);
 void ufs_debugfs_hba_init(struct ufs_hba *hba);
 void ufs_debugfs_hba_exit(struct ufs_hba *hba);
+void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status);
 #else
 static inline void ufs_debugfs_init(void) {}
 static inline void ufs_debugfs_exit(void) {}
 static inline void ufs_debugfs_hba_init(struct ufs_hba *hba) {}
 static inline void ufs_debugfs_hba_exit(struct ufs_hba *hba) {}
+static inline void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 
status) {}
 #endif
 
 #endif
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 065a662e7886..42d9a96a5721 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5160,14 +5160,14 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
}
 }
 
-static int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
+int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
 {
return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
   QUERY_ATTR_IDN_EE_CONTROL, 0, 0,
   _ctrl_mask);
 }
 
-static int ufshcd_write_ee_control(struct ufs_hba *hba)
+int ufshcd_write_ee_control(struct ufs_hba *hba)
 {
int err;
 
@@ -5635,6 +5635,7 @@ static void ufshcd_exception_event_handler(struct 
work_struct 

[PATCH V2 1/4] scsi: ufs: Add exception event tracepoint

2021-02-08 Thread Adrian Hunter
Currently, exception event status can be read from wExceptionEventStatus
attribute (sysfs file attributes/exception_event_status under the UFS host
controller device directory). Polling that attribute to track UFS exception
events is impractical, so add a tracepoint to track exception events for
testing and debugging purposes.

Note, by the time the exception event status is read, the exception event
may have cleared, so the value can be zero - see example below.

Note also, only enabled exception events can be reported. A subsequent
patch adds the ability for users to enable selected exception events via
debugfs.

Example with driver instrumented to enable all exception events:

  # echo 1 > /sys/kernel/debug/tracing/events/ufs/ufshcd_exception_event/enable

  ... do some I/O ...

  # cat /sys/kernel/debug/tracing/trace
  # tracer: nop
  #
  # entries-in-buffer/entries-written: 3/3   #P:5
  #
  #_-=> irqs-off
  #   / _=> need-resched
  #  | / _---=> hardirq/softirq
  #  || / _--=> preempt-depth
  #  ||| / delay
  #   TASK-PID CPU#     TIMESTAMP  FUNCTION
  #  | | |     | |
   kworker/2:2-173 [002]    731.486419: ufshcd_exception_event: 
:00:12.5: status 0x0
   kworker/2:2-173 [002]    732.608918: ufshcd_exception_event: 
:00:12.5: status 0x4
   kworker/2:2-173 [002]    732.609312: ufshcd_exception_event: 
:00:12.5: status 0x4

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufshcd.c  |  2 ++
 include/trace/events/ufs.h | 21 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 721f55db181f..d6fdce655388 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5616,6 +5616,8 @@ static void ufshcd_exception_event_handler(struct 
work_struct *work)
goto out;
}
 
+   trace_ufshcd_exception_event(dev_name(hba->dev), status);
+
status &= hba->ee_ctrl_mask;
 
if (status & MASK_EE_URGENT_BKOPS)
diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
index e151477d645c..1cb6f1afba0e 100644
--- a/include/trace/events/ufs.h
+++ b/include/trace/events/ufs.h
@@ -349,6 +349,27 @@ TRACE_EVENT(ufshcd_upiu,
)
 );
 
+TRACE_EVENT(ufshcd_exception_event,
+
+   TP_PROTO(const char *dev_name, u16 status),
+
+   TP_ARGS(dev_name, status),
+
+   TP_STRUCT__entry(
+   __string(dev_name, dev_name)
+   __field(u16, status)
+   ),
+
+   TP_fast_assign(
+   __assign_str(dev_name, dev_name);
+   __entry->status = status;
+   ),
+
+   TP_printk("%s: status 0x%x",
+   __get_str(dev_name), __entry->status
+   )
+);
+
 #endif /* if !defined(_TRACE_UFS_H) || defined(TRACE_HEADER_MULTI_READ) */
 
 /* This part must be outside protection */
-- 
2.17.1



[PATCH V2 2/4] scsi: ufs: Add exception event definitions

2021-02-08 Thread Adrian Hunter
For readability and completeness, add exception event definitions.

Signed-off-by: Adrian Hunter 
Reviewed-by: Bean Huo 
---
 drivers/scsi/ufs/ufs.h | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index bf1897a72532..cb80b9670bfe 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -348,8 +348,14 @@ enum power_desc_param_offset {
 
 /* Exception event mask values */
 enum {
-   MASK_EE_STATUS  = 0x,
-   MASK_EE_URGENT_BKOPS= (1 << 2),
+   MASK_EE_STATUS  = 0x,
+   MASK_EE_DYNCAP_EVENT= BIT(0),
+   MASK_EE_SYSPOOL_EVENT   = BIT(1),
+   MASK_EE_URGENT_BKOPS= BIT(2),
+   MASK_EE_TOO_HIGH_TEMP   = BIT(3),
+   MASK_EE_TOO_LOW_TEMP= BIT(4),
+   MASK_EE_WRITEBOOSTER_EVENT  = BIT(5),
+   MASK_EE_PERFORMANCE_THROTTLING  = BIT(6),
 };
 
 /* Background operation status */
-- 
2.17.1



[PATCH V2 0/4] scsi: ufs-debugfs: Add UFS Exception Event reporting

2021-02-08 Thread Adrian Hunter
Hi

Here are V2 patches to add a tracepoint for UFS Exception Events and to
allow users to enable specific exception events without affecting the
driver's use of exception events.


Changes in V2:

scsi: ufs: Add exception event tracepoint
Change status field from "exception event status" to "status"

scsi: ufs: Add exception event definitions
Add Reviewed-by: Bean Huo


Adrian Hunter (4):
  scsi: ufs: Add exception event tracepoint
  scsi: ufs: Add exception event definitions
  scsi: ufs-debugfs: Add user-defined exception_event_mask
  scsi: ufs-debugfs: Add user-defined exception event rate limiting

 drivers/scsi/ufs/ufs-debugfs.c | 90 ++
 drivers/scsi/ufs/ufs-debugfs.h |  2 +
 drivers/scsi/ufs/ufs.h | 10 -
 drivers/scsi/ufs/ufshcd.c  | 87 +---
 drivers/scsi/ufs/ufshcd.h  | 26 +++-
 include/trace/events/ufs.h | 21 ++
 6 files changed, 201 insertions(+), 35 deletions(-)


Regards
Adrian


[PATCH 4/4] perf intel-pt: Add PSB events

2021-02-05 Thread Adrian Hunter
Emitting a PSB+ can cause a CPU a slight delay. When doing timing analysis
of code with Intel PT, it is useful to know if a timing bubble was caused
by Intel PT or not. Add reporting of PSB events via perf script. PSB
events are printed with the existing itrace 'p' option which also prints
power and frequency changes. The PSB event contains the trace offset at
which the PSB occurs, to allow easy reference back to the PSB+ packets.

The PSB event timestamp is always the timestamp from the PSB+ TSC
packet, and the ip is always the address from the PSB+ FUP packet.

The code changes are non-trivial because the decoder must walk to the
PSB+ FUP address before outputting the PSB event.

Example:

$ perf record -e intel_pt/cyc,psb_period=0/u uname
Linux
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.046 MB perf.data ]
$ perf script --itrace=p --ns
perf 17981 [006] 25617.510820383: psb:  psb 
offs: 0  0 [unknown] ([unknown])
perf 17981 [006] 25617.510820383: cbr:  
cbr: 42 freq: 4219 MHz (156%)0 [unknown] ([unknown])
   uname 17981 [006] 25617.510889753: psb:  psb 
offs: 0xb50   7f78c12a212e __GI___tunables_init+0xee 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.510899162: psb:  psb 
offs: 0x12d0  7f78c128af1c dl_main+0x93c 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.510939242: psb:  psb 
offs: 0x1a50  7f78c128eefc _dl_map_object_from_fd+0x13c 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.510981274: psb:  psb 
offs: 0x21c8  7f78c1296307 _dl_relocate_object+0x927 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.510993034: psb:  psb 
offs: 0x2948  7f78c12940e4 _dl_lookup_symbol_x+0x14 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.511003871: psb:  psb 
offs: 0x30c8  7f78c12937b3 do_lookup_x+0x2f3 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.511019854: psb:  psb 
offs: 0x3850  7f78c1295eed _dl_relocate_object+0x50d 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.511029015: psb:  psb 
offs: 0x4390  7f78c12a855a strcmp+0xf6a 
(/usr/lib/x86_64-linux-gnu/ld-2.31.so)
   uname 17981 [006] 25617.511064876: psb:  psb 
offs: 0x4b10 0 [unknown] ([unknown])
   uname 17981 [006] 25617.511080762: psb:  psb 
offs: 0x5290  7f78c11db53d _dl_addr+0x13d 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511086035: psb:  psb 
offs: 0x5a08  7f78c11db538 _dl_addr+0x138 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511091381: psb:  psb 
offs: 0x6190  7f78c11db534 _dl_addr+0x134 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511096681: psb:  psb 
offs: 0x6910  7f78c11db4c3 _dl_addr+0xc3 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.59520: psb:  psb 
offs: 0x7090  7f78c10ada5e _nl_intern_locale_data+0x12e 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511126584: psb:  psb 
offs: 0x7818  7f78c10ada50 _nl_intern_locale_data+0x120 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511132775: psb:  psb 
offs: 0x8358  7f78c10c20c0 getenv+0xa0 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511134598: psb:  psb 
offs: 0x8ad0  7f78c10ada09 _nl_intern_locale_data+0xd9 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511135685: psb:  psb 
offs: 0x9258  7f78c10ada50 _nl_intern_locale_data+0x120 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511138322: psb:  psb 
offs: 0x99d0  7f78c11fffd9 __strncmp_avx2+0x39 
(/usr/lib/x86_64-linux-gnu/libc-2.31.so)
   uname 17981 [006] 25617.511158907: psb:  psb 
offs: 0xa150 0 [unknown] ([unknown])

Signed-off-by: Adrian Hunter

[PATCH 3/4] perf intel-pt: Fix IPC with CYC threshold

2021-02-05 Thread Adrian Hunter
The code assumed every CYC-eligible packet has a CYC packet, which is not
the case when CYC thresholds are used. Fix by checking if a CYC packet is
actually present in that case.

Fixes: 5b1dc0fd1da06 ("perf intel-pt: Add support for samples to contain IPC 
ratio")
Signed-off-by: Adrian Hunter 
---
 .../util/intel-pt-decoder/intel-pt-decoder.c  | 27 +++
 .../util/intel-pt-decoder/intel-pt-decoder.h  |  1 +
 tools/perf/util/intel-pt.c| 13 +
 3 files changed, 41 insertions(+)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index ef29f6b25e60..197eb58a39cb 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -24,6 +24,13 @@
 #include "intel-pt-decoder.h"
 #include "intel-pt-log.h"
 
+#define BITULL(x) (1ULL << (x))
+
+/* IA32_RTIT_CTL MSR bits */
+#define INTEL_PT_CYC_ENABLEBITULL(1)
+#define INTEL_PT_CYC_THRESHOLD (BITULL(22) | BITULL(21) | BITULL(20) | 
BITULL(19))
+#define INTEL_PT_CYC_THRESHOLD_SHIFT   19
+
 #define INTEL_PT_BLK_SIZE 1024
 
 #define BIT63 (((uint64_t)1 << 63))
@@ -167,6 +174,8 @@ struct intel_pt_decoder {
uint64_t sample_tot_cyc_cnt;
uint64_t base_cyc_cnt;
uint64_t cyc_cnt_timestamp;
+   uint64_t ctl;
+   uint64_t cyc_threshold;
double tsc_to_cyc;
bool continuous_period;
bool overflow;
@@ -204,6 +213,14 @@ static uint64_t intel_pt_lower_power_of_2(uint64_t x)
return x << i;
 }
 
+static uint64_t intel_pt_cyc_threshold(uint64_t ctl)
+{
+   if (!(ctl & INTEL_PT_CYC_ENABLE))
+   return 0;
+
+   return (ctl & INTEL_PT_CYC_THRESHOLD) >> INTEL_PT_CYC_THRESHOLD_SHIFT;
+}
+
 static void intel_pt_setup_period(struct intel_pt_decoder *decoder)
 {
if (decoder->period_type == INTEL_PT_PERIOD_TICKS) {
@@ -245,12 +262,15 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct 
intel_pt_params *params)
 
decoder->flags  = params->flags;
 
+   decoder->ctl= params->ctl;
decoder->period = params->period;
decoder->period_type= params->period_type;
 
decoder->max_non_turbo_ratio= params->max_non_turbo_ratio;
decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio;
 
+   decoder->cyc_threshold = intel_pt_cyc_threshold(decoder->ctl);
+
intel_pt_setup_period(decoder);
 
decoder->mtc_shift = params->mtc_period;
@@ -2017,6 +2037,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder 
*decoder, bool *no_tip, in
 
 static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
 {
+   int last_packet_type = INTEL_PT_PAD;
bool no_tip = false;
int err;
 
@@ -2025,6 +2046,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder 
*decoder)
if (err)
return err;
 next:
+   if (decoder->cyc_threshold) {
+   if (decoder->sample_cyc && last_packet_type != 
INTEL_PT_CYC)
+   decoder->sample_cyc = false;
+   last_packet_type = decoder->packet.type;
+   }
+
if (decoder->hop) {
switch (intel_pt_hop_trace(decoder, _tip, )) {
case HOP_IGNORE:
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index b52937b03c8c..48adaa78acfc 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -244,6 +244,7 @@ struct intel_pt_params {
void *data;
bool return_compression;
bool branch_enable;
+   uint64_t ctl;
uint64_t period;
enum intel_pt_period_type period_type;
unsigned max_non_turbo_ratio;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index d6d93ee03019..2fff6f760457 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -893,6 +893,18 @@ static bool intel_pt_sampling_mode(struct intel_pt *pt)
return false;
 }
 
+static u64 intel_pt_ctl(struct intel_pt *pt)
+{
+   struct evsel *evsel;
+   u64 config;
+
+   evlist__for_each_entry(pt->session->evlist, evsel) {
+   if (intel_pt_get_config(pt, >core.attr, ))
+   return config;
+   }
+   return 0;
+}
+
 static u64 intel_pt_ns_to_ticks(const struct intel_pt *pt, u64 ns)
 {
u64 quot, rem;
@@ -1026,6 +1038,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct 
intel_pt *pt,
params.data = ptq;
params.return_compression = intel_pt_return_compression(pt);
params.branch_enable = intel_pt_

[PATCH 2/4] perf intel-pt: Fix premature IPC

2021-02-05 Thread Adrian Hunter
The code assumed a change in cycle count means accurate IPC. That is not
correct, for example when sampling both branches and instructions, or at
a FUP packet (which is not CYC-eligible) address. Fix by using an explicit
flag to indicate when IPC can be sampled.

Fixes: 5b1dc0fd1da06 ("perf intel-pt: Add support for samples to contain IPC 
ratio")
Signed-off-by: Adrian Hunter 
---
 .../util/intel-pt-decoder/intel-pt-decoder.c | 11 ++-
 .../util/intel-pt-decoder/intel-pt-decoder.h |  1 +
 tools/perf/util/intel-pt.c   | 16 ++--
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 91cba0582736..ef29f6b25e60 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -2814,9 +2814,18 @@ const struct intel_pt_state *intel_pt_decode(struct 
intel_pt_decoder *decoder)
}
if (intel_pt_sample_time(decoder->pkt_state)) {
intel_pt_update_sample_time(decoder);
-   if (decoder->sample_cyc)
+   if (decoder->sample_cyc) {
decoder->sample_tot_cyc_cnt = 
decoder->tot_cyc_cnt;
+   decoder->state.flags |= INTEL_PT_SAMPLE_IPC;
+   decoder->sample_cyc = false;
+   }
}
+   /*
+* When using only TSC/MTC to compute cycles, IPC can be
+* sampled as soon as the cycle count changes.
+*/
+   if (!decoder->have_cyc)
+   decoder->state.flags |= INTEL_PT_SAMPLE_IPC;
}
 
decoder->state.timestamp = decoder->sample_timestamp;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 8645fc265481..b52937b03c8c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -17,6 +17,7 @@
 #define INTEL_PT_ABORT_TX  (1 << 1)
 #define INTEL_PT_ASYNC (1 << 2)
 #define INTEL_PT_FUP_IP(1 << 3)
+#define INTEL_PT_SAMPLE_IPC(1 << 4)
 
 enum intel_pt_sample_type {
INTEL_PT_BRANCH = 1 << 0,
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 60214de42f31..d6d93ee03019 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1381,7 +1381,8 @@ static int intel_pt_synth_branch_sample(struct 
intel_pt_queue *ptq)
sample.branch_stack = (struct branch_stack *)_bs;
}
 
-   sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_br_cyc_cnt;
+   if (ptq->state->flags & INTEL_PT_SAMPLE_IPC)
+   sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_br_cyc_cnt;
if (sample.cyc_cnt) {
sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_br_insn_cnt;
ptq->last_br_insn_cnt = ptq->ipc_insn_cnt;
@@ -1431,7 +1432,8 @@ static int intel_pt_synth_instruction_sample(struct 
intel_pt_queue *ptq)
else
sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt;
 
-   sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_in_cyc_cnt;
+   if (ptq->state->flags & INTEL_PT_SAMPLE_IPC)
+   sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_in_cyc_cnt;
if (sample.cyc_cnt) {
sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_in_insn_cnt;
ptq->last_in_insn_cnt = ptq->ipc_insn_cnt;
@@ -1966,14 +1968,8 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
 
ptq->have_sample = false;
 
-   if (ptq->state->tot_cyc_cnt > ptq->ipc_cyc_cnt) {
-   /*
-* Cycle count and instruction count only go together to create
-* a valid IPC ratio when the cycle count changes.
-*/
-   ptq->ipc_insn_cnt = ptq->state->tot_insn_cnt;
-   ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
-   }
+   ptq->ipc_insn_cnt = ptq->state->tot_insn_cnt;
+   ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
 
/*
 * Do PEBS first to allow for the possibility that the PEBS timestamp
-- 
2.17.1



[PATCH 4/0] perf intel-pt: Add PSB events

2021-02-05 Thread Adrian Hunter
Hi

Here are 3 fixes and 1 minor new feature, for Intel PT.


Adrian Hunter (4):
  perf intel-pt: Fix missing CYC processing in PSB
  perf intel-pt: Fix premature IPC
  perf intel-pt: Fix IPC with CYC threshold
  perf intel-pt: Add PSB events

 tools/perf/Documentation/itrace.txt|   2 +-
 tools/perf/Documentation/perf-intel-pt.txt |   7 +-
 tools/perf/builtin-script.c|  14 ++
 tools/perf/util/event.h|   7 +
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 273 +
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |   4 +
 tools/perf/util/intel-pt.c |  69 +-
 7 files changed, 312 insertions(+), 64 deletions(-)


Regards
Adrian


[PATCH 1/4] perf intel-pt: Fix missing CYC processing in PSB

2021-02-05 Thread Adrian Hunter
Add missing CYC packet processing when walking through PSB+. This
improves the accuracy of timestamps that follow PSB+, until the next
MTC.

Fixes: 3d49807870f08 ("perf tools: Add new Intel PT packet definitions")
Signed-off-by: Adrian Hunter 
---
 tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c 
b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 697513f35154..91cba0582736 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -1761,6 +1761,9 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder 
*decoder)
break;
 
case INTEL_PT_CYC:
+   intel_pt_calc_cyc_timestamp(decoder);
+   break;
+
case INTEL_PT_VMCS:
case INTEL_PT_MNT:
case INTEL_PT_PAD:
-- 
2.17.1



Re: [PATCH 2/2] mmc: mmc_test: use erase_arg for mmc_erase command

2021-02-04 Thread Adrian Hunter
On 4/02/21 2:05 pm, yann.gaut...@foss.st.com wrote:
> From: Yann Gautier 
> 
> Since [1], the erase argument for mmc_erase() function is saved in
> erase_arg field of card structure. It is preferable to use it instead of
> hard-coded MMC_SECURE_ERASE_ARG, which from eMMC 4.51 spec is not
> recommended:
> "6.6.16 Secure Erase
> NOTE Secure Erase is included for backwards compatibility. New system
> level implementations (based on v4.51 devices and beyond) should use
> Erase combined with Sanitize instead of secure erase."
> 
>  [1] commit 01904ff77676 ("mmc: core: Calculate the discard arg only once")
> 

Did you experience an issue because of this?  You could add that to the
commit message.

There does not seem to be a need for secure erase, so:

Acked-by: Adrian Hunter 


> Signed-off-by: Yann Gautier 
> ---
>  drivers/mmc/core/mmc_test.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c
> index 39a478874ca3..63524551a13a 100644
> --- a/drivers/mmc/core/mmc_test.c
> +++ b/drivers/mmc/core/mmc_test.c
> @@ -2110,7 +2110,7 @@ static int mmc_test_rw_multiple(struct mmc_test_card 
> *test,
>   if (mmc_can_erase(test->card) &&
>   tdata->prepare & MMC_TEST_PREP_ERASE) {
>   ret = mmc_erase(test->card, dev_addr,
> - size / 512, MMC_SECURE_ERASE_ARG);
> + size / 512, test->card->erase_arg);
>   if (ret)
>   ret = mmc_erase(test->card, dev_addr,
>   size / 512, MMC_ERASE_ARG);
> 



Re: [PATCH 3/4] scsi: ufs-debugfs: Add user-defined exception_event_mask

2021-02-04 Thread Adrian Hunter
On 4/02/21 4:58 pm, Bean Huo wrote:
> On Wed, 2021-02-03 at 11:56 +0200, Adrian Hunter wrote:
>>>
>>> Hallo Adrian
>>
>> Hi Bean
>>
>> Thanks for the review
>>
>>>
>>> Would you like sharing the advantage of this debugfs node comparing
>>> to
>>> sysfs node "attributes/exception_event_control(if it is writable)"?
>>
>> Primarily this is being done as a debug interface, but the user's
>> exception
>> events also need to be kept separate from the driver's ones.
>>
>>> what is the value of this?
>>
>> To be able to determine if the UFS device is being affected by
>> exception events.
>>
>>> Also, now I can disable/enable UFS event over ufs-bsg.
>>
>> That will be overwritten by the driver when it updates the e.g. bkops
>> control, or sometimes also suspend/resume.
> 
> Hi Adrian
> yes, I saw that, they are not tracked by driver.
> 
> I have one question that why "exception_event_mask" cannot represent
> the current QUERY_ATTR_IDN_EE_CONTROL value? only after writing it.

It represents only the user's exception events (ee_usr_mask), not the
driver's ones (ee_drv_mask) as well.  ee_usr_mask is updated after
successfully ensuring it is set on the device.


Re: [PATCH 3/4] scsi: ufs-debugfs: Add user-defined exception_event_mask

2021-02-03 Thread Adrian Hunter
On 3/02/21 11:45 am, Bean Huo wrote:
> On Tue, 2021-01-19 at 16:15 +0200, Adrian Hunter wrote:
>> Allow users to enable specific exception events via debugfs.
>>
>> The bits enabled by the driver ee_drv_ctrl are separated from the
>> bits
>> enabled by the user ee_usr_ctrl. The control mask ee_mask_ctrl is the
>> logical-or of those two. A mutex is needed to ensure that the masks
>> match
>> what was written to the device.
> 
> Hallo Adrian

Hi Bean

Thanks for the review

> 
> Would you like sharing the advantage of this debugfs node comparing to
> sysfs node "attributes/exception_event_control(if it is writable)"?

Primarily this is being done as a debug interface, but the user's exception
events also need to be kept separate from the driver's ones.

> what is the value of this?

To be able to determine if the UFS device is being affected by exception events.

> Also, now I can disable/enable UFS event over ufs-bsg.

That will be overwritten by the driver when it updates the e.g. bkops
control, or sometimes also suspend/resume.


Re: [PATCH 0/4] scsi: ufs-debugfs: Add UFS Exception Event reporting

2021-02-02 Thread Adrian Hunter
On 19/01/21 4:15 pm, Adrian Hunter wrote:
> Hi
> 
> Here are patches to add a tracepoint for UFS Exception Events and to allow
> users to enable specific exception events without affecting the driver's
> use of exception events.
> 
> 
> Adrian Hunter (4):
>   scsi: ufs: Add exception event tracepoint
>   scsi: ufs: Add exception event definitions
>   scsi: ufs-debugfs: Add user-defined exception_event_mask
>   scsi: ufs-debugfs: Add user-defined exception event rate limiting
> 
>  drivers/scsi/ufs/ufs-debugfs.c | 90 
> ++
>  drivers/scsi/ufs/ufs-debugfs.h |  2 +
>  drivers/scsi/ufs/ufs.h | 10 -
>  drivers/scsi/ufs/ufshcd.c  | 87 +---
>  drivers/scsi/ufs/ufshcd.h  | 26 +++-
>  include/trace/events/ufs.h | 21 ++
>  6 files changed, 201 insertions(+), 35 deletions(-)

Any comments on this?


Re: [PATCH] mmc: queue: Remove unused define

2021-02-02 Thread Adrian Hunter
On 3/02/21 9:20 am, Chanwoo Lee wrote:
> From: ChanWoo Lee 
> 
> MMC_CQE_QUEUE_FULL is not set and is only cleared.
> Therefore, define is unnecessary.
> 
> Signed-off-by: ChanWoo Lee 

Looks like a pre blk-mq remanent.

Acked-by: Adrian Hunter 

> ---
>  drivers/mmc/core/queue.c | 2 --
>  drivers/mmc/core/queue.h | 1 -
>  2 files changed, 3 deletions(-)
> 
> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
> index 002426e3cf76..9f37a8b909e8 100644
> --- a/drivers/mmc/core/queue.c
> +++ b/drivers/mmc/core/queue.c
> @@ -33,8 +33,6 @@ void mmc_cqe_check_busy(struct mmc_queue *mq)
>  {
>   if ((mq->cqe_busy & MMC_CQE_DCMD_BUSY) && !mmc_cqe_dcmd_busy(mq))
>   mq->cqe_busy &= ~MMC_CQE_DCMD_BUSY;
> -
> - mq->cqe_busy &= ~MMC_CQE_QUEUE_FULL;
>  }
>  
>  static inline bool mmc_cqe_can_dcmd(struct mmc_host *host)
> diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
> index fd11491ced9f..57c59b6cb1b9 100644
> --- a/drivers/mmc/core/queue.h
> +++ b/drivers/mmc/core/queue.h
> @@ -81,7 +81,6 @@ struct mmc_queue {
>   int in_flight[MMC_ISSUE_MAX];
>   unsigned intcqe_busy;
>  #define MMC_CQE_DCMD_BUSYBIT(0)
> -#define MMC_CQE_QUEUE_FULL   BIT(1)
>   boolbusy;
>   booluse_cqe;
>   boolrecovery_needed;
> 



Re: [PATCH] scsi: ufs: Add total count for each error history

2021-02-02 Thread Adrian Hunter
On 3/02/21 8:53 am, DooHyun Hwang wrote:
> Since the total error history count is unknown because the error history
> records only the number of UFS_EVENT_HIST_LENGTH, add a member to count
> each error history.
> 
> Signed-off-by: DooHyun Hwang 

Hi

Please note that the following patch is already queued - see linux-next


   
commit b6cacaf2044fd9b82e5ceac88d8d17e04a01982f 

  
Author: Adrian Hunter  

  
Date:   Thu Jan 7 09:25:38 2021 +0200   

  


  
scsi: ufs: ufs-debugfs: Add error counters  

  


  
People testing have a need to know how many errors might be occurring over  

  
time. Add error counters and expose them via debugfs.   

  


  
A module initcall is used to create a debugfs root directory for

  
ufshcd-related items. In the case that modules are built-in, then   

  
initialization is done in link order, so move ufshcd-core to the top of the
Makefile.

Link: 
https://lore.kernel.org/r/20210107072538.21782-1-adrian.hun...@intel.com
Reviewed-by: Avri Altman 
Reviewed-by: Bean Huo 
Reviewed-by: Can Guo 
Signed-off-by: Adrian Hunter 
Signed-off-by: Martin K. Petersen 


> ---
>  drivers/scsi/ufs/ufshcd.c | 3 +++
>  drivers/scsi/ufs/ufshcd.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index fb32d122f2e3..7ebc892553fc 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -437,6 +437,8 @@ static void ufshcd_print_evt(struct ufs_hba *hba, u32 id,
>  
>   if (!found)
>   dev_err(hba->dev, "No record of %s\n", err_name);
> + else
> + dev_err(hba->dev, "%s: total count=%u\n", err_name, e->count);
>  }
>  
>  static void ufshcd_print_evt_hist(struct ufs_hba *hba)
> @@ -4544,6 +4546,7 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 
> id, u32 val)
>   e->val[e->pos] = val;
>   e->tstamp[e->pos] = ktime_get();
>   e->pos = (e->pos + 1) % UFS_EVENT_HIST_LENGTH;
> + e->count++;
>  
>   ufshcd_vops_event_notify(hba, id, );
>  }
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index aa9ea3552323..df28d3fc89a5 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -450,6 +450,7 @@ struct ufs_event_hist {
>   int pos;
>   u32 val[UFS_EVENT_HIST_LENGTH];
>   ktime_t tstamp[UFS_EVENT_HIST_LENGTH];
> + u32 count;
>  };
>  
>  /**
> 



[PATCH] perf auxtrace: Automatically group aux-output events

2021-01-21 Thread Adrian Hunter
aux-output events need to have an AUX area event as the group leader.
However, grouping events does not allow the AUX area event to be given
an address filter because the --filter option must come after the event,
which conflicts with the grouping syntax.

To allow filtering in that case, automatically create a group since that
is the requirement anyway.

Example: (requires Intel Tremont)

  perf record -c 500 -e 'intel_pt//u' --filter 'filter main @ /bin/ls' -e 
'cycles/aux-output/pp' ls

Signed-off-by: Adrian Hunter 
---
 tools/perf/builtin-record.c |  2 ++
 tools/perf/util/auxtrace.c  | 15 +++
 tools/perf/util/auxtrace.h  |  6 ++
 3 files changed, 23 insertions(+)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8a0127d4fb52..687f1449a845 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -731,6 +731,8 @@ static int record__auxtrace_init(struct record *rec)
if (err)
return err;
 
+   auxtrace_regroup_aux_output(rec->evlist);
+
return auxtrace_parse_filters(rec->evlist);
 }
 
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a60878498139..953f4afacd3b 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -788,6 +788,21 @@ int auxtrace_parse_sample_options(struct auxtrace_record 
*itr,
return auxtrace_validate_aux_sample_size(evlist, opts);
 }
 
+void auxtrace_regroup_aux_output(struct evlist *evlist)
+{
+   struct evsel *evsel, *aux_evsel = NULL;
+   struct evsel_config_term *term;
+
+   evlist__for_each_entry(evlist, evsel) {
+   if (evsel__is_aux_event(evsel))
+   aux_evsel = evsel;
+   term = evsel__get_config_term(evsel, AUX_OUTPUT);
+   /* If possible, group with the AUX event */
+   if (term && aux_evsel)
+   evlist__regroup(evlist, aux_evsel, evsel);
+   }
+}
+
 struct auxtrace_record *__weak
 auxtrace_record__init(struct evlist *evlist __maybe_unused, int *err)
 {
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 7e5c9e1552bd..a4fbb33b7245 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -559,6 +559,7 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record 
*itr,
 int auxtrace_parse_sample_options(struct auxtrace_record *itr,
  struct evlist *evlist,
  struct record_opts *opts, const char *str);
+void auxtrace_regroup_aux_output(struct evlist *evlist);
 int auxtrace_record__options(struct auxtrace_record *itr,
 struct evlist *evlist,
 struct record_opts *opts);
@@ -740,6 +741,11 @@ int auxtrace_parse_sample_options(struct auxtrace_record 
*itr __maybe_unused,
return -EINVAL;
 }
 
+static inline
+void auxtrace_regroup_aux_output(struct evlist *evlist __maybe_unused)
+{
+}
+
 static inline
 int auxtrace__process_event(struct perf_session *session __maybe_unused,
union perf_event *event __maybe_unused,
-- 
2.17.1



Re: [PATCH] perf evlist: Fix id index for heterogeneous systems

2021-01-21 Thread Adrian Hunter
On 21/01/21 3:19 pm, Arnaldo Carvalho de Melo wrote:
> Em Thu, Jan 21, 2021 at 02:54:46PM +0200, Adrian Hunter escreveu:
>> perf_evlist__set_sid_idx() updates perf_sample_id with the evlist map
>> index, cpu number and tid. It is passed indexes to the evsel's cpu and
>> thread maps, but references the evlist's maps instead. That results in
>> using incorrect cpu numbers on heterogeneous systems. Fix by using evsel
>> maps.
>>
>> The id index (PERF_RECORD_ID_INDEX) is used by AUX area tracing when in
>> sampling mode. Having an incorrect cpu number causes the trace data to
>> be attributed to the wrong cpu, and can result in decoder errors because
>> the trace data is then associated with the wrong process.
> 
> Can you please provide a Fixes: tag so that the sta...@kernel.org guys
> can apply where appropriate?

Oops sorry missed that.  Here it is:

Fixes: 3c659eedada2 ("perf tools: Add id index")


[PATCH] perf evlist: Fix id index for heterogeneous systems

2021-01-21 Thread Adrian Hunter
perf_evlist__set_sid_idx() updates perf_sample_id with the evlist map
index, cpu number and tid. It is passed indexes to the evsel's cpu and
thread maps, but references the evlist's maps instead. That results in
using incorrect cpu numbers on heterogeneous systems. Fix by using evsel
maps.

The id index (PERF_RECORD_ID_INDEX) is used by AUX area tracing when in
sampling mode. Having an incorrect cpu number causes the trace data to
be attributed to the wrong cpu, and can result in decoder errors because
the trace data is then associated with the wrong process.

Signed-off-by: Adrian Hunter 
---
 tools/lib/perf/evlist.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
index cfcdbd7be066..37be8042889f 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -367,21 +367,13 @@ static struct perf_mmap* perf_evlist__alloc_mmap(struct 
perf_evlist *evlist, boo
return map;
 }
 
-static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
-struct perf_evsel *evsel, int idx, int cpu,
-int thread)
+static void set_sid_idx(struct perf_evsel *evsel, int idx, int cpu, int thread)
 {
struct perf_sample_id *sid = SID(evsel, cpu, thread);
 
sid->idx = idx;
-   if (evlist->cpus && cpu >= 0)
-   sid->cpu = evlist->cpus->map[cpu];
-   else
-   sid->cpu = -1;
-   if (!evsel->system_wide && evlist->threads && thread >= 0)
-   sid->tid = perf_thread_map__pid(evlist->threads, thread);
-   else
-   sid->tid = -1;
+   sid->cpu = perf_cpu_map__cpu(evsel->cpus, cpu);
+   sid->tid = perf_thread_map__pid(evsel->threads, thread);
 }
 
 static struct perf_mmap*
@@ -500,8 +492,7 @@ mmap_per_evsel(struct perf_evlist *evlist, struct 
perf_evlist_mmap_ops *ops,
if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
   fd) < 0)
return -1;
-   perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
-thread);
+   set_sid_idx(evsel, idx, cpu, thread);
}
}
 
-- 
2.17.1



[PATCH 2/4] scsi: ufs: Add exception event definitions

2021-01-19 Thread Adrian Hunter
For readability and completeness, add exception event definitions.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufs.h | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 09c7cc8a678d..5d4a2740a159 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -348,8 +348,14 @@ enum power_desc_param_offset {
 
 /* Exception event mask values */
 enum {
-   MASK_EE_STATUS  = 0x,
-   MASK_EE_URGENT_BKOPS= (1 << 2),
+   MASK_EE_STATUS  = 0x,
+   MASK_EE_DYNCAP_EVENT= BIT(0),
+   MASK_EE_SYSPOOL_EVENT   = BIT(1),
+   MASK_EE_URGENT_BKOPS= BIT(2),
+   MASK_EE_TOO_HIGH_TEMP   = BIT(3),
+   MASK_EE_TOO_LOW_TEMP= BIT(4),
+   MASK_EE_WRITEBOOSTER_EVENT  = BIT(5),
+   MASK_EE_PERFORMANCE_THROTTLING  = BIT(6),
 };
 
 /* Background operation status */
-- 
2.17.1



[PATCH 1/4] scsi: ufs: Add exception event tracepoint

2021-01-19 Thread Adrian Hunter
Currently, exception event status can be read from wExceptionEventStatus
attribute (sysfs file attributes/exception_event_status under the UFS host
controller device directory). Polling that attribute to track UFS exception
events is impractical, so add a tracepoint to track exception events for
testing and debugging purposes.

Note, by the time the exception event status is read, the exception event
may have cleared, so the value can be zero - see example below.

Note also, only enabled exception events can be reported. A subsequent
patch adds the ability for users to enable selected exception events via
debugfs.

Example with driver instrumented to enable all exception events:

  # echo 1 > /sys/kernel/debug/tracing/events/ufs/ufshcd_exception_event/enable

  ... do some I/O ...

  # cat /sys/kernel/debug/tracing/trace
  # tracer: nop
  #
  # entries-in-buffer/entries-written: 3/3   #P:5
  #
  #_-=> irqs-off
  #   / _=> need-resched
  #  | / _---=> hardirq/softirq
  #  || / _--=> preempt-depth
  #  ||| / delay
  #   TASK-PID CPU#     TIMESTAMP  FUNCTION
  #  | | |     | |
   kworker/2:2-173 [002]    731.486419: ufshcd_exception_event: 
:00:12.5: exception event status 0x0
   kworker/2:2-173 [002]    732.608918: ufshcd_exception_event: 
:00:12.5: exception event status 0x4
   kworker/2:2-173 [002]    732.609312: ufshcd_exception_event: 
:00:12.5: exception event status 0x4

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufshcd.c  |  2 ++
 include/trace/events/ufs.h | 21 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 46a499b7e8a8..7d46b2c278dd 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5624,6 +5624,8 @@ static void ufshcd_exception_event_handler(struct 
work_struct *work)
goto out;
}
 
+   trace_ufshcd_exception_event(dev_name(hba->dev), status);
+
status &= hba->ee_ctrl_mask;
 
if (status & MASK_EE_URGENT_BKOPS)
diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
index e151477d645c..5a2586217eb6 100644
--- a/include/trace/events/ufs.h
+++ b/include/trace/events/ufs.h
@@ -349,6 +349,27 @@ TRACE_EVENT(ufshcd_upiu,
)
 );
 
+TRACE_EVENT(ufshcd_exception_event,
+
+   TP_PROTO(const char *dev_name, u16 status),
+
+   TP_ARGS(dev_name, status),
+
+   TP_STRUCT__entry(
+   __string(dev_name, dev_name)
+   __field(u16, status)
+   ),
+
+   TP_fast_assign(
+   __assign_str(dev_name, dev_name);
+   __entry->status = status;
+   ),
+
+   TP_printk("%s: exception event status 0x%x",
+   __get_str(dev_name), __entry->status
+   )
+);
+
 #endif /* if !defined(_TRACE_UFS_H) || defined(TRACE_HEADER_MULTI_READ) */
 
 /* This part must be outside protection */
-- 
2.17.1



[PATCH 0/4] scsi: ufs-debugfs: Add UFS Exception Event reporting

2021-01-19 Thread Adrian Hunter
Hi

Here are patches to add a tracepoint for UFS Exception Events and to allow
users to enable specific exception events without affecting the driver's
use of exception events.


Adrian Hunter (4):
  scsi: ufs: Add exception event tracepoint
  scsi: ufs: Add exception event definitions
  scsi: ufs-debugfs: Add user-defined exception_event_mask
  scsi: ufs-debugfs: Add user-defined exception event rate limiting

 drivers/scsi/ufs/ufs-debugfs.c | 90 ++
 drivers/scsi/ufs/ufs-debugfs.h |  2 +
 drivers/scsi/ufs/ufs.h | 10 -
 drivers/scsi/ufs/ufshcd.c  | 87 +---
 drivers/scsi/ufs/ufshcd.h  | 26 +++-
 include/trace/events/ufs.h | 21 ++
 6 files changed, 201 insertions(+), 35 deletions(-)


Regards
Adrian


[PATCH 4/4] scsi: ufs-debugfs: Add user-defined exception event rate limiting

2021-01-19 Thread Adrian Hunter
An enabled user-specified exception event that does not clear quickly will
repeatedly cause the handler to run. That could unduly disturb the driver
behaviour being tested or debugged. To prevent that add debugfs file
exception_event_rate_limit_ms. When a exception event happens, it is
disabled, and then after a period of time (default 20ms) the exception
event is enabled again.

Note that if the driver also has that exception event enabled, it will not
be disabled.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufs-debugfs.c | 44 ++
 drivers/scsi/ufs/ufs-debugfs.h |  2 ++
 drivers/scsi/ufs/ufshcd.c  |  5 ++--
 drivers/scsi/ufs/ufshcd.h  |  4 
 4 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 59729073b569..ced9ef4d7c78 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -88,15 +88,59 @@ static int ee_usr_mask_set(void *data, u64 val)
 
 DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, 
"%#llx\n");
 
+void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status)
+{
+   bool chgd = false;
+   u16 ee_ctrl_mask;
+   int err = 0;
+
+   if (!hba->debugfs_ee_rate_limit_ms || !status)
+   return;
+
+   mutex_lock(>ee_ctrl_mutex);
+   ee_ctrl_mask = hba->ee_drv_mask | (hba->ee_usr_mask & ~status);
+   chgd = ee_ctrl_mask != hba->ee_ctrl_mask;
+   if (chgd) {
+   err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
+   if (err)
+   dev_err(hba->dev, "%s: failed to write ee control %d\n",
+   __func__, err);
+   }
+   mutex_unlock(>ee_ctrl_mutex);
+
+   if (chgd && !err) {
+   unsigned long delay = 
msecs_to_jiffies(hba->debugfs_ee_rate_limit_ms);
+
+   queue_delayed_work(system_freezable_wq, >debugfs_ee_work, 
delay);
+   }
+}
+
+static void ufs_debugfs_restart_ee(struct work_struct *work)
+{
+   struct ufs_hba *hba = container_of(work, struct ufs_hba, 
debugfs_ee_work.work);
+
+   if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) ||
+   ufs_debugfs_get_user_access(hba))
+   return;
+   ufshcd_write_ee_control(hba);
+   ufs_debugfs_put_user_access(hba);
+}
+
 void ufs_debugfs_hba_init(struct ufs_hba *hba)
 {
+   /* Set default exception event rate limit period to 20ms */
+   hba->debugfs_ee_rate_limit_ms = 20;
+   INIT_DELAYED_WORK(>debugfs_ee_work, ufs_debugfs_restart_ee);
hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), 
ufs_debugfs_root);
debugfs_create_file("stats", 0400, hba->debugfs_root, hba, 
_debugfs_stats_fops);
debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
hba, _usr_mask_fops);
+   debugfs_create_u32("exception_event_rate_limit_ms", 0600, 
hba->debugfs_root,
+  >debugfs_ee_rate_limit_ms);
 }
 
 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
 {
debugfs_remove_recursive(hba->debugfs_root);
+   cancel_delayed_work_sync(>debugfs_ee_work);
 }
diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index f35b39c4b4f5..3ca29d30460a 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -12,11 +12,13 @@ void __init ufs_debugfs_init(void);
 void __exit ufs_debugfs_exit(void);
 void ufs_debugfs_hba_init(struct ufs_hba *hba);
 void ufs_debugfs_hba_exit(struct ufs_hba *hba);
+void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status);
 #else
 static inline void ufs_debugfs_init(void) {}
 static inline void ufs_debugfs_exit(void) {}
 static inline void ufs_debugfs_hba_init(struct ufs_hba *hba) {}
 static inline void ufs_debugfs_hba_exit(struct ufs_hba *hba) {}
+static inline void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 
status) {}
 #endif
 
 #endif
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d68f5ecc9b13..f0959b9609fd 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5147,14 +5147,14 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
}
 }
 
-static int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
+int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
 {
return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
   QUERY_ATTR_IDN_EE_CONTROL, 0, 0,
   _ctrl_mask);
 }
 
-static int ufshcd_write_ee_control(struct ufs_hba *hba)
+int ufshcd_write_ee_control(struct ufs_hba *hba)
 {
int err;
 
@@ -5643,6 +5643,7 @@ static void ufshcd_exception_event_handler(struct 
work_struct 

[PATCH 3/4] scsi: ufs-debugfs: Add user-defined exception_event_mask

2021-01-19 Thread Adrian Hunter
Allow users to enable specific exception events via debugfs.

The bits enabled by the driver ee_drv_ctrl are separated from the bits
enabled by the user ee_usr_ctrl. The control mask ee_mask_ctrl is the
logical-or of those two. A mutex is needed to ensure that the masks match
what was written to the device.

Signed-off-by: Adrian Hunter 
---
 drivers/scsi/ufs/ufs-debugfs.c | 46 ++
 drivers/scsi/ufs/ufshcd.c  | 86 +-
 drivers/scsi/ufs/ufshcd.h  | 22 -
 3 files changed, 120 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index dee98dc72d29..59729073b569 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -44,10 +44,56 @@ static int ufs_debugfs_stats_show(struct seq_file *s, void 
*data)
 }
 DEFINE_SHOW_ATTRIBUTE(ufs_debugfs_stats);
 
+static int ee_usr_mask_get(void *data, u64 *val)
+{
+   struct ufs_hba *hba = data;
+
+   *val = hba->ee_usr_mask;
+   return 0;
+}
+
+static int ufs_debugfs_get_user_access(struct ufs_hba *hba)
+__acquires(>host_sem)
+{
+   down(>host_sem);
+   if (!ufshcd_is_user_access_allowed(hba)) {
+   up(>host_sem);
+   return -EBUSY;
+   }
+   pm_runtime_get_sync(hba->dev);
+   return 0;
+}
+
+static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
+__releases(>host_sem)
+{
+   pm_runtime_put_sync(hba->dev);
+   up(>host_sem);
+}
+
+static int ee_usr_mask_set(void *data, u64 val)
+{
+   struct ufs_hba *hba = data;
+   int err;
+
+   if (val & ~(u64)MASK_EE_STATUS)
+   return -EINVAL;
+   err = ufs_debugfs_get_user_access(hba);
+   if (err)
+   return err;
+   err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS);
+   ufs_debugfs_put_user_access(hba);
+   return err;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, 
"%#llx\n");
+
 void ufs_debugfs_hba_init(struct ufs_hba *hba)
 {
hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), 
ufs_debugfs_root);
debugfs_create_file("stats", 0400, hba->debugfs_root, hba, 
_debugfs_stats_fops);
+   debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
+   hba, _usr_mask_fops);
 }
 
 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7d46b2c278dd..d68f5ecc9b13 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5147,6 +5147,46 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
}
 }
 
+static int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask)
+{
+   return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+  QUERY_ATTR_IDN_EE_CONTROL, 0, 0,
+  _ctrl_mask);
+}
+
+static int ufshcd_write_ee_control(struct ufs_hba *hba)
+{
+   int err;
+
+   mutex_lock(>ee_ctrl_mutex);
+   err = __ufshcd_write_ee_control(hba, hba->ee_ctrl_mask);
+   mutex_unlock(>ee_ctrl_mutex);
+   if (err)
+   dev_err(hba->dev, "%s: failed to write ee control %d\n",
+   __func__, err);
+   return err;
+}
+
+int ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask, u16 *other_mask,
+u16 set, u16 clr)
+{
+   u16 new_mask, ee_ctrl_mask;
+   int err = 0;
+
+   mutex_lock(>ee_ctrl_mutex);
+   new_mask = (*mask & ~clr) | set;
+   ee_ctrl_mask = new_mask | *other_mask;
+   if (ee_ctrl_mask != hba->ee_ctrl_mask)
+   err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
+   /* Still need to update 'mask' even if 'ee_ctrl_mask' was unchanged */
+   if (!err) {
+   hba->ee_ctrl_mask = ee_ctrl_mask;
+   *mask = new_mask;
+   }
+   mutex_unlock(>ee_ctrl_mutex);
+   return err;
+}
+
 /**
  * ufshcd_disable_ee - disable exception event
  * @hba: per-adapter instance
@@ -5157,22 +5197,9 @@ static irqreturn_t ufshcd_transfer_req_compl(struct 
ufs_hba *hba)
  *
  * Returns zero on success, non-zero error value on failure.
  */
-static int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)
+static inline int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)
 {
-   int err = 0;
-   u32 val;
-
-   if (!(hba->ee_ctrl_mask & mask))
-   goto out;
-
-   val = hba->ee_ctrl_mask & ~mask;
-   val &= MASK_EE_STATUS;
-   err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
-   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
-   if (!err)
-   hba->ee_ctrl_mask &= ~mask;
-out:
-   return err;
+   return ufshcd_update_ee_drv_mask(hba, 0, mask);
 }
 
 /*

Re: [PATCH v6 1/6] scsi: ufs: Add "wb_on" sysfs node to control WB on/off

2021-01-19 Thread Adrian Hunter
On 19/01/21 11:33 am, Bean Huo wrote:
> On Tue, 2021-01-19 at 09:01 +0200, Adrian Hunter wrote:
>> On 18/01/21 10:10 pm, Bean Huo wrote:
>>> From: Bean Huo 
>>>
>>> Currently UFS WriteBooster driver uses clock scaling up/down to set
>>> WB on/off, for the platform which doesn't support
>>> UFSHCD_CAP_CLK_SCALING,
>>> WB will be always on. Provide a sysfs attribute to enable/disable
>>> WB
>>> during runtime. Write 1/0 to "wb_on" sysfs node to enable/disable
>>> UFS WB.
>>
>> Is it so, that after a full reset, WB is always enabled again?  Is
>> that
>> intended?
> 
> Hello Adrian
> Good questions. yes, after a full reset, the UFS device side by default
> is wb disabled,  then WB will be always enabled agaion in
> ufshcd_wb_config(hba). but, for the platform which
> supports UFSHCD_CAP_CLK_SCALING, wb will be disabled again while clk
> scaling down and enabled while clk scaling up.
> 
> Regarding the last question, I think OEM wants to do that. maybe they
> suppose there will be a lot of writing after reset?? From the UFS
> device's point of view, the control of WB is up to the user.

If it is by design enabled after reset, then perhaps it should be mentioned
in the sysfs documentation.


  1   2   3   4   5   6   7   8   9   10   >