Re: [Patch v1 0/7] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-09-03 Thread Sreekanth Reddy
On Fri, Aug 31, 2018 at 2:25 PM, Lukas Wunner  wrote:
> [cc += linux-pci, benh]
>
> On Fri, Aug 31, 2018 at 7:37 AM Suganath Prabu S 
>  wrote:
>> Posting below set of patches to support PCIe Hot Plug surprise removal,
>> and few defect fixes.
>
> Please cross-post to linux-pci in the future.
>
>
> Regarding [PATCH 1/7] mpt3sas: Introduce mpt3sas_base_pci_device_is_unplugged:
> https://www.spinics.net/lists/linux-scsi/msg122962.html
>
> * mpt3sas_base_pci_device_is_unplugged() is a duplication of the existing
>   pci_device_is_present().

Thanks for pointing this pci_device_is_present() API, we will replace
mpt3sas_base_pci_device_is_unplugged() with  pci_device_is_present().

>
> * Just reading the vendor ID may not be sufficient to detect unplug,
>   it may also read as "all ones" if the link is down due to error
>   recovery by DPC.

So, is their any other way to detect pci device unplug apart from
reading the vendor ID, I mean we have check any other flags, etc?

>
>
> Regarding [PATCH 2/7] mpt3sas: Add HBA hot plug watchdog thread:
> https://www.spinics.net/lists/linux-scsi/msg122963.html
>
> * I don't see why you need to poll for the device's removal from a
>   watchdog thread.  pciehp will invoke your driver's ->remove hook
>   once the device is gone.

If we have some three to four PCI devices and all pci devices are hot
unplugged simultaneously, then we observed that driver's-remove hook
is called sequentially. So it takes some time to call fourth PCI
device driver's->remove hook. so during this time we want all the
outstanding commands to be gracefully terminated and hence we added
this watchdog thread to quickly detect the hba unplug and take
necessary steps such as gracefully terminate the outstanding IOs and
stop receiving further IOs on it. At later time when PCI subsystem
calls driver's-remove hook then driver can quickly release the
resources allocated for this unplugged device.

>
> * A recent discussion initiated by Benjamin Herrenschmidt came to the
>   conclusion that device removal should be treated as a type of
>   error state (either pci_channel_io_perm_failure or another, newly
>   introduced state).  It will then be possible to detect the device's
>   inaccessibility with pci_channel_offline().  Please help work towards
>   such a future solution in the PCI core instead of solutions localized
>   to a single device driver.  Sorry, the discussion was lengthy, it is
>   available here:
>   https://www.spinics.net/lists/linux-pci/msg75425.html

Oh great, sure. We have very limited knowledge on PCI subsystem but we
try our best in future to provide solutions in the PCI core.

>
> Thanks,
>
> Lukas


[PATCH -next] scsi: aic7xxx: remove set but not used variable 'shared_scb_data'

2018-09-03 Thread YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:

drivers/scsi/aic7xxx/aic79xx_pci.c: In function 'ahd_pci_config':
drivers/scsi/aic7xxx/aic79xx_pci.c:291:19: warning:
 variable 'shared_scb_data' set but not used [-Wunused-but-set-variable]

Signed-off-by: YueHaibing 
---
 drivers/scsi/aic7xxx/aic79xx_pci.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c 
b/drivers/scsi/aic7xxx/aic79xx_pci.c
index c68943b..8397ae9 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -288,13 +288,11 @@ static void   ahd_configure_termination(struct 
ahd_softc *ahd,
 int
 ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
 {
-   struct scb_data *shared_scb_data;
u_intcommand;
uint32_t devconfig;
uint16_t subvendor; 
int  error;
 
-   shared_scb_data = NULL;
ahd->description = entry->name;
/*
 * Record if this is an HP board.



[PATCH -next] scsi: libfc: remove set but not used variable 'rpriv'

2018-09-03 Thread YueHaibing
Fixes gcc '-Wunused-but-set-variable' warning:

drivers/scsi/libfc/fc_fcp.c: In function 'fc_queuecommand':
drivers/scsi/libfc/fc_fcp.c:1875:30: warning:
 variable 'rpriv' set but not used [-Wunused-but-set-variable]

Signed-off-by: YueHaibing 
---
 drivers/scsi/libfc/fc_fcp.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 563247d..b1bd283 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1872,7 +1872,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct 
scsi_cmnd *sc_cmd)
struct fc_lport *lport = shost_priv(shost);
struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
struct fc_fcp_pkt *fsp;
-   struct fc_rport_libfc_priv *rpriv;
int rval;
int rc = 0;
struct fc_stats *stats;
@@ -1894,8 +1893,6 @@ int fc_queuecommand(struct Scsi_Host *shost, struct 
scsi_cmnd *sc_cmd)
goto out;
}
 
-   rpriv = rport->dd_data;
-
if (!fc_fcp_lport_queue_ready(lport)) {
if (lport->qfull) {
if (fc_fcp_can_queue_ramp_down(lport))



[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,
+ &mib_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,
+ &mib_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(&uc, &bsg_request->tsf.uc, UIC_CMD_SIZE);
+   ret = ufs_bsg_exec_uic_cmd(&uc);
+   memcpy(&bsg_reply->tsf.uc, &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 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 = &bsg_request->tsf.qr;
+   if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC)
+   goto not_supported;
+
+   if (ufs_bsg_get_query_desc_size(qr, &desc_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 *)&bsg_request->header;
+   rsp_upiu = (struct utp_upiu_req *)&bsg_reply->header;
+   ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba,
+  req_upiu, rsp_upiu, msgcode,
+  desc_buff, &desc_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 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 = &hba->lrb[tag];
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp);
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, &resp);
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, &resp);
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ &resp);
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, &resp);
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, &resp);
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(&hba->clk_scaling_lock);
+
+   wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, &tag));
+
+   init_completion(&wait);
+   lrbp = &hba->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, &upiu_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 = &wait;
+
+   /* 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_UPIU_REQUEST_SIZE);
+
+   ufshcd_put_dev_cmd_tag(hba, tag)

[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 = &node->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
+ *
+ * Should be called when unloading the driver.
+ */
+void ufs_bsg_remove(void)

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

2018-09-03 Thread Avri Altman
Call the probe/remove APIs.

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

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9d5d2ca..ed37914 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 
@@ -6652,6 +6653,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
hba->clk_scaling.is_allowed = true;
}
 
+   ufs_bsg_probe(hba);
+
scsi_scan_host(hba->host);
pm_runtime_put_sync(hba->dev);
}
@@ -7875,6 +7878,7 @@ int ufshcd_shutdown(struct ufs_hba *hba)
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+   ufs_bsg_remove();
ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
/* disable interrupts */
-- 
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