RE: [PATCH v6 1/9] rpmb: add Replay Protected Memory Block (RPMB) subsystem

2016-09-23 Thread Avri Altman

> 
> Signed-off-by: Tomas Winkler <tomas.wink...@intel.com>
> Signed-off-by: Alexander Usyskin <alexander.usys...@intel.com>
Tested-by: Avri Altman <avri.alt...@sandisk.com>

- mmc -  full functionality. One issue found that was fixed on V6: patch V6 2/9.
- ufs - read & read counter only.  Testing is still wip.


> +static int rpmb_request_verify(struct rpmb_dev *rdev, struct rpmb_data
> +*rpmbd) {

Seems excessive - Isn't the standard should be enforced by the device?

Cheers,
Avri



RE: [PATCH] scsi: ufs: reqs and tasks were put in the wrong order

2017-08-30 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Zang Leigang
> Sent: Thursday, August 24, 2017 5:57 AM
> To: vinholika...@gmail.com; j...@linux.vnet.ibm.com;
> martin.peter...@oracle.com
> Cc: linux-scsi@vger.kernel.org
> Subject: [PATCH] scsi: ufs: reqs and tasks were put in the wrong order
> 
> Signed-off-by: Zang Leigang <zangleig...@hisilicon.com>
Acked-by: Avri Altman <avri.alt...@sandisk.com>

> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
> 5bc9dc14e075..794a4600e952 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -438,7 +438,7 @@ static void ufshcd_print_host_state(struct ufs_hba
> *hba)  {
>   dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
>   dev_err(hba->dev, "lrb in use=0x%lx, outstanding reqs=0x%lx
> tasks=0x%lx\n",
> - hba->lrb_in_use, hba->outstanding_tasks, hba-
> >outstanding_reqs);
> + hba->lrb_in_use, hba->outstanding_reqs, hba-
> >outstanding_tasks);
>   dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x\n",
>   hba->saved_err, hba->saved_uic_err);
>   dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n",
> --
> 2.14.1



RE: [PATCH] scsi: ufs: Fix Runtime PM

2017-11-13 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Michal Potomski
> Sent: Thursday, November 09, 2017 11:17 AM
> To: linux-scsi@vger.kernel.org
> Cc: vinholika...@gmail.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com; subha...@codeaurora.org;
> szymonx.mielcza...@intel.com
> Subject: [PATCH] scsi: ufs: Fix Runtime PM
> 
> From: Michał Potomski 
> 
> Recent testing of Runtime PM for UFS has shown it's not working as intended.
> To acheive fully working Runtime PM, first we have to put back scsi_device
> autopm reference counter.
> 
> Existing implementation was prone to races and not working for tranfsers to
> sleeping devices. 

Wouldn't calling  pm_runtime_mark_last_busy() just before 
pm_runtime_put_autosuspend() suffice?

This commit aims to fix this to acheive fully working
> environment. Due to runtime PM being previously disabled by not putting
> scsi_device autopm counter, the Runtime PM is set to be forbidden as
> default, to not cause problems with hosts and devices, which do not fully
> support different Device and Link states.
> 
> It can be still enabled through sysFS power/control attribute.
> 
> Signed-off-by: Michał Potomski 
> ---
>  drivers/scsi/ufs/ufshcd-pci.c |  4 +++-
>  drivers/scsi/ufs/ufshcd.c | 55 ++---
> --
>  2 files changed, 47 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c 
> index
> 925b0ec7ec54..4fffb1123876 100644
> --- a/drivers/scsi/ufs/ufshcd-pci.c
> +++ b/drivers/scsi/ufs/ufshcd-pci.c
> @@ -184,8 +184,10 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct
> pci_device_id *id)
>   }
> 
>   pci_set_drvdata(pdev, hba);
> + pm_runtime_set_autosuspend_delay(>dev, 3000);
> + pm_runtime_use_autosuspend(>dev);
>   pm_runtime_put_noidle(>dev);
> - pm_runtime_allow(>dev);
> + pm_runtime_forbid(>dev);
> 
>   return 0;
>  }
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
> 011c3369082c..e7c7ed9bf8a5 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -240,6 +240,28 @@ static inline bool ufshcd_valid_tag(struct ufs_hba
> *hba, int tag)
>   return tag >= 0 && tag < hba->nutrs;
>  }
> 
> +static void ufshcd_pm_runtime_get(struct device *dev) {
> + // Don't trigger PM events while in transition states
> + if (dev->power.runtime_status == RPM_RESUMING ||
> + dev->power.runtime_status == RPM_SUSPENDING)
> + pm_runtime_get_noresume(dev);
> + else
> + pm_runtime_get_sync(dev);
> +}
> +
> +static void ufshcd_pm_runtime_put(struct device *dev) {
> + pm_runtime_mark_last_busy(dev);
> +
> + // Don't trigger PM events while in transition states
> + if (dev->power.runtime_status == RPM_RESUMING ||
> + dev->power.runtime_status == RPM_SUSPENDING)
> + pm_runtime_put_noidle(dev);
> + else
> + pm_runtime_put_autosuspend(dev);
> +}
> +
>  static inline int ufshcd_enable_irq(struct ufs_hba *hba)  {
>   int ret = 0;
> @@ -1345,7 +1367,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct
> device *dev,
>   if (value == hba->clk_scaling.is_allowed)
>   goto out;
> 
> - pm_runtime_get_sync(hba->dev);
> + ufshcd_pm_runtime_get(hba->dev);
>   ufshcd_hold(hba, false);
> 
>   cancel_work_sync(>clk_scaling.suspend_work);
> @@ -1364,7 +1386,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct
> device *dev,
>   }
> 
>   ufshcd_release(hba);
> - pm_runtime_put_sync(hba->dev);
> + ufshcd_pm_runtime_put(hba->dev);
>  out:
>   return count;
>  }
> @@ -1948,6 +1970,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   unsigned long flags;
> 
>   ufshcd_hold(hba, false);
> + ufshcd_pm_runtime_get(hba->dev);
>   mutex_lock(>uic_cmd_mutex);
>   ufshcd_add_delay_before_dme_cmd(hba);
> 
> @@ -1959,6 +1982,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
> 
>   mutex_unlock(>uic_cmd_mutex);
> 
> + ufshcd_pm_runtime_put(hba->dev);
>   ufshcd_release(hba);
>   return ret;
>  }
> @@ -2345,6 +2369,7 @@ static int ufshcd_queuecommand(struct Scsi_Host
> *host, struct scsi_cmnd *cmd)
>   clear_bit_unlock(tag, >lrb_in_use);
>   goto out;
>   }
> + ufshcd_pm_runtime_get(hba->dev);
>   WARN_ON(hba->clk_gating.state != CLKS_ON);
> 
>   lrbp = >lrb[tag];
> @@ -3555,6 +3580,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>   int ret;
>   bool reenable_intr = false;
> 
> + ufshcd_pm_runtime_get(hba->dev);
>   mutex_lock(>uic_cmd_mutex);
>   init_completion(_async_done);
>   ufshcd_add_delay_before_dme_cmd(hba);
> @@ -3609,6 +3635,7 @@ static int 

RE: [PATCH 4/4] scsi: ufs: make ufshcd_config_pwr_mode of non-static func

2018-05-16 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org <linux-scsi-ow...@vger.kernel.org>
> On Behalf Of Alim Akhtar
> Sent: Sunday, May 06, 2018 1:14 PM
> To: linux-scsi@vger.kernel.org; linux-ker...@vger.kernel.org
> Cc: j...@linux.vnet.ibm.com; martin.peter...@oracle.com;
> vivek.gau...@codeaurora.org; subha...@codeaurora.org;
> vinholika...@gmail.com; o...@lixom.net; alim.akh...@samsung.com
> Subject: [PATCH 4/4] scsi: ufs: make ufshcd_config_pwr_mode of non-static
> func
> 
> This makes ufshcd_config_pwr_mode non-static so that other vendors like
> exynos can use the same.
> 
> Signed-off-by: Seungwon Jeon <ess...@gmail.com>
> Signed-off-by: Alim Akhtar <alim.akh...@samsung.com>
Acked-by: Avri Altman <avri.alt...@wdc.com>

Might be also useful exporting an API for all uic commands?

Thanks,
Avri 


RE: [PATCH 1/1] scsi: ufs: make sure all interrupts are processed

2018-01-30 Thread Avri Altman
Hi,
Can you elaborate how this can even happen?
Isn't the interrupt aggregation capability should attend for those cases?

Thanks,
Avri

> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Asutosh Das
> Sent: Tuesday, January 30, 2018 6:54 AM
> To: subha...@codeaurora.org; c...@codeaurora.org;
> vivek.gau...@codeaurora.org; rna...@codeaurora.org;
> vinholika...@gmail.com; j...@linux.vnet.ibm.com;
> martin.peter...@oracle.com
> Cc: linux-scsi@vger.kernel.org; Venkat Gopalakrishnan
> ; Asutosh Das ; open
> list 
> Subject: [PATCH 1/1] scsi: ufs: make sure all interrupts are processed
> 
> From: Venkat Gopalakrishnan 
> 
> As multiple requests are submitted to the ufs host controller in parallel 
> there
> could be instances where the command completion interrupt arrives later for a
> request that is already processed earlier as the corresponding doorbell was
> cleared when handling the previous interrupt. Read the interrupt status in a
> loop after processing the received interrupt to catch such interrupts and 
> handle
> it.
> 
> Signed-off-by: Venkat Gopalakrishnan 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufshcd.c | 27 +++
>  1 file changed, 19 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
> 8af2af3..58d81de 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -5357,19 +5357,30 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
>   u32 intr_status, enabled_intr_status;
>   irqreturn_t retval = IRQ_NONE;
>   struct ufs_hba *hba = __hba;
> + int retries = hba->nutrs;
> 
>   spin_lock(hba->host->host_lock);
>   intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
> - enabled_intr_status =
> - intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
> 
> - if (intr_status)
> - ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
> + /*
> +  * There could be max of hba->nutrs reqs in flight and in worst case
> +  * if the reqs get finished 1 by 1 after the interrupt status is
> +  * read, make sure we handle them by checking the interrupt status
> +  * again in a loop until we process all of the reqs before returning.
> +  */
> + do {
> + enabled_intr_status =
> + intr_status & ufshcd_readl(hba,
> REG_INTERRUPT_ENABLE);
> + if (intr_status)
> + ufshcd_writel(hba, intr_status,
> REG_INTERRUPT_STATUS);
> + if (enabled_intr_status) {
> + ufshcd_sl_intr(hba, enabled_intr_status);
> + retval = IRQ_HANDLED;
> + }
> +
> + intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
> + } while (intr_status && --retries);
> 
> - if (enabled_intr_status) {
> - ufshcd_sl_intr(hba, enabled_intr_status);
> - retval = IRQ_HANDLED;
> - }
>   spin_unlock(hba->host->host_lock);
>   return retval;
>  }
> --
> Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center,
> Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux
> Foundation Collaborative Project.



RE: [PATCH 1/1] scsi: ufs: make sure all interrupts are processed

2018-02-05 Thread Avri Altman


> >>> -Original Message-
> >>> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> >>> ow...@vger.kernel.org] On Behalf Of Asutosh Das
> >>> Sent: Tuesday, January 30, 2018 6:54 AM
> >>> To: subha...@codeaurora.org; c...@codeaurora.org;
> >>> vivek.gau...@codeaurora.org; rna...@codeaurora.org;
> >>> vinholika...@gmail.com; j...@linux.vnet.ibm.com;
> >>> martin.peter...@oracle.com
> >>> Cc: linux-scsi@vger.kernel.org; Venkat Gopalakrishnan
> >>> ; Asutosh Das ;
> >>> open list 
> >>> Subject: [PATCH 1/1] scsi: ufs: make sure all interrupts are
> >>> processed
> >>>
> >>> From: Venkat Gopalakrishnan 
> >>>
> >>> As multiple requests are submitted to the ufs host controller in
> >>> parallel there could be instances where the command completion
> >>> interrupt arrives later for a request that is already processed
> >>> earlier as the corresponding doorbell was cleared when handling the
> >>> previous interrupt. Read the interrupt status in a loop after
> >>> processing the received interrupt to catch such interrupts and
> >>> handle it.
> >>>
> >>> Signed-off-by: Venkat Gopalakrishnan 
> >>> Signed-off-by: Asutosh Das 
Tested-by: avri.alt...@wdc.com

Tested on kirin960 (mate9)  and msm8998 (htc11), both where interrupt 
aggregation is not allowed.

As a side note, I noticed that this patch is part of several patches, fixing 
some qcom-staff.
Maybe you want to put them all in a patchset?

Thanks,
Avri


RE: [PATCH 1/1] scsi: ufs: Add support for Auto-Hibernate Idle Timer

2018-02-18 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Adrian Hunter
> Sent: Friday, February 16, 2018 2:01 PM
> To: Vinayak Holikatti ; Martin K. Petersen
> ; James E.J. Bottomley
> 
> Cc: Stanislav Nijnikov ; Jaegeuk Kim
> ; Bart Van Assche ; linux-
> s...@vger.kernel.org; linux-ker...@vger.kernel.org; Michal Potomski
> ; Szymon Mielczarek
> 
> Subject: [PATCH 1/1] scsi: ufs: Add support for Auto-Hibernate Idle Timer
> 
> UFS host controllers may support an autonomous power management
> feature called the Auto-Hibernate Idle Timer. The timer is set to the number
> of microseconds of idle time before the UFS host controller will
> autonomously put the link into Hibernate state. That will save power at the
> expense of increased latency. Any access to the host controller interface
> registers will automatically put the link out of Hibernate state. So once
> configured, the feature is transparent to the driver.
> 
> Expose the Auto-Hibernate Idle Timer value via SysFS to allow users to
> choose between power efficiency or lower latency. Set a default value of
> 150 ms.
> 
> Signed-off-by: Adrian Hunter 
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 15 ++
>  drivers/scsi/ufs/ufs-sysfs.c   | 77 
> ++
>  drivers/scsi/ufs/ufshcd.c  | 26 ++
>  drivers/scsi/ufs/ufshcd.h  |  3 ++
>  drivers/scsi/ufs/ufshci.h  |  7 +++
>  5 files changed, 128 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index 07f1c2f8dbfc..c7f9441079eb 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -1,3 +1,18 @@
> +What:/sys/bus/*/drivers/ufshcd/*/auto_hibern8
> +Date:February 2018
> +Contact: linux-scsi@vger.kernel.org
> +Description:
> + This file contains the auto-hibernate idle timer setting of a
> + UFS host controller. A value of '-1' means auto-hibernate is
> not
> + supported. A value of '0' means auto-hibernate is not
> enabled.
> + Otherwise the value is the number of microseconds of idle
> time
> + before the UFS host controller will autonomously put the link
> + into hibernate state. That will save power at the expense of
> + increased latency. Note that the hardware supports 10-bit
> values
> + with a power-of-ten multiplier which allows a maximum
> value of
> + 10230. Refer to the UFS Host Controller Interface
> + specification for more details.
> +
>  What:
>   /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type
>  Date:February 2018
>  Contact: Stanislav Nijnikov 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index
> cd7174d2d225..a0e38776dc92 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -3,6 +3,7 @@
> 
>  #include 
>  #include 
> +#include 
>  #include 
> 
>  #include "ufs.h"
> @@ -123,12 +124,88 @@ static ssize_t spm_lvl_store(struct device *dev,
>   return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false);  }
> 
> +static void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) {
> + unsigned long flags;
> +
> + if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT))
> + return;
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + if (hba->ahit == ahit)
> + goto out_unlock;
> + hba->ahit = ahit;
> + if (!pm_runtime_suspended(hba->dev))
> + ufshcd_writel(hba, hba->ahit,
> REG_AUTO_HIBERNATE_IDLE_TIMER);
> +out_unlock:
> + spin_unlock_irqrestore(hba->host->host_lock, flags); }
> +
> +/* Convert Auto-Hibernate Idle Timer register value to microseconds */
> +static int ufshcd_ahit_to_us(u32 ahit) {
> + int timer = FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, ahit);
> + int scale = FIELD_GET(UFSHCI_AHIBERN8_SCALE_MASK, ahit);
> +
> + for (; scale > 0; --scale)
> + timer *= UFSHCI_AHIBERN8_SCALE_FACTOR;
> +
> + return timer;
> +}
> +
> +/* Convert microseconds to Auto-Hibernate Idle Timer register value */
> +static u32 ufshcd_us_to_ahit(unsigned int timer) {
> + unsigned int scale;
> +
> + for (scale = 0; timer > UFSHCI_AHIBERN8_TIMER_MASK; ++scale)
> + timer /= UFSHCI_AHIBERN8_SCALE_FACTOR;
> +
> + return FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, timer) |
> +FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale); }
> +
> +static ssize_t auto_hibern8_show(struct device 

RE: [PATCH 2/2 v4] scsi: ufs: introduce sysfs entries exposing UFS health info

2017-12-27 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
> ow...@vger.kernel.org] On Behalf Of Greg Kroah-Hartman
> Sent: Thursday, December 21, 2017 10:00 AM
> To: Jaegeuk Kim 
> Cc: linux-ker...@vger.kernel.org; linux-scsi@vger.kernel.org; Jaegeuk Kim
> 
> Subject: Re: [PATCH 2/2 v4] scsi: ufs: introduce sysfs entries exposing UFS
> health info
> 
> On Wed, Dec 20, 2017 at 02:13:25PM -0800, Jaegeuk Kim wrote:
> > This patch adds a new sysfs group, namely health, via:
> >
> >/sys/devices/soc/X.ufshc/health/
As device health is just one piece of information out of the device management,
I think that you should address this in a more comprehensive way,
And set hooks for much more device info:
Allow access to device descriptors, attributes and flags.
The attributes and flags should be placed in separate subfolders
The LUN specific descriptors and attributes should be placed in a luns 
subfolder, and then per descriptor / attribute type
You might also would like to consider differentiating read and write - to 
control those type of accesses as well.

Cheers,
Avri



RE: [PATCH 6/6] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-08-02 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 01, 2018 6:39 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH 6/6] scsi: ufs-bsg: Add support for uic commands in
> ufs_bsg_request()
> 
> On Wed, 2018-08-01 at 11:04 +0300, Avri Altman wrote:
> > +   struct uic_command uc = {0};
> 
> Please use "{ }" or "{}" for structure initialization as is done elsewhere in
> the kernel instead of "{0}".
Done.

> 
> > +#define UIC_CMD_SIZE (sizeof(u32) * 4)
> 
> Please add a comment above this definition that explains whether this
> constant
> comes from the spec or whether it has another origin.
Done.

> 
> Thanks,
> 
> Bart.



RE: [PATCH 1/6] scsi: Add ufs transport class

2018-08-01 Thread Avri Altman
Johannes,
Thanks a lot for your comments.

Cheers,
Avri

> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org 
> On Behalf Of Johannes Thumshirn
> Sent: Wednesday, August 01, 2018 2:17 PM
> To: Avri Altman 
> Cc: Christoph Hellwig ; Hannes Reinecke ;
> Bart Van Assche ; James E.J. Bottomley
> ; Martin K. Petersen
> ; linux-scsi@vger.kernel.org; Stanislav
> Nijnikov ; Avi Shchislowski
> ; Alex Lemberg ;
> Subhash Jadavani ; Vinayak Holikatti
> 
> Subject: Re: [PATCH 1/6] scsi: Add ufs transport class
> 
> Hi Avri,
> 
> On Wed, Aug 01, 2018 at 11:04:27AM +0300, Avri Altman wrote:
> [...
> 
> > +#include 
> 
> Why do you include bsg.h here and bsg-lib.h in the scsi_transport_ufs.h?
> 
> [...]
Right, will move both to the same place.

> 
> > +#define to_ufs_internal(tmpl)  container_of(tmpl, struct
> ufs_internal, t)
> 
> I'd personally prefer this to be a inline function instead of a define
> for type safety reasons.
Ok.

> 
> > +
> > +struct ufs_host_attrs {
> > +   atomic_t next_port_id;
> > +};
> > +#define to_ufs_host_attrs(x) ((struct ufs_host_attrs *)(x)->shost_data)
> 
> Ditto.
Ok.

> 
> [...]
> 
> > +
> > +   port->id = atomic_inc_return(_host->next_port_id);
> 
> Any reason you can't use an IDA for the port->id?
Ok. Will change to use it.

> 
> [...]
> > +
> > +   error = device_add(dev);
> > +
> > +   if (error)
> > +   return error;
> 
> No blank line please.
Done.

> 
> [...]
> 
> > +#define dev_to_ufs_port(d) \
> > +   container_of((d), struct ufs_port, dev)
> 
> Inline function as well, please.
Done.

> 
> --
> Johannes Thumshirn  Storage
> jthumsh...@suse.de+49 911 74053 689
> SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
> GF: Felix Imendörffer, Jane Smithard, Graham Norton
> HRB 21284 (AG Nürnberg)
> Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850


[RFC 4/6] scsi: ufs: Add API to execute raw upiu commands

2018-07-29 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 225 ++
 drivers/scsi/ufs/ufshcd.h |   4 +
 2 files changed, 229 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c2ae406..5abf697 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -257,6 +257,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool 
on,
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp);
+
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
return tag >= 0 && tag < hba->nutrs;
@@ -3106,6 +3108,229 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
 EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
 
 /**
+ * ufshcd_issue_tm_upiu_cmd - API for sending "utmrd" requests
+ * @hba -  UFS hba
+ * @req_upiu - bsg request
+ * @rsp_upiu - bsg reply
+ *
+ * Those requests uses UTP Task Management Request Descriptor - utmrd.
+ * Therefore, it "rides" the task management infrastructure: uses its tag and
+ * tasks work queues.
+ */
+static int ufshcd_issue_tm_upiu_cmd(struct ufs_hba *hba,
+   __be32 *req_upiu,
+   __be32 *rsp_upiu)
+{
+   struct utp_task_req_desc *task_req_descp;
+   struct Scsi_Host *host = hba->host;
+   unsigned long flags;
+   int free_slot;
+   u8 tm_response = 0xF;
+   int err;
+   int task_tag;
+
+   wait_event(hba->tm_tag_wq, ufshcd_get_tm_free_slot(hba, _slot));
+   ufshcd_hold(hba, false);
+
+   spin_lock_irqsave(host->host_lock, flags);
+
+   task_req_descp = hba->utmrdl_base_addr;
+   task_req_descp += free_slot;
+
+   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
+   task_req_descp->header.dword_2 =
+   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+   task_tag = hba->nutrs + free_slot;
+
+   req_upiu[0] |= cpu_to_be32(task_tag);
+
+   /* just copy the upiu request as it is */
+   memcpy(task_req_descp->task_req_upiu, req_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
+
+   /* send command to the controller */
+   __set_bit(free_slot, >outstanding_tasks);
+
+   /* Make sure descriptors are ready before ringing the task doorbell */
+   wmb();
+
+   ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
+   /* Make sure that doorbell is committed immediately */
+   wmb();
+
+   spin_unlock_irqrestore(host->host_lock, flags);
+
+   /* wait until the task management command is completed */
+   err = wait_event_timeout(hba->tm_wq,
+   test_bit(free_slot, >tm_condition),
+   msecs_to_jiffies(TM_CMD_TIMEOUT));
+   if (!err) {
+   dev_err(hba->dev, "%s: bsg task management cmd timed-out\n",
+   __func__);
+   if (ufshcd_clear_tm_cmd(hba, free_slot))
+   dev_WARN(hba->dev,
+"%s: unable clear tm cmd (slot %d) timeout\n",
+ __func__, free_slot);
+   err = -ETIMEDOUT;
+   } else {
+   err = ufshcd_task_req_compl(hba, free_slot, _response);
+   }
+
+   /* just copy the upiu response as it is */
+   memcpy(rsp_upiu, task_req_descp->task_rsp_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
+
+   clear_bit(free_slot, >tm_condition);
+   ufshcd_put_tm_slot(hba, free_slot);
+   wake_up(>tm_tag_wq);
+
+   ufshcd_release(hba);
+   return err;
+}
+
+/**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request - 8 dwards
+ * @rsp_upiu:  upiu reply - 8 dwards
+ * @msgc

[RFC 3/6] scsi: ufs: Instantiate a ufs transport if its available

2018-07-29 Thread Avri Altman
Call the Attach/Probe/Remove APIs.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3560185..c2ae406 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -46,6 +46,7 @@
 #include "ufs_quirks.h"
 #include "unipro.h"
 #include "ufs-sysfs.h"
+#include "ufs_bsg.h"
 
 #define CREATE_TRACE_POINTS
 #include 
@@ -6651,6 +6652,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
hba->clk_scaling.is_allowed = true;
}
 
+   if (hba->host->transportt)
+   ufs_bsg_probe(hba);
+
scsi_scan_host(hba->host);
pm_runtime_put_sync(hba->dev);
}
@@ -7874,6 +7878,7 @@ int ufshcd_shutdown(struct ufs_hba *hba)
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+   ufs_bsg_remove(hba->host);
ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
/* disable interrupts */
@@ -8067,6 +8072,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
hba->is_irq_enabled = true;
}
 
+   ufs_bsg_attach_transport(hba);
+
err = scsi_add_host(host, hba->dev);
if (err) {
dev_err(hba->dev, "scsi_add_host failed\n");
-- 
1.9.1



[RFC 6/6] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-07-29 Thread Avri Altman
Add support to those uic commands, that are currently supported
by ufshcd api: the variants of dme_{peer}_{set_get}.

At this point better not to add any new api, as careless
uic command may turn the device into a brick.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 56 +-
 drivers/scsi/ufs/ufs_bsg.h |  1 +
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index d077e42..441d096 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -63,6 +63,55 @@ static int ufs_bsg_verify_query_size(unsigned int 
request_len,
return 0;
 }
 
+static int ufs_bsg_exec_uic_cmd(struct uic_command *uc)
+{
+   u32 attr_sel = uc->argument1;
+   u8 attr_set = (uc->argument2 >> 16) & 0xff;
+   u32 mib_val = uc->argument3;
+   int cmd = uc->command;
+   int ret = 0;
+
+   switch (cmd) {
+   case UIC_CMD_DME_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_PEER_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_PEER);
+   break;
+   case UIC_CMD_DME_PEER_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_PEER);
+   break;
+   case UIC_CMD_DME_POWERON:
+   case UIC_CMD_DME_POWEROFF:
+   case UIC_CMD_DME_ENABLE:
+   case UIC_CMD_DME_RESET:
+   case UIC_CMD_DME_END_PT_RST:
+   case UIC_CMD_DME_LINK_STARTUP:
+   case UIC_CMD_DME_HIBER_ENTER:
+   case UIC_CMD_DME_HIBER_EXIT:
+   case UIC_CMD_DME_TEST_MODE:
+   ret = -ENOTSUPP;
+   pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   if (ret)
+   pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+   uc->argument3 = mib_val;
+
+   return ret;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
@@ -70,6 +119,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+   struct uic_command uc = {0};
__be32 *req_upiu = NULL;
__be32 *rsp_upiu = NULL;
int msgcode;
@@ -124,7 +174,11 @@ static int ufs_bsg_request(struct bsg_job *job)
 
break;
case UPIU_TRANSACTION_UIC_CMD:
-   /* later */
+   memcpy(, _request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd();
+   memcpy(_reply->tsf.uc, , UIC_CMD_SIZE);
+
+   break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
 not_supported:
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index 0fd2859..651ffb3 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -15,6 +15,7 @@
 
 #define UFS_BSG_NOP (-1)
 #define UPIU_TRANSACTION_UIC_CMD 0x1F
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 enum {
REQ_UPIU_SIZE_DWORDS= 8,
-- 
1.9.1



[RFC 5/6] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-07-29 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 119 +++--
 drivers/scsi/ufs/ufs_bsg.h |   1 +
 2 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 71826ba..d077e42 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -19,18 +19,129 @@ struct ufs_bsg {
.bsg_request = ufs_bsg_request,
 };
 
+static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr,
+  int *buff_len)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret = 0;
+
+   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC ||
+   desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id, buff_len);
+
+   if (ret || !buff_len)
+   return -EINVAL;
+
+   *buff_len = min_t(int, *buff_len, desc_size);
+
+   return ret;
+}
+
+static int ufs_bsg_verify_query_size(unsigned int request_len,
+unsigned int reply_len,
+int rw, int buff_len)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (rw == UFS_BSG_NOP)
+   goto null_buff;
+
+   if (rw == WRITE)
+   min_req_len += buff_len;
+
+null_buff:
+   if (min_req_len > request_len)
+   return -EINVAL;
+
+   if (min_rsp_len > reply_len)
+   return -EINVAL;
+
+   return 0;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   unsigned int request_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   struct utp_upiu_query *qr;
+   __be32 *req_upiu = NULL;
+   __be32 *rsp_upiu = NULL;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int buff_len = 0;
+   int rw = UFS_BSG_NOP;
+   int ret;
 
+   ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, buff_len);
+   if (ret) {
+   dev_err(job->dev, "not enough space assigned\n");
+   goto out;
+   }
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   qr = _request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(qr, _len))
+   goto null_desc_buff;
+
+   if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   rw = WRITE;
+   desc_buff = ((uint8_t *)bsg_request) +
+   sizeof(struct ufs_bsg_request);
+   }
+
+null_desc_buff:
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   /* Now that we know if its a read or write, verify again */
+   if (rw != UFS_BSG_NOP || buff_len) {
+   ret = ufs_bsg_verify_query_size(request_len, reply_len,
+   rw, buff_len);
+   if (ret) {
+   dev_err(job->dev,
+   "not enough space assigned\n");
+   goto out;
+   }
+   }
+
+   req_upiu = (__be32 *)_request->header;
+   rsp_upiu = (__be32 *)_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba,
+  req_upiu, rsp_upiu, msgcode,
+  desc_buff, _len, rw);
+
+   break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   /* later */
+   case UPIU_TRANSACTION_COMMAND:
+   case UPIU_TRANSACTION_DATA_OUT:
+not_supported:
+   /* for the time being, we do not support data transfer upi

[RFC 1/6] scsi: Add ufs transport class

2018-07-29 Thread Avri Altman
Scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

In addition to the basic SCSI core objects this transport class
introduces two additional (currently empty) class objects:
“ufs-host” and “ufs-port”.  There is only one “ufs-host” in the
system, but can be more-than-one “ufs-ports”.

Those classes are left empty for now, as ufs-sysfs already contains
an abundant amount of attributes.

A “ufs-port” is purely a software object. Evidently, the function
template takes no port as an argument, as the driver has no concept
of "port".  We only need it as a hanging point in the bsg device tree,
so maybe a more appropriate term would be: "ufs-bsg-dev-node".

The ufs-port has a pretty lean structure.  This is because we are
using upiu transactions that contains the outmost detailed info,
so we don't really need complex constructs to support it.

The transport will keep track of its  ufs-ports via its scsi host.

Signed-off-by: Avri Altman 
---
 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 337 ++
 include/scsi/scsi_transport_ufs.h |  40 +
 4 files changed, 391 insertions(+)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 include/scsi/scsi_transport_ufs.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8fc851a..9e99275 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -290,6 +290,19 @@ config SCSI_SAS_ATTRS
  If you wish to export transport-specific information about
  each attached SAS device to sysfs, say Y.
 
+config SCSI_UFS_ATTRS
+   tristate "UFS Transport Attributes"
+   depends on SCSI
+   select BLK_DEV_BSGLIB
+   help
+ Scsi transport is a framework that allow to send scsi commands to
+ a non-scsi devices. Still, it is flexible enough to allow sending
+ non-scsi commands as well. We will use this framework to manage
+ ufs devices by sending UPIU transactions.
+
+ If you wish to export transport-specific information about
+ each attached UFS device to sysfs, say Y.
+
 source "drivers/scsi/libsas/Kconfig"
 
 config SCSI_SRP_ATTRS
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index d1bad43..e0efc06 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS)+= 
scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)   += scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_LIBSAS)  += libsas/
 obj-$(CONFIG_SCSI_SRP_ATTRS)   += scsi_transport_srp.o
+obj-$(CONFIG_SCSI_UFS_ATTRS)   += scsi_transport_ufs.o
 obj-$(CONFIG_SCSI_DH)  += device_handler/
 
 obj-$(CONFIG_LIBFC)+= libfc/
diff --git a/drivers/scsi/scsi_transport_ufs.c 
b/drivers/scsi/scsi_transport_ufs.c
new file mode 100644
index 000..62aec49
--- /dev/null
+++ b/drivers/scsi/scsi_transport_ufs.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCSI UFS transport class
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define UFS_HOST_ATTRS 0
+#define UFS_PORT_ATTRS 0
+
+struct ufs_internal {
+   struct scsi_transport_template t;
+   struct ufs_function_template *f;
+
+   struct device_attribute *host_attrs[UFS_HOST_ATTRS + 1];
+   struct device_attribute *port_attrs[UFS_PORT_ATTRS + 1];
+   struct transport_container port_attr_cont;
+};
+#define to_ufs_internal(tmpl)  container_of(tmpl, struct ufs_internal, t)
+
+struct ufs_host_attrs {
+   atomic_t next_port_id;
+};
+#define to_ufs_host_attrs(x) ((struct ufs_host_attrs *)(x)->shost_data)
+
+static int ufs_bsg_dispatch(struct bsg_job *job)
+{
+   struct Scsi_Host *shost = dev_to_shost(job->dev);
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   /* check for payload_len when we'll support data transfer upiu */
+
+   return i->f->bsg_request(job);
+}
+
+static int ufs_bsg_initialize(struct Scsi_Host *shost, struct ufs_port *port)
+{
+   struct request_queue *q;
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   if (!i->f->bsg_request) {
+   pr_info("%s can't handle ufs requests\n", shost->hostt->name);
+   return 0;
+   }
+
+   q = bsg_setup_queue(>dev, dev_name(>dev),
+   ufs_bsg_dispatch, 0, NULL);
+   if (IS_ERR(q))
+   return PTR_ERR(q);
+   port->q = q;
+
+   return 0;
+}
+
+static int ufs_host_setup(struct transport_container *tc, struct device *dev,
+  

[RFC 2/6] scsi: ufs: Add ufs-bsg module

2018-07-29 Thread Avri Altman
A LLD companion for the ufs scsi transport.
For now, just provide an API to instantiate the ufs transport,
allocating and removing ufs-ports.

As we are attaching the transport template to the scsi host
that was already alocated for the ufs hba,
we'll need to pay extra attention on where to call the
provided API from ufshcd.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get  access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/Makefile|   1 +
 drivers/scsi/ufs/ufs_bsg.c   | 127 +++
 drivers/scsi/ufs/ufs_bsg.h   |  74 +++
 include/uapi/scsi/scsi_bsg_ufs.h |  56 +
 4 files changed, 258 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..5227bfb 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
+obj-$(CONFIG_SCSI_UFS_ATTRS) += ufs_bsg.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 000..71826ba
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SSCSI transport companion for UFS HBA
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg {
+   struct ufs_hba *hba;
+   struct ufs_port *port;
+};
+static struct ufs_bsg *bsg_host;
+
+static int ufs_bsg_request(struct bsg_job *job);
+
+static struct scsi_transport_template *ufs_transport_template;
+static struct ufs_function_template ufs_transport_functions = {
+   .bsg_request = ufs_bsg_request,
+};
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+   struct ufs_bsg_request *bsg_request = job->request;
+   struct ufs_bsg_reply *bsg_reply = job->reply;
+   int ret = -ENOTSUPP;
+
+   bsg_reply->reply_payload_rcv_len = 0;
+
+   /* Do Nothing for now */
+   dev_err(job->dev, "unsupported message_code 0x%x\n",
+   bsg_request->msgcode);
+
+   bsg_reply->result = ret;
+   if (ret)
+   job->reply_len = sizeof(uint32_t);
+   else
+   job->reply_len = sizeof(struct ufs_bsg_reply) +
+bsg_reply->reply_payload_rcv_len;
+
+   bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+   return ret;
+}
+
+/**
+ * ufs_bsg_attach_transport - instantiate UFS transport template
+ * @hba:   hba to attach the transport template to
+ *
+ * Call this before scsi_add_host() publishes it to the scsi midlayer
+ */
+void ufs_bsg_attach_transport(struct ufs_hba *hba)
+{
+   ufs_transport_template =
+   ufs_attach_transport(_transport_functions);
+   if (!ufs_transport_template)
+   return;
+
+   hba->host->transportt = ufs_transport_template;
+}
+
+/**
+ * ufs_bsg_remove - detach and remove the added ufs-ports
+ * @shost: scsi host that is parenting the ufs-ports
+ *
+ * Should be called when unloading the driver.
+ */
+void ufs_bsg_remove(struct Scsi_Host *shost)
+{
+   if (!bsg_host)
+   return;
+
+   ufs_remove_host(shost);
+
+   if (ufs_transport_template) {
+   ufs_release_transport(ufs_transport_template);
+   ufs_transport_template = NULL;
+   }
+
+   kfree(bsg_host);
+}
+
+/**
+ * ufs_bsg_probe - Add and report ufs device to ufs transport
+ * @hba: per adapter object
+ *
+ * Called during initial loading of the driver, and before scsi_scan_host.
+ * Should be called only if the attach phase was successful
+ */
+
+int ufs_bsg_probe(struct ufs_hba *hba)
+{
+   struct ufs_port *port;
+   int ret;
+
+   if (WARN_ON(!ufs_transport_template))
+   return -ENODEV;
+
+   bsg_host = kzalloc(sizeof(*bsg_host), GFP_KERNEL);
+   if (!bsg_host) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   port = ufs_port_alloc(hba->host);
+   if (!port) {
+   ret = -ENOMEM;
+

[RFC 0/6] scsi: scsi transport for ufs devices

2018-07-29 Thread Avri Altman
Here is a proposal to use the scsi transport subsystem to manage
ufs devices.

scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

We added a new scsi transport module, a ufs-bsg LLD companion, 
and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
We are planning to add this capability in the future.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

Avri Altman (6):
  scsi: Add ufs transport class
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Instantiate a ufs transport if its available
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 337 ++
 drivers/scsi/ufs/Makefile |   1 +
 drivers/scsi/ufs/ufs_bsg.c| 292 +
 drivers/scsi/ufs/ufs_bsg.h|  76 +
 drivers/scsi/ufs/ufshcd.c | 232 ++
 drivers/scsi/ufs/ufshcd.h |   4 +
 include/scsi/scsi_transport_ufs.h |  40 +
 include/uapi/scsi/scsi_bsg_ufs.h  |  56 +++
 10 files changed, 1052 insertions(+)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/scsi/scsi_transport_ufs.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



RE: [RFC 0/6] scsi: scsi transport for ufs devices

2018-08-01 Thread Avri Altman


> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org 
> On Behalf Of Douglas Gilbert
> Sent: Monday, July 30, 2018 9:53 PM
> To: Hannes Reinecke ; Bart Van Assche
> ; h...@lst.de; j...@linux.vnet.ibm.com; linux-
> s...@vger.kernel.org; jthumsh...@suse.de; martin.peter...@oracle.com;
> Avri Altman 
> Cc: Vinayak Holikatti ; Avi Shchislowski
> ; Alex Lemberg ;
> Stanislav Nijnikov ; subha...@codeaurora.org
> Subject: Re: [RFC 0/6] scsi: scsi transport for ufs devices
> 
> On 2018-07-30 02:13 PM, Hannes Reinecke wrote:
> > On 07/30/2018 08:01 PM, Bart Van Assche wrote:
> >> On Sun, 2018-07-29 at 16:33 +0300, Avri Altman wrote:
> >>> Here is a proposal to use the scsi transport subsystem to manage
> >>> ufs devices.
> >>>
> >>> scsi transport is a framework that allow to send scsi commands to
> >>> a non-scsi devices. Still, it is flexible enough to allow
> >>> sending non-scsi commands as well. We will use this framework to
> >>> manage ufs devices by sending UPIU transactions.
> >>>
> >>> We added a new scsi transport module, a ufs-bsg LLD companion,
> >>> and some new API to the ufs driver.
> >>
> >> My understanding is that all upstream code uses the bsg interface for
> *SCSI*
> >> commands. Sending UPIU commands over a bsg interface seems like
> abuse of that
> >> interface to me. Aren't you opening a can of worms with such an
> approach?
> >>
> > I beg to disagree.
> >
> > bsg was precisely designed to handle non-SCSI commands, as this was the
> main
> > limitation of the original 'sg' interface.
> > The original intention was to allow sending of transport frames for the
> various
> > SCSI transports (like FC or SAS), but there is no direct requirement for 
> > bsg to
> > be limited to SCSI.
> > Quite the contrary.
> 
> I designed 'struct sg_io_v4' found in include/uapi/linux/bsg.h to handle
> storage
> related protocols, not just the SCSI command set. After the guard, the next
> two fields in that structure are:
>  __u32 protocol; /* [i] 0 -> SCSI ,  */
>  __u32 subprotocol;  /* [i] 0 -> SCSI command, 1 -> SCSI task
> management function,  */
> 
> So there is lots of room for other protocols. Also the naming of fields is in
> terms of request, response, data-in and data-out rather than SCSI command
> specific terms (e.g. SCSI sense data maps to the response, while the SCSI
> status is returned via a layered error mechanism). It also handles bidi data
> transfers (which the sg_io_v3 interface does not).
> 
> 
> NVMe didn't exist when struct sg_io_v4 was designed. If it was then I would
> have made provisions for "metadata" transfers. One use for metadata
> transfer might be to send protection information separately (i.e. as
> metadata) rather than interleave with the user data as SCSI does. Is
> NVMe metadata much used? And the extreme case:
> bidi_data+bidi_metadata,
> any examples of that?
> 
> Doug Gilbert
OK then. Let's give it a try. Will re-send it as patchset.
Thanks,
Avri


[PATCH 1/6] scsi: Add ufs transport class

2018-08-01 Thread Avri Altman
Scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

In addition to the basic SCSI core objects this transport class
introduces two additional (currently empty) class objects:
“ufs-host” and “ufs-port”.  There is only one “ufs-host” in the
system, but can be more-than-one “ufs-ports”.

Those classes are left empty for now, as ufs-sysfs already contains
an abundant amount of attributes.

A “ufs-port” is purely a software object. Evidently, the function
template takes no port as an argument, as the driver has no concept
of "port".  We only need it as a hanging point in the bsg device tree,
so maybe a more appropriate term would be: "ufs-bsg-dev-node".

The ufs-port has a pretty lean structure.  This is because we are
using upiu transactions that contains the outmost detailed info,
so we don't really need complex constructs to support it.

The transport will keep track of its  ufs-ports via its scsi host.


Signed-off-by: Avri Altman 
---
 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 337 ++
 include/scsi/scsi_transport_ufs.h |  40 +
 4 files changed, 391 insertions(+)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 include/scsi/scsi_transport_ufs.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8fc851a..9e99275 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -290,6 +290,19 @@ config SCSI_SAS_ATTRS
  If you wish to export transport-specific information about
  each attached SAS device to sysfs, say Y.
 
+config SCSI_UFS_ATTRS
+   tristate "UFS Transport Attributes"
+   depends on SCSI
+   select BLK_DEV_BSGLIB
+   help
+ Scsi transport is a framework that allow to send scsi commands to
+ a non-scsi devices. Still, it is flexible enough to allow sending
+ non-scsi commands as well. We will use this framework to manage
+ ufs devices by sending UPIU transactions.
+
+ If you wish to export transport-specific information about
+ each attached UFS device to sysfs, say Y.
+
 source "drivers/scsi/libsas/Kconfig"
 
 config SCSI_SRP_ATTRS
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index d1bad43..e0efc06 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS)+= 
scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)   += scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_LIBSAS)  += libsas/
 obj-$(CONFIG_SCSI_SRP_ATTRS)   += scsi_transport_srp.o
+obj-$(CONFIG_SCSI_UFS_ATTRS)   += scsi_transport_ufs.o
 obj-$(CONFIG_SCSI_DH)  += device_handler/
 
 obj-$(CONFIG_LIBFC)+= libfc/
diff --git a/drivers/scsi/scsi_transport_ufs.c 
b/drivers/scsi/scsi_transport_ufs.c
new file mode 100644
index 000..62aec49
--- /dev/null
+++ b/drivers/scsi/scsi_transport_ufs.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCSI UFS transport class
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define UFS_HOST_ATTRS 0
+#define UFS_PORT_ATTRS 0
+
+struct ufs_internal {
+   struct scsi_transport_template t;
+   struct ufs_function_template *f;
+
+   struct device_attribute *host_attrs[UFS_HOST_ATTRS + 1];
+   struct device_attribute *port_attrs[UFS_PORT_ATTRS + 1];
+   struct transport_container port_attr_cont;
+};
+#define to_ufs_internal(tmpl)  container_of(tmpl, struct ufs_internal, t)
+
+struct ufs_host_attrs {
+   atomic_t next_port_id;
+};
+#define to_ufs_host_attrs(x) ((struct ufs_host_attrs *)(x)->shost_data)
+
+static int ufs_bsg_dispatch(struct bsg_job *job)
+{
+   struct Scsi_Host *shost = dev_to_shost(job->dev);
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   /* check for payload_len when we'll support data transfer upiu */
+
+   return i->f->bsg_request(job);
+}
+
+static int ufs_bsg_initialize(struct Scsi_Host *shost, struct ufs_port *port)
+{
+   struct request_queue *q;
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   if (!i->f->bsg_request) {
+   pr_info("%s can't handle ufs requests\n", shost->hostt->name);
+   return 0;
+   }
+
+   q = bsg_setup_queue(>dev, dev_name(>dev),
+   ufs_bsg_dispatch, 0, NULL);
+   if (IS_ERR(q))
+   return PTR_ERR(q);
+   port->q = q;
+
+   return 0;
+}
+
+static int ufs_host_setup(struct transport_container *tc, struct device *dev,
+  

[PATCH 0/6] scsi: scsi transport for ufs devices

2018-08-01 Thread Avri Altman
Here is a proposal to use the scsi transport subsystem to manage
ufs devices.

scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

We added a new scsi transport module, a ufs-bsg LLD companion, 
and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
We are planning to add this capability in the future.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

Avri Altman (6):
  scsi: Add ufs transport class
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Instantiate a ufs transport if its available
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 337 ++
 drivers/scsi/ufs/Makefile |   1 +
 drivers/scsi/ufs/ufs_bsg.c| 292 +
 drivers/scsi/ufs/ufs_bsg.h|  76 +
 drivers/scsi/ufs/ufshcd.c | 232 ++
 drivers/scsi/ufs/ufshcd.h |   4 +
 include/scsi/scsi_transport_ufs.h |  40 +
 include/uapi/scsi/scsi_bsg_ufs.h  |  56 +++
 10 files changed, 1052 insertions(+)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/scsi/scsi_transport_ufs.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



[PATCH 5/6] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-08-01 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 119 +++--
 drivers/scsi/ufs/ufs_bsg.h |   1 +
 2 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 71826ba..d077e42 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -19,18 +19,129 @@ struct ufs_bsg {
.bsg_request = ufs_bsg_request,
 };
 
+static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr,
+  int *buff_len)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret = 0;
+
+   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC ||
+   desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id, buff_len);
+
+   if (ret || !buff_len)
+   return -EINVAL;
+
+   *buff_len = min_t(int, *buff_len, desc_size);
+
+   return ret;
+}
+
+static int ufs_bsg_verify_query_size(unsigned int request_len,
+unsigned int reply_len,
+int rw, int buff_len)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (rw == UFS_BSG_NOP)
+   goto null_buff;
+
+   if (rw == WRITE)
+   min_req_len += buff_len;
+
+null_buff:
+   if (min_req_len > request_len)
+   return -EINVAL;
+
+   if (min_rsp_len > reply_len)
+   return -EINVAL;
+
+   return 0;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   unsigned int request_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   struct utp_upiu_query *qr;
+   __be32 *req_upiu = NULL;
+   __be32 *rsp_upiu = NULL;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int buff_len = 0;
+   int rw = UFS_BSG_NOP;
+   int ret;
 
+   ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, buff_len);
+   if (ret) {
+   dev_err(job->dev, "not enough space assigned\n");
+   goto out;
+   }
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   qr = _request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(qr, _len))
+   goto null_desc_buff;
+
+   if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   rw = WRITE;
+   desc_buff = ((uint8_t *)bsg_request) +
+   sizeof(struct ufs_bsg_request);
+   }
+
+null_desc_buff:
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   /* Now that we know if its a read or write, verify again */
+   if (rw != UFS_BSG_NOP || buff_len) {
+   ret = ufs_bsg_verify_query_size(request_len, reply_len,
+   rw, buff_len);
+   if (ret) {
+   dev_err(job->dev,
+   "not enough space assigned\n");
+   goto out;
+   }
+   }
+
+   req_upiu = (__be32 *)_request->header;
+   rsp_upiu = (__be32 *)_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba,
+  req_upiu, rsp_upiu, msgcode,
+  desc_buff, _len, rw);
+
+   break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   /* later */
+   case UPIU_TRANSACTION_COMMAND:
+   case UPIU_TRANSACTION_DATA_OUT:
+not_supported:
+   /* for the time being, we do not support data transfer upi

[PATCH 4/6] scsi: ufs: Add API to execute raw upiu commands

2018-08-01 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 225 ++
 drivers/scsi/ufs/ufshcd.h |   4 +
 2 files changed, 229 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c2ae406..5abf697 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -257,6 +257,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool 
on,
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp);
+
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
return tag >= 0 && tag < hba->nutrs;
@@ -3106,6 +3108,229 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
 EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
 
 /**
+ * ufshcd_issue_tm_upiu_cmd - API for sending "utmrd" requests
+ * @hba -  UFS hba
+ * @req_upiu - bsg request
+ * @rsp_upiu - bsg reply
+ *
+ * Those requests uses UTP Task Management Request Descriptor - utmrd.
+ * Therefore, it "rides" the task management infrastructure: uses its tag and
+ * tasks work queues.
+ */
+static int ufshcd_issue_tm_upiu_cmd(struct ufs_hba *hba,
+   __be32 *req_upiu,
+   __be32 *rsp_upiu)
+{
+   struct utp_task_req_desc *task_req_descp;
+   struct Scsi_Host *host = hba->host;
+   unsigned long flags;
+   int free_slot;
+   u8 tm_response = 0xF;
+   int err;
+   int task_tag;
+
+   wait_event(hba->tm_tag_wq, ufshcd_get_tm_free_slot(hba, _slot));
+   ufshcd_hold(hba, false);
+
+   spin_lock_irqsave(host->host_lock, flags);
+
+   task_req_descp = hba->utmrdl_base_addr;
+   task_req_descp += free_slot;
+
+   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
+   task_req_descp->header.dword_2 =
+   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+   task_tag = hba->nutrs + free_slot;
+
+   req_upiu[0] |= cpu_to_be32(task_tag);
+
+   /* just copy the upiu request as it is */
+   memcpy(task_req_descp->task_req_upiu, req_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
+
+   /* send command to the controller */
+   __set_bit(free_slot, >outstanding_tasks);
+
+   /* Make sure descriptors are ready before ringing the task doorbell */
+   wmb();
+
+   ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL);
+   /* Make sure that doorbell is committed immediately */
+   wmb();
+
+   spin_unlock_irqrestore(host->host_lock, flags);
+
+   /* wait until the task management command is completed */
+   err = wait_event_timeout(hba->tm_wq,
+   test_bit(free_slot, >tm_condition),
+   msecs_to_jiffies(TM_CMD_TIMEOUT));
+   if (!err) {
+   dev_err(hba->dev, "%s: bsg task management cmd timed-out\n",
+   __func__);
+   if (ufshcd_clear_tm_cmd(hba, free_slot))
+   dev_WARN(hba->dev,
+"%s: unable clear tm cmd (slot %d) timeout\n",
+ __func__, free_slot);
+   err = -ETIMEDOUT;
+   } else {
+   err = ufshcd_task_req_compl(hba, free_slot, _response);
+   }
+
+   /* just copy the upiu response as it is */
+   memcpy(rsp_upiu, task_req_descp->task_rsp_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
+
+   clear_bit(free_slot, >tm_condition);
+   ufshcd_put_tm_slot(hba, free_slot);
+   wake_up(>tm_tag_wq);
+
+   ufshcd_release(hba);
+   return err;
+}
+
+/**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request - 8 dwards
+ * @rsp_upiu:  upiu reply - 8 dwards
+ * @msgc

[PATCH 3/6] scsi: ufs: Instantiate a ufs transport if its available

2018-08-01 Thread Avri Altman
Call the Attach/Probe/Remove APIs.


Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3560185..c2ae406 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -46,6 +46,7 @@
 #include "ufs_quirks.h"
 #include "unipro.h"
 #include "ufs-sysfs.h"
+#include "ufs_bsg.h"
 
 #define CREATE_TRACE_POINTS
 #include 
@@ -6651,6 +6652,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
hba->clk_scaling.is_allowed = true;
}
 
+   if (hba->host->transportt)
+   ufs_bsg_probe(hba);
+
scsi_scan_host(hba->host);
pm_runtime_put_sync(hba->dev);
}
@@ -7874,6 +7878,7 @@ int ufshcd_shutdown(struct ufs_hba *hba)
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+   ufs_bsg_remove(hba->host);
ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
/* disable interrupts */
@@ -8067,6 +8072,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
hba->is_irq_enabled = true;
}
 
+   ufs_bsg_attach_transport(hba);
+
err = scsi_add_host(host, hba->dev);
if (err) {
dev_err(hba->dev, "scsi_add_host failed\n");
-- 
1.9.1



[PATCH 2/6] scsi: ufs: Add ufs-bsg module

2018-08-01 Thread Avri Altman
A LLD companion for the ufs scsi transport.
For now, just provide an API to instantiate the ufs transport,
allocating and removing ufs-ports.

As we are attaching the transport template to the scsi host
that was already alocated for the ufs hba,
we'll need to pay extra attention on where to call the
provided API from ufshcd.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get  access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.


Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/Makefile|   1 +
 drivers/scsi/ufs/ufs_bsg.c   | 127 +++
 drivers/scsi/ufs/ufs_bsg.h   |  74 +++
 include/uapi/scsi/scsi_bsg_ufs.h |  56 +
 4 files changed, 258 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..5227bfb 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
+obj-$(CONFIG_SCSI_UFS_ATTRS) += ufs_bsg.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 000..71826ba
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SSCSI transport companion for UFS HBA
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg {
+   struct ufs_hba *hba;
+   struct ufs_port *port;
+};
+static struct ufs_bsg *bsg_host;
+
+static int ufs_bsg_request(struct bsg_job *job);
+
+static struct scsi_transport_template *ufs_transport_template;
+static struct ufs_function_template ufs_transport_functions = {
+   .bsg_request = ufs_bsg_request,
+};
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+   struct ufs_bsg_request *bsg_request = job->request;
+   struct ufs_bsg_reply *bsg_reply = job->reply;
+   int ret = -ENOTSUPP;
+
+   bsg_reply->reply_payload_rcv_len = 0;
+
+   /* Do Nothing for now */
+   dev_err(job->dev, "unsupported message_code 0x%x\n",
+   bsg_request->msgcode);
+
+   bsg_reply->result = ret;
+   if (ret)
+   job->reply_len = sizeof(uint32_t);
+   else
+   job->reply_len = sizeof(struct ufs_bsg_reply) +
+bsg_reply->reply_payload_rcv_len;
+
+   bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+   return ret;
+}
+
+/**
+ * ufs_bsg_attach_transport - instantiate UFS transport template
+ * @hba:   hba to attach the transport template to
+ *
+ * Call this before scsi_add_host() publishes it to the scsi midlayer
+ */
+void ufs_bsg_attach_transport(struct ufs_hba *hba)
+{
+   ufs_transport_template =
+   ufs_attach_transport(_transport_functions);
+   if (!ufs_transport_template)
+   return;
+
+   hba->host->transportt = ufs_transport_template;
+}
+
+/**
+ * ufs_bsg_remove - detach and remove the added ufs-ports
+ * @shost: scsi host that is parenting the ufs-ports
+ *
+ * Should be called when unloading the driver.
+ */
+void ufs_bsg_remove(struct Scsi_Host *shost)
+{
+   if (!bsg_host)
+   return;
+
+   ufs_remove_host(shost);
+
+   if (ufs_transport_template) {
+   ufs_release_transport(ufs_transport_template);
+   ufs_transport_template = NULL;
+   }
+
+   kfree(bsg_host);
+}
+
+/**
+ * ufs_bsg_probe - Add and report ufs device to ufs transport
+ * @hba: per adapter object
+ *
+ * Called during initial loading of the driver, and before scsi_scan_host.
+ * Should be called only if the attach phase was successful
+ */
+
+int ufs_bsg_probe(struct ufs_hba *hba)
+{
+   struct ufs_port *port;
+   int ret;
+
+   if (WARN_ON(!ufs_transport_template))
+   return -ENODEV;
+
+   bsg_host = kzalloc(sizeof(*bsg_host), GFP_KERNEL);
+   if (!bsg_host) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   port = ufs_port_alloc(hba->host);
+   if (!port) {
+   ret = -ENOMEM;
+

[PATCH 6/6] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-08-01 Thread Avri Altman
Add support to those uic commands, that are currently supported
by ufshcd api: the variants of dme_{peer}_{set_get}.

At this point better not to add any new api, as careless
uic command may turn the device into a brick.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 56 +-
 drivers/scsi/ufs/ufs_bsg.h |  1 +
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index d077e42..441d096 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -63,6 +63,55 @@ static int ufs_bsg_verify_query_size(unsigned int 
request_len,
return 0;
 }
 
+static int ufs_bsg_exec_uic_cmd(struct uic_command *uc)
+{
+   u32 attr_sel = uc->argument1;
+   u8 attr_set = (uc->argument2 >> 16) & 0xff;
+   u32 mib_val = uc->argument3;
+   int cmd = uc->command;
+   int ret = 0;
+
+   switch (cmd) {
+   case UIC_CMD_DME_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_PEER_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_PEER);
+   break;
+   case UIC_CMD_DME_PEER_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_PEER);
+   break;
+   case UIC_CMD_DME_POWERON:
+   case UIC_CMD_DME_POWEROFF:
+   case UIC_CMD_DME_ENABLE:
+   case UIC_CMD_DME_RESET:
+   case UIC_CMD_DME_END_PT_RST:
+   case UIC_CMD_DME_LINK_STARTUP:
+   case UIC_CMD_DME_HIBER_ENTER:
+   case UIC_CMD_DME_HIBER_EXIT:
+   case UIC_CMD_DME_TEST_MODE:
+   ret = -ENOTSUPP;
+   pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   if (ret)
+   pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+   uc->argument3 = mib_val;
+
+   return ret;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
@@ -70,6 +119,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+   struct uic_command uc = {0};
__be32 *req_upiu = NULL;
__be32 *rsp_upiu = NULL;
int msgcode;
@@ -124,7 +174,11 @@ static int ufs_bsg_request(struct bsg_job *job)
 
break;
case UPIU_TRANSACTION_UIC_CMD:
-   /* later */
+   memcpy(, _request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd();
+   memcpy(_reply->tsf.uc, , UIC_CMD_SIZE);
+
+   break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
 not_supported:
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index 0fd2859..651ffb3 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -15,6 +15,7 @@
 
 #define UFS_BSG_NOP (-1)
 #define UPIU_TRANSACTION_UIC_CMD 0x1F
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 enum {
REQ_UPIU_SIZE_DWORDS= 8,
-- 
1.9.1



[PATCH v2 2/8] scsi: ufs: Add ufs-bsg module

2018-08-05 Thread Avri Altman
A LLD companion for the ufs scsi transport.
For now, just provide an API to instantiate the ufs transport,
allocating and removing ufs-ports.

As we are attaching the transport template to the scsi host
that was already alocated for the ufs hba,
we'll need to pay extra attention on where to call the
provided API from ufshcd.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get  access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/Makefile|   1 +
 drivers/scsi/ufs/ufs_bsg.c   | 127 +++
 drivers/scsi/ufs/ufs_bsg.h   |  72 ++
 include/uapi/scsi/scsi_bsg_ufs.h |  56 +
 4 files changed, 256 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..5227bfb 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
+obj-$(CONFIG_SCSI_UFS_ATTRS) += ufs_bsg.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 000..6f1941b
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCSI transport companion for UFS HBA
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg {
+   struct ufs_hba *hba;
+   struct ufs_port *port;
+};
+static struct ufs_bsg *bsg_host;
+
+static int ufs_bsg_request(struct bsg_job *job);
+
+static struct scsi_transport_template *ufs_transport_template;
+static struct ufs_function_template ufs_transport_functions = {
+   .bsg_request = ufs_bsg_request,
+};
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+   struct ufs_bsg_request *bsg_request = job->request;
+   struct ufs_bsg_reply *bsg_reply = job->reply;
+   int ret = -ENOTSUPP;
+
+   bsg_reply->reply_payload_rcv_len = 0;
+
+   /* Do Nothing for now */
+   dev_err(job->dev, "unsupported message_code 0x%x\n",
+   bsg_request->msgcode);
+
+   bsg_reply->result = ret;
+   if (ret)
+   job->reply_len = sizeof(uint32_t);
+   else
+   job->reply_len = sizeof(struct ufs_bsg_reply) +
+bsg_reply->reply_payload_rcv_len;
+
+   bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+   return ret;
+}
+
+/**
+ * ufs_bsg_attach_transport - instantiate UFS transport template
+ * @hba:   hba to attach the transport template to
+ *
+ * Call this before scsi_add_host() publishes it to the scsi midlayer
+ */
+void ufs_bsg_attach_transport(struct ufs_hba *hba)
+{
+   ufs_transport_template =
+   ufs_attach_transport(_transport_functions);
+   if (!ufs_transport_template)
+   return;
+
+   hba->host->transportt = ufs_transport_template;
+}
+
+/**
+ * ufs_bsg_remove - detach and remove the added ufs-ports
+ * @shost: scsi host that is parenting the ufs-ports
+ *
+ * Should be called when unloading the driver.
+ */
+void ufs_bsg_remove(struct Scsi_Host *shost)
+{
+   if (!bsg_host)
+   return;
+
+   ufs_remove_host(shost);
+
+   if (ufs_transport_template) {
+   ufs_release_transport(ufs_transport_template);
+   ufs_transport_template = NULL;
+   }
+
+   kfree(bsg_host);
+}
+
+/**
+ * ufs_bsg_probe - Add and report ufs device to ufs transport
+ * @hba: per adapter object
+ *
+ * Called during initial loading of the driver, and before scsi_scan_host.
+ * Should be called only if the attach phase was successful
+ */
+
+int ufs_bsg_probe(struct ufs_hba *hba)
+{
+   struct ufs_port *port;
+   int ret;
+
+   if (WARN_ON(!ufs_transport_template))
+   return -ENODEV;
+
+   bsg_host = kzalloc(sizeof(*bsg_host), GFP_KERNEL);
+   if (!bsg_host) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   port = ufs_port_alloc(hba->host);
+   if (!port) {
+   ret = -ENOMEM;
+

[PATCH v2 4/8] scsi: ufs: Add fill task management request

2018-08-05 Thread Avri Altman
Do that in preparation to re-use ufshcd_issue_tm_cmd code.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 50 +++
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c2ae406..4206bab 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5597,6 +5597,32 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
+static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
+  int lun_id, int task_id, u8 tm_function,
+  int task_tag)
+{
+   struct utp_upiu_task_req *task_req_upiup;
+
+   /* Configure task request descriptor */
+   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
+   task_req_descp->header.dword_2 =
+   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+   task_req_upiup =
+   (struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
+   task_req_upiup->header.dword_0 =
+   UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0, lun_id,
+ task_tag);
+   task_req_upiup->header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0,
+  0);
+   /*
+* The host shall provide the same value for LUN field in the basic
+* header and for Input Parameter.
+*/
+   task_req_upiup->input_param1 = cpu_to_be32(lun_id);
+   task_req_upiup->input_param2 = cpu_to_be32(task_id);
+}
+
 /**
  * ufshcd_issue_tm_cmd - issues task management commands to controller
  * @hba: per adapter instance
@@ -5611,7 +5637,6 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
u8 tm_function, u8 *tm_response)
 {
struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_req *task_req_upiup;
struct Scsi_Host *host;
unsigned long flags;
int free_slot;
@@ -5631,27 +5656,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
spin_lock_irqsave(host->host_lock, flags);
task_req_descp = hba->utmrdl_base_addr;
task_req_descp += free_slot;
-
-   /* Configure task request descriptor */
-   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   task_req_descp->header.dword_2 =
-   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
-   task_req_upiup =
-   (struct utp_upiu_task_req *) task_req_descp->task_req_upiu;
task_tag = hba->nutrs + free_slot;
-   task_req_upiup->header.dword_0 =
-   UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
- lun_id, task_tag);
-   task_req_upiup->header.dword_1 =
-   UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   task_req_upiup->input_param1 = cpu_to_be32(lun_id);
-   task_req_upiup->input_param2 = cpu_to_be32(task_id);
+
+   ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function,
+  task_tag);
 
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
-- 
1.9.1



[PATCH v2 0/8] scsi: scsi transport for ufs devices

2018-08-05 Thread Avri Altman
Here is a proposal to use the scsi transport subsystem to manage
ufs devices.

scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

We added a new scsi transport module, a ufs-bsg LLD companion, 
and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
We are planning to add this capability in the future.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed another patch for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.

Avri Altman (8):
  scsi: Add ufs transport class
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Instantiate a ufs transport if its available
  scsi: ufs: Add fill task management request
  scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 354 ++
 drivers/scsi/ufs/Makefile |   1 +
 drivers/scsi/ufs/ufs_bsg.c| 291 +++
 drivers/scsi/ufs/ufs_bsg.h|  75 
 drivers/scsi/ufs/ufshcd.c | 242 +++---
 drivers/scsi/ufs/ufshcd.h |   6 +
 include/scsi/scsi_transport_ufs.h |  44 +
 include/uapi/scsi/scsi_bsg_ufs.h  |  56 ++
 10 files changed, 1055 insertions(+), 28 deletions(-)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/scsi/scsi_transport_ufs.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



[PATCH v2 1/8] scsi: Add ufs transport class

2018-08-05 Thread Avri Altman
Scsi transport is a framework that allow to send scsi commands to
a non-scsi devices. Still, it is flexible enough to allow
sending non-scsi commands as well. We will use this framework to
manage ufs devices by sending UPIU transactions.

In addition to the basic SCSI core objects this transport class
introduces two additional (currently empty) class objects:
“ufs-host” and “ufs-port”.  There is only one “ufs-host” in the
system, but can be more-than-one “ufs-ports”.

Those classes are left empty for now, as ufs-sysfs already contains
an abundant amount of attributes.

A “ufs-port” is purely a software object. Evidently, the function
template takes no port as an argument, as the driver has no concept
of "port".  We only need it as a hanging point in the bsg device tree,
so maybe a more appropriate term would be: "ufs-bsg-dev-node".

The ufs-port has a pretty lean structure.  This is because we are
using upiu transactions that contains the outmost detailed info,
so we don't really need complex constructs to support it.

The transport will keep track of its  ufs-ports via its scsi host.

Signed-off-by: Avri Altman 
---
 drivers/scsi/Kconfig  |  13 ++
 drivers/scsi/Makefile |   1 +
 drivers/scsi/scsi_transport_ufs.c | 354 ++
 include/scsi/scsi_transport_ufs.h |  44 +
 4 files changed, 412 insertions(+)
 create mode 100644 drivers/scsi/scsi_transport_ufs.c
 create mode 100644 include/scsi/scsi_transport_ufs.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8fc851a..9e99275 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -290,6 +290,19 @@ config SCSI_SAS_ATTRS
  If you wish to export transport-specific information about
  each attached SAS device to sysfs, say Y.
 
+config SCSI_UFS_ATTRS
+   tristate "UFS Transport Attributes"
+   depends on SCSI
+   select BLK_DEV_BSGLIB
+   help
+ Scsi transport is a framework that allow to send scsi commands to
+ a non-scsi devices. Still, it is flexible enough to allow sending
+ non-scsi commands as well. We will use this framework to manage
+ ufs devices by sending UPIU transactions.
+
+ If you wish to export transport-specific information about
+ each attached UFS device to sysfs, say Y.
+
 source "drivers/scsi/libsas/Kconfig"
 
 config SCSI_SRP_ATTRS
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index d1bad43..e0efc06 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS)+= 
scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)   += scsi_transport_sas.o
 obj-$(CONFIG_SCSI_SAS_LIBSAS)  += libsas/
 obj-$(CONFIG_SCSI_SRP_ATTRS)   += scsi_transport_srp.o
+obj-$(CONFIG_SCSI_UFS_ATTRS)   += scsi_transport_ufs.o
 obj-$(CONFIG_SCSI_DH)  += device_handler/
 
 obj-$(CONFIG_LIBFC)+= libfc/
diff --git a/drivers/scsi/scsi_transport_ufs.c 
b/drivers/scsi/scsi_transport_ufs.c
new file mode 100644
index 000..06349c6
--- /dev/null
+++ b/drivers/scsi/scsi_transport_ufs.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SCSI UFS transport class
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+
+#define UFS_HOST_ATTRS 0
+#define UFS_PORT_ATTRS 0
+
+#define MAX_PORTS 256
+static DEFINE_IDA(ufs_ida);
+
+struct ufs_internal {
+   struct scsi_transport_template t;
+   struct ufs_function_template *f;
+
+   struct device_attribute *host_attrs[UFS_HOST_ATTRS + 1];
+   struct device_attribute *port_attrs[UFS_PORT_ATTRS + 1];
+   struct transport_container port_attr_cont;
+};
+
+static inline struct ufs_internal *
+to_ufs_internal(struct scsi_transport_template *tmpl)
+{
+   return container_of(tmpl, struct ufs_internal, t);
+}
+
+struct ufs_host_attrs {
+   atomic_t active_ports;
+};
+
+static inline struct ufs_host_attrs *
+to_ufs_host_attrs(struct Scsi_Host *shost)
+{
+   return (struct ufs_host_attrs *)shost->shost_data;
+}
+
+static int ufs_bsg_dispatch(struct bsg_job *job)
+{
+   struct Scsi_Host *shost = dev_to_shost(job->dev);
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   /* check for payload_len when we'll support data transfer upiu */
+
+   return i->f->bsg_request(job);
+}
+
+static int ufs_bsg_initialize(struct Scsi_Host *shost, struct ufs_port *port)
+{
+   struct request_queue *q;
+   struct ufs_internal *i = to_ufs_internal(shost->transportt);
+
+   if (!i->f->bsg_request) {
+   pr_info("%s can't handle ufs requests\n", shost->hostt->name);
+   return 0;
+   }
+
+   q = bsg_setup_queue(>dev, dev_name(>dev),
+   ufs_bsg_dispatch, 0);
+   if (IS_ERR(q))
+ 

[PATCH v2 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-08-05 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 118 +++--
 drivers/scsi/ufs/ufs_bsg.h |   1 +
 2 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 6f1941b..f4986f0 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -19,18 +19,128 @@ struct ufs_bsg {
.bsg_request = ufs_bsg_request,
 };
 
+static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr,
+  int *desc_len)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret = 0;
+
+   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC || desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id, desc_len);
+
+   if (ret || !(*desc_len))
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return ret;
+}
+
+static int ufs_bsg_verify_query_size(unsigned int request_len,
+unsigned int reply_len,
+int rw, int desc_len)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (rw == WRITE)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len)
+   return -EINVAL;
+
+   if (min_rsp_len > reply_len)
+   return -EINVAL;
+
+   return 0;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   unsigned int request_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   struct utp_upiu_query *qr;
+   struct utp_upiu_req *req_upiu = NULL;
+   struct utp_upiu_req *rsp_upiu = NULL;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   int rw = UFS_BSG_NOP;
+   int ret;
 
+   ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, desc_len);
+   if (ret) {
+   dev_err(job->dev, "not enough space assigned\n");
+   goto out;
+   }
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   qr = _request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(qr, _len))
+   goto null_desc_buff;
+
+   if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   rw = WRITE;
+   desc_buff = ((uint8_t *)bsg_request) +
+   sizeof(struct ufs_bsg_request);
+   }
+
+null_desc_buff:
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   /* Now that we know if its a read or write, verify again */
+   if (rw != UFS_BSG_NOP || desc_len) {
+   ret = ufs_bsg_verify_query_size(request_len, reply_len,
+   rw, desc_len);
+   if (ret) {
+   dev_err(job->dev,
+   "not enough space assigned\n");
+   goto out;
+   }
+   }
+
+   req_upiu = (struct utp_upiu_req *)_request->header;
+   rsp_upiu = (struct utp_upiu_req *)_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba,
+  req_upiu, rsp_upiu, msgcode,
+  desc_buff, _len, rw);
+
+   break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   /* later */
+   case UPIU_TRANSACTION_COMMAND:
+   case UPIU_TRANSACTION_DATA_OUT:
+not_supported:
+   /* for the time being, we do not support data transfer upiu */
+   ret = -ENOTSUPP

[PATCH v2 8/8] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-08-05 Thread Avri Altman
Add support to those uic commands, that are currently supported
by ufshcd api: the variants of dme_{peer}_{set_get}.

At this point better not to add any new api, as careless
uic command may turn the device into a brick.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 56 +-
 drivers/scsi/ufs/ufs_bsg.h |  2 ++
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index f4986f0..b2e48ad 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -58,6 +58,55 @@ static int ufs_bsg_verify_query_size(unsigned int 
request_len,
return 0;
 }
 
+static int ufs_bsg_exec_uic_cmd(struct uic_command *uc)
+{
+   u32 attr_sel = uc->argument1;
+   u8 attr_set = (uc->argument2 >> 16) & 0xff;
+   u32 mib_val = uc->argument3;
+   int cmd = uc->command;
+   int ret = 0;
+
+   switch (cmd) {
+   case UIC_CMD_DME_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_PEER_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_PEER);
+   break;
+   case UIC_CMD_DME_PEER_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_PEER);
+   break;
+   case UIC_CMD_DME_POWERON:
+   case UIC_CMD_DME_POWEROFF:
+   case UIC_CMD_DME_ENABLE:
+   case UIC_CMD_DME_RESET:
+   case UIC_CMD_DME_END_PT_RST:
+   case UIC_CMD_DME_LINK_STARTUP:
+   case UIC_CMD_DME_HIBER_ENTER:
+   case UIC_CMD_DME_HIBER_EXIT:
+   case UIC_CMD_DME_TEST_MODE:
+   ret = -ENOTSUPP;
+   pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   if (ret)
+   pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+   uc->argument3 = mib_val;
+
+   return ret;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
@@ -65,6 +114,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+   struct uic_command uc = {};
struct utp_upiu_req *req_upiu = NULL;
struct utp_upiu_req *rsp_upiu = NULL;
int msgcode;
@@ -119,7 +169,11 @@ static int ufs_bsg_request(struct bsg_job *job)
 
break;
case UPIU_TRANSACTION_UIC_CMD:
-   /* later */
+   memcpy(, _request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd();
+   memcpy(_reply->tsf.uc, , UIC_CMD_SIZE);
+
+   break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
 not_supported:
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index 876de9f..b9c8dc5 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -15,6 +15,8 @@
 
 #define UFS_BSG_NOP (-1)
 #define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 enum {
REQ_UPIU_SIZE_DWORDS= 8,
-- 
1.9.1



[PATCH v2 5/8] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius

2018-08-05 Thread Avri Altman
Do that in order to re-use its code if the task request and response
UPIUs are given externally.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 4206bab..2df87e0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5598,6 +5598,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
 }
 
 static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
+  struct utp_upiu_task_req *raw_task_req_upiup,
   int lun_id, int task_id, u8 tm_function,
   int task_tag)
 {
@@ -5608,6 +5609,13 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc 
*task_req_descp,
task_req_descp->header.dword_2 =
cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
 
+   if (raw_task_req_upiup) {
+   raw_task_req_upiup->header.dword_0 |= cpu_to_be32(task_tag);
+   memcpy(task_req_descp->task_req_upiu, raw_task_req_upiup,
+  GENERAL_UPIU_REQUEST_SIZE);
+   return;
+   }
+
task_req_upiup =
(struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
task_req_upiup->header.dword_0 =
@@ -5633,8 +5641,11 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc 
*task_req_descp,
  *
  * Returns non-zero value on error, zero on success.
  */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+  struct utp_upiu_task_req *raw_task_req_upiup,
+  struct utp_upiu_task_req *raw_task_rsp_upiup,
+  int lun_id, int task_id, u8 tm_function,
+  u8 *tm_response)
 {
struct utp_task_req_desc *task_req_descp;
struct Scsi_Host *host;
@@ -5658,8 +5669,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
task_req_descp += free_slot;
task_tag = hba->nutrs + free_slot;
 
-   ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function,
-  task_tag);
+   ufshcd_fill_tm_req(task_req_descp, raw_task_req_upiup, lun_id, task_id,
+  tm_function, task_tag);
 
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
@@ -5691,6 +5702,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
err = -ETIMEDOUT;
} else {
err = ufshcd_task_req_compl(hba, free_slot, tm_response);
+   if (raw_task_rsp_upiup)
+   memcpy(raw_task_rsp_upiup,
+  task_req_descp->task_rsp_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete");
}
 
@@ -5725,7 +5740,8 @@ static int ufshcd_eh_device_reset_handler(struct 
scsi_cmnd *cmd)
tag = cmd->request->tag;
 
lrbp = >lrb[tag];
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err)
err = resp;
@@ -5855,8 +5871,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
}
 
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_QUERY_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ );
if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
/* cmd pending in the device */
dev_err(hba->dev, "%s: cmd pending in the device. tag = 
%d\n",
@@ -5894,8 +5911,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto out;
}
 
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_ABORT_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err) {
err = resp; /* service response error */
-- 
1.9.1



[PATCH v2 3/8] scsi: ufs: Instantiate a ufs transport if its available

2018-08-05 Thread Avri Altman
Call the Attach/Probe/Remove APIs.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3560185..c2ae406 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -46,6 +46,7 @@
 #include "ufs_quirks.h"
 #include "unipro.h"
 #include "ufs-sysfs.h"
+#include "ufs_bsg.h"
 
 #define CREATE_TRACE_POINTS
 #include 
@@ -6651,6 +6652,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
hba->clk_scaling.is_allowed = true;
}
 
+   if (hba->host->transportt)
+   ufs_bsg_probe(hba);
+
scsi_scan_host(hba->host);
pm_runtime_put_sync(hba->dev);
}
@@ -7874,6 +7878,7 @@ int ufshcd_shutdown(struct ufs_hba *hba)
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+   ufs_bsg_remove(hba->host);
ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
/* disable interrupts */
@@ -8067,6 +8072,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
hba->is_irq_enabled = true;
}
 
+   ufs_bsg_attach_transport(hba);
+
err = scsi_add_host(host, hba->dev);
if (err) {
dev_err(hba->dev, "scsi_add_host failed\n");
-- 
1.9.1



[PATCH v2 6/8] scsi: ufs: Add API to execute raw upiu commands

2018-08-05 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 154 ++
 drivers/scsi/ufs/ufshcd.h |   6 ++
 2 files changed, 160 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2df87e0..24f8a03 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -257,6 +257,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool 
on,
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp);
+
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
return tag >= 0 && tag < hba->nutrs;
@@ -5718,6 +5720,158 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @rw:either READ or WRITE
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type, int rw)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+   u8 *descp;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->command_type = (hba->ufs_version == UFSHCI_VERSION_10 ||
+ hba->ufs_version == UFSHCI_VERSION_11) ?
+ UTP_CMD_TYPE_DEV_MANAGE :
+ UTP_CMD_TYPE_UFS_STORAGE;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, GENERAL_UPIU_REQUEST_SIZE);
+
+   if (desc_buff && rw == WRITE) {
+   descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
+   memcpy(descp, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   /*
+* ignore the returning value here - ufshcd_check_query_response is
+* bound to fail since dev_cmd.query and dev_cmd.type were left empty.
+* read the response directly ignoring all errors.
+*/
+   ufshcd_wait_for_dev_cmd(hba, lrbp, QUERY_REQ_TIMEOUT);
+
+   /* just copy the upiu requ

RE: [PATCH 5/6] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-08-02 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 01, 2018 6:36 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH 5/6] scsi: ufs-bsg: Add support for raw upiu in
> ufs_bsg_request()
> 
> On Wed, 2018-08-01 at 11:04 +0300, Avri Altman wrote:
> > +   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC ||
> > +   desc_size <= 0)
> > +   return -EINVAL;
> 
> Please use the full line length and don't split lines if that is not 
> necessary.
Done.

> 
> > +   ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id,
> buff_len);
> > +
> > +   if (ret || !buff_len)
> > +   return -EINVAL;
> 
> Why is buff_len only tested after it has been passed as an argument to
> ufshcd_map_desc_id_to_length()? That seems weird to me.
buff_len here is an int * and I'm using it to verify that enough space was 
allocated 
in the case it is a "write descriptor" upiu.
So I need to fix 2 things:
1) should be if (ret || !(*buff_len)) and not if (ret || !buff_len)
2) don't utilize the buff_len variable for that, which is using to obtain 
The reply_payload_rcv_len eventually.  Use a separate desc_len variable.

> 
> > +static int ufs_bsg_verify_query_size(unsigned int request_len,
> > +unsigned int reply_len,
> > +int rw, int buff_len)
> > +{
> > +   int min_req_len = sizeof(struct ufs_bsg_request);
> > +   int min_rsp_len = sizeof(struct ufs_bsg_reply);
> > +
> > +   if (rw == UFS_BSG_NOP)
> > +   goto null_buff;
> > +
> > +   if (rw == WRITE)
> > +   min_req_len += buff_len;
> 
> Can the "goto" statement be avoided by using a switch/case on 'rw'?
Yes.  Actually if (rw == UFS_BSG_NOP) is not needed at all.


> 
> Thanks,
> 
> Bart.



RE: [PATCH 2/6] scsi: ufs: Add ufs-bsg module

2018-08-02 Thread Avri Altman
Bart,
Thanks a lot,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 01, 2018 6:13 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH 2/6] scsi: ufs: Add ufs-bsg module
> 
> On Wed, 2018-08-01 at 11:04 +0300, Avri Altman wrote:
> > +++ b/drivers/scsi/ufs/ufs_bsg.c
> > @@ -0,0 +1,127 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * SSCSI transport companion for UFS HBA
> 
> What is "SSCSI"?
Done

> 
> > diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
> > new file mode 100644
> 
> [ ... ]
> 
> > +struct ufs_bsg_request {
> > +   uint32_t msgcode;
> > +   struct utp_upiu_header header;
> > +   union {
> > +   struct utp_upiu_query   qr;
> > +   struct utp_upiu_task_reqtr;
> > +   /* use utp_upiu_query to host the 4 dwards of uic command
> */
> 
> What are "dwards"?
Done.

> 
> > +   struct utp_upiu_query   uc;
> > +   } tsf;
> > +   uint8_t data[0];
> 
> The offset of the data member will change if a member will be added to the
> union with a larger size than the existing members. That seems like an API
> design bug to me.
Actually I am not using it, so will just remove it.

> 
> > +} __packed;
> 
> Would the data member offsets be the same without "__packed"? If so,
> __packed
> should be left out because it results in generation of suboptimal code on
> architectures that do not support unaligned multi-byte reads (e.g. IA-64).
Done

> 
> > +struct ufs_bsg_reply {
> > +   /*
> > +* The completion result. Result exists in two forms:
> > +* if negative, it is an -Exxx system errno value. There will
> > +* be no further reply information supplied.
> > +* else, it's the 4-byte scsi error result, with driver, host,
> > +* msg and status fields. The per-msgcode reply structure
> > +* will contain valid data.
> > +*/
> > +   uint32_t result;
> > +
> > +   /* If there was reply_payload, how much was recevied ? */
> 
> Did you perhaps mean "received"?
Done.

> 
> > +   uint32_t reply_payload_rcv_len;
> > +
> > +   struct utp_upiu_header header;
> > +   union {
> > +   struct utp_upiu_query   qr;
> > +   struct utp_upiu_task_rsptr;
> > +   struct utp_upiu_query   uc;
> > +   } tsf;
> > +   uint8_t data[0];
> > +};
> > +
> > +struct ufs_bsg_raw_upiu {
> > +   struct ufs_bsg_upiu request;
> > +   struct ufs_bsg_upiu reply;
> > +};
> 
> Are any of the above data structures needed by user space software? Should
> these
> data structure definitions perhaps be moved to a header file under
> include/uapi?
I wanted to benefit from ufs.h and ufshcd.h so used it here.
In include/uapi/scsi/scsi_bsg_ufs.h I defined an 8 dw*o*rds opaque structs for 
the request and reply.
 
> 
> Thanks,
> 
> Bart.



RE: [PATCH 4/6] scsi: ufs: Add API to execute raw upiu commands

2018-08-02 Thread Avri Altman
Bart, thanks.

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 01, 2018 6:28 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH 4/6] scsi: ufs: Add API to execute raw upiu commands
> 
> On Wed, 2018-08-01 at 11:04 +0300, Avri Altman wrote:
> > +   wait_event(hba->tm_tag_wq, ufshcd_get_tm_free_slot(hba,
> _slot));
> 
> The above is the weirdest API I have seen so far for tag allocation.
> Why does ufshcd_get_tm_free_slot() does a linear search through a bitmap
> instead of using the sbitmap data structure?
See my answer below.

> 
> > +   ufshcd_writel(hba, 1 << free_slot,
> REG_UTP_TASK_REQ_DOOR_BELL);
> > +   /* Make sure that doorbell is committed immediately */
> > +   wmb();
> 
> This is the first time that I see someone claiming that issuing a write memory
> barrier causes the write to be executed faster than without memory barrier.
> Are you sure that comment is correct and that that wmb() is necessary?
See my answer below


> 
> > +   spin_unlock_irqrestore(host->host_lock, flags);
> > +
> > +   /* wait until the task management command is completed */
> > +   err = wait_event_timeout(hba->tm_wq,
> > +   test_bit(free_slot, >tm_condition),
> > +   msecs_to_jiffies(TM_CMD_TIMEOUT));
> 
> Did you perhaps start implementing the ufshcd_issue_tm_upiu_cmd()
> function by
> copy/pasting ufshcd_issue_tm_cmd()? Please don't do that and instead avoid
> code
> duplication by moving shared code in a new function.
Yes I did.
I wanted to avoid changing any of the driver's core functionality, just adding 
the new one.
And yes,  this weird tagging mechanism and strange comments are just part of 
ufshcd_issue_tm_cmd().
I will try to do what you said.  Thanks.


> 
> > +   /* ignore the returning value here - ufshcd_check_query_response is
> > +* bound to fail since dev_cmd.query and dev_cmd.type were left
> empty.
> > +* read the response directly ignoring all errors.
> > +*/
> 
> Have you verified this patch with checkpatch? This is not the proper kernel
> comment style.
Yes I did.  
Anyway, as this patch is changing significantly, will run it again.

> 
> Thanks,
> 
> Bart.



RE: [PATCH 4/6] scsi: ufs: Add API to execute raw upiu commands

2018-08-02 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 01, 2018 6:36 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH 4/6] scsi: ufs: Add API to execute raw upiu commands
> 
> On Wed, 2018-08-01 at 11:04 +0300, Avri Altman wrote:
> > +/**
> > + * ufshcd_exec_raw_upiu_cmd - API function for sending raw upiu
> commands
> > + * @hba:   per-adapter instance
> > + * @req_upiu:  upiu request - 8 dwards
> > + * @rsp_upiu:  upiu reply - 8 dwards
> > + * @msgcode:   message code, one of UPIU Transaction Codes
> Initiator to Target
> > + * @desc_buff: pointer to descriptor buffer, NULL if NA
> > + * @buff_len:  descriptor size, 0 if NA
> > + * @rw:either READ or WRITE
> > + *
> > + * Supports UTP Transfer requests (nop and query), and UTP Task
> > + * Management requests.
> > + * It is up to the caller to fill the upiu conent properly, as it will
> > + * be copied without any further input validations.
> > + */
> > +int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
> > +__be32 *req_upiu, __be32 *rsp_upiu,
> > +int msgcode,
> > +u8 *desc_buff, int *buff_len, int rw)
> > +{
> 
> Again, what are "dwards"?
> 
> Documenting the size of a data structure in a function header is very weird.
> Please change the data type of req_upiu and rsp_upio into a pointer to a
> structure of the proper size.
Ok.

> 
> Thanks,
> 
> Bart.
> 



RE: [PATCH v2 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-08-09 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 08, 2018 7:40 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 7/8] scsi: ufs-bsg: Add support for raw upiu in
> ufs_bsg_request()
> 
> On Sun, 2018-08-05 at 14:39 +0300, Avri Altman wrote:
> > +   if (ret || !(*desc_len))
> > +   return -EINVAL;
> 
> No parentheses around *desc_len please.
Done.

> 
> Thanks,
> 
> Bart.



RE: [PATCH v2 2/8] scsi: ufs: Add ufs-bsg module

2018-08-09 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 08, 2018 7:27 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 2/8] scsi: ufs: Add ufs-bsg module
> 
> On Sun, 2018-08-05 at 14:39 +0300, Avri Altman wrote:
> > A LLD companion for the ufs scsi transport.
> 
> This description is misleading. How about changing this into "Add a bsg
> endpoint that supports UPIUs"?
Done.

> 
> diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
> > new file mode 100644
> > index 000..6f1941b
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs_bsg.c
> > @@ -0,0 +1,127 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * SCSI transport companion for UFS HBA
> 
> This description is misleading too. Please consider to change this into
> something like "bsg endpoint that supports UPIUs".
Done.

> 
> Thanks,
> 
> Bart.



RE: [PATCH v2 6/8] scsi: ufs: Add API to execute raw upiu commands

2018-08-09 Thread Avri Altman
Thanks,
Avri

> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 08, 2018 7:39 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 6/8] scsi: ufs: Add API to execute raw upiu commands
> 
> On Sun, 2018-08-05 at 14:39 +0300, Avri Altman wrote:
> > +   lrbp->command_type = (hba->ufs_version == UFSHCI_VERSION_10
> ||
> > + hba->ufs_version == UFSHCI_VERSION_11) ?
> > + UTP_CMD_TYPE_DEV_MANAGE :
> > + UTP_CMD_TYPE_UFS_STORAGE;
> 
> Parentheses are not needed around the logical or expression because logical
> or has a higher precedence than ?: so please leave the parentheses out.
Done.


> 
> Thanks,
> 
> Bart.



RE: [PATCH v2 1/8] scsi: Add ufs transport class

2018-08-09 Thread Avri Altman



> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 08, 2018 7:21 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 1/8] scsi: Add ufs transport class
> 
> On Sun, 2018-08-05 at 14:39 +0300, Avri Altman wrote:
> > +config SCSI_UFS_ATTRS
> > +   tristate "UFS Transport Attributes"
> > +   depends on SCSI
> > +   select BLK_DEV_BSGLIB
> > +   help
> > + Scsi transport is a framework that allow to send scsi commands to
> > + a non-scsi devices. Still, it is flexible enough to allow sending
> > + non-scsi commands as well. We will use this framework to manage
> > + ufs devices by sending UPIU transactions.
> > +
> > + If you wish to export transport-specific information about
> > + each attached UFS device to sysfs, say Y.
> > +
> 
> The above text is misleading because it suggests that the primary purpose of
> SCSI transport drivers is to send SCSI commands to non-SCSI devices. That is
> not correct. Please improve that text, e.g. by changing it into something
> like the following:
> 
> "Universal Flash Storage (UFS) is SCSI transport specification for accessing
> flash
> storage on digital cameras, mobile phones and consumer electronic devices.
> An UFS
> controller communicates with an UFS device by exchanging UFS Protocol
> Information
> Units (UPIUs). UPIUs can not only be used as a transport layer for the SCSI
> protocol
> but are also used by the UFS native command set. This transport driver
> supports
> exchanging UFS protocol information units with an UFS device. See also the
> ufshcd
> driver, which is a SCSI driver that supports UFS devices.
> 
> If you wish to exchange UPIU packets that are not SCSI packets with UFS
> devices,
> say Y."
Done.

> 
> Thanks,
> 
> Bart.



RE: [PATCH v2 0/8] scsi: scsi transport for ufs devices

2018-08-07 Thread Avri Altman



> On Sun, Aug 05, 2018 at 02:39:48PM +0300, Avri Altman wrote:
> > Here is a proposal to use the scsi transport subsystem to manage
> > ufs devices.
> 
> This should superceed previous patches to provide provisioning
> support through sysfs or configfs, right?
Yes.

Thanks,
Avri


RE: [PATCH v2 1/8] scsi: Add ufs transport class

2018-08-09 Thread Avri Altman



> -Original Message-
> From: Bart Van Assche
> Sent: Wednesday, August 08, 2018 7:58 PM
> To: h...@lst.de; Avri Altman ; linux-scsi@vger.kernel.org;
> jthumsh...@suse.de; h...@suse.com; martin.peter...@oracle.com;
> j...@linux.vnet.ibm.com
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ; Stanislav Nijnikov ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 1/8] scsi: Add ufs transport class
> 
> On Sun, 2018-08-05 at 14:39 +0300, Avri Altman wrote:
> > A “ufs-port” is purely a software object. Evidently, the function
> > template takes no port as an argument, as the driver has no concept
> > of "port".  We only need it as a hanging point in the bsg device tree,
> > so maybe a more appropriate term would be: "ufs-bsg-dev-node".
> >
> > The ufs-port has a pretty lean structure.  This is because we are
> > using upiu transactions that contains the outmost detailed info,
> > so we don't really need complex constructs to support it.
> >
> > The transport will keep track of its  ufs-ports via its scsi host.
> 
> Since no port concept has been defined in the UFS standard, can the port
> concept be left out? Have you considered to attach the bsg queue directly
> to the UFS SCSI host? There are two struct device instances in each Scsi_Host
> structure, namely shost_gendev and shost_dev. I think the former
> corresponds
> to /sys/bus/scsi/devices/host and the latter corresponds to
> /sys/class/scsi_host/host. The bsg queue probably can be attached to the
> latter. Several SCSI drivers already add additional sysfs attributes to the
> /sys/class/scsi_host/host.
Yeah - so today we are using shost_gendev, and the newly created classes points 
to /sys/devices/... :

htc_ocnwhl:/sys/class/ufs_host # ls -la
lrwxrwxrwx  1 root root 0 2018-06-17 13:15 host0 -> 
../../devices/soc/1da4000.ufshc/host0/ufs_host/host0

htc_ocnwhl:/sys/class/ufs_ports # ls -la
lrwxrwxrwx  1 root root 0 2018-06-17 13:05 ufs-port-0:1 -> 
../../devices/soc/1da4000.ufshc/host0/ufs-port-0:1/ufs_ports/ufs-port-0:0

and under /dev/ we get:
htc_ocnwhl:/dev # ls -la | grep ufs
crw---  1 root  root 246,   3 1970-02-26 03:12 ufs-port-0:0

We didn't add any sysfs attribute to those classes, and I don't expect any to 
be added,
as I tried to explain in the commit:
"Those classes are left empty for now, as ufs-sysfs already contains
an abundant amount of attributes."

Practically, this infrastructure provides the bsg device files /dev/.

Anyway, if you think it's better, I will try to switch it as you suggested.
Can you please refer me to those scsi drivers that you mentioned?

Thanks a lot,
Avri

> 
> Thanks,
> 
> Bart.


RE: [PATCH v2 1/8] scsi: Add ufs transport class

2018-08-20 Thread Avri Altman
Hi Bart,

> -Original Message-
> From: Bart Van Assche
> Sent: Tuesday, August 21, 2018 4:54 AM
> To: jthumsh...@suse.de; h...@lst.de; Avri Altman ;
> martin.peter...@oracle.com; linux-scsi@vger.kernel.org; h...@suse.com;
> j...@linux.vnet.ibm.com; Stanislav Nijnikov
> Cc: Vinayak Holikatti ; Avi Shchislowski ; Alex Lemberg ;
> subha...@codeaurora.org
> Subject: Re: [PATCH v2 1/8] scsi: Add ufs transport class
> 
> On Tue, 2018-08-14 at 11:42 +, Stanislav Nijnikov wrote:
> > From: Bart Van Assche
> > > Are you perhaps referring to the transport_class_register() calls in SCSI
> > > transport drivers? From what I see in existing SCSI transport drivers the
> > > transport_class_register() function is used to register link, port, host,
> > > vport, rport and other objects. I don't think that a SCSI transport driver
> > > is required to register host and port objects.
> > >
> > > Maybe we should take a step back and discuss first why the new bsg
> queues
> > > are registered by a transport driver? Since in case of UFS as far as I can
> > > see there is no real need to introduce a transport driver other than for
> > > creating the bsg device nodes, have you considered to add the code for
> > > creating bsg device nodes to the UFS driver instead of in a UFS transport
> > > driver? I think transport drivers were introduced as a way to share code
> > > between multiple SCSI LLDs that use the same transport mechanism. In
> the
> > > case of UFS there is only one SCSI LLD. Hence I'm wondering whether we
> > > really need an UFS transport driver.
> >
> > At the moment, the SCSI transport related code could be found at
> driver/scsi/scsi_transport_* files.
> > What is a point of hiding the UFS transport code inside the UFS driver?
> 
> Have you tried to implement the approach I proposed? If so, did you
> encounter
> any issues that made it impossible to implement that approach? If you have
> not yet tried to implement the above proposal, what are you waiting for?
Your proposal makes a perfect sense, and it is certainly a feasible path.
I also accept your point and withdraw from my intension to create multiple bsg 
dev nodes.

It is just that I couldn't find any other lld that creates its own bsg queue - 
Currently this is only done within scsi transport and scsi sysfs.
So before sending a new RFC, I was hoping to get additional support for your 
proposal.
Will send it in the coming days.

Thanks a lot,
Avri


RE: [PATCH v3 3/7] scsi: ufs: Add fill task management request

2018-09-05 Thread Avri Altman


> On Wed, Sep 05, 2018 at 07:30:03AM +0000, Avri Altman wrote:
> > Looking into the UFSHCI spec (JESD223C March 2016) paragraph 6.2,
> > It doesn't specify any inner structure of the task management
> > request or response, just a bunch of 8 DW each.
> > I guess this is why it is defined as a __le32 array.
> >
> > So the host controller is not aware of the inner structure of this
> > Sequence, and probably shouldn't. Making it aware of that,
> > e.g. by moving utp_upiu_task_req and utp_upiu_task_rsp
> > from ufs.h to ufshci.h will break this abstraction.
> 
> Well, then just kill struct utp_upiu_task_req entirely and use
> the dwords form the spec.
But on the other hand, task management request and response UPIUs
are honorable members of the ufs spec (JEDEC 220C paragraphs 10.7.6 & 10.7.7).
and indeed they lives in ufs.h, where they should.
So just removing it, replacing it with an opaque array is pointless.

Trying to understand why this is happening for task management requests,
But not for device management requests, I came to realized that you were 
originally right
Saying: " I think someone needs to untangle how the data structures are used in 
this part of the code."

Unlike utrd-typed requests (scsi & device management), that have their memory 
space
properly configured (utrdl_base_addr in ufshcd_host_memory_configure()),
task management requests - utmrd-typed requests (utmrdl_base_addr) do not get 
similar attention.

Will fix that in a separate patch prior to this one.

Thanks,
Avri


RE: [PATCH v3 2/7] scsi: ufs: Instantiate a ufs bsg if its available

2018-09-05 Thread Avri Altman


> -Original Message-
> From: Christoph Hellwig 
> Sent: Tuesday, September 04, 2018 10:16 PM
> To: Avri Altman 
> Cc: Christoph Hellwig ; Johannes Thumshirn
> ; Hannes Reinecke ; Bart Van Assche
> ; James E.J. Bottomley
> ; Martin K. Petersen
> ; linux-scsi@vger.kernel.org; Stanislav Nijnikov
> ; Avi Shchislowski
> ; Alex Lemberg ;
> Subhash Jadavani ; Vinayak Holikatti
> 
> Subject: Re: [PATCH v3 2/7] scsi: ufs: Instantiate a ufs bsg if its available
> 
> On Mon, Sep 03, 2018 at 01:33:11PM +0300, Avri Altman wrote:
> > Call the probe/remove APIs.
> 
> This belongs into the previous patch.
Done.

Thanks,
Avri


RE: [PATCH v3 1/7] scsi: ufs: Add ufs-bsg module

2018-09-05 Thread Avri Altman


> > + */
> > +#ifndef SCSI_BSG_UFS_H
> > +#define SCSI_BSG_UFS_H
> > +
> > +/*
> > + * This file intended to be included by both kernel and user space
> > + */
> > +
> > +
> > +/**
> > + * struct ufs_bsg_upiu - upiu transaction structure
> > + *
> > + * @header: upiu header
> > + * @tsf: Transaction Specific Fields
> > + * @data: payload pointer
> > + *
> > + * This structure supports all ufs transaction types per JEDEC
> > UFSv2.1
> > + * paragraph 10.7
> > + */
> > +struct ufs_bsg_upiu {
> > + uint32_t header[3];
> > + uint32_t tsf[5];
> > + uint8_t data[0];
> > +};
> 
> 
> In addition to Christoph's comments: is this a redefinition of an
> existing data structure (struct utp_upiu_header)? Please do not
> introduce variants of existing data structures but instead proceed as
> follows:
> - Move the relevant existing data structures (utp_upiu_header,
> utp_upiu_query, ...) from drivers/scsi/ufs/ufs.h into a header file
> under include/uapi.
> - Add a new patch at the beginning of this series that does nothing
> else than moving these data structures.
> - Use the existing data structures instead of introducing struct ufs_bsg_upiu.
Actually those are leftovers of scsi transport that I forgot to omit.
Sorry about that.
ufs-bsg is doing nothing with those, so it can be just left out.

Thanks,
Avri

> 
> Thanks,
> 
> Bart.


RE: [PATCH v3 1/7] scsi: ufs: Add ufs-bsg module

2018-09-05 Thread Avri Altman



> -Original Message-
> From: Christoph Hellwig 
> Sent: Tuesday, September 04, 2018 10:20 PM
> To: Avri Altman 
> Cc: Christoph Hellwig ; Johannes Thumshirn
> ; Hannes Reinecke ; Bart Van Assche
> ; James E.J. Bottomley
> ; Martin K. Petersen
> ; linux-scsi@vger.kernel.org; Stanislav Nijnikov
> ; Avi Shchislowski
> ; Alex Lemberg ;
> Subhash Jadavani ; Vinayak Holikatti
> 
> Subject: Re: [PATCH v3 1/7] scsi: ufs: Add ufs-bsg module
> 
> > +config SCSI_UFS_BSG
> > +   bool "Universal Flash Storage BSG device node"
> 
> So this a bool,
> 
> >  obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> >  obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
> >  obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
> > +obj-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
> 
> But built as a separate module, which is rather odd.   I think
> you wan to build this into the main ufshcd-core driver as a conditionally
> compiled object instead.
Done.

> 
> > +
> > +struct ufs_bsg {
> > +   struct ufs_hba *hba;
> > +   struct ufs_bsg_node *node;
> > +};
> > +static struct ufs_bsg *bsg_host;
> 
> This looks odd.  Why would you want a global variable like this?
> I'd expect every ufs host to have a ufs_bsg_node, and in fact
> we should probably just merge the ufs_bsg_node into the ufs_hba
> structure.
Done.

Thanks,
Avri


RE: [PATCH v3 3/7] scsi: ufs: Add fill task management request

2018-09-05 Thread Avri Altman



> -Original Message-
> From: linux-scsi-ow...@vger.kernel.org 
> On Behalf Of Christoph Hellwig
> Sent: Tuesday, September 04, 2018 10:12 PM
> To: Avri Altman 
> Cc: Christoph Hellwig ; Johannes Thumshirn
> ; Hannes Reinecke ; Bart Van Assche
> ; James E.J. Bottomley
> ; Martin K. Petersen
> ; linux-scsi@vger.kernel.org; Stanislav Nijnikov
> ; Avi Shchislowski
> ; Alex Lemberg ;
> Subhash Jadavani ; Vinayak Holikatti
> 
> Subject: Re: [PATCH v3 3/7] scsi: ufs: Add fill task management request
> 
> In general this looks good, but a question below:
> 
> > index ed37914..d18832a 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -5598,6 +5598,32 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba
> *hba, int tag)
> > return err;
> >  }
> >
> > +static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
> > +  int lun_id, int task_id, u8 tm_function,
> > +  int task_tag)
> > +{
> > +   struct utp_upiu_task_req *task_req_upiup;
> > +
> > +   /* Configure task request descriptor */
> > +   task_req_descp->header.dword_0 =
> cpu_to_le32(UTP_REQ_DESC_INT_CMD);
> > +   task_req_descp->header.dword_2 =
> > +   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> > +
> > +   task_req_upiup =
> > +   (struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
> 
> 
> Why is task_req_upiu a __le32 array instead of using the proper
> structure?
Looking into the UFSHCI spec (JESD223C March 2016) paragraph 6.2,
It doesn't specify any inner structure of the task management
request or response, just a bunch of 8 DW each.
I guess this is why it is defined as a __le32 array.

So the host controller is not aware of the inner structure of this
Sequence, and probably shouldn't. Making it aware of that,
e.g. by moving utp_upiu_task_req and utp_upiu_task_rsp 
from ufs.h to ufshci.h will break this abstraction.

> 
> Doing that would nicely clean up the code:
> 
> static void ufshcd_fill_tm_req(struct utp_task_req_desc *treq,
>  int lun_id, int task_id, u8 tm_function,
>  int task_tag)
> {
>   /* Configure task request descriptor */
>   treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
>   treq->header.dword_2 =
> cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> 
>   treq->task_req_upiup->header.dword_0 =
>   UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
> lun_id,
> task_tag);
>   treq->task_req_upiup->header.dword_1 =
>   UPIU_HEADER_DWORD(0, tm_function, 0, 0);
>   treq->task_req_upiup->input_param1 = cpu_to_be32(lun_id);
>   treq->task_req_upiup->input_param2 = cpu_to_be32(task_id);
> }


RE: [PATCH v3 4/7] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius

2018-09-05 Thread Avri Altman


> > ---
> >  drivers/scsi/ufs/ufshcd.c | 35 ++-
> >  1 file changed, 26 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index d18832a..15be103 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -5599,6 +5599,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba
> *hba, int tag)
> >  }
> >
> >  static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
> > +  struct utp_upiu_task_req *raw_task_req_upiup,
> >int lun_id, int task_id, u8 tm_function,
> >int task_tag)
> >  {
> > @@ -5609,6 +5610,13 @@ static void ufshcd_fill_tm_req(struct
> utp_task_req_desc *task_req_descp,
> > task_req_descp->header.dword_2 =
> > cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> >
> > +   if (raw_task_req_upiup) {
> > +   raw_task_req_upiup->header.dword_0 |=
> cpu_to_be32(task_tag);
> > +   memcpy(task_req_descp->task_req_upiu,
> raw_task_req_upiup,
> > +  GENERAL_UPIU_REQUEST_SIZE);
> > +   return;
> > +   }
> 
> The only thing actually shared here is initializing two fields.  Why
> can't we always pass in the a raw
See below
 
> 
> > +static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
> > +  struct utp_upiu_task_req *raw_task_req_upiup,
> > +  struct utp_upiu_task_req *raw_task_rsp_upiup,
> > +  int lun_id, int task_id, u8 tm_function,
> > +  u8 *tm_response)
> >  {
> 
> And the architecture here seems similar odd.  I think someone needs
> to untangle how the data structures are used in this part of the code.
> 
> E.g. aways prepare a raw structure in the caller (possibly on stack)
> and pass it into ufshcd_issue_tm_cmd, which copies it into the
> DMAable region.
Task management is sent on device reset and task abort.
This is actually a rare event, and on some platforms, I find it quite difficult 
to trigger.
So preparing the request upiu as a separate step seems a little bit excessive.
Another reason why it is a good idea to do it together, Is that both
preparing the task request upiu and ringing its doorbell are done under
the same host lock.

We can however, as you proposed, prepare a "raw" upiu if none is given,
But I think we'll end up with the same amount of code,
Maybe even less obvious than filling the upiu in one place.


RE: [PATCH v3 3/7] scsi: ufs: Add fill task management request

2018-09-06 Thread Avri Altman
Ok thanks.
Will test and those as the first 2 patches in the series.

Thanks a lot,
Avri

> -Original Message-
> From: Christoph Hellwig 
> Sent: Wednesday, September 05, 2018 8:15 PM
> To: Avri Altman 
> Cc: Christoph Hellwig ; Johannes Thumshirn
> ; Hannes Reinecke ; Bart Van Assche
> ; James E.J. Bottomley
> ; Martin K. Petersen
> ; linux-scsi@vger.kernel.org; Stanislav Nijnikov
> ; Avi Shchislowski
> ; Alex Lemberg ;
> Subhash Jadavani ; Vinayak Holikatti
> 
> Subject: Re: [PATCH v3 3/7] scsi: ufs: Add fill task management request
> 
> On Wed, Sep 05, 2018 at 07:08:50PM +0200, Christoph Hellwig wrote:
> > On Wed, Sep 05, 2018 at 03:53:41PM +, Avri Altman wrote:
> > > But on the other hand, task management request and response UPIUs
> > > are honorable members of the ufs spec (JEDEC 220C paragraphs 10.7.6 &
> 10.7.7).
> > > and indeed they lives in ufs.h, where they should.
> >
> > There is no other use anywhere.  Remember that there is no need to
> > have C data structure match what is in the spec, in fact doing so
> > often leads to worse code, which is why we often avoid it.
> >
> > I'll send out a little series (untested) to show how I'd like to see
> > this task menagement code look like.
> 
> Ok, the wifi at the meeting I'm at right now doesn't allow sending
> mail, so here are the patches as an attachment.


[PATCH v4 0/7] scsi: ufs bsg endpoint

2018-09-07 Thread Avri Altman
Here is a proposal to use a bsg endpoint to manage ufs devices.

We will do that by adding a bsg device node to the ufs driver,
and use it to send UPIU transactions to the ufs device.
It will serve as a ufs device management infrastructure, 
for device configuration, provisioning, testing and validation, etc.

We added a new ufs-bsg module, and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
This has nothing to do with the recent removal of bsg read/write support,
we might add this capability in the future, but it is not our current focus.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

V3->v4:
Squashed the bsg node Instantiation into "Add ufs-bsg".
Build ufs-bsg as part of ufshcd-core and not as a separate module.
Also merged the ufs_bsg_node into the ufs_hba structure.
Christoph refactored the task management code, cleaning it up 
and making it much more readable - attached as the first 2 patches
In the series.  Afterward passing an external upiu to ufshcd_issue_tm_cmd
Just blends in.

V2->v3:
We dropped the scsi transport code (and changed this patch title
to account for it) as we actually just need the bsg device node.
We also withdraw (brokenhearted) from our intension to create
several bsg devices, and add just one. 
Rephrased the doc in Kconfig.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed a couple of patches for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.


Avri Altman (5):
  scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw upiu
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

Christoph Hellwig (2):
  scsi: ufs: cleanup struct utp_task_req_desc
  scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

 drivers/scsi/ufs/Kconfig   |  19 +++
 drivers/scsi/ufs/Makefile  |   3 +
 drivers/scsi/ufs/ufs.h |  30 
 drivers/scsi/ufs/ufs_bsg.c | 327 
 drivers/scsi/ufs/ufs_bsg.h |  67 +
 drivers/scsi/ufs/ufshcd.c  | 362 ++---
 drivers/scsi/ufs/ufshcd.h  |   8 +
 drivers/scsi/ufs/ufshci.h  |  25 ++--
 8 files changed, 681 insertions(+), 160 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h

-- 
1.9.1



[PATCH v4 4/7] scsi: ufs: Add ufs-bsg module

2018-09-07 Thread Avri Altman
Add a bsg endpoint that supports UPIUs.

For now, just provide an API to allocate and remove
ufs-bsg node. We will use this framework to
manage ufs devices by sending UPIU transactions.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Moreover and as a result, our core structure - ufs_bsg_node has
a pretty lean structure: using upiu transactions that contains
the outmost detailed info, so we don't really need complex
constructs to support it.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/Kconfig   |  19 ++
 drivers/scsi/ufs/Makefile  |   3 +
 drivers/scsi/ufs/ufs_bsg.c | 156 +
 drivers/scsi/ufs/ufs_bsg.h |  64 +++
 drivers/scsi/ufs/ufshcd.c  |   4 ++
 drivers/scsi/ufs/ufshcd.h  |   2 +
 6 files changed, 248 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e09fe6a..83ba979 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -109,3 +109,22 @@ config SCSI_UFS_HISI
 
  Select this if you have UFS controller on Hisilicon chipset.
  If unsure, say N.
+
+config SCSI_UFS_BSG
+   bool "Universal Flash Storage BSG device node"
+   depends on SCSI_UFSHCD
+   select BLK_DEV_BSGLIB
+   help
+ Universal Flash Storage (UFS) is SCSI transport specification for
+ accessing flash storage on digital cameras, mobile phones and
+ consumer electronic devices.
+ An UFS controller communicates with an UFS device by exchanging
+ UFS Protocol Information Units (UPIUs).
+ UPIUs can not only be used as a transport layer for the SCSI protocol
+ but are also used by the UFS native command set.
+ This transport driver supports exchanging UFS protocol information 
units
+ with an UFS device. See also the ufshcd driver, which is a SCSI driver
+ that supports UFS devices.
+
+ Select this if you need a bsg device node for your UFS controller.
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..80041ab 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -5,6 +5,9 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o 
ufshcd-dwc.o tc-d
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
 ufshcd-core-objs := ufshcd.o ufs-sysfs.o
+ifeq ($(CONFIG_SCSI_UFS_BSG),y)
+ufshcd-core-objs += ufs_bsg.o
+endif
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 000..d33ada9
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * bsg endpoint that supports UPIUs
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg_node {
+   struct device   dev;
+   struct request_queue*q;
+};
+
+
+static inline struct ufs_bsg_node *dev_to_ufs_node(struct device *d)
+{
+   return container_of(d, struct ufs_bsg_node, dev);
+}
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+   struct ufs_bsg_request *bsg_request = job->request;
+   struct ufs_bsg_reply *bsg_reply = job->reply;
+   int ret = -ENOTSUPP;
+
+   bsg_reply->reply_payload_rcv_len = 0;
+
+   /* Do Nothing for now */
+   dev_err(job->dev, "unsupported message_code 0x%x\n",
+   bsg_request->msgcode);
+
+   bsg_reply->result = ret;
+   if (ret)
+   job->reply_len = sizeof(uint32_t);
+   else
+   job->reply_len = sizeof(struct ufs_bsg_reply) +
+bsg_reply->reply_payload_rcv_len;
+
+   bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+   return ret;
+}
+
+static void ufs_bsg_node_delete(struct ufs_bsg_node *node)
+{
+   struct device *dev = >dev;
+
+   if (node->q)
+   bsg_unregister_queue(node->q);
+
+   device_del(dev);
+
+   put_device(dev);
+}
+
+/**
+ * ufs_bsg_remove - detach and remove t

[PATCH v4 5/7] scsi: ufs: Add API to execute raw upiu commands

2018-09-07 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 151 ++
 drivers/scsi/ufs/ufshcd.h |   6 ++
 2 files changed, 157 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e53e145..efde4d82 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -257,6 +257,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool 
on,
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
return tag >= 0 && tag < hba->nutrs;
@@ -5663,6 +5664,156 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @rw:either READ or WRITE
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type, int rw)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+   u8 *descp;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->command_type = hba->ufs_version == UFSHCI_VERSION_10 ||
+hba->ufs_version == UFSHCI_VERSION_11 ?
+UTP_CMD_TYPE_DEV_MANAGE :
+UTP_CMD_TYPE_UFS_STORAGE;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, GENERAL_UPIU_REQUEST_SIZE);
+
+   if (desc_buff && rw == WRITE) {
+   descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
+   memcpy(descp, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   /*
+* ignore the returning value here - ufshcd_check_query_response is
+* bound to fail since dev_cmd.query and dev_cmd.type were left empty.
+* read the response directly ignoring all errors.
+*/
+   ufshcd_wait_for_dev_cmd(hba, lrbp, QUERY_REQ_TIMEOUT);
+
+   /* just copy the upiu request as it is */
+   memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, GENERAL_UP

[PATCH v4 3/7] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw upiu

2018-09-07 Thread Avri Altman
Do that in order to re-use its code if the task request and response
UPIUs are given externally.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 39 ---
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c7809fa..d021c3a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5610,12 +5610,20 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
  *
  * Returns non-zero value on error, zero on success.
  */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+  struct utp_upiu_req *req_upiu,
+  struct utp_upiu_req *rsp_upiu,
+  int lun_id, int task_id,
+  u8 tm_function, u8 *tm_response)
 {
struct utp_task_req_desc treq = { { 0 }, };
int ocs_value, err;
 
+   if (req_upiu) {
+   memcpy(_header, req_upiu, GENERAL_UPIU_REQUEST_SIZE);
+   goto issue_tm_cmd;
+   }
+
/* Configure task request descriptor */
treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
@@ -5632,17 +5640,24 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
treq.input_param1 = cpu_to_be32(lun_id);
treq.input_param2 = cpu_to_be32(task_id);
 
+issue_tm_cmd:
err = __ufshcd_issue_tm_cmd(hba, , tm_function);
if (err == -ETIMEDOUT)
return err;
 
ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS;
-   if (ocs_value != OCS_SUCCESS)
+   if (ocs_value != OCS_SUCCESS) {
dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
__func__, ocs_value);
-   else if (tm_response)
-   *tm_response = be32_to_cpu(treq.output_param1) &
-   MASK_TM_SERVICE_RESP;
+   } else {
+   if (tm_response)
+   *tm_response = be32_to_cpu(treq.output_param1) &
+   MASK_TM_SERVICE_RESP;
+   if (rsp_upiu)
+   memcpy(rsp_upiu, _header,
+  GENERAL_UPIU_REQUEST_SIZE);
+
+   }
return err;
 }
 
@@ -5669,7 +5684,8 @@ static int ufshcd_eh_device_reset_handler(struct 
scsi_cmnd *cmd)
tag = cmd->request->tag;
 
lrbp = >lrb[tag];
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err)
err = resp;
@@ -5799,8 +5815,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
}
 
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_QUERY_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ );
if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
/* cmd pending in the device */
dev_err(hba->dev, "%s: cmd pending in the device. tag = 
%d\n",
@@ -5838,8 +5855,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto out;
}
 
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_ABORT_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err) {
err = resp; /* service response error */
-- 
1.9.1



[PATCH v4 7/7] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-09-07 Thread Avri Altman
Add support to those uic commands, that are currently supported
by ufshcd api: the variants of dme_{peer}_{set_get}.

At this point better not to add any new api, as careless
uic command may turn the device into a brick.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 54 +-
 drivers/scsi/ufs/ufs_bsg.h |  2 ++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index c6c2ac7..65144ae 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -64,6 +64,53 @@ static int ufs_bsg_verify_query_size(unsigned int 
request_len,
return 0;
 }
 
+static int ufs_bsg_exec_uic_cmd(struct ufs_hba *hba, struct uic_command *uc)
+{
+   u32 attr_sel = uc->argument1;
+   u8 attr_set = (uc->argument2 >> 16) & 0xff;
+   u32 mib_val = uc->argument3;
+   int cmd = uc->command;
+   int ret = 0;
+
+   switch (cmd) {
+   case UIC_CMD_DME_GET:
+   ret = ufshcd_dme_get_attr(hba, attr_sel, _val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_SET:
+   ret = ufshcd_dme_set_attr(hba, attr_sel, attr_set, mib_val,
+ DME_LOCAL);
+   break;
+   case UIC_CMD_DME_PEER_GET:
+   ret = ufshcd_dme_get_attr(hba, attr_sel, _val, DME_PEER);
+   break;
+   case UIC_CMD_DME_PEER_SET:
+   ret = ufshcd_dme_set_attr(hba, attr_sel, attr_set, mib_val,
+ DME_PEER);
+   break;
+   case UIC_CMD_DME_POWERON:
+   case UIC_CMD_DME_POWEROFF:
+   case UIC_CMD_DME_ENABLE:
+   case UIC_CMD_DME_RESET:
+   case UIC_CMD_DME_END_PT_RST:
+   case UIC_CMD_DME_LINK_STARTUP:
+   case UIC_CMD_DME_HIBER_ENTER:
+   case UIC_CMD_DME_HIBER_EXIT:
+   case UIC_CMD_DME_TEST_MODE:
+   ret = -ENOTSUPP;
+   pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   if (ret)
+   pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+   uc->argument3 = mib_val;
+
+   return ret;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
@@ -72,6 +119,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+   struct uic_command uc = {};
struct utp_upiu_req *req_upiu = NULL;
struct utp_upiu_req *rsp_upiu = NULL;
int msgcode;
@@ -126,7 +174,11 @@ static int ufs_bsg_request(struct bsg_job *job)
 
break;
case UPIU_TRANSACTION_UIC_CMD:
-   /* later */
+   memcpy(, _request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd(hba, );
+   memcpy(_reply->tsf.uc, , UIC_CMD_SIZE);
+
+   break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
 not_supported:
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index 4da1837..3373a25 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -14,6 +14,8 @@
 
 #define UFS_BSG_NOP (-1)
 #define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 enum {
REQ_UPIU_SIZE_DWORDS= 8,
-- 
1.9.1



[PATCH v4 6/7] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-09-07 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 127 +++--
 drivers/scsi/ufs/ufs_bsg.h |   1 +
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index d33ada9..c6c2ac7 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -17,18 +17,137 @@ static inline struct ufs_bsg_node *dev_to_ufs_node(struct 
device *d)
return container_of(d, struct ufs_bsg_node, dev);
 }
 
+static inline struct ufs_hba *dev_to_ufs_hba(struct device *d)
+{
+   struct Scsi_Host *shost = dev_to_shost(d->parent);
+
+   return shost_priv(shost);
+}
+
+static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba,
+  struct utp_upiu_query *qr,
+  int *desc_len)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret = 0;
+
+   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC || desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
+
+   if (ret || !*desc_len)
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return ret;
+}
+
+static int ufs_bsg_verify_query_size(unsigned int request_len,
+unsigned int reply_len,
+int rw, int desc_len)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (rw == WRITE)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len)
+   return -EINVAL;
+
+   if (min_rsp_len > reply_len)
+   return -EINVAL;
+
+   return 0;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   struct ufs_hba *hba = dev_to_ufs_hba(job->dev);
+   unsigned int request_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   struct utp_upiu_query *qr;
+   struct utp_upiu_req *req_upiu = NULL;
+   struct utp_upiu_req *rsp_upiu = NULL;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   int rw = UFS_BSG_NOP;
+   int ret;
 
+   ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, desc_len);
+   if (ret) {
+   dev_err(job->dev, "not enough space assigned\n");
+   goto out;
+   }
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   qr = _request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(hba, qr, _len))
+   goto null_desc_buff;
+
+   if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   rw = WRITE;
+   desc_buff = ((uint8_t *)bsg_request) +
+   sizeof(struct ufs_bsg_request);
+   }
+
+null_desc_buff:
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   /* Now that we know if its a read or write, verify again */
+   if (rw != UFS_BSG_NOP || desc_len) {
+   ret = ufs_bsg_verify_query_size(request_len, reply_len,
+   rw, desc_len);
+   if (ret) {
+   dev_err(job->dev,
+   "not enough space assigned\n");
+   goto out;
+   }
+   }
+
+   req_upiu = (struct utp_upiu_req *)_request->header;
+   rsp_upiu = (struct utp_upiu_req *)_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(hba, req_upiu, rsp_upiu,
+  msgcode, desc_buff, _len,
+  

[PATCH v4 1/7] scsi: ufs: cleanup struct utp_task_req_desc

2018-09-07 Thread Avri Altman
From: Christoph Hellwig 

Remove the pointless task_req_upiu and task_rsp_upiu indirections,
which are __le32 arrays always cast to given structures and just add
the members directly.  Also clean up variables names in use in the
callers a bit to make the code more readable.

Signed-off-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufs.h| 30 -
 drivers/scsi/ufs/ufshcd.c | 68 ++-
 drivers/scsi/ufs/ufshci.h | 25 +
 3 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 14e5bf7..16230df 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -520,36 +520,6 @@ struct utp_upiu_rsp {
 };
 
 /**
- * struct utp_upiu_task_req - Task request UPIU structure
- * @header - UPIU header structure DW0 to DW-2
- * @input_param1: Input parameter 1 DW-3
- * @input_param2: Input parameter 2 DW-4
- * @input_param3: Input parameter 3 DW-5
- * @reserved: Reserved double words DW-6 to DW-7
- */
-struct utp_upiu_task_req {
-   struct utp_upiu_header header;
-   __be32 input_param1;
-   __be32 input_param2;
-   __be32 input_param3;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_task_rsp - Task Management Response UPIU structure
- * @header: UPIU header structure DW0-DW-2
- * @output_param1: Ouput parameter 1 DW3
- * @output_param2: Output parameter 2 DW4
- * @reserved: Reserved double words DW-5 to DW-7
- */
-struct utp_upiu_task_rsp {
-   struct utp_upiu_header header;
-   __be32 output_param1;
-   __be32 output_param2;
-   __be32 reserved[3];
-};
-
-/**
  * struct ufs_query_req - parameters for building a query request
  * @query_func: UPIU header query function
  * @upiu_req: the query request data
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9d5d2ca..178bbf7 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -326,14 +326,11 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba 
*hba, unsigned int tag,
 static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
-   struct utp_task_req_desc *descp;
-   struct utp_upiu_task_req *task_req;
int off = (int)tag - hba->nutrs;
+   struct utp_task_req_desc *descp = >utmrdl_base_addr[off];
 
-   descp = >utmrdl_base_addr[off];
-   task_req = (struct utp_upiu_task_req *)descp->task_req_upiu;
-   trace_ufshcd_upiu(dev_name(hba->dev), str, _req->header,
-   _req->input_param1);
+   trace_ufshcd_upiu(dev_name(hba->dev), str, >req_header,
+   >input_param1);
 }
 
 static void ufshcd_add_command_trace(struct ufs_hba *hba,
@@ -475,22 +472,13 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long 
bitmap, bool pr_prdt)
 
 static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
 {
-   struct utp_task_req_desc *tmrdp;
int tag;
 
for_each_set_bit(tag, , hba->nutmrs) {
-   tmrdp = >utmrdl_base_addr[tag];
+   struct utp_task_req_desc *tmrdp = >utmrdl_base_addr[tag];
+
dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag);
-   ufshcd_hex_dump("TM TRD: ", >header,
-   sizeof(struct request_desc_header));
-   dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
-   sizeof(struct utp_upiu_req));
-   dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
-   sizeof(struct utp_task_req_desc));
+   ufshcd_hex_dump("", tmrdp, sizeof(*tmrdp));
}
 }
 
@@ -4610,31 +4598,22 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
  */
 static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 {
-   struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_rsp *task_rsp_upiup;
+   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
unsigned long flags;
int ocs_value;
-   int task_result;
 
spin_lock_irqsave(hba->host->host_lock, flags);
 
/* Clear completed tasks from outstanding_tasks */
__clear_bit(index, >outstanding_tasks);
 
-   task_req_descp = hba->utmrdl_base_addr;
-   ocs_value = ufshcd_get_tmr_ocs(_req_descp[index]);
+   ocs_value = ufshcd_get_tmr_ocs(treq);
 
-   if (ocs_value == OCS_SUCCESS) {
-   task_rsp_upiup = (struct utp_upiu_task_rsp *)
-   task_req_descp[index].task_rsp_upiu;
-   task_result = be32_to_cpu(task_rsp_upiup->output_param1);
-   task_result = task_result & MASK_TM_SERVICE_RESP;
-  

[PATCH v4 2/7] scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

2018-09-07 Thread Avri Altman
From: Christoph Hellwig 

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support.  Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufshcd.c | 140 --
 1 file changed, 60 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 178bbf7..c7809fa 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -634,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb 
*lrbp)
 }
 
 /**
- * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
- * @task_req_descp: pointer to utp_task_req_desc structure
- *
- * This function is used to get the OCS field from UTMRD
- * Returns the OCS field in the UTMRD
- */
-static inline int
-ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
-{
-   return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
-}
-
-/**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
  * @free_slot: pointer to variable with available slot value
@@ -4589,37 +4576,6 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
 }
 
 /**
- * ufshcd_task_req_compl - handle task management request completion
- * @hba: per adapter instance
- * @index: index of the completed request
- * @resp: task management service response
- *
- * Returns non-zero value on error, zero on success
- */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
-{
-   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
-   unsigned long flags;
-   int ocs_value;
-
-   spin_lock_irqsave(hba->host->host_lock, flags);
-
-   /* Clear completed tasks from outstanding_tasks */
-   __clear_bit(index, >outstanding_tasks);
-
-   ocs_value = ufshcd_get_tmr_ocs(treq);
-
-   if (ocs_value != OCS_SUCCESS)
-   dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-   __func__, ocs_value);
-   else if (resp)
-   *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
-   spin_unlock_irqrestore(hba->host->host_lock, flags);
-
-   return ocs_value;
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrbp: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -5576,27 +5532,12 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
-/**
- * ufshcd_issue_tm_cmd - issues task management commands to controller
- * @hba: per adapter instance
- * @lun_id: LUN ID to which TM command is sent
- * @task_id: task ID to which the TM command is applicable
- * @tm_function: task management function opcode
- * @tm_response: task management service response return value
- *
- * Returns non-zero value on error, zero on success.
- */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+   struct utp_task_req_desc *treq, u8 tm_function)
 {
-   struct utp_task_req_desc *treq;
-   struct Scsi_Host *host;
+   struct Scsi_Host *host = hba->host;
unsigned long flags;
-   int free_slot;
-   int err;
-   int task_tag;
-
-   host = hba->host;
+   int free_slot, task_tag, err;
 
/*
 * Get free slot, sleep if slots are unavailable.
@@ -5607,24 +5548,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
ufshcd_hold(hba, false);
 
spin_lock_irqsave(host->host_lock, flags);
-   treq = hba->utmrdl_base_addr + free_slot;
-
-   /* Configure task request descriptor */
-   treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
task_tag = hba->nutrs + free_slot;
-   treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
-   0, lun_id, task_tag);
-   treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   treq->input_param1 = cpu_to_be32(lun_id);
-   treq->input_param2 = cpu_to_be32(task_id);
 
+   treq->req_header.dword_0 |= cpu_to_be32(task_tag);
+
+   memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
/* send command to the controller */
@@ -5654,8 +5582,14 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
__func__, free_slot);
err = -ETIMEDOUT;
} else {
-  

Re: [PATCH v8 0/8] scsi: Add ufs bsg endpoint

2018-10-05 Thread Avri Altman
hi,
Thanks for trying to test it.
You need to elaborate not only the ufs driver, but also the bsg driver, and 
some block layer patches as well.
Will reply with the full list on Sunday.

Thanks,
Avri

From: Bean Huo (beanhuo) 
Sent: Friday, October 5, 2018 12:28 AM
To: Avri Altman; Christoph Hellwig; Johannes Thumshirn; Hannes Reinecke; Bart 
Van Assche; James E.J. Bottomley; Martin K. Petersen; linux-scsi@vger.kernel.org
Cc: Stanislav Nijnikov; Avi Shchislowski; Alex Lemberg; Subhash Jadavani; 
Vinayak Holikatti
Subject: RE: [PATCH v8 0/8] scsi: Add ufs bsg endpoint

Hi, Avri

>We tested it on a Hikey-960 platform with a V4.14 kernel, "modernized" by
>recent bsg and ufs patches.

Which kernel version is V8 based on? I patched to 4.14-rc7, it failed.





[PATCH v7 2/8] scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

2018-09-29 Thread Avri Altman
From: Christoph Hellwig 

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support.  Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig 
Tested-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 141 --
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 906011b..5005432 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -634,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb 
*lrbp)
 }
 
 /**
- * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
- * @task_req_descp: pointer to utp_task_req_desc structure
- *
- * This function is used to get the OCS field from UTMRD
- * Returns the OCS field in the UTMRD
- */
-static inline int
-ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
-{
-   return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
-}
-
-/**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
  * @free_slot: pointer to variable with available slot value
@@ -4617,37 +4604,6 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
 }
 
 /**
- * ufshcd_task_req_compl - handle task management request completion
- * @hba: per adapter instance
- * @index: index of the completed request
- * @resp: task management service response
- *
- * Returns non-zero value on error, zero on success
- */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
-{
-   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
-   unsigned long flags;
-   int ocs_value;
-
-   spin_lock_irqsave(hba->host->host_lock, flags);
-
-   /* Clear completed tasks from outstanding_tasks */
-   __clear_bit(index, >outstanding_tasks);
-
-   ocs_value = ufshcd_get_tmr_ocs(treq);
-
-   if (ocs_value != OCS_SUCCESS)
-   dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-   __func__, ocs_value);
-   else if (resp)
-   *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
-   spin_unlock_irqrestore(hba->host->host_lock, flags);
-
-   return ocs_value;
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrbp: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -5604,27 +5560,12 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
-/**
- * ufshcd_issue_tm_cmd - issues task management commands to controller
- * @hba: per adapter instance
- * @lun_id: LUN ID to which TM command is sent
- * @task_id: task ID to which the TM command is applicable
- * @tm_function: task management function opcode
- * @tm_response: task management service response return value
- *
- * Returns non-zero value on error, zero on success.
- */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+   struct utp_task_req_desc *treq, u8 tm_function)
 {
-   struct utp_task_req_desc *treq;
-   struct Scsi_Host *host;
+   struct Scsi_Host *host = hba->host;
unsigned long flags;
-   int free_slot;
-   int err;
-   int task_tag;
-
-   host = hba->host;
+   int free_slot, task_tag, err;
 
/*
 * Get free slot, sleep if slots are unavailable.
@@ -5635,24 +5576,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
ufshcd_hold(hba, false);
 
spin_lock_irqsave(host->host_lock, flags);
-   treq = hba->utmrdl_base_addr + free_slot;
-
-   /* Configure task request descriptor */
-   treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
task_tag = hba->nutrs + free_slot;
-   treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
-   0, lun_id, task_tag);
-   treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   treq->input_param1 = cpu_to_be32(lun_id);
-   treq->input_param2 = cpu_to_be32(task_id);
 
+   treq->req_header.dword_0 |= cpu_to_be32(task_tag);
+
+   memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
/* send command to the controller */
@@ -5682,8 +5610,15 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
  

[PATCH v7 3/8] uapi: ufs: Make utp_upiu_req visible to user space

2018-09-29 Thread Avri Altman
in preparation to send UPIU requests via bsg.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs.h   | 61 +
 include/uapi/scsi/scsi_bsg_ufs.h | 74 
 2 files changed, 75 insertions(+), 60 deletions(-)
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 16230df..f1d77dc 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,8 +38,8 @@
 
 #include 
 #include 
+#include 
 
-#define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
@@ -433,65 +433,6 @@ enum ufs_dev_pwr_mode {
 };
 
 /**
- * struct utp_upiu_header - UPIU header structure
- * @dword_0: UPIU header DW-0
- * @dword_1: UPIU header DW-1
- * @dword_2: UPIU header DW-2
- */
-struct utp_upiu_header {
-   __be32 dword_0;
-   __be32 dword_1;
-   __be32 dword_2;
-};
-
-/**
- * struct utp_upiu_cmd - Command UPIU structure
- * @data_transfer_len: Data Transfer Length DW-3
- * @cdb: Command Descriptor Block CDB DW-4 to DW-7
- */
-struct utp_upiu_cmd {
-   __be32 exp_data_transfer_len;
-   u8 cdb[MAX_CDB_SIZE];
-};
-
-/**
- * struct utp_upiu_query - upiu request buffer structure for
- * query request.
- * @opcode: command to perform B-0
- * @idn: a value that indicates the particular type of data B-1
- * @index: Index to further identify data B-2
- * @selector: Index to further identify data B-3
- * @reserved_osf: spec reserved field B-4,5
- * @length: number of descriptor bytes to read/write B-6,7
- * @value: Attribute value to be written DW-5
- * @reserved: spec reserved DW-6,7
- */
-struct utp_upiu_query {
-   u8 opcode;
-   u8 idn;
-   u8 index;
-   u8 selector;
-   __be16 reserved_osf;
-   __be16 length;
-   __be32 value;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_req - general upiu request structure
- * @header:UPIU header structure DW-0 to DW-2
- * @sc: fields structure for scsi command DW-3 to DW-7
- * @qr: fields structure for query request DW-3 to DW-7
- */
-struct utp_upiu_req {
-   struct utp_upiu_header header;
-   union {
-   struct utp_upiu_cmd sc;
-   struct utp_upiu_query qr;
-   };
-};
-
-/**
  * struct utp_cmd_rsp - Response UPIU structure
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
new file mode 100644
index 000..fbebf2d
--- /dev/null
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TBD - UFS Transport SGIO v4 BSG Message Support
+ *
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ */
+#ifndef SCSI_BSG_UFS_H
+#define SCSI_BSG_UFS_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+#define MAX_CDB_SIZE   16
+
+/**
+ * struct utp_upiu_header - UPIU header structure
+ * @dword_0: UPIU header DW-0
+ * @dword_1: UPIU header DW-1
+ * @dword_2: UPIU header DW-2
+ */
+struct utp_upiu_header {
+   __be32 dword_0;
+   __be32 dword_1;
+   __be32 dword_2;
+};
+
+/**
+ * struct utp_upiu_query - upiu request buffer structure for
+ * query request.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @reserved_osf: spec reserved field B-4,5
+ * @length: number of descriptor bytes to read/write B-6,7
+ * @value: Attribute value to be written DW-5
+ * @reserved: spec reserved DW-6,7
+ */
+struct utp_upiu_query {
+   u8 opcode;
+   u8 idn;
+   u8 index;
+   u8 selector;
+   __be16 reserved_osf;
+   __be16 length;
+   __be32 value;
+   __be32 reserved[2];
+};
+
+/**
+ * struct utp_upiu_cmd - Command UPIU structure
+ * @data_transfer_len: Data Transfer Length DW-3
+ * @cdb: Command Descriptor Block CDB DW-4 to DW-7
+ */
+struct utp_upiu_cmd {
+   __be32 exp_data_transfer_len;
+   u8 cdb[MAX_CDB_SIZE];
+};
+
+/**
+ * struct utp_upiu_req - general upiu request structure
+ * @header:UPIU header structure DW-0 to DW-2
+ * @sc: fields structure for scsi command DW-3 to DW-7
+ * @qr: fields structure for query request DW-3 to DW-7
+ */
+struct utp_upiu_req {
+   struct utp_upiu_header header;
+   union {
+   struct utp_upiu_cmd sc;
+   struct utp_upiu_query   qr;
+   };
+};
+#endif /* UFS_BSG_H */
-- 
1.9.1



[PATCH v7 4/8] scsi: ufs: Add ufs-bsg module

2018-09-29 Thread Avri Altman
Add a bsg endpoint that supports UPIUs.

For now, just provide an API to allocate and remove
ufs-bsg node. We will use this framework to
manage ufs devices by sending UPIU transactions.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Moreover and as a result, our core structure - ufs_bsg_node has
a pretty lean structure: using upiu transactions that contains
the outmost detailed info, so we don't really need complex
constructs to support it.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 Documentation/scsi/ufs.txt   | 20 +
 drivers/scsi/ufs/Kconfig | 19 
 drivers/scsi/ufs/Makefile|  3 +-
 drivers/scsi/ufs/ufs_bsg.c   | 93 
 drivers/scsi/ufs/ufs_bsg.h   | 23 ++
 drivers/scsi/ufs/ufshcd.c|  4 ++
 drivers/scsi/ufs/ufshcd.h|  3 ++
 include/uapi/scsi/scsi_bsg_ufs.h | 30 -
 8 files changed, 193 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h

diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.txt
index 41a6164..2616d5f 100644
--- a/Documentation/scsi/ufs.txt
+++ b/Documentation/scsi/ufs.txt
@@ -128,6 +128,26 @@ The current UFSHCD implementation supports following 
functionality,
 In this version of UFSHCD Query requests and power management
 functionality are not implemented.
 
+4. BSG Support
+--
+
+This transport driver supports exchanging UFS protocol information units
+(UPIUs) with an UFS device. Typically, user space will allocate
+struct ufs_bsg_request and struct ufs_bsg_reply (see ufs_bsg.h) as
+request_upiu and reply_upiu respectively.  Filling those UPIUs should
+be done in accordance with JEDEC spec UFS2.1 paragraph 10.7.
+*Caveat emptor*: The driver makes no further input validations and sends the
+UPIU to the device as it is.  Open the bsg device in /dev/ufs-bsg and
+send SG_IO with the applicable sg_io_v4:
+
+   io_hdr_v4.guard = 'Q';
+   io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
+   io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
+   io_hdr_v4.response = (__u64)reply_upiu;
+   io_hdr_v4.max_response_len = reply_len;
+   io_hdr_v4.request_len = request_len;
+   io_hdr_v4.request = (__u64)request_upiu;
+
 UFS Specifications can be found at,
 UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
 UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e09fe6a..83ba979 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -109,3 +109,22 @@ config SCSI_UFS_HISI
 
  Select this if you have UFS controller on Hisilicon chipset.
  If unsure, say N.
+
+config SCSI_UFS_BSG
+   bool "Universal Flash Storage BSG device node"
+   depends on SCSI_UFSHCD
+   select BLK_DEV_BSGLIB
+   help
+ Universal Flash Storage (UFS) is SCSI transport specification for
+ accessing flash storage on digital cameras, mobile phones and
+ consumer electronic devices.
+ An UFS controller communicates with an UFS device by exchanging
+ UFS Protocol Information Units (UPIUs).
+ UPIUs can not only be used as a transport layer for the SCSI protocol
+ but are also used by the UFS native command set.
+ This transport driver supports exchanging UFS protocol information 
units
+ with an UFS device. See also the ufshcd driver, which is a SCSI driver
+ that supports UFS devices.
+
+ Select this if you need a bsg device node for your UFS controller.
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..aca4813 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o 
ufshcd-dwc.o tc-dwc-g210.
 obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o 
tc-dwc-g210.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
-ufshcd-core-objs := ufshcd.o ufs-sysfs.o
+ufshcd-core-y  += ufshcd.o ufs-sysfs.o
+ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
 obj-$(CONFIG_SCSI_

[PATCH v7 1/8] scsi: ufs: cleanup struct utp_task_req_desc

2018-09-29 Thread Avri Altman
From: Christoph Hellwig 

Remove the pointless task_req_upiu and task_rsp_upiu indirections,
which are __le32 arrays always cast to given structures and just add
the members directly.  Also clean up variables names in use in the
callers a bit to make the code more readable.

Signed-off-by: Christoph Hellwig 
Tested-by: Avri Altman 
---
 drivers/scsi/ufs/ufs.h| 30 -
 drivers/scsi/ufs/ufshcd.c | 68 ++-
 drivers/scsi/ufs/ufshci.h | 25 +
 3 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 14e5bf7..16230df 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -520,36 +520,6 @@ struct utp_upiu_rsp {
 };
 
 /**
- * struct utp_upiu_task_req - Task request UPIU structure
- * @header - UPIU header structure DW0 to DW-2
- * @input_param1: Input parameter 1 DW-3
- * @input_param2: Input parameter 2 DW-4
- * @input_param3: Input parameter 3 DW-5
- * @reserved: Reserved double words DW-6 to DW-7
- */
-struct utp_upiu_task_req {
-   struct utp_upiu_header header;
-   __be32 input_param1;
-   __be32 input_param2;
-   __be32 input_param3;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_task_rsp - Task Management Response UPIU structure
- * @header: UPIU header structure DW0-DW-2
- * @output_param1: Ouput parameter 1 DW3
- * @output_param2: Output parameter 2 DW4
- * @reserved: Reserved double words DW-5 to DW-7
- */
-struct utp_upiu_task_rsp {
-   struct utp_upiu_header header;
-   __be32 output_param1;
-   __be32 output_param2;
-   __be32 reserved[3];
-};
-
-/**
  * struct ufs_query_req - parameters for building a query request
  * @query_func: UPIU header query function
  * @upiu_req: the query request data
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 905e405..906011b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -326,14 +326,11 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba 
*hba, unsigned int tag,
 static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
-   struct utp_task_req_desc *descp;
-   struct utp_upiu_task_req *task_req;
int off = (int)tag - hba->nutrs;
+   struct utp_task_req_desc *descp = >utmrdl_base_addr[off];
 
-   descp = >utmrdl_base_addr[off];
-   task_req = (struct utp_upiu_task_req *)descp->task_req_upiu;
-   trace_ufshcd_upiu(dev_name(hba->dev), str, _req->header,
-   _req->input_param1);
+   trace_ufshcd_upiu(dev_name(hba->dev), str, >req_header,
+   >input_param1);
 }
 
 static void ufshcd_add_command_trace(struct ufs_hba *hba,
@@ -475,22 +472,13 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long 
bitmap, bool pr_prdt)
 
 static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
 {
-   struct utp_task_req_desc *tmrdp;
int tag;
 
for_each_set_bit(tag, , hba->nutmrs) {
-   tmrdp = >utmrdl_base_addr[tag];
+   struct utp_task_req_desc *tmrdp = >utmrdl_base_addr[tag];
+
dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag);
-   ufshcd_hex_dump("TM TRD: ", >header,
-   sizeof(struct request_desc_header));
-   dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
-   sizeof(struct utp_upiu_req));
-   dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
-   sizeof(struct utp_task_req_desc));
+   ufshcd_hex_dump("", tmrdp, sizeof(*tmrdp));
}
 }
 
@@ -4638,31 +4626,22 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
  */
 static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 {
-   struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_rsp *task_rsp_upiup;
+   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
unsigned long flags;
int ocs_value;
-   int task_result;
 
spin_lock_irqsave(hba->host->host_lock, flags);
 
/* Clear completed tasks from outstanding_tasks */
__clear_bit(index, >outstanding_tasks);
 
-   task_req_descp = hba->utmrdl_base_addr;
-   ocs_value = ufshcd_get_tmr_ocs(_req_descp[index]);
+   ocs_value = ufshcd_get_tmr_ocs(treq);
 
-   if (ocs_value == OCS_SUCCESS) {
-   task_rsp_upiup = (struct utp_upiu_task_rsp *)
-   task_req_d

[PATCH v7 8/8] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-09-29 Thread Avri Altman
Make ufshcd_send_uic_cmd() public for that.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c   | 11 +++
 drivers/scsi/ufs/ufshcd.c|  3 +--
 drivers/scsi/ufs/ufshcd.h|  2 ++
 include/uapi/scsi/scsi_bsg_ufs.h |  3 +++
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 306e5f1..e5f8e54 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -84,6 +84,7 @@ static int ufs_bsg_request(struct bsg_job *job)
struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
unsigned int req_len = job->request_len;
unsigned int reply_len = job->reply_len;
+   struct uic_command uc = {};
int msgcode;
uint8_t *desc_buff = NULL;
int desc_len = 0;
@@ -117,6 +118,16 @@ static int ufs_bsg_request(struct bsg_job *job)
"exe raw upiu: error code %d\n", ret);
 
break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   memcpy(, _request->upiu_req.uc, UIC_CMD_SIZE);
+   ret = ufshcd_send_uic_cmd(hba, );
+   if (ret)
+   dev_dbg(hba->dev,
+   "send uic cmd: error code %d\n", ret);
+
+   memcpy(_reply->upiu_rsp.uc, , UIC_CMD_SIZE);
+
+   break;
default:
ret = -ENOTSUPP;
dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 241efd4..0bbf5a2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2059,8 +2059,7 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  *
  * Returns 0 only if success.
  */
-static int
-ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
int ret;
unsigned long flags;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0878134..1a1c2b4 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -895,6 +895,8 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum 
desc_idn desc_id,
 
 u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
 
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+
 int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 struct utp_upiu_req *req_upiu,
 struct utp_upiu_req *rsp_upiu,
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 201a872..b6d1cd0 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -13,6 +13,9 @@
  */
 
 #define MAX_CDB_SIZE   16
+#define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 /**
  * struct utp_upiu_header - UPIU header structure
-- 
1.9.1



[PATCH v7 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-09-29 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c | 114 +++--
 1 file changed, 110 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 1036c52..306e5f1 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -6,19 +6,125 @@
  */
 #include "ufs_bsg.h"
 
+static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
+  struct utp_upiu_query *qr)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret;
+
+   if (desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
+   if (ret || !*desc_len)
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
+unsigned int request_len,
+unsigned int reply_len,
+int desc_len, enum query_opcode desc_op)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len || min_rsp_len > reply_len) {
+   dev_err(hba->dev, "not enough space assigned\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_params(struct ufs_hba *hba,
+  struct ufs_bsg_request *bsg_request,
+  unsigned int request_len,
+  unsigned int reply_len,
+  uint8_t *desc_buff, int *desc_len,
+  enum query_opcode desc_op)
+{
+   struct utp_upiu_query *qr;
+
+   if (desc_op == UPIU_QUERY_OPCODE_READ_DESC) {
+   dev_err(hba->dev, "unsupported opcode %d\n", desc_op);
+   return -ENOTSUPP;
+   }
+
+   if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC)
+   goto out;
+
+   qr = _request->upiu_req.qr;
+   if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) {
+   dev_err(hba->dev, "Illegal desc size\n");
+   return -EINVAL;
+   }
+
+   if (ufs_bsg_verify_query_size(hba, request_len, reply_len, *desc_len,
+ desc_op))
+   return -EINVAL;
+
+   desc_buff = (uint8_t *)(bsg_request + 1);
+
+out:
+   return 0;
+}
 
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
+   unsigned int req_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
+   int ret;
+
+   ret = ufs_bsg_verify_query_size(hba, req_len, reply_len, 0, desc_op);
+   if (ret)
+   goto out;
 
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   desc_op = bsg_request->upiu_req.qr.opcode;
+   ret = ufs_bsg_verify_query_params(hba, bsg_request, req_len,
+ reply_len, desc_buff,
+ _len, desc_op);
+   if (ret)
+   goto out;
+
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   ret = ufshcd_exec_raw_upiu_cmd(hba, _request->upiu_req,
+  _reply->upiu_rsp, msgcode,
+  desc_buff, _len, desc_op);
+  

[PATCH v7 5/8] scsi: ufs: Use data structure size in pointer arithmetic

2018-09-29 Thread Avri Altman
Use the structure size in pointer arithmetic's instead of
an opaque 32 bytes for the over allocation of descriptors.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufs.h| 2 +-
 drivers/scsi/ufs/ufshcd.c | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f1d77dc..f5800c32 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -40,7 +40,7 @@
 #include 
 #include 
 
-#define GENERAL_UPIU_REQUEST_SIZE 32
+#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
 #define QUERY_DESC_HDR_SIZE   2
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index bba5df7..5627a3b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2262,7 +2262,6 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
struct ufs_query *query = >dev_cmd.query;
u16 len = be16_to_cpu(query->request.upiu_req.length);
-   u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
 
/* Query request header */
ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -2284,7 +2283,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
 
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
-   memcpy(descp, query->descriptor, len);
+   memcpy(ucd_req_ptr + 1, query->descriptor, len);
 
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
-- 
1.9.1



[PATCH v7 6/8] scsi: ufs: Add API to execute raw upiu commands

2018-09-29 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs.h|   1 +
 drivers/scsi/ufs/ufshcd.c | 176 ++
 drivers/scsi/ufs/ufshcd.h |   7 ++
 3 files changed, 184 insertions(+)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f5800c32..58087d3 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -414,6 +414,7 @@ enum {
MASK_RSP_UPIU_DATA_SEG_LEN  = 0x,
MASK_RSP_EXCEPTION_EVENT= 0x1,
MASK_TM_SERVICE_RESP= 0xFF,
+   MASK_TM_FUNC= 0xFF,
 };
 
 /* Task management service response */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5627a3b..241efd4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5676,6 +5676,182 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @desc_op:   descriptor operation
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type,
+   enum query_opcode desc_op)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   switch (hba->ufs_version) {
+   case UFSHCI_VERSION_10:
+   case UFSHCI_VERSION_11:
+   lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+   break;
+   default:
+   lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+   break;
+   }
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr));
+   if (desc_buff && desc_op == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   /* The Data Segment Area is optional depending upon the query
+* function value. for WRITE DESCRIPTOR, the data segment
+* follows right after the tsf.
+*/
+   memcpy(lrbp->ucd_req_ptr + 1, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);

[PATCH v7 0/8] scsi: Add ufs bsg endpoint

2018-09-29 Thread Avri Altman
Here is a proposal to use a bsg endpoint to manage ufs devices.

We will do that by adding a bsg device node to the ufs driver,
and use it to send UPIU transactions to the ufs device.
It will serve as a ufs device management infrastructure, 
for device configuration, provisioning, testing and validation, etc.

We added a new ufs-bsg module, and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
This has nothing to do with the recent removal of bsg read/write support,
we might add this capability in the future,
but it is not our current focus.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

Many thanks to Christoph and Bart for their much appreciated support
and comments.

V6->v7:
Split out a new prep patch that creates include/uapi/scsi/scsi_bsg_ufs.h.
Check for a desc_op instead of passing the magic UFS_BSG_NOP in 
ufshcd_exec_raw_upiu_cmd.
Add Reviewed-by tags.

V5->v6:
Remove the host and device indices from the bsg device name,
as there can be only one.
Use the structure size in pointer arithmetic's instead of 
an opaque 32 bytes for the over allocation of descriptors.
Move ufs_bsg_request and ufs_bsg_reply to include/uapi/scsi/scsi_bsg_ufs.h.
Withdraw from decoding uic command, and just use ufshcd_send_uic_cmd 
Instead.

V4->v5:
use the new lower-level __ufshcd_issue_tm_cmd directly, so
"Allow ufshcd_issue_tm_cmd accept raw upiu" is not needed any more.
Get rid of struct ufs_bsg_node which simplifies ufs_bsg_probe().
Also some small adjustments to v4 fixes.
Have only one length and format for the reply.
Add a documentation of the API as a paragraph in
Documentation/scsi/ufs.txt.

V3->v4:
Squashed the bsg node Instantiation into "Add ufs-bsg".
Build ufs-bsg as part of  ufshcd-core and not as a separate module.
Also merged the ufs_bsg_node into the ufs_hba structure.
Christoph refactored the task management code, cleaning it up 
and making it much more readable - attached as the first 2 patches
In the series.  Afterward passing an external upiu to ufshcd_issue_tm_cmd
Just blends in.

V2->v3:
We dropped the scsi transport code (and changed this patch title
to account for it) as we actually just need the bsg device node.
We also withdraw (brokenhearted) from our intension to create
several bsg devices, and add just one. 
Rephrased the doc in Kconfig.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed a couple of patches for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.

Avri Altman (6):
  uapi: ufs: Make utp_upiu_req visible to user space
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Use data structure size in pointer arithmetic
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

Christoph Hellwig (2):
  scsi: ufs: cleanup struct utp_task_req_desc
  scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

 Documentation/scsi/ufs.txt   |  20 +++
 drivers/scsi/ufs/Kconfig |  19 ++
 drivers/scsi/ufs/Makefile|   3 +-
 drivers/scsi/ufs/ufs.h   |  94 +-
 drivers/scsi/ufs/ufs_bsg.c   | 210 ++
 drivers/scsi/ufs/ufs_bsg.h   |  23 +++
 drivers/scsi/ufs/ufshcd.c| 367 ++-
 drivers/scsi/ufs/ufshcd.h|  12 ++
 drivers/scsi/ufs/ufshci.h|  25 +--
 include/uapi/scsi/scsi_bsg_ufs.h | 105 +++
 10 files changed, 657 insertions(+), 221 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



RE: [PATCH v7 3/8] uapi: ufs: Make utp_upiu_req visible to user space

2018-10-01 Thread Avri Altman
> > +
> > +/*
> > + * This file intended to be included by both kernel and user space
> > + */
> > +
> > +#define MAX_CDB_SIZE   16
> 
> Please rename this constant such that it has either "UFS" or "UTP" in its
> name. This name is too generic for a protocol-specific header file.
Done.


Thanks,
Avri

> 
> Thanks,
> 
> Bart.



[PATCH v8 1/8] scsi: ufs: cleanup struct utp_task_req_desc

2018-10-03 Thread Avri Altman
From: Christoph Hellwig 

Remove the pointless task_req_upiu and task_rsp_upiu indirections,
which are __le32 arrays always cast to given structures and just add
the members directly.  Also clean up variables names in use in the
callers a bit to make the code more readable.

Signed-off-by: Christoph Hellwig 
Tested-by: Avri Altman 
---
 drivers/scsi/ufs/ufs.h| 30 -
 drivers/scsi/ufs/ufshcd.c | 68 ++-
 drivers/scsi/ufs/ufshci.h | 25 +
 3 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 14e5bf7..16230df 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -520,36 +520,6 @@ struct utp_upiu_rsp {
 };
 
 /**
- * struct utp_upiu_task_req - Task request UPIU structure
- * @header - UPIU header structure DW0 to DW-2
- * @input_param1: Input parameter 1 DW-3
- * @input_param2: Input parameter 2 DW-4
- * @input_param3: Input parameter 3 DW-5
- * @reserved: Reserved double words DW-6 to DW-7
- */
-struct utp_upiu_task_req {
-   struct utp_upiu_header header;
-   __be32 input_param1;
-   __be32 input_param2;
-   __be32 input_param3;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_task_rsp - Task Management Response UPIU structure
- * @header: UPIU header structure DW0-DW-2
- * @output_param1: Ouput parameter 1 DW3
- * @output_param2: Output parameter 2 DW4
- * @reserved: Reserved double words DW-5 to DW-7
- */
-struct utp_upiu_task_rsp {
-   struct utp_upiu_header header;
-   __be32 output_param1;
-   __be32 output_param2;
-   __be32 reserved[3];
-};
-
-/**
  * struct ufs_query_req - parameters for building a query request
  * @query_func: UPIU header query function
  * @upiu_req: the query request data
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 905e405..906011b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -326,14 +326,11 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba 
*hba, unsigned int tag,
 static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
-   struct utp_task_req_desc *descp;
-   struct utp_upiu_task_req *task_req;
int off = (int)tag - hba->nutrs;
+   struct utp_task_req_desc *descp = >utmrdl_base_addr[off];
 
-   descp = >utmrdl_base_addr[off];
-   task_req = (struct utp_upiu_task_req *)descp->task_req_upiu;
-   trace_ufshcd_upiu(dev_name(hba->dev), str, _req->header,
-   _req->input_param1);
+   trace_ufshcd_upiu(dev_name(hba->dev), str, >req_header,
+   >input_param1);
 }
 
 static void ufshcd_add_command_trace(struct ufs_hba *hba,
@@ -475,22 +472,13 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long 
bitmap, bool pr_prdt)
 
 static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
 {
-   struct utp_task_req_desc *tmrdp;
int tag;
 
for_each_set_bit(tag, , hba->nutmrs) {
-   tmrdp = >utmrdl_base_addr[tag];
+   struct utp_task_req_desc *tmrdp = >utmrdl_base_addr[tag];
+
dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag);
-   ufshcd_hex_dump("TM TRD: ", >header,
-   sizeof(struct request_desc_header));
-   dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
-   sizeof(struct utp_upiu_req));
-   dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
-   sizeof(struct utp_task_req_desc));
+   ufshcd_hex_dump("", tmrdp, sizeof(*tmrdp));
}
 }
 
@@ -4638,31 +4626,22 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
  */
 static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 {
-   struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_rsp *task_rsp_upiup;
+   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
unsigned long flags;
int ocs_value;
-   int task_result;
 
spin_lock_irqsave(hba->host->host_lock, flags);
 
/* Clear completed tasks from outstanding_tasks */
__clear_bit(index, >outstanding_tasks);
 
-   task_req_descp = hba->utmrdl_base_addr;
-   ocs_value = ufshcd_get_tmr_ocs(_req_descp[index]);
+   ocs_value = ufshcd_get_tmr_ocs(treq);
 
-   if (ocs_value == OCS_SUCCESS) {
-   task_rsp_upiup = (struct utp_upiu_task_rsp *)
-   task_req_d

[PATCH v8 0/8] scsi: Add ufs bsg endpoint

2018-10-03 Thread Avri Altman
Here is a proposal to use a bsg endpoint to manage ufs devices.

We will do that by adding a bsg device node to the ufs driver,
and use it to send UPIU transactions to the ufs device.
It will serve as a ufs device management infrastructure, 
for device configuration, provisioning, testing and validation, etc.

We added a new ufs-bsg module, and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
This has nothing to do with the recent removal of bsg read/write support,
we might add this capability in the future,
but it is not our current focus.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

Many thanks to Christoph and Bart for their much appreciated support
and comments.

V7->v8:
Rename MAX_CDB_SIZE UFS_CDB_SIZE

V6->v7:
Split out a new prep patch that creates include/uapi/scsi/scsi_bsg_ufs.h.
Check a desc_op instead of passing the magic UFS_BSG_NOP in 
ufshcd_exec_raw_upiu_cmd.
Add Reviewed-by tags.

V5->v6:
Remove the host and device indices from the bsg device name,
as there can be only one.
Use the structure size in pointer arithmetic's instead of 
an opaque 32 bytes for the over allocation of descriptors.
Move ufs_bsg_request and ufs_bsg_reply to include/uapi/scsi/scsi_bsg_ufs.h.
Withdraw from decoding uic command, and just use ufshcd_send_uic_cmd 
Instead.

V4->v5:
use the new lower-level __ufshcd_issue_tm_cmd directly, so
"Allow ufshcd_issue_tm_cmd accept raw upiu" is not needed any more.
Get rid of struct ufs_bsg_node which simplifies ufs_bsg_probe().
Also some small adjustments to v4 fixes.
Have only one length and format for the reply.
Add a documentation of the API as a paragraph in
Documentation/scsi/ufs.txt.

V3->v4:
Squashed the bsg node Instantiation into "Add ufs-bsg".
Build ufs-bsg as part of  ufshcd-core and not as a separate module.
Also merged the ufs_bsg_node into the ufs_hba structure.
Christoph refactored the task management code, cleaning it up 
and making it much more readable - attached as the first 2 patches
In the series.  Afterward passing an external upiu to ufshcd_issue_tm_cmd
Just blends in.

V2->v3:
We dropped the scsi transport code (and changed this patch title
to account for it) as we actually just need the bsg device node.
We also withdraw (brokenhearted) from our intension to create
several bsg devices, and add just one. 
Rephrased the doc in Kconfig.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed a couple of patches for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.

Avri Altman (6):
  uapi: ufs: Make utp_upiu_req visible to user space
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Use data structure size in pointer arithmetic
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

Christoph Hellwig (2):
  scsi: ufs: cleanup struct utp_task_req_desc
  scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

 Documentation/scsi/ufs.txt   |  20 +++
 drivers/scsi/ufs/Kconfig |  19 ++
 drivers/scsi/ufs/Makefile|   3 +-
 drivers/scsi/ufs/ufs.h   |  94 +-
 drivers/scsi/ufs/ufs_bsg.c   | 210 ++
 drivers/scsi/ufs/ufs_bsg.h   |  23 +++
 drivers/scsi/ufs/ufshcd.c| 373 ++-
 drivers/scsi/ufs/ufshcd.h|  12 ++
 drivers/scsi/ufs/ufshci.h|  25 +--
 include/uapi/scsi/scsi_bsg_ufs.h | 105 +++
 10 files changed, 660 insertions(+), 224 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



[PATCH v8 3/8] uapi: ufs: Make utp_upiu_req visible to user space

2018-10-03 Thread Avri Altman
in preparation to send UPIU requests via bsg.

Signed-off-by: Avri Altman 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs.h   | 61 +
 drivers/scsi/ufs/ufshcd.c|  6 ++--
 include/uapi/scsi/scsi_bsg_ufs.h | 74 
 3 files changed, 78 insertions(+), 63 deletions(-)
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 16230df..f1d77dc 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,8 +38,8 @@
 
 #include 
 #include 
+#include 
 
-#define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
@@ -433,65 +433,6 @@ enum ufs_dev_pwr_mode {
 };
 
 /**
- * struct utp_upiu_header - UPIU header structure
- * @dword_0: UPIU header DW-0
- * @dword_1: UPIU header DW-1
- * @dword_2: UPIU header DW-2
- */
-struct utp_upiu_header {
-   __be32 dword_0;
-   __be32 dword_1;
-   __be32 dword_2;
-};
-
-/**
- * struct utp_upiu_cmd - Command UPIU structure
- * @data_transfer_len: Data Transfer Length DW-3
- * @cdb: Command Descriptor Block CDB DW-4 to DW-7
- */
-struct utp_upiu_cmd {
-   __be32 exp_data_transfer_len;
-   u8 cdb[MAX_CDB_SIZE];
-};
-
-/**
- * struct utp_upiu_query - upiu request buffer structure for
- * query request.
- * @opcode: command to perform B-0
- * @idn: a value that indicates the particular type of data B-1
- * @index: Index to further identify data B-2
- * @selector: Index to further identify data B-3
- * @reserved_osf: spec reserved field B-4,5
- * @length: number of descriptor bytes to read/write B-6,7
- * @value: Attribute value to be written DW-5
- * @reserved: spec reserved DW-6,7
- */
-struct utp_upiu_query {
-   u8 opcode;
-   u8 idn;
-   u8 index;
-   u8 selector;
-   __be16 reserved_osf;
-   __be16 length;
-   __be32 value;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_req - general upiu request structure
- * @header:UPIU header structure DW-0 to DW-2
- * @sc: fields structure for scsi command DW-3 to DW-7
- * @qr: fields structure for query request DW-3 to DW-7
- */
-struct utp_upiu_req {
-   struct utp_upiu_header header;
-   union {
-   struct utp_upiu_cmd sc;
-   struct utp_upiu_query qr;
-   };
-};
-
-/**
  * struct utp_cmd_rsp - Response UPIU structure
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5005432..fdbf07a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2241,8 +2241,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb 
*lrbp, u32 upiu_flags)
ucd_req_ptr->sc.exp_data_transfer_len =
cpu_to_be32(lrbp->cmd->sdb.length);
 
-   cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
-   memset(ucd_req_ptr->sc.cdb, 0, MAX_CDB_SIZE);
+   cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, UFS_CDB_SIZE);
+   memset(ucd_req_ptr->sc.cdb, 0, UFS_CDB_SIZE);
memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
 
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
@@ -8007,7 +8007,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
host->max_lun = UFS_MAX_LUNS;
host->max_channel = UFSHCD_MAX_CHANNEL;
host->unique_id = host->host_no;
-   host->max_cmd_len = MAX_CDB_SIZE;
+   host->max_cmd_len = UFS_CDB_SIZE;
 
hba->max_pwr_info.is_valid = false;
 
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
new file mode 100644
index 000..4108ce3
--- /dev/null
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TBD - UFS Transport SGIO v4 BSG Message Support
+ *
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ */
+#ifndef SCSI_BSG_UFS_H
+#define SCSI_BSG_UFS_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+#define UFS_CDB_SIZE   16
+
+/**
+ * struct utp_upiu_header - UPIU header structure
+ * @dword_0: UPIU header DW-0
+ * @dword_1: UPIU header DW-1
+ * @dword_2: UPIU header DW-2
+ */
+struct utp_upiu_header {
+   __be32 dword_0;
+   __be32 dword_1;
+   __be32 dword_2;
+};
+
+/**
+ * struct utp_upiu_query - upiu request buffer structure for
+ * query request.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @reserved_osf: spec reserved field B-4,5
+ * @length: number of descriptor bytes to read/write B-6,7
+ * @value: Attribute value to be written DW-5
+ * @reserved: spec res

[PATCH v8 5/8] scsi: ufs: Use data structure size in pointer arithmetic

2018-10-03 Thread Avri Altman
Use the structure size in pointer arithmetic's instead of
an opaque 32 bytes for the over allocation of descriptors.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufs.h| 2 +-
 drivers/scsi/ufs/ufshcd.c | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f1d77dc..f5800c32 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -40,7 +40,7 @@
 #include 
 #include 
 
-#define GENERAL_UPIU_REQUEST_SIZE 32
+#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
 #define QUERY_DESC_HDR_SIZE   2
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7f376fb..ccad830 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2262,7 +2262,6 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
struct ufs_query *query = >dev_cmd.query;
u16 len = be16_to_cpu(query->request.upiu_req.length);
-   u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
 
/* Query request header */
ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -2284,7 +2283,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
 
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
-   memcpy(descp, query->descriptor, len);
+   memcpy(ucd_req_ptr + 1, query->descriptor, len);
 
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
-- 
1.9.1



[PATCH v8 2/8] scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

2018-10-03 Thread Avri Altman
From: Christoph Hellwig 

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support.  Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig 
Tested-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 141 --
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 906011b..5005432 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -634,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb 
*lrbp)
 }
 
 /**
- * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
- * @task_req_descp: pointer to utp_task_req_desc structure
- *
- * This function is used to get the OCS field from UTMRD
- * Returns the OCS field in the UTMRD
- */
-static inline int
-ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
-{
-   return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
-}
-
-/**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
  * @free_slot: pointer to variable with available slot value
@@ -4617,37 +4604,6 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
 }
 
 /**
- * ufshcd_task_req_compl - handle task management request completion
- * @hba: per adapter instance
- * @index: index of the completed request
- * @resp: task management service response
- *
- * Returns non-zero value on error, zero on success
- */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
-{
-   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
-   unsigned long flags;
-   int ocs_value;
-
-   spin_lock_irqsave(hba->host->host_lock, flags);
-
-   /* Clear completed tasks from outstanding_tasks */
-   __clear_bit(index, >outstanding_tasks);
-
-   ocs_value = ufshcd_get_tmr_ocs(treq);
-
-   if (ocs_value != OCS_SUCCESS)
-   dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-   __func__, ocs_value);
-   else if (resp)
-   *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
-   spin_unlock_irqrestore(hba->host->host_lock, flags);
-
-   return ocs_value;
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrbp: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -5604,27 +5560,12 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
-/**
- * ufshcd_issue_tm_cmd - issues task management commands to controller
- * @hba: per adapter instance
- * @lun_id: LUN ID to which TM command is sent
- * @task_id: task ID to which the TM command is applicable
- * @tm_function: task management function opcode
- * @tm_response: task management service response return value
- *
- * Returns non-zero value on error, zero on success.
- */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+   struct utp_task_req_desc *treq, u8 tm_function)
 {
-   struct utp_task_req_desc *treq;
-   struct Scsi_Host *host;
+   struct Scsi_Host *host = hba->host;
unsigned long flags;
-   int free_slot;
-   int err;
-   int task_tag;
-
-   host = hba->host;
+   int free_slot, task_tag, err;
 
/*
 * Get free slot, sleep if slots are unavailable.
@@ -5635,24 +5576,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
ufshcd_hold(hba, false);
 
spin_lock_irqsave(host->host_lock, flags);
-   treq = hba->utmrdl_base_addr + free_slot;
-
-   /* Configure task request descriptor */
-   treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
task_tag = hba->nutrs + free_slot;
-   treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
-   0, lun_id, task_tag);
-   treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   treq->input_param1 = cpu_to_be32(lun_id);
-   treq->input_param2 = cpu_to_be32(task_id);
 
+   treq->req_header.dword_0 |= cpu_to_be32(task_tag);
+
+   memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
/* send command to the controller */
@@ -5682,8 +5610,15 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
  

[PATCH v8 8/8] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-10-03 Thread Avri Altman
Make ufshcd_send_uic_cmd() public for that.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c   | 11 +++
 drivers/scsi/ufs/ufshcd.c|  3 +--
 drivers/scsi/ufs/ufshcd.h|  2 ++
 include/uapi/scsi/scsi_bsg_ufs.h |  3 +++
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 306e5f1..e5f8e54 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -84,6 +84,7 @@ static int ufs_bsg_request(struct bsg_job *job)
struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
unsigned int req_len = job->request_len;
unsigned int reply_len = job->reply_len;
+   struct uic_command uc = {};
int msgcode;
uint8_t *desc_buff = NULL;
int desc_len = 0;
@@ -117,6 +118,16 @@ static int ufs_bsg_request(struct bsg_job *job)
"exe raw upiu: error code %d\n", ret);
 
break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   memcpy(, _request->upiu_req.uc, UIC_CMD_SIZE);
+   ret = ufshcd_send_uic_cmd(hba, );
+   if (ret)
+   dev_dbg(hba->dev,
+   "send uic cmd: error code %d\n", ret);
+
+   memcpy(_reply->upiu_rsp.uc, , UIC_CMD_SIZE);
+
+   break;
default:
ret = -ENOTSUPP;
dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9515bc7..d7218d2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2059,8 +2059,7 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  *
  * Returns 0 only if success.
  */
-static int
-ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
int ret;
unsigned long flags;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0878134..1a1c2b4 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -895,6 +895,8 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum 
desc_idn desc_id,
 
 u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
 
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+
 int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 struct utp_upiu_req *req_upiu,
 struct utp_upiu_req *rsp_upiu,
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index 3b83375..74039c1 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -13,6 +13,9 @@
  */
 
 #define UFS_CDB_SIZE   16
+#define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 /**
  * struct utp_upiu_header - UPIU header structure
-- 
1.9.1



[PATCH v8 4/8] scsi: ufs: Add ufs-bsg module

2018-10-03 Thread Avri Altman
Add a bsg endpoint that supports UPIUs.

For now, just provide an API to allocate and remove
ufs-bsg node. We will use this framework to
manage ufs devices by sending UPIU transactions.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Moreover and as a result, our core structure - ufs_bsg_node has
a pretty lean structure: using upiu transactions that contains
the outmost detailed info, so we don't really need complex
constructs to support it.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 Documentation/scsi/ufs.txt   | 20 +
 drivers/scsi/ufs/Kconfig | 19 
 drivers/scsi/ufs/Makefile|  3 +-
 drivers/scsi/ufs/ufs_bsg.c   | 93 
 drivers/scsi/ufs/ufs_bsg.h   | 23 ++
 drivers/scsi/ufs/ufshcd.c|  4 ++
 drivers/scsi/ufs/ufshcd.h|  3 ++
 include/uapi/scsi/scsi_bsg_ufs.h | 30 -
 8 files changed, 193 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h

diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.txt
index 41a6164..2616d5f 100644
--- a/Documentation/scsi/ufs.txt
+++ b/Documentation/scsi/ufs.txt
@@ -128,6 +128,26 @@ The current UFSHCD implementation supports following 
functionality,
 In this version of UFSHCD Query requests and power management
 functionality are not implemented.
 
+4. BSG Support
+--
+
+This transport driver supports exchanging UFS protocol information units
+(UPIUs) with an UFS device. Typically, user space will allocate
+struct ufs_bsg_request and struct ufs_bsg_reply (see ufs_bsg.h) as
+request_upiu and reply_upiu respectively.  Filling those UPIUs should
+be done in accordance with JEDEC spec UFS2.1 paragraph 10.7.
+*Caveat emptor*: The driver makes no further input validations and sends the
+UPIU to the device as it is.  Open the bsg device in /dev/ufs-bsg and
+send SG_IO with the applicable sg_io_v4:
+
+   io_hdr_v4.guard = 'Q';
+   io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
+   io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
+   io_hdr_v4.response = (__u64)reply_upiu;
+   io_hdr_v4.max_response_len = reply_len;
+   io_hdr_v4.request_len = request_len;
+   io_hdr_v4.request = (__u64)request_upiu;
+
 UFS Specifications can be found at,
 UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
 UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e09fe6a..83ba979 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -109,3 +109,22 @@ config SCSI_UFS_HISI
 
  Select this if you have UFS controller on Hisilicon chipset.
  If unsure, say N.
+
+config SCSI_UFS_BSG
+   bool "Universal Flash Storage BSG device node"
+   depends on SCSI_UFSHCD
+   select BLK_DEV_BSGLIB
+   help
+ Universal Flash Storage (UFS) is SCSI transport specification for
+ accessing flash storage on digital cameras, mobile phones and
+ consumer electronic devices.
+ An UFS controller communicates with an UFS device by exchanging
+ UFS Protocol Information Units (UPIUs).
+ UPIUs can not only be used as a transport layer for the SCSI protocol
+ but are also used by the UFS native command set.
+ This transport driver supports exchanging UFS protocol information 
units
+ with an UFS device. See also the ufshcd driver, which is a SCSI driver
+ that supports UFS devices.
+
+ Select this if you need a bsg device node for your UFS controller.
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..aca4813 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o 
ufshcd-dwc.o tc-dwc-g210.
 obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o 
tc-dwc-g210.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
-ufshcd-core-objs := ufshcd.o ufs-sysfs.o
+ufshcd-core-y  += ufshcd.o ufs-sysfs.o
+ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
 obj-$(CONFIG_SCSI_

[PATCH v8 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-10-03 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c | 114 +++--
 1 file changed, 110 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 1036c52..306e5f1 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -6,19 +6,125 @@
  */
 #include "ufs_bsg.h"
 
+static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
+  struct utp_upiu_query *qr)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret;
+
+   if (desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
+   if (ret || !*desc_len)
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
+unsigned int request_len,
+unsigned int reply_len,
+int desc_len, enum query_opcode desc_op)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len || min_rsp_len > reply_len) {
+   dev_err(hba->dev, "not enough space assigned\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_params(struct ufs_hba *hba,
+  struct ufs_bsg_request *bsg_request,
+  unsigned int request_len,
+  unsigned int reply_len,
+  uint8_t *desc_buff, int *desc_len,
+  enum query_opcode desc_op)
+{
+   struct utp_upiu_query *qr;
+
+   if (desc_op == UPIU_QUERY_OPCODE_READ_DESC) {
+   dev_err(hba->dev, "unsupported opcode %d\n", desc_op);
+   return -ENOTSUPP;
+   }
+
+   if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC)
+   goto out;
+
+   qr = _request->upiu_req.qr;
+   if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) {
+   dev_err(hba->dev, "Illegal desc size\n");
+   return -EINVAL;
+   }
+
+   if (ufs_bsg_verify_query_size(hba, request_len, reply_len, *desc_len,
+ desc_op))
+   return -EINVAL;
+
+   desc_buff = (uint8_t *)(bsg_request + 1);
+
+out:
+   return 0;
+}
 
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
+   unsigned int req_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
+   int ret;
+
+   ret = ufs_bsg_verify_query_size(hba, req_len, reply_len, 0, desc_op);
+   if (ret)
+   goto out;
 
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   desc_op = bsg_request->upiu_req.qr.opcode;
+   ret = ufs_bsg_verify_query_params(hba, bsg_request, req_len,
+ reply_len, desc_buff,
+ _len, desc_op);
+   if (ret)
+   goto out;
+
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   ret = ufshcd_exec_raw_upiu_cmd(hba, _request->upiu_req,
+  _reply->upiu_rsp, msgcode,
+  desc_buff, _len, desc_op);
+  

[PATCH v8 6/8] scsi: ufs: Add API to execute raw upiu commands

2018-10-03 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs.h|   1 +
 drivers/scsi/ufs/ufshcd.c | 176 ++
 drivers/scsi/ufs/ufshcd.h |   7 ++
 3 files changed, 184 insertions(+)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f5800c32..58087d3 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -414,6 +414,7 @@ enum {
MASK_RSP_UPIU_DATA_SEG_LEN  = 0x,
MASK_RSP_EXCEPTION_EVENT= 0x1,
MASK_TM_SERVICE_RESP= 0xFF,
+   MASK_TM_FUNC= 0xFF,
 };
 
 /* Task management service response */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ccad830..9515bc7 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5676,6 +5676,182 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @desc_op:   descriptor operation
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type,
+   enum query_opcode desc_op)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   switch (hba->ufs_version) {
+   case UFSHCI_VERSION_10:
+   case UFSHCI_VERSION_11:
+   lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+   break;
+   default:
+   lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+   break;
+   }
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr));
+   if (desc_buff && desc_op == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   /* The Data Segment Area is optional depending upon the query
+* function value. for WRITE DESCRIPTOR, the data segment
+* follows right after the tsf.
+*/
+   memcpy(lrbp->ucd_req_ptr + 1, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);

[PATCH v9 3/8] uapi: ufs: Make utp_upiu_req visible to user space

2018-10-07 Thread Avri Altman
in preparation to send UPIU requests via bsg.

Signed-off-by: Avri Altman 
Reviewed-by: Bart Van Assche 
Reviewed-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufs.h   | 61 +
 drivers/scsi/ufs/ufshcd.c|  6 ++--
 include/uapi/scsi/scsi_bsg_ufs.h | 74 
 3 files changed, 78 insertions(+), 63 deletions(-)
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 16230df..f1d77dc 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,8 +38,8 @@
 
 #include 
 #include 
+#include 
 
-#define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
@@ -433,65 +433,6 @@ enum ufs_dev_pwr_mode {
 };
 
 /**
- * struct utp_upiu_header - UPIU header structure
- * @dword_0: UPIU header DW-0
- * @dword_1: UPIU header DW-1
- * @dword_2: UPIU header DW-2
- */
-struct utp_upiu_header {
-   __be32 dword_0;
-   __be32 dword_1;
-   __be32 dword_2;
-};
-
-/**
- * struct utp_upiu_cmd - Command UPIU structure
- * @data_transfer_len: Data Transfer Length DW-3
- * @cdb: Command Descriptor Block CDB DW-4 to DW-7
- */
-struct utp_upiu_cmd {
-   __be32 exp_data_transfer_len;
-   u8 cdb[MAX_CDB_SIZE];
-};
-
-/**
- * struct utp_upiu_query - upiu request buffer structure for
- * query request.
- * @opcode: command to perform B-0
- * @idn: a value that indicates the particular type of data B-1
- * @index: Index to further identify data B-2
- * @selector: Index to further identify data B-3
- * @reserved_osf: spec reserved field B-4,5
- * @length: number of descriptor bytes to read/write B-6,7
- * @value: Attribute value to be written DW-5
- * @reserved: spec reserved DW-6,7
- */
-struct utp_upiu_query {
-   u8 opcode;
-   u8 idn;
-   u8 index;
-   u8 selector;
-   __be16 reserved_osf;
-   __be16 length;
-   __be32 value;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_req - general upiu request structure
- * @header:UPIU header structure DW-0 to DW-2
- * @sc: fields structure for scsi command DW-3 to DW-7
- * @qr: fields structure for query request DW-3 to DW-7
- */
-struct utp_upiu_req {
-   struct utp_upiu_header header;
-   union {
-   struct utp_upiu_cmd sc;
-   struct utp_upiu_query qr;
-   };
-};
-
-/**
  * struct utp_cmd_rsp - Response UPIU structure
  * @residual_transfer_count: Residual transfer count DW-3
  * @reserved: Reserved double words DW-4 to DW-7
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5005432..fdbf07a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2241,8 +2241,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb 
*lrbp, u32 upiu_flags)
ucd_req_ptr->sc.exp_data_transfer_len =
cpu_to_be32(lrbp->cmd->sdb.length);
 
-   cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
-   memset(ucd_req_ptr->sc.cdb, 0, MAX_CDB_SIZE);
+   cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, UFS_CDB_SIZE);
+   memset(ucd_req_ptr->sc.cdb, 0, UFS_CDB_SIZE);
memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
 
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
@@ -8007,7 +8007,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem 
*mmio_base, unsigned int irq)
host->max_lun = UFS_MAX_LUNS;
host->max_channel = UFSHCD_MAX_CHANNEL;
host->unique_id = host->host_no;
-   host->max_cmd_len = MAX_CDB_SIZE;
+   host->max_cmd_len = UFS_CDB_SIZE;
 
hba->max_pwr_info.is_valid = false;
 
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
new file mode 100644
index 000..5e0b9d9
--- /dev/null
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * UFS Transport SGIO v4 BSG Message Support
+ *
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ */
+#ifndef SCSI_BSG_UFS_H
+#define SCSI_BSG_UFS_H
+
+/*
+ * This file intended to be included by both kernel and user space
+ */
+
+#define UFS_CDB_SIZE   16
+
+/**
+ * struct utp_upiu_header - UPIU header structure
+ * @dword_0: UPIU header DW-0
+ * @dword_1: UPIU header DW-1
+ * @dword_2: UPIU header DW-2
+ */
+struct utp_upiu_header {
+   __be32 dword_0;
+   __be32 dword_1;
+   __be32 dword_2;
+};
+
+/**
+ * struct utp_upiu_query - upiu request buffer structure for
+ * query request.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @reserved_osf: spec reserved field B-4,5
+ * @length: number of descriptor bytes to read/write B-6,7
+ * @value: Attribute value to be written DW-5
+ *

[PATCH v9 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-10-07 Thread Avri Altman
Do that for the currently supported UPIUs: query, nop out,
and task management.

We do not support UPIU of type scsi command yet, while we are using the
job's request and reply pointers to hold the payload.  We will look into
it in later patches. We might need to elaborate the raw upiu api for
that.

We also still not supporting uic commands: For first phase, we plan to
use the existing api, and send only uic commands that are already
supported. Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c | 114 +++--
 1 file changed, 110 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 1036c52..306e5f1 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -6,19 +6,125 @@
  */
 #include "ufs_bsg.h"
 
+static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
+  struct utp_upiu_query *qr)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret;
+
+   if (desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
+   if (ret || !*desc_len)
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
+unsigned int request_len,
+unsigned int reply_len,
+int desc_len, enum query_opcode desc_op)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len || min_rsp_len > reply_len) {
+   dev_err(hba->dev, "not enough space assigned\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+static int ufs_bsg_verify_query_params(struct ufs_hba *hba,
+  struct ufs_bsg_request *bsg_request,
+  unsigned int request_len,
+  unsigned int reply_len,
+  uint8_t *desc_buff, int *desc_len,
+  enum query_opcode desc_op)
+{
+   struct utp_upiu_query *qr;
+
+   if (desc_op == UPIU_QUERY_OPCODE_READ_DESC) {
+   dev_err(hba->dev, "unsupported opcode %d\n", desc_op);
+   return -ENOTSUPP;
+   }
+
+   if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC)
+   goto out;
+
+   qr = _request->upiu_req.qr;
+   if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) {
+   dev_err(hba->dev, "Illegal desc size\n");
+   return -EINVAL;
+   }
+
+   if (ufs_bsg_verify_query_size(hba, request_len, reply_len, *desc_len,
+ desc_op))
+   return -EINVAL;
+
+   desc_buff = (uint8_t *)(bsg_request + 1);
+
+out:
+   return 0;
+}
 
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
+   unsigned int req_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
+   int ret;
+
+   ret = ufs_bsg_verify_query_size(hba, req_len, reply_len, 0, desc_op);
+   if (ret)
+   goto out;
 
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   desc_op = bsg_request->upiu_req.qr.opcode;
+   ret = ufs_bsg_verify_query_params(hba, bsg_request, req_len,
+ reply_len, desc_buff,
+ _len, desc_op);
+   if (ret)
+   goto out;
+
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   ret = ufshcd_exec_raw_upiu_cmd(hba, _request->upiu_req,
+  _reply->upiu_rsp, msgcode,
+  desc_buff, _len, desc_op);
+  

[PATCH v9 0/8] scsi: Add ufs bsg endpoint

2018-10-07 Thread Avri Altman
Here is a proposal to use a bsg endpoint to manage ufs devices.

We will do that by adding a bsg device node to the ufs driver,
and use it to send UPIU transactions to the ufs device.
It will serve as a ufs device management infrastructure, 
for device configuration, provisioning, testing and validation, etc.

We added a new ufs-bsg module, and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
This has nothing to do with the recent removal of bsg read/write support,
we might add this capability in the future,
but it is not our current focus.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.

Many thanks to Christoph and Bart for their much appreciated support
and comments.

V8->v9:
Use __u8 instead of u8 for uapi headers.
Use up to 73 characters per line to make the changelogs more Readable.
Some more editorial comments.

V7->v8:
Rename MAX_CDB_SIZE UFS_CDB_SIZE

V6->v7:
Split out a new prep patch that creates include/uapi/scsi/scsi_bsg_ufs.h.
Check a desc_op instead of passing the magic UFS_BSG_NOP in 
ufshcd_exec_raw_upiu_cmd.
Add Reviewed-by tags.

V5->v6:
Remove the host and device indices from the bsg device name,
as there can be only one.
Use the structure size in pointer arithmetic's instead of 
an opaque 32 bytes for the over allocation of descriptors.
Move ufs_bsg_request and ufs_bsg_reply to include/uapi/scsi/scsi_bsg_ufs.h.
Withdraw from decoding uic command, and just use ufshcd_send_uic_cmd 
Instead.

V4->v5:
use the new lower-level __ufshcd_issue_tm_cmd directly, so
"Allow ufshcd_issue_tm_cmd accept raw upiu" is not needed any more.
Get rid of struct ufs_bsg_node which simplifies ufs_bsg_probe().
Also some small adjustments to v4 fixes.
Have only one length and format for the reply.
Add a documentation of the API as a paragraph in
Documentation/scsi/ufs.txt.

V3->v4:
Squashed the bsg node Instantiation into "Add ufs-bsg".
Build ufs-bsg as part of  ufshcd-core and not as a separate module.
Also merged the ufs_bsg_node into the ufs_hba structure.
Christoph refactored the task management code, cleaning it up 
and making it much more readable - attached as the first 2 patches
In the series.  Afterward passing an external upiu to ufshcd_issue_tm_cmd
Just blends in.

V2->v3:
We dropped the scsi transport code (and changed this patch title
to account for it) as we actually just need the bsg device node.
We also withdraw (brokenhearted) from our intension to create
several bsg devices, and add just one. 
Rephrased the doc in Kconfig.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed a couple of patches for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.

Avri Altman (6):
  uapi: ufs: Make utp_upiu_req visible to user space
  scsi: ufs: Add a bsg endpoint that supports UPIUs
  scsi: ufs: Use data structure size in pointer arithmetic
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

Christoph Hellwig (2):
  scsi: ufs: cleanup struct utp_task_req_desc
  scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

 Documentation/scsi/ufs.txt   |  20 +++
 drivers/scsi/ufs/Kconfig |  19 ++
 drivers/scsi/ufs/Makefile|   3 +-
 drivers/scsi/ufs/ufs.h   |  94 +-
 drivers/scsi/ufs/ufs_bsg.c   | 210 ++
 drivers/scsi/ufs/ufs_bsg.h   |  23 +++
 drivers/scsi/ufs/ufshcd.c| 373 ++-
 drivers/scsi/ufs/ufshcd.h|  12 ++
 drivers/scsi/ufs/ufshci.h|  25 +--
 include/uapi/scsi/scsi_bsg_ufs.h | 105 +++
 10 files changed, 660 insertions(+), 224 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



[PATCH v9 2/8] scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper

2018-10-07 Thread Avri Altman
From: Christoph Hellwig 

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support.  Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig 
Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 141 --
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 906011b..5005432 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -634,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb 
*lrbp)
 }
 
 /**
- * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
- * @task_req_descp: pointer to utp_task_req_desc structure
- *
- * This function is used to get the OCS field from UTMRD
- * Returns the OCS field in the UTMRD
- */
-static inline int
-ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
-{
-   return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
-}
-
-/**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
  * @free_slot: pointer to variable with available slot value
@@ -4617,37 +4604,6 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
 }
 
 /**
- * ufshcd_task_req_compl - handle task management request completion
- * @hba: per adapter instance
- * @index: index of the completed request
- * @resp: task management service response
- *
- * Returns non-zero value on error, zero on success
- */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
-{
-   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
-   unsigned long flags;
-   int ocs_value;
-
-   spin_lock_irqsave(hba->host->host_lock, flags);
-
-   /* Clear completed tasks from outstanding_tasks */
-   __clear_bit(index, >outstanding_tasks);
-
-   ocs_value = ufshcd_get_tmr_ocs(treq);
-
-   if (ocs_value != OCS_SUCCESS)
-   dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-   __func__, ocs_value);
-   else if (resp)
-   *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
-   spin_unlock_irqrestore(hba->host->host_lock, flags);
-
-   return ocs_value;
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrbp: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -5604,27 +5560,12 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
-/**
- * ufshcd_issue_tm_cmd - issues task management commands to controller
- * @hba: per adapter instance
- * @lun_id: LUN ID to which TM command is sent
- * @task_id: task ID to which the TM command is applicable
- * @tm_function: task management function opcode
- * @tm_response: task management service response return value
- *
- * Returns non-zero value on error, zero on success.
- */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+   struct utp_task_req_desc *treq, u8 tm_function)
 {
-   struct utp_task_req_desc *treq;
-   struct Scsi_Host *host;
+   struct Scsi_Host *host = hba->host;
unsigned long flags;
-   int free_slot;
-   int err;
-   int task_tag;
-
-   host = hba->host;
+   int free_slot, task_tag, err;
 
/*
 * Get free slot, sleep if slots are unavailable.
@@ -5635,24 +5576,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
ufshcd_hold(hba, false);
 
spin_lock_irqsave(host->host_lock, flags);
-   treq = hba->utmrdl_base_addr + free_slot;
-
-   /* Configure task request descriptor */
-   treq->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   treq->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
task_tag = hba->nutrs + free_slot;
-   treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
-   0, lun_id, task_tag);
-   treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   treq->input_param1 = cpu_to_be32(lun_id);
-   treq->input_param2 = cpu_to_be32(task_id);
 
+   treq->req_header.dword_0 |= cpu_to_be32(task_tag);
+
+   memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
/* send command to the controller */
@@ -5682,8 +5610,15 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
  

[PATCH v9 4/8] scsi: ufs: Add a bsg endpoint that supports UPIUs

2018-10-07 Thread Avri Altman
For now, just provide an API to allocate and remove ufs-bsg node. We
will use this framework to manage ufs devices by sending UPIU
transactions.

For the time being, implements an empty bsg_request() - will add some
more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use: UFS
Transport Protocol Transactions. UFS transactions consist of packets
called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses, data in and
data out, task management, utility functions, vendor functions,
transaction synchronization and control, and more.

By using UPIUs, we get access to the most fine-grained internals of this
protocol, and able to communicate with the device in ways, that are
sometimes beyond the capacity of the ufs driver.

Moreover and as a result, our core structure - ufs_bsg_node has a pretty
lean structure: using upiu transactions that contains the outmost
detailed info, so we don't really need complex constructs to support it.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 Documentation/scsi/ufs.txt   | 20 +
 drivers/scsi/ufs/Kconfig | 19 
 drivers/scsi/ufs/Makefile|  3 +-
 drivers/scsi/ufs/ufs_bsg.c   | 93 
 drivers/scsi/ufs/ufs_bsg.h   | 23 ++
 drivers/scsi/ufs/ufshcd.c|  4 ++
 drivers/scsi/ufs/ufshcd.h|  3 ++
 include/uapi/scsi/scsi_bsg_ufs.h | 28 
 8 files changed, 192 insertions(+), 1 deletion(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h

diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.txt
index 41a6164..2616d5f 100644
--- a/Documentation/scsi/ufs.txt
+++ b/Documentation/scsi/ufs.txt
@@ -128,6 +128,26 @@ The current UFSHCD implementation supports following 
functionality,
 In this version of UFSHCD Query requests and power management
 functionality are not implemented.
 
+4. BSG Support
+--
+
+This transport driver supports exchanging UFS protocol information units
+(UPIUs) with an UFS device. Typically, user space will allocate
+struct ufs_bsg_request and struct ufs_bsg_reply (see ufs_bsg.h) as
+request_upiu and reply_upiu respectively.  Filling those UPIUs should
+be done in accordance with JEDEC spec UFS2.1 paragraph 10.7.
+*Caveat emptor*: The driver makes no further input validations and sends the
+UPIU to the device as it is.  Open the bsg device in /dev/ufs-bsg and
+send SG_IO with the applicable sg_io_v4:
+
+   io_hdr_v4.guard = 'Q';
+   io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
+   io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
+   io_hdr_v4.response = (__u64)reply_upiu;
+   io_hdr_v4.max_response_len = reply_len;
+   io_hdr_v4.request_len = request_len;
+   io_hdr_v4.request = (__u64)request_upiu;
+
 UFS Specifications can be found at,
 UFS - http://www.jedec.org/sites/default/files/docs/JESD220.pdf
 UFSHCI - http://www.jedec.org/sites/default/files/docs/JESD223.pdf
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e09fe6a..83ba979 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -109,3 +109,22 @@ config SCSI_UFS_HISI
 
  Select this if you have UFS controller on Hisilicon chipset.
  If unsure, say N.
+
+config SCSI_UFS_BSG
+   bool "Universal Flash Storage BSG device node"
+   depends on SCSI_UFSHCD
+   select BLK_DEV_BSGLIB
+   help
+ Universal Flash Storage (UFS) is SCSI transport specification for
+ accessing flash storage on digital cameras, mobile phones and
+ consumer electronic devices.
+ An UFS controller communicates with an UFS device by exchanging
+ UFS Protocol Information Units (UPIUs).
+ UPIUs can not only be used as a transport layer for the SCSI protocol
+ but are also used by the UFS native command set.
+ This transport driver supports exchanging UFS protocol information 
units
+ with an UFS device. See also the ufshcd driver, which is a SCSI driver
+ that supports UFS devices.
+
+ Select this if you need a bsg device node for your UFS controller.
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..aca4813 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o 
ufshcd-dwc.o tc-dwc-g210.
 obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o 
tc-dwc-g210.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
-ufshcd-core-objs := ufshcd.o ufs-sysfs.o
+ufshcd-core-y  += ufshcd.o ufs-sysfs.o
+ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHC

[PATCH v9 8/8] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-10-07 Thread Avri Altman
Make ufshcd_send_uic_cmd() public for that.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs_bsg.c   | 11 +++
 drivers/scsi/ufs/ufshcd.c|  3 +--
 drivers/scsi/ufs/ufshcd.h|  2 ++
 include/uapi/scsi/scsi_bsg_ufs.h |  3 +++
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 306e5f1..e5f8e54 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -84,6 +84,7 @@ static int ufs_bsg_request(struct bsg_job *job)
struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
unsigned int req_len = job->request_len;
unsigned int reply_len = job->reply_len;
+   struct uic_command uc = {};
int msgcode;
uint8_t *desc_buff = NULL;
int desc_len = 0;
@@ -117,6 +118,16 @@ static int ufs_bsg_request(struct bsg_job *job)
"exe raw upiu: error code %d\n", ret);
 
break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   memcpy(, _request->upiu_req.uc, UIC_CMD_SIZE);
+   ret = ufshcd_send_uic_cmd(hba, );
+   if (ret)
+   dev_dbg(hba->dev,
+   "send uic cmd: error code %d\n", ret);
+
+   memcpy(_reply->upiu_rsp.uc, , UIC_CMD_SIZE);
+
+   break;
default:
ret = -ENOTSUPP;
dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9515bc7..d7218d2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2059,8 +2059,7 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  *
  * Returns 0 only if success.
  */
-static int
-ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
int ret;
unsigned long flags;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0878134..1a1c2b4 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -895,6 +895,8 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum 
desc_idn desc_id,
 
 u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
 
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+
 int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
 struct utp_upiu_req *req_upiu,
 struct utp_upiu_req *rsp_upiu,
diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h
index e426204..1b25930 100644
--- a/include/uapi/scsi/scsi_bsg_ufs.h
+++ b/include/uapi/scsi/scsi_bsg_ufs.h
@@ -13,6 +13,9 @@
  */
 
 #define UFS_CDB_SIZE   16
+#define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 /**
  * struct utp_upiu_header - UPIU header structure
-- 
1.9.1



[PATCH v9 1/8] scsi: ufs: cleanup struct utp_task_req_desc

2018-10-07 Thread Avri Altman
From: Christoph Hellwig 

Remove the pointless task_req_upiu and task_rsp_upiu indirections,
which are __le32 arrays always cast to given structures and just add
the members directly.  Also clean up variables names in use in the
callers a bit to make the code more readable.

Signed-off-by: Christoph Hellwig 
Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs.h| 30 -
 drivers/scsi/ufs/ufshcd.c | 68 ++-
 drivers/scsi/ufs/ufshci.h | 25 +
 3 files changed, 34 insertions(+), 89 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 14e5bf7..16230df 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -520,36 +520,6 @@ struct utp_upiu_rsp {
 };
 
 /**
- * struct utp_upiu_task_req - Task request UPIU structure
- * @header - UPIU header structure DW0 to DW-2
- * @input_param1: Input parameter 1 DW-3
- * @input_param2: Input parameter 2 DW-4
- * @input_param3: Input parameter 3 DW-5
- * @reserved: Reserved double words DW-6 to DW-7
- */
-struct utp_upiu_task_req {
-   struct utp_upiu_header header;
-   __be32 input_param1;
-   __be32 input_param2;
-   __be32 input_param3;
-   __be32 reserved[2];
-};
-
-/**
- * struct utp_upiu_task_rsp - Task Management Response UPIU structure
- * @header: UPIU header structure DW0-DW-2
- * @output_param1: Ouput parameter 1 DW3
- * @output_param2: Output parameter 2 DW4
- * @reserved: Reserved double words DW-5 to DW-7
- */
-struct utp_upiu_task_rsp {
-   struct utp_upiu_header header;
-   __be32 output_param1;
-   __be32 output_param2;
-   __be32 reserved[3];
-};
-
-/**
  * struct ufs_query_req - parameters for building a query request
  * @query_func: UPIU header query function
  * @upiu_req: the query request data
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 905e405..906011b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -326,14 +326,11 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba 
*hba, unsigned int tag,
 static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
 {
-   struct utp_task_req_desc *descp;
-   struct utp_upiu_task_req *task_req;
int off = (int)tag - hba->nutrs;
+   struct utp_task_req_desc *descp = >utmrdl_base_addr[off];
 
-   descp = >utmrdl_base_addr[off];
-   task_req = (struct utp_upiu_task_req *)descp->task_req_upiu;
-   trace_ufshcd_upiu(dev_name(hba->dev), str, _req->header,
-   _req->input_param1);
+   trace_ufshcd_upiu(dev_name(hba->dev), str, >req_header,
+   >input_param1);
 }
 
 static void ufshcd_add_command_trace(struct ufs_hba *hba,
@@ -475,22 +472,13 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long 
bitmap, bool pr_prdt)
 
 static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
 {
-   struct utp_task_req_desc *tmrdp;
int tag;
 
for_each_set_bit(tag, , hba->nutmrs) {
-   tmrdp = >utmrdl_base_addr[tag];
+   struct utp_task_req_desc *tmrdp = >utmrdl_base_addr[tag];
+
dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag);
-   ufshcd_hex_dump("TM TRD: ", >header,
-   sizeof(struct request_desc_header));
-   dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
-   sizeof(struct utp_upiu_req));
-   dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n",
-   tag);
-   ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
-   sizeof(struct utp_task_req_desc));
+   ufshcd_hex_dump("", tmrdp, sizeof(*tmrdp));
}
 }
 
@@ -4638,31 +4626,22 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
  */
 static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
 {
-   struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_rsp *task_rsp_upiup;
+   struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
unsigned long flags;
int ocs_value;
-   int task_result;
 
spin_lock_irqsave(hba->host->host_lock, flags);
 
/* Clear completed tasks from outstanding_tasks */
__clear_bit(index, >outstanding_tasks);
 
-   task_req_descp = hba->utmrdl_base_addr;
-   ocs_value = ufshcd_get_tmr_ocs(_req_descp[index]);
+   ocs_value = ufshcd_get_tmr_ocs(treq);
 
-   if (ocs_value == OCS_SUCCESS) {
-   task_rsp_upiup = (struct utp_upiu_task_rsp *)
-   task_req_d

[PATCH v9 5/8] scsi: ufs: Use data structure size in pointer arithmetic

2018-10-07 Thread Avri Altman
Use the structure size in pointer arithmetic's instead of an opaque 32
bytes for the over allocation of descriptors.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
---
 drivers/scsi/ufs/ufs.h| 2 +-
 drivers/scsi/ufs/ufshcd.c | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f1d77dc..f5800c32 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -40,7 +40,7 @@
 #include 
 #include 
 
-#define GENERAL_UPIU_REQUEST_SIZE 32
+#define GENERAL_UPIU_REQUEST_SIZE (sizeof(struct utp_upiu_req))
 #define QUERY_DESC_MAX_SIZE   255
 #define QUERY_DESC_MIN_SIZE   2
 #define QUERY_DESC_HDR_SIZE   2
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7f376fb..ccad830 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2262,7 +2262,6 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
struct ufs_query *query = >dev_cmd.query;
u16 len = be16_to_cpu(query->request.upiu_req.length);
-   u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
 
/* Query request header */
ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -2284,7 +2283,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
 
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
-   memcpy(descp, query->descriptor, len);
+   memcpy(ucd_req_ptr + 1, query->descriptor, len);
 
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
-- 
1.9.1



[PATCH v9 6/8] scsi: ufs: Add API to execute raw upiu commands

2018-10-07 Thread Avri Altman
The UFS host software uses a combination of a host register set, and
Transfer Request Descriptors in system memory to communicate with host
controller hardware. In its mmio space, a separate places are assigned
to UTP Transfer Request Descriptor ("utrd") list, and to UTP Task
Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out and device
management commands. It also supports utmrd-type requests:
task management requests. Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly, as it will be
copied without any further input validations.

Signed-off-by: Avri Altman 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Bart Van Assche 
---
 drivers/scsi/ufs/ufs.h|   1 +
 drivers/scsi/ufs/ufshcd.c | 176 ++
 drivers/scsi/ufs/ufshcd.h |   7 ++
 3 files changed, 184 insertions(+)

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f5800c32..58087d3 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -414,6 +414,7 @@ enum {
MASK_RSP_UPIU_DATA_SEG_LEN  = 0x,
MASK_RSP_EXCEPTION_EVENT= 0x1,
MASK_TM_SERVICE_RESP= 0xFF,
+   MASK_TM_FUNC= 0xFF,
 };
 
 /* Task management service response */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ccad830..9515bc7 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5676,6 +5676,182 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @desc_op:   descriptor operation
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type,
+   enum query_opcode desc_op)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   switch (hba->ufs_version) {
+   case UFSHCI_VERSION_10:
+   case UFSHCI_VERSION_11:
+   lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+   break;
+   default:
+   lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+   break;
+   }
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr));
+   if (desc_buff && desc_op == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   /* The Data Segment Area is optional depending upon the query
+* function value. for WRITE DESCRIPTOR, the data segment
+* follows right after the tsf.
+*/
+   memcpy(lrbp->ucd_req_ptr + 1, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);

RE: [PATCH v8 3/8] uapi: ufs: Make utp_upiu_req visible to user space

2018-10-06 Thread Avri Altman
> >
> > diff --git a/include/uapi/scsi/scsi_bsg_ufs.h 
> > b/include/uapi/scsi/scsi_bsg_ufs.h
> > new file mode 100644
> > index 000..4108ce3
> > --- /dev/null
> > +++ b/include/uapi/scsi/scsi_bsg_ufs.h
> > @@ -0,0 +1,74 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * TBD - UFS Transport SGIO v4 BSG Message Support
> 
> What does the TBD stand for here?  I'd just remove it.
Done.

> 
> > +struct utp_upiu_query {
> > +   u8 opcode;
> > +   u8 idn;
> > +   u8 index;
> > +   u8 selector;
> 
> Please use __u8 instead of u8 for uapi headers.
Done.

> 
> With those tweaks it looks fine to me:
> 
> Reviewed-by: Christoph Hellwig 


RE: [PATCH v8 1/8] scsi: ufs: cleanup struct utp_task_req_desc

2018-10-06 Thread Avri Altman
> On Thu, Oct 04, 2018 at 08:20:30AM +0300, Avri Altman wrote:
> > From: Christoph Hellwig 
> >
> > Remove the pointless task_req_upiu and task_rsp_upiu indirections,
> > which are __le32 arrays always cast to given structures and just add
> > the members directly.  Also clean up variables names in use in the
> > callers a bit to make the code more readable.
> >
> > Signed-off-by: Christoph Hellwig 
> > Tested-by: Avri Altman 
> 
> Btw, if you send someones patches on as part of your series you
> should generally also add your own Signed-off-by.
Done.


RE: [PATCH v8 4/8] scsi: ufs: Add ufs-bsg module

2018-10-06 Thread Avri Altman
> > Add a bsg endpoint that supports UPIUs.
> 
> This should probably go into the subject line.
Done.

> 
> >
> > For now, just provide an API to allocate and remove
> > ufs-bsg node. We will use this framework to
> > manage ufs devices by sending UPIU transactions.
> 
> Please use up to 73 characters per line to make your changelogs more
> readable, e.g.
> 
> Subject: scsi: ufs: add a bsg endpoint that supports UPIUs
> 
> For now, just provide an API to allocate and remove ufs-bsg node.  We
> will use this framework to manage ufs devices by sending UPIU
> transactions.
> 
> [and so on]
Done.


RE: [PATCH v8 0/8] scsi: Add ufs bsg endpoint

2018-10-07 Thread Avri Altman
> 
> Hi, Avri
> Having patched them into v4.18 with problem free.  I will test it on my own
> platform.
> Thanks.
Great.
Anyway, as there's no public mainline ufs platform available,
for whomever wishes to use hike960 to test this,
here are the patch list (27) that I used to "modernized" the ufs & bsg drivers 
to v4.18.

Thanks,
Avri

block: remove parent device reference from struct bsg_class_device
scsi: ufs: add reference counting for scsi block requests
scsi: ufs: add trace event for ufs upiu
scsi: ufs: Add support for Auto-Hibernate Idle Timer
bsg: split handling of SCSI CDBs vs transport requeues
bsg-lib: remove bsg_job.req
bsg-lib: introduce a timeout field in struct bsg_job
 scsi: ufs: Fix kernel-doc errors and warnings
scsi: ufs: sysfs: reworking of the rpm_lvl and spm_lvl entries
scsi: ufs: sysfs: attributes
scsi: ufs: sysfs: flags
scsi: ufs: sysfs: unit descriptor
scsi: core: host template attribute groups
scsi: ufs: sysfs: string descriptors
scsi: ufs: sysfs: power descriptor
scsi: ufs: sysfs: health descriptor
scsi: ufs: sysfs: geometry descriptor
scsi: ufs: sysfs: interconnect descriptor
scsi: ufs: sysfs: device descriptor
scsi: ufs: sysfs: attribute group for existing sysfs entries.
scsi: ufs: Enable quirk to ignore sending WRITE_SAME command
bsg: use pr_debug instead of hand crafted macros
block: Fix kernel-doc warnings reported when building with W=1
block: pass full fmode_t to blk_verify_command
scsi: ufs: add ufs a command complete time stamp
scsi: ufs: continue to boot even with Boot LUN is disabled
scsi: ufs: fix a pclint warning


> 
> >hi,
> >Thanks for trying to test it.
> >You need to elaborate not only the ufs driver, but also the bsg driver, and
> >some block layer patches as well.
> >Will reply with the full list on Sunday.
> >
> >Thanks,
> >Avri
> >____
> >From: Bean Huo (beanhuo) 
> >Sent: Friday, October 5, 2018 12:28 AM
> >To: Avri Altman; Christoph Hellwig; Johannes Thumshirn; Hannes Reinecke;
> >Bart Van Assche; James E.J. Bottomley; Martin K. Petersen; linux-
> >s...@vger.kernel.org
> >Cc: Stanislav Nijnikov; Avi Shchislowski; Alex Lemberg; Subhash Jadavani;
> >Vinayak Holikatti
> >Subject: RE: [PATCH v8 0/8] scsi: Add ufs bsg endpoint
> >
> >Hi, Avri
> >
> >>We tested it on a Hikey-960 platform with a V4.14 kernel, "modernized"
> >>by recent bsg and ufs patches.
> >
> >Which kernel version is V8 based on? I patched to 4.14-rc7, it failed.
> >
> >



[PATCH v3 6/7] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()

2018-09-03 Thread Avri Altman
Do that for the currently supported UPIUs:
query, nop out, and task management.

We do not support UPIU of type scsi command yet, while
we are using the job's request and reply pointers to hold
the payload.  We will look into it in later patches.
We might need to elaborate the raw upiu api for that.

We also still not supporting uic commands:
For first phase, we plan to use the existing api,
and send only uic commands that are already supported.
Anyway, all that will come in the next patch.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 118 +++--
 drivers/scsi/ufs/ufs_bsg.h |   1 +
 2 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index b099ee2..8c9167d 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -22,18 +22,128 @@ static inline struct ufs_bsg_node *dev_to_ufs_node(struct 
device *d)
return container_of(d, struct ufs_bsg_node, dev);
 }
 
+static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr,
+  int *desc_len)
+{
+   int desc_size = be16_to_cpu(qr->length);
+   int desc_id = qr->idn;
+   int ret = 0;
+
+   if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC || desc_size <= 0)
+   return -EINVAL;
+
+   ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id, desc_len);
+
+   if (ret || !*desc_len)
+   return -EINVAL;
+
+   *desc_len = min_t(int, *desc_len, desc_size);
+
+   return ret;
+}
+
+static int ufs_bsg_verify_query_size(unsigned int request_len,
+unsigned int reply_len,
+int rw, int desc_len)
+{
+   int min_req_len = sizeof(struct ufs_bsg_request);
+   int min_rsp_len = sizeof(struct ufs_bsg_reply);
+
+   if (rw == WRITE)
+   min_req_len += desc_len;
+
+   if (min_req_len > request_len)
+   return -EINVAL;
+
+   if (min_rsp_len > reply_len)
+   return -EINVAL;
+
+   return 0;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
struct ufs_bsg_reply *bsg_reply = job->reply;
-   int ret = -ENOTSUPP;
+   unsigned int request_len = job->request_len;
+   unsigned int reply_len = job->reply_len;
+   struct utp_upiu_query *qr;
+   struct utp_upiu_req *req_upiu = NULL;
+   struct utp_upiu_req *rsp_upiu = NULL;
+   int msgcode;
+   uint8_t *desc_buff = NULL;
+   int desc_len = 0;
+   int rw = UFS_BSG_NOP;
+   int ret;
 
+   ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, desc_len);
+   if (ret) {
+   dev_err(job->dev, "not enough space assigned\n");
+   goto out;
+   }
bsg_reply->reply_payload_rcv_len = 0;
 
-   /* Do Nothing for now */
-   dev_err(job->dev, "unsupported message_code 0x%x\n",
-   bsg_request->msgcode);
+   msgcode = bsg_request->msgcode;
+   switch (msgcode) {
+   case UPIU_TRANSACTION_QUERY_REQ:
+   qr = _request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(qr, _len))
+   goto null_desc_buff;
+
+   if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
+   rw = WRITE;
+   desc_buff = ((uint8_t *)bsg_request) +
+   sizeof(struct ufs_bsg_request);
+   }
+
+null_desc_buff:
+   /* fall through */
+   case UPIU_TRANSACTION_NOP_OUT:
+   case UPIU_TRANSACTION_TASK_REQ:
+   /* Now that we know if its a read or write, verify again */
+   if (rw != UFS_BSG_NOP || desc_len) {
+   ret = ufs_bsg_verify_query_size(request_len, reply_len,
+   rw, desc_len);
+   if (ret) {
+   dev_err(job->dev,
+   "not enough space assigned\n");
+   goto out;
+   }
+   }
+
+   req_upiu = (struct utp_upiu_req *)_request->header;
+   rsp_upiu = (struct utp_upiu_req *)_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba,
+  req_upiu, rsp_upiu, msgcode,
+  desc_buff, _len, rw);
+
+   break;
+   case UPIU_TRANSACTION_UIC_CMD:
+   /* later */
+   case UPIU_TRANSACTION_COMMAND:
+   case UPIU_TRANSACTION_DATA_OUT:
+not_supported:
+   /* for the time being, we do 

[PATCH v3 7/7] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

2018-09-03 Thread Avri Altman
Add support to those uic commands, that are currently supported
by ufshcd api: the variants of dme_{peer}_{set_get}.

At this point better not to add any new api, as careless
uic command may turn the device into a brick.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufs_bsg.c | 56 +-
 drivers/scsi/ufs/ufs_bsg.h |  2 ++
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 8c9167d..d1255be 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -61,6 +61,55 @@ static int ufs_bsg_verify_query_size(unsigned int 
request_len,
return 0;
 }
 
+static int ufs_bsg_exec_uic_cmd(struct uic_command *uc)
+{
+   u32 attr_sel = uc->argument1;
+   u8 attr_set = (uc->argument2 >> 16) & 0xff;
+   u32 mib_val = uc->argument3;
+   int cmd = uc->command;
+   int ret = 0;
+
+   switch (cmd) {
+   case UIC_CMD_DME_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_LOCAL);
+   break;
+   case UIC_CMD_DME_PEER_GET:
+   ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel,
+ _val, DME_PEER);
+   break;
+   case UIC_CMD_DME_PEER_SET:
+   ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set,
+ mib_val, DME_PEER);
+   break;
+   case UIC_CMD_DME_POWERON:
+   case UIC_CMD_DME_POWEROFF:
+   case UIC_CMD_DME_ENABLE:
+   case UIC_CMD_DME_RESET:
+   case UIC_CMD_DME_END_PT_RST:
+   case UIC_CMD_DME_LINK_STARTUP:
+   case UIC_CMD_DME_HIBER_ENTER:
+   case UIC_CMD_DME_HIBER_EXIT:
+   case UIC_CMD_DME_TEST_MODE:
+   ret = -ENOTSUPP;
+   pr_err("%s unsupported command 0x%x\n", __func__, cmd);
+   break;
+   default:
+   ret = -EINVAL;
+   }
+
+   if (ret)
+   pr_err("%s error in command 0x%x\n", __func__, cmd);
+
+   uc->argument3 = mib_val;
+
+   return ret;
+}
+
 static int ufs_bsg_request(struct bsg_job *job)
 {
struct ufs_bsg_request *bsg_request = job->request;
@@ -68,6 +117,7 @@ static int ufs_bsg_request(struct bsg_job *job)
unsigned int request_len = job->request_len;
unsigned int reply_len = job->reply_len;
struct utp_upiu_query *qr;
+   struct uic_command uc = {};
struct utp_upiu_req *req_upiu = NULL;
struct utp_upiu_req *rsp_upiu = NULL;
int msgcode;
@@ -122,7 +172,11 @@ static int ufs_bsg_request(struct bsg_job *job)
 
break;
case UPIU_TRANSACTION_UIC_CMD:
-   /* later */
+   memcpy(, _request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd();
+   memcpy(_reply->tsf.uc, , UIC_CMD_SIZE);
+
+   break;
case UPIU_TRANSACTION_COMMAND:
case UPIU_TRANSACTION_DATA_OUT:
 not_supported:
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index 9cc71bc..219597d 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -15,6 +15,8 @@
 
 #define UFS_BSG_NOP (-1)
 #define UPIU_TRANSACTION_UIC_CMD 0x1F
+/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */
+#define UIC_CMD_SIZE (sizeof(u32) * 4)
 
 enum {
REQ_UPIU_SIZE_DWORDS= 8,
-- 
1.9.1



[PATCH v3 0/7] scsi: ufs bsg endpoint

2018-09-03 Thread Avri Altman
Here is a proposal to use a bsg endpoint to manage ufs devices.

We will do that by adding a bsg device node to the ufs driver,
and use it to send UPIU transactions to the ufs device.
It will serve as a ufs device management infrastructure, 
for device configuration, provisioning, testing and validation, etc.

We added a new ufs-bsg module, and some new API to the ufs driver.

For the time being, we will not use it for data transfer,
but just for device management per-se.
This has nothing to do with the recent removal of bsg read/write
support, we might add this capability in the future, 
but it is not our current focus.

We tested it on a Hikey-960 platform with a V4.14 kernel,
"modernized" by recent bsg and ufs patches.
We also used a htc11 with a V4.4 kernel, but needed much more
transport/bsg/ufs patches to make it relevant.


V2->v3:
We dropped the scsi transport code (and changed this patch title
to account for it) as we actually just need the bsg device node.
We also withdraw (brokenhearted) from our intension to create
several bsg devices, and add just one. 
Rephrased the doc in Kconfig.

V1->v2:
Use inline functions instead of defines, and ida to obtain the 
port indices, in scsi_transport_ufs module.
Remove the closing data pointer and __packed notation from
struct ufs_bsg_{request_reply}.
Re-use ufshcd_issue_tm_cmd code - needed a couple of patches for that,
and call req_upiu and rsp_upio with their appropriate struct pointers.
Use a more appropriate name when checking if enough memory
was  allocated for write descriptor, and remove redundant goto.
Add reference to the spec to explain uic command size.
Fix a lot of typos.

Avri Altman (7):
  scsi: ufs: Add ufs-bsg module
  scsi: ufs: Instantiate a ufs bsg if its available
  scsi: ufs: Add fill task management request
  scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius
  scsi: ufs: Add API to execute raw upiu commands
  scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request()
  scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request()

 drivers/scsi/ufs/Kconfig |  19 +++
 drivers/scsi/ufs/Makefile|   1 +
 drivers/scsi/ufs/ufs_bsg.c   | 337 +++
 drivers/scsi/ufs/ufs_bsg.h   |  73 +
 drivers/scsi/ufs/ufshcd.c| 239 +++
 drivers/scsi/ufs/ufshcd.h|   6 +
 include/uapi/scsi/scsi_bsg_ufs.h |  56 +++
 7 files changed, 703 insertions(+), 28 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

-- 
1.9.1



[PATCH v3 1/7] scsi: ufs: Add ufs-bsg module

2018-09-03 Thread Avri Altman
Add a bsg endpoint that supports UPIUs.

For now, just provide an API to allocate and remove
ufs-bsg node. We will use this framework to
manage ufs devices by sending UPIU transactions.

For the time being, implements an empty bsg_request() -
will add some more functionality in coming patches.

Nonetheless, we reveal here the protocol we are planning to use:
UFS Transport Protocol Transactions. UFS transactions consist
of packets called UFS Protocol Information Units (UPIU).

There are UPIU’s defined for UFS SCSI commands, responses,
data in and data out, task management, utility functions,
vendor functions, transaction synchronization and control, and more.

By using UPIUs, we get access to the most fine-grained internals
of this protocol, and able to communicate with the device in ways,
that are sometimes beyond the capacity of the ufs driver.

Moreover and as a result, our core structure - ufs_bsg_node has
a pretty lean structure: using upiu transactions that contains
the outmost detailed info, so we don't really need complex
constructs to support it.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/Kconfig |  19 +
 drivers/scsi/ufs/Makefile|   1 +
 drivers/scsi/ufs/ufs_bsg.c   | 173 +++
 drivers/scsi/ufs/ufs_bsg.h   |  70 
 include/uapi/scsi/scsi_bsg_ufs.h |  56 +
 5 files changed, 319 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufs_bsg.c
 create mode 100644 drivers/scsi/ufs/ufs_bsg.h
 create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e09fe6a..83ba979 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -109,3 +109,22 @@ config SCSI_UFS_HISI
 
  Select this if you have UFS controller on Hisilicon chipset.
  If unsure, say N.
+
+config SCSI_UFS_BSG
+   bool "Universal Flash Storage BSG device node"
+   depends on SCSI_UFSHCD
+   select BLK_DEV_BSGLIB
+   help
+ Universal Flash Storage (UFS) is SCSI transport specification for
+ accessing flash storage on digital cameras, mobile phones and
+ consumer electronic devices.
+ An UFS controller communicates with an UFS device by exchanging
+ UFS Protocol Information Units (UPIUs).
+ UPIUs can not only be used as a transport layer for the SCSI protocol
+ but are also used by the UFS native command set.
+ This transport driver supports exchanging UFS protocol information 
units
+ with an UFS device. See also the ufshcd driver, which is a SCSI driver
+ that supports UFS devices.
+
+ Select this if you need a bsg device node for your UFS controller.
+ If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2c50f03..8f7138a 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
+obj-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
new file mode 100644
index 000..b099ee2
--- /dev/null
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * bsg endpoint that supports UPIUs
+ *
+ * Copyright (C) 2018 Western Digital Corporation
+ */
+#include "ufs_bsg.h"
+
+struct ufs_bsg_node {
+   struct device   dev;
+   struct request_queue*q;
+};
+
+struct ufs_bsg {
+   struct ufs_hba *hba;
+   struct ufs_bsg_node *node;
+};
+static struct ufs_bsg *bsg_host;
+
+static inline struct ufs_bsg_node *dev_to_ufs_node(struct device *d)
+{
+   return container_of(d, struct ufs_bsg_node, dev);
+}
+
+static int ufs_bsg_request(struct bsg_job *job)
+{
+   struct ufs_bsg_request *bsg_request = job->request;
+   struct ufs_bsg_reply *bsg_reply = job->reply;
+   int ret = -ENOTSUPP;
+
+   bsg_reply->reply_payload_rcv_len = 0;
+
+   /* Do Nothing for now */
+   dev_err(job->dev, "unsupported message_code 0x%x\n",
+   bsg_request->msgcode);
+
+   bsg_reply->result = ret;
+   if (ret)
+   job->reply_len = sizeof(uint32_t);
+   else
+   job->reply_len = sizeof(struct ufs_bsg_reply) +
+bsg_reply->reply_payload_rcv_len;
+
+   bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+   return ret;
+}
+
+static void ufs_bsg_node_delete(struct ufs_bsg_node *node)
+{
+   struct device *dev = >dev;
+
+   if (node->q)
+   bsg_unregister_queue(node->q);
+
+   device_del(dev);
+
+   put_device(dev);
+}
+
+/**
+ * ufs_bsg_remove - detach and remove the added ufs-bsg node
+ *
+ * Sh

[PATCH v3 3/7] scsi: ufs: Add fill task management request

2018-09-03 Thread Avri Altman
Do that in preparation to re-use ufshcd_issue_tm_cmd code.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 50 +++
 1 file changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ed37914..d18832a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5598,6 +5598,32 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
return err;
 }
 
+static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
+  int lun_id, int task_id, u8 tm_function,
+  int task_tag)
+{
+   struct utp_upiu_task_req *task_req_upiup;
+
+   /* Configure task request descriptor */
+   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
+   task_req_descp->header.dword_2 =
+   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+   task_req_upiup =
+   (struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
+   task_req_upiup->header.dword_0 =
+   UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0, lun_id,
+ task_tag);
+   task_req_upiup->header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0,
+  0);
+   /*
+* The host shall provide the same value for LUN field in the basic
+* header and for Input Parameter.
+*/
+   task_req_upiup->input_param1 = cpu_to_be32(lun_id);
+   task_req_upiup->input_param2 = cpu_to_be32(task_id);
+}
+
 /**
  * ufshcd_issue_tm_cmd - issues task management commands to controller
  * @hba: per adapter instance
@@ -5612,7 +5638,6 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
u8 tm_function, u8 *tm_response)
 {
struct utp_task_req_desc *task_req_descp;
-   struct utp_upiu_task_req *task_req_upiup;
struct Scsi_Host *host;
unsigned long flags;
int free_slot;
@@ -5632,27 +5657,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
spin_lock_irqsave(host->host_lock, flags);
task_req_descp = hba->utmrdl_base_addr;
task_req_descp += free_slot;
-
-   /* Configure task request descriptor */
-   task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-   task_req_descp->header.dword_2 =
-   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-   /* Configure task request UPIU */
-   task_req_upiup =
-   (struct utp_upiu_task_req *) task_req_descp->task_req_upiu;
task_tag = hba->nutrs + free_slot;
-   task_req_upiup->header.dword_0 =
-   UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
- lun_id, task_tag);
-   task_req_upiup->header.dword_1 =
-   UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-   /*
-* The host shall provide the same value for LUN field in the basic
-* header and for Input Parameter.
-*/
-   task_req_upiup->input_param1 = cpu_to_be32(lun_id);
-   task_req_upiup->input_param2 = cpu_to_be32(task_id);
+
+   ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function,
+  task_tag);
 
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
-- 
1.9.1



[PATCH v3 4/7] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius

2018-09-03 Thread Avri Altman
Do that in order to re-use its code if the task request and response
UPIUs are given externally.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d18832a..15be103 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5599,6 +5599,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
 }
 
 static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
+  struct utp_upiu_task_req *raw_task_req_upiup,
   int lun_id, int task_id, u8 tm_function,
   int task_tag)
 {
@@ -5609,6 +5610,13 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc 
*task_req_descp,
task_req_descp->header.dword_2 =
cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
 
+   if (raw_task_req_upiup) {
+   raw_task_req_upiup->header.dword_0 |= cpu_to_be32(task_tag);
+   memcpy(task_req_descp->task_req_upiu, raw_task_req_upiup,
+  GENERAL_UPIU_REQUEST_SIZE);
+   return;
+   }
+
task_req_upiup =
(struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
task_req_upiup->header.dword_0 =
@@ -5634,8 +5642,11 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc 
*task_req_descp,
  *
  * Returns non-zero value on error, zero on success.
  */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-   u8 tm_function, u8 *tm_response)
+static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+  struct utp_upiu_task_req *raw_task_req_upiup,
+  struct utp_upiu_task_req *raw_task_rsp_upiup,
+  int lun_id, int task_id, u8 tm_function,
+  u8 *tm_response)
 {
struct utp_task_req_desc *task_req_descp;
struct Scsi_Host *host;
@@ -5659,8 +5670,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
task_req_descp += free_slot;
task_tag = hba->nutrs + free_slot;
 
-   ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function,
-  task_tag);
+   ufshcd_fill_tm_req(task_req_descp, raw_task_req_upiup, lun_id, task_id,
+  tm_function, task_tag);
 
ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
@@ -5692,6 +5703,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
err = -ETIMEDOUT;
} else {
err = ufshcd_task_req_compl(hba, free_slot, tm_response);
+   if (raw_task_rsp_upiup)
+   memcpy(raw_task_rsp_upiup,
+  task_req_descp->task_rsp_upiu,
+  GENERAL_UPIU_REQUEST_SIZE);
ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete");
}
 
@@ -5726,7 +5741,8 @@ static int ufshcd_eh_device_reset_handler(struct 
scsi_cmnd *cmd)
tag = cmd->request->tag;
 
lrbp = >lrb[tag];
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err)
err = resp;
@@ -5856,8 +5872,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
}
 
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_QUERY_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ );
if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
/* cmd pending in the device */
dev_err(hba->dev, "%s: cmd pending in the device. tag = 
%d\n",
@@ -5895,8 +5912,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto out;
}
 
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-   UFS_ABORT_TASK, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err) {
err = resp; /* service response error */
-- 
1.9.1



[PATCH v3 5/7] scsi: ufs: Add API to execute raw upiu commands

2018-09-03 Thread Avri Altman
The UFS host software uses a combination of a host register set,
and Transfer Request Descriptors in system memory to communicate
with host controller hardware. In its mmio space, a separate places
are assigned to UTP Transfer Request Descriptor ("utrd") list, and
to UTP Task Management Request Descriptor ("utmrd") list.

The provided API supports utrd-typed requests: nop out
and device management commands. It also supports utmrd-type
requests: task management requests.
Other UPIU types are not supported for now.

We utilize the already existing code for tag and task work queues.
That is, all utrd-typed UPIUs are "disguised" as device management
commands. Similarly, the utmrd-typed UPUIs uses the task management
infrastructure.

It is up to the caller to fill the upiu request properly,
as it will be copied without any further input validations.

Signed-off-by: Avri Altman 
---
 drivers/scsi/ufs/ufshcd.c | 154 ++
 drivers/scsi/ufs/ufshcd.h |   6 ++
 2 files changed, 160 insertions(+)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 15be103..3618be0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -257,6 +257,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool 
on,
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 struct ufs_pa_layer_attr *pwr_mode);
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp);
+
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
return tag >= 0 && tag < hba->nutrs;
@@ -5719,6 +5721,158 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 }
 
 /**
+ * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:   per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @rw:either READ or WRITE
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+   struct utp_upiu_req *req_upiu,
+   struct utp_upiu_req *rsp_upiu,
+   u8 *desc_buff, int *buff_len,
+   int cmd_type, int rw)
+{
+   struct ufshcd_lrb *lrbp;
+   int err = 0;
+   int tag;
+   struct completion wait;
+   unsigned long flags;
+   u32 upiu_flags;
+   u8 *descp;
+
+   down_read(>clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, ));
+
+   init_completion();
+   lrbp = >lrb[tag];
+   WARN_ON(lrbp->cmd);
+
+   lrbp->cmd = NULL;
+   lrbp->sense_bufflen = 0;
+   lrbp->sense_buffer = NULL;
+   lrbp->task_tag = tag;
+   lrbp->lun = 0;
+   lrbp->command_type = hba->ufs_version == UFSHCI_VERSION_10 ||
+hba->ufs_version == UFSHCI_VERSION_11 ?
+UTP_CMD_TYPE_DEV_MANAGE :
+UTP_CMD_TYPE_UFS_STORAGE;
+   lrbp->intr_cmd = true;
+   hba->dev_cmd.type = cmd_type;
+
+   /* update the task tag in the request upiu */
+   req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+   ufshcd_prepare_req_desc_hdr(lrbp, _flags, DMA_NONE);
+
+   /* just copy the upiu request as it is */
+   memcpy(lrbp->ucd_req_ptr, req_upiu, GENERAL_UPIU_REQUEST_SIZE);
+
+   if (desc_buff && rw == WRITE) {
+   descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
+   memcpy(descp, desc_buff, *buff_len);
+   *buff_len = 0;
+   }
+
+   memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+   hba->dev_cmd.complete = 
+
+   /* Make sure descriptors are ready before ringing the doorbell */
+   wmb();
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   ufshcd_send_command(hba, tag);
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+   /*
+* ignore the returning value here - ufshcd_check_query_response is
+* bound to fail since dev_cmd.query and dev_cmd.type were left empty.
+* read the response directly ignoring all errors.
+*/
+   ufshcd_wait_for_dev_cmd(hba, lrbp, QUERY_REQ_TIMEOUT);
+
+   /* just copy the upiu requ

  1   2   >