From patchwork Fri Sep 7 09:49:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591965 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 197DF6CB for ; Fri, 7 Sep 2018 09:50:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EAA252AD14 for ; Fri, 7 Sep 2018 09:50:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DEFDF2AD64; Fri, 7 Sep 2018 09:50:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 384822AD61 for ; Fri, 7 Sep 2018 09:50:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728606AbeIGOar (ORCPT ); Fri, 7 Sep 2018 10:30:47 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:59770 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728603AbeIGOar (ORCPT ); Fri, 7 Sep 2018 10:30:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313838; x=1567849838; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=J5di2JHzxLGqyUNQyKIwMBVAy/RITEqfBC0mQ7dQfpU=; b=qq+E1UnzQAUC0pLgx07QcxJoQv+zySo+fOgjg9tntrJKIObzkXAXC8mN e87YeCnALoTUr+Z8jjqLzIJcg83qUuFeikTLyrxkt6V+idl5RWN9O2IeD 34Qo2bm9z8AfDIT8ocUQVgRQlCFw8hfBc+g5EJcGEaacMNNqcimbnkOvU wIMIm3jnMscOB5dE0/DzCs7HmLeFdDW5n91aExh9fZ04gSetkqWOn5JKU FmQcH//K/0aUjNjMiZJRT3INFkTIp+AMjgdgWPGVVh7/G/7Rh9g2v0/9B mmxlk4QRXACyrRgrW5oMnwR96gViWryLlhOKo5DmpLOVpnbufavCKvLSj w==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="90229886" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:50:38 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 07 Sep 2018 02:37:08 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:50:36 -0700 From: Avri Altman To: 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: [PATCH v4 1/7] scsi: ufs: cleanup struct utp_task_req_desc Date: Fri, 7 Sep 2018 12:49:37 +0300 Message-Id: <1536313783-13025-2-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 = &hba->utmrdl_base_addr[off]; - descp = &hba->utmrdl_base_addr[off]; - task_req = (struct utp_upiu_task_req *)descp->task_req_upiu; - trace_ufshcd_upiu(dev_name(hba->dev), str, &task_req->header, - &task_req->input_param1); + trace_ufshcd_upiu(dev_name(hba->dev), str, &descp->req_header, + &descp->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, &bitmap, hba->nutmrs) { - tmrdp = &hba->utmrdl_base_addr[tag]; + struct utp_task_req_desc *tmrdp = &hba->utmrdl_base_addr[tag]; + dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag); - ufshcd_hex_dump("TM TRD: ", &tmrdp->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, &hba->outstanding_tasks); - task_req_descp = hba->utmrdl_base_addr; - ocs_value = ufshcd_get_tmr_ocs(&task_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; - if (resp) - *resp = (u8)task_result; - } else { + 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; @@ -5610,8 +5589,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) 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 utp_task_req_desc *treq; struct Scsi_Host *host; unsigned long flags; int free_slot; @@ -5629,29 +5607,23 @@ 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); - task_req_descp = hba->utmrdl_base_addr; - task_req_descp += free_slot; + treq = hba->utmrdl_base_addr + 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); + 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_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); + 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. */ - task_req_upiup->input_param1 = cpu_to_be32(lun_id); - task_req_upiup->input_param2 = cpu_to_be32(task_id); + treq->input_param1 = cpu_to_be32(lun_id); + treq->input_param2 = cpu_to_be32(task_id); ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index bb5d9c7..6fa889d 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -433,22 +433,25 @@ struct utp_transfer_req_desc { __le16 prd_table_offset; }; -/** - * struct utp_task_req_desc - UTMRD structure - * @header: UTMRD header DW-0 to DW-3 - * @task_req_upiu: Pointer to task request UPIU DW-4 to DW-11 - * @task_rsp_upiu: Pointer to task response UPIU DW12 to DW-19 +/* + * UTMRD structure. */ struct utp_task_req_desc { - /* DW 0-3 */ struct request_desc_header header; - /* DW 4-11 */ - __le32 task_req_upiu[TASK_REQ_UPIU_SIZE_DWORDS]; - - /* DW 12-19 */ - __le32 task_rsp_upiu[TASK_RSP_UPIU_SIZE_DWORDS]; + /* DW 4-11 - Task request UPIU structure */ + struct utp_upiu_header req_header; + __be32 input_param1; + __be32 input_param2; + __be32 input_param3; + __be32 __reserved1[2]; + + /* DW 12-19 - Task Management Response UPIU structure */ + struct utp_upiu_header rsp_header; + __be32 output_param1; + __be32 output_param2; + __be32 __reserved2[3]; }; #endif /* End of Header */ From patchwork Fri Sep 7 09:49:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591967 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4E15D1669 for ; Fri, 7 Sep 2018 09:51:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2BF612AD14 for ; Fri, 7 Sep 2018 09:51:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 204BB2AD61; Fri, 7 Sep 2018 09:51:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D95B2AD64 for ; Fri, 7 Sep 2018 09:50:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728229AbeIGObH (ORCPT ); Fri, 7 Sep 2018 10:31:07 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:59796 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGObH (ORCPT ); Fri, 7 Sep 2018 10:31:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313859; x=1567849859; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=56Uu+PmI5cglR4GHkWCzZ6+f9w+xgFsd7DJAc1KeoQI=; b=dNPiRMnGb/lCWxgydTeGTSN/HipWNvK0B3+ZECF22JH/G3fuSM6f16uD IPR8EB9+7GnZPkNW6CqkKuUxi6F5qmH4nyQC53ryL5g0nh8Lc8vFiVx3V 4lYaxDGtjMbtgWPOQv8dSoXXfu4TrnJunMOB71hCBQzcUrStW++8m1F9D sfGBk6PGoTI3eaZ1Ms0FuTh5uWOkiUmBR3crDI5rqXKc1Y7L4zY4luM86 KnEpUT4f3eysbEZ6YsbM1KEW9TvvYR8m5eo+b4AKknaye2KDlbQ3yZqC/ NF1S7u4AlAKq9E7qOHdWkhH9kLxzqqPVUS5IePiFSKwaFgwyRlot/r2Bn A==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="90229897" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:50:58 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 07 Sep 2018 02:37:39 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:50:56 -0700 From: Avri Altman To: 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: [PATCH v4 2/7] scsi: ufs: add a low-level __ufshcd_issue_tm_cmd helper Date: Fri, 7 Sep 2018 12:49:38 +0300 Message-Id: <1536313783-13025-3-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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, &hba->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 { - err = ufshcd_task_req_compl(hba, free_slot, tm_response); + memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); + ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete"); + + spin_lock_irqsave(hba->host->host_lock, flags); + __clear_bit(free_slot, &hba->outstanding_tasks); + spin_unlock_irqrestore(hba->host->host_lock, flags); + } clear_bit(free_slot, &hba->tm_condition); @@ -5667,6 +5601,52 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, } /** + * 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) +{ + struct utp_task_req_desc treq = { { 0 }, }; + int ocs_value, err; + + /* 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 */ + treq.req_header.dword_0 = cpu_to_be32(lun_id << 8) | + cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24); + treq.req_header.dword_1 = cpu_to_be32(tm_function << 16); + + /* + * 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); + + err = __ufshcd_issue_tm_cmd(hba, &treq, tm_function); + if (err == -ETIMEDOUT) + return err; + + ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS; + 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; + return err; +} + +/** * ufshcd_eh_device_reset_handler - device reset handler registered to * scsi layer. * @cmd: SCSI command pointer From patchwork Fri Sep 7 09:49:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591969 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 787F46CB for ; Fri, 7 Sep 2018 09:51:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57E872AD61 for ; Fri, 7 Sep 2018 09:51:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4BC492AD72; Fri, 7 Sep 2018 09:51:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C85652AD61 for ; Fri, 7 Sep 2018 09:51:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728296AbeIGObP (ORCPT ); Fri, 7 Sep 2018 10:31:15 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:52672 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGObP (ORCPT ); Fri, 7 Sep 2018 10:31:15 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313866; x=1567849866; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=R1wqg9yl9wHO57SV9dMDxZdUuiZWNNXLpVd3obHN068=; b=UgAzgrNBSxr+rxySXfml3m9kGTcd298zJQo6yl7/OhylKtmhMGaPctTB IBrrCkiPs7ULdEjZTjpZEgnbTO/3fPtrROInwGlruXk7fobY+LAA4iD/N Iix2FSnn/BHKET/Sa1sQY+DV578/Y90OHn4ZDsoVGZVXPZiK1HuAz0HCN dLDf50HrcaPkxjEvNiHuBwcFVl7amIibmUNad+t09eu/zfw2CsD0ke7no ZEYmm0c1Hm3Zm8zxoHjmitzacvAJ2KYOuaWlbedpdUD9wfOteh9htQ7US tyN25XBYwRTSAjoYYxcm03lnwe5RNyMitJBRuCcxOFgTB+rrzQk3KyVop g==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="89268009" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:51:06 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 07 Sep 2018 02:37:36 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:51:03 -0700 From: Avri Altman To: 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 , Avri Altman Subject: [PATCH v4 3/7] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw upiu Date: Fri, 7 Sep 2018 12:49:39 +0300 Message-Id: <1536313783-13025-4-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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(&treq.req_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, &treq, 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, &treq.rsp_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 = &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; @@ -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, &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", @@ -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, &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 */ From patchwork Fri Sep 7 09:49:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591971 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6C65A6CB for ; Fri, 7 Sep 2018 09:51:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4BF6F2AD14 for ; Fri, 7 Sep 2018 09:51:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F1072AD64; Fri, 7 Sep 2018 09:51:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 705A72AD14 for ; Fri, 7 Sep 2018 09:51:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728336AbeIGObW (ORCPT ); Fri, 7 Sep 2018 10:31:22 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:52679 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGObW (ORCPT ); Fri, 7 Sep 2018 10:31:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313873; x=1567849873; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jrnoq7YHlAqEERumIXBtSXEHEObjEVZqwMM0GahCyC8=; b=LeKfLwKj3HHLl+i0Bm4U34LaZlFtQ1uqrzhkhJlKYgKCTu8JJFzETyS3 h0ziLBCHgzFYakHArQ817xGmV/XMqiSDVo5Nj0YzeC18xo79uRjj0D5cE RthT7lNrJX1l33u7yhiWZTylr4UtydzBB4TU2WkQAHpgT3wNipxkUdmTs 20shoHYtZ0UEBQnWbuF12C6DIemfFJu+QvgedaSCvYh5rCBp+PR7ToDP+ gdJO9RQIQlU9IkDcTun8pC46qApC1atic2UTemRujuMyWUIphnzWrpT+v 7m6XrJv4evzdX/Pfm5VDIYi9i+Iy7ckhSmcFv/alvtvHVk1cEIn/+Fdkk A==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="89268018" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:51:13 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 07 Sep 2018 02:37:54 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:51:11 -0700 From: Avri Altman To: 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 , Avri Altman Subject: [PATCH v4 4/7] scsi: ufs: Add ufs-bsg module Date: Fri, 7 Sep 2018 12:49:40 +0300 Message-Id: <1536313783-13025-5-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 0000000..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 = &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(struct ufs_hba *hba) +{ + if (!hba->bsg_node) + return; + + ufs_bsg_node_delete(hba->bsg_node); +} + +static void ufs_bsg_node_release(struct device *dev) +{ + struct ufs_bsg_node *node = dev_to_ufs_node(dev); + + put_device(dev->parent); + kfree(node); +} + +static struct ufs_bsg_node *ufs_bsg_node_alloc(struct Scsi_Host *shost) +{ + struct ufs_bsg_node *node; + struct device *parent = &shost->shost_gendev; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return NULL; + + device_initialize(&node->dev); + + node->dev.parent = get_device(parent); + node->dev.release = ufs_bsg_node_release; + + dev_set_name(&node->dev, "ufs-bsg-%d:0", shost->host_no); + + return node; +} + +static int ufs_bsg_initialize(struct Scsi_Host *shost, + struct ufs_bsg_node *node) +{ + struct request_queue *q; + + q = bsg_setup_queue(&node->dev, dev_name(&node->dev), + ufs_bsg_request, 0); + if (IS_ERR(q)) + return PTR_ERR(q); + node->q = q; + + return 0; +} + +static int ufs_bsg_node_add(struct ufs_bsg_node *node) +{ + struct device *dev = &node->dev; + struct Scsi_Host *shost = dev_to_shost(dev->parent); + int error; + + error = device_add(dev); + if (error) + return error; + + if (ufs_bsg_initialize(shost, node)) + dev_err(dev, "fail to initialize a bsg dev %d\n", + shost->host_no); + + return 0; +} + +/** + * ufs_bsg_probe - Add ufs bsg device node + * @hba: per adapter object + * + * Called during initial loading of the driver, and before scsi_scan_host. + */ +int ufs_bsg_probe(struct ufs_hba *hba) +{ + struct ufs_bsg_node *node; + int ret; + + node = ufs_bsg_node_alloc(hba->host); + if (!node) { + ret = -ENOMEM; + goto out; + } + + ret = ufs_bsg_node_add(node); + if (ret) + goto out_free_node; + + hba->bsg_node = node; + + return 0; + +out_free_node: + put_device(&node->dev); +out: + return ret; +} diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h new file mode 100644 index 0000000..36d3a12 --- /dev/null +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Western Digital Corporation + */ +#ifndef UFS_BSG_H +#define UFS_BSG_H + +#include +#include +#include + +#include "ufshcd.h" +#include "ufs.h" + +#define UPIU_TRANSACTION_UIC_CMD 0x1F + +enum { + REQ_UPIU_SIZE_DWORDS = 8, + RSP_UPIU_SIZE_DWORDS = 8, +}; + +struct ufs_bsg_request { + uint32_t msgcode; + struct utp_upiu_header header; + union { + struct utp_upiu_query qr; + struct utp_upiu_query tr; + /* use utp_upiu_query to host the 4 dwords of uic command */ + struct utp_upiu_query uc; + } tsf; +}; + + +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 received? */ + uint32_t reply_payload_rcv_len; + + struct utp_upiu_header header; + union { + struct utp_upiu_query qr; + struct utp_upiu_query tr; + struct utp_upiu_query uc; + } tsf; +}; + +#ifdef CONFIG_SCSI_UFS_BSG +void ufs_bsg_remove(struct ufs_hba *hba); +int ufs_bsg_probe(struct ufs_hba *hba); +#else +static inline void ufs_bsg_remove(struct ufs_hba *hba) {} +static inline int ufs_bsg_probe(struct ufs_hba *hba) {return 0; } +#endif + +#endif /* UFS_BSG_H */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d021c3a..e53e145 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 @@ -6621,6 +6622,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); } @@ -7844,6 +7847,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) */ void ufshcd_remove(struct ufs_hba *hba) { + ufs_bsg_remove(hba); ufs_sysfs_remove_nodes(hba->dev); scsi_remove_host(hba->host); /* disable interrupts */ diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 33fdd3f..46ea7c3 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -702,6 +702,8 @@ struct ufs_hba { struct rw_semaphore clk_scaling_lock; struct ufs_desc_size desc_size; atomic_t scsi_block_reqs_cnt; + + struct ufs_bsg_node *bsg_node; }; /* Returns true if clocks can be gated. Otherwise false */ From patchwork Fri Sep 7 09:49:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591973 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B1F8714E0 for ; Fri, 7 Sep 2018 09:51:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 908E82AD14 for ; Fri, 7 Sep 2018 09:51:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 84A992AD64; Fri, 7 Sep 2018 09:51:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E38442AD14 for ; Fri, 7 Sep 2018 09:51:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728378AbeIGOb1 (ORCPT ); Fri, 7 Sep 2018 10:31:27 -0400 Received: from esa2.hgst.iphmx.com ([68.232.143.124]:37238 "EHLO esa2.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGOb1 (ORCPT ); Fri, 7 Sep 2018 10:31:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313947; x=1567849947; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=Ogub4OltWnuZPZ7jpTbIEoNFfUI2AYe9ViQJhS7lgvw=; b=iTWdni8uXFZlYHri8F9QEKqD+rXPkFFiRZZvmiUZvXbUz8dRospuhUzT hvmMju2cVTHY9rcIawDfQq9f/BJ1Scr7JlDiaOFyIFT8FEim8jnI0KZ/A vXim02CHSXbfYxwna0QwKgwmSeR2xv0G+DR7yoAl0QSXhiZ6PLYuEXNPC lR2962J3yvrrtJO0NXVLVZFDjI1C7s10NnhxM9yB2SeonsRRxWRVTjLEv I21LCiVsYwWNVI/tWk7OcUUY3V1GqP4dG5wGTWF9xmQs+UQ3TwOJxkoyx oL1k3DxLlLSA45SuQbpk/XghX93ueWqV8fF+/mWgNJycm++pFoWRKRZS0 Q==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="186775550" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:52:27 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 07 Sep 2018 02:37:59 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:51:16 -0700 From: Avri Altman To: 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 , Avri Altman Subject: [PATCH v4 5/7] scsi: ufs: Add API to execute raw upiu commands Date: Fri, 7 Sep 2018 12:49:41 +0300 Message-Id: <1536313783-13025-6-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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(&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); + wake_up(&hba->dev_cmd.tag_wq); + up_read(&hba->clk_scaling_lock); + return err; +} + +/** + * ufshcd_exec_raw_upiu_cmd - API function for sending raw upiu commands + * @hba: per-adapter instance + * @req_upiu: upiu request + * @rsp_upiu: upiu reply - only 8 DW as we do not support scsi commands + * @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, + struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, + int msgcode, + u8 *desc_buff, int *buff_len, int rw) +{ + int err; + int cmd_type = DEV_CMD_TYPE_QUERY; + u8 resp = 0xF; + + if (desc_buff && rw == READ) { + err = -ENOTSUPP; + goto out; + } + + switch (msgcode) { + case UPIU_TRANSACTION_NOP_OUT: + cmd_type = DEV_CMD_TYPE_NOP; + /* fall through */ + case UPIU_TRANSACTION_QUERY_REQ: + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); + err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu, + desc_buff, buff_len, + cmd_type, rw); + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); + + break; + case UPIU_TRANSACTION_TASK_REQ: + err = ufshcd_issue_tm_cmd(hba, req_upiu, rsp_upiu, 0, 0, 0, + &resp); + + break; + default: + err = -EINVAL; + + break; + } + +out: + return err; +} + +/** * ufshcd_eh_device_reset_handler - device reset handler registered to * scsi layer. * @cmd: SCSI command pointer diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 46ea7c3..01e2a82 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -894,6 +894,12 @@ 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_exec_raw_upiu_cmd(struct ufs_hba *hba, + struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, + int msgcode, + u8 *desc_buff, int *buff_len, int rw); + /* Wrapper functions for safely calling variant operations */ static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) { From patchwork Fri Sep 7 09:49:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591975 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 670FA14E0 for ; Fri, 7 Sep 2018 09:51:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 474F92AD14 for ; Fri, 7 Sep 2018 09:51:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3BA712AD64; Fri, 7 Sep 2018 09:51:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5ABA2AD14 for ; Fri, 7 Sep 2018 09:51:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728413AbeIGObc (ORCPT ); Fri, 7 Sep 2018 10:31:32 -0400 Received: from esa2.hgst.iphmx.com ([68.232.143.124]:37245 "EHLO esa2.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGObc (ORCPT ); Fri, 7 Sep 2018 10:31:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313954; x=1567849954; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=qRHHmuCOlwLFxPtEkC7hjXkVCR++6XOtn/6D0d5i9DM=; b=LyV7boJtU3jxiAJx7wWZjH4VWvDlJ6kJBAeIN7LhXA5xDjANrRljwy++ donrpIfwBRQQgBW9H6e9ucysMdIXv4jFNkYKf4p2K0r8mTX8Oau92n/5i VgA4yY94mz3FUOXhd3hNgPqY58Fif9ObvwDfiaw15miEcEn55Vngh7ZyI vrJ8HwKH8kf/k666SZy+ns5H53bKFl6QVZRRU/WtcpvIMDALsLZaB1NA+ /ACQxnUC6CTyy2hU08haBIu7oA5R9tczGn0OiYRLtP5Iio+M03t+fxGt6 jY7+hG4v4li8y2MewEPExgxsPpU+6YyGStgbm8i7hP8w0Yay7zVcUdeTB Q==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="186775558" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:52:34 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 07 Sep 2018 02:38:03 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:51:20 -0700 From: Avri Altman To: 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 , Avri Altman Subject: [PATCH v4 6/7] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request() Date: Fri, 7 Sep 2018 12:49:42 +0300 Message-Id: <1536313783-13025-7-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 = &bsg_request->tsf.qr; + if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC) + goto not_supported; + + if (ufs_bsg_get_query_desc_size(hba, 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(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; + dev_err(job->dev, "unsupported msgcode 0x%x\n", msgcode); + + break; + default: + ret = -EINVAL; + + break; + } + /* + * As we do not support read descriptor, the returning + * reply_payload_rcv_len is always 0. + */ + bsg_reply->reply_payload_rcv_len = 0; + +out: bsg_reply->result = ret; if (ret) job->reply_len = sizeof(uint32_t); diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h index 36d3a12..4da1837 100644 --- a/drivers/scsi/ufs/ufs_bsg.h +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -12,6 +12,7 @@ #include "ufshcd.h" #include "ufs.h" +#define UFS_BSG_NOP (-1) #define UPIU_TRANSACTION_UIC_CMD 0x1F enum { From patchwork Fri Sep 7 09:49:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10591977 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B9AD56CB for ; Fri, 7 Sep 2018 09:51:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 993ED2AD14 for ; Fri, 7 Sep 2018 09:51:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8B82E2AD64; Fri, 7 Sep 2018 09:51:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 241642AD14 for ; Fri, 7 Sep 2018 09:51:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728601AbeIGObg (ORCPT ); Fri, 7 Sep 2018 10:31:36 -0400 Received: from esa2.hgst.iphmx.com ([68.232.143.124]:37250 "EHLO esa2.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726031AbeIGObg (ORCPT ); Fri, 7 Sep 2018 10:31:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1536313961; x=1567849961; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=wbrCSjYhfROT2qRcg7S56DI4Ftf38hKEtNOr+drpGT4=; b=Gc/37bM3KiDPQxP5nWAaFIanZEZ23mLHz+PTVbPsNoAPatH7O6bwbp7k RXWghvi6PI8iXju6l1YBOjG97Cn/Vs1bLvfcjo3LZdIIaKS09M0+JWPpa qxHAxfstp25eLDVEyFPWQfvvhRgVF4Q+akIgFqqoDhSg1JWmYi3LedoSE RahsvAv4FMV0aC5MEORVNBtFHNtNiLtSMxX9rw4t0+Q/6ZqO4KWqCdtNG wM2a7KyAtFVf49ZDMSsxBRL09fENraVtgmq5FnNiFpZhESixpcknwqMux JFU0BQ3W/POwmiamT/a+jA66h0ZCIUceVMME0FLIEghHwLY0bs9nT0GXu g==; X-IronPort-AV: E=Sophos;i="5.53,341,1531756800"; d="scan'208";a="186775561" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2018 17:52:41 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 07 Sep 2018 02:38:08 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2018 02:51:25 -0700 From: Avri Altman To: 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 , Avri Altman Subject: [PATCH v4 7/7] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request() Date: Fri, 7 Sep 2018 12:49:43 +0300 Message-Id: <1536313783-13025-8-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> References: <1536313783-13025-1-git-send-email-avri.altman@wdc.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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, &mib_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, &mib_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(&uc, &bsg_request->tsf.uc, UIC_CMD_SIZE); + ret = ufs_bsg_exec_uic_cmd(hba, &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 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,