From patchwork Thu May 11 14:01:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Potomski, MichalX" X-Patchwork-Id: 9722437 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4CA936031B for ; Thu, 11 May 2017 16:25:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 41D41286AD for ; Thu, 11 May 2017 16:25:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 36BBF286B8; Thu, 11 May 2017 16:25:38 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 5F205286AD for ; Thu, 11 May 2017 16:25:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933491AbdEKOCv (ORCPT ); Thu, 11 May 2017 10:02:51 -0400 Received: from mga14.intel.com ([192.55.52.115]:44524 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933460AbdEKOBm (ORCPT ); Thu, 11 May 2017 10:01:42 -0400 Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 May 2017 07:01:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,324,1491289200"; d="scan'208";a="1146633437" Received: from mpotom-tieto.ir.intel.com ([10.103.116.163]) by fmsmga001.fm.intel.com with ESMTP; 11 May 2017 07:01:39 -0700 From: Michal Potomski To: linux-scsi@vger.kernel.org Cc: vinholikatti@gmail.com, martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, subhashj@codeaurora.org, =?UTF-8?q?Micha=C5=82=20Potomski?= Subject: [PATCH v1 3/4] scsi: ufs: Expose Task Management to ioctl() UAPI Date: Thu, 11 May 2017 16:01:48 +0200 Message-Id: <1494511309-32256-4-git-send-email-michalx.potomski@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1494511309-32256-1-git-send-email-michalx.potomski@intel.com> References: <1494511309-32256-1-git-send-email-michalx.potomski@intel.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 From: Michał Potomski Since we already have UFS ioctl() API some additional tools like task management are "nice-to-have" for testing and management purposes. Using this API we can transparently from user perspective query or abort tasks and reset Logical Units. This will help to test all hosts and devices to check their stability, error handling, etc. While this feature does not present great value for standard user, it might help a lot in troubleshooting of the device. Signed-off-by: Michał Potomski --- Documentation/scsi/ufs.txt | 35 +++++++++++++++++++++++++ drivers/scsi/ufs/ufs.h | 10 -------- drivers/scsi/ufs/ufshcd-ioctl.c | 57 +++++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.c | 2 +- drivers/scsi/ufs/ufshcd.h | 4 +++ include/scsi/scsi.h | 2 +- include/uapi/scsi/ufs/ioctl.h | 18 +++++++++++++ include/uapi/scsi/ufs/ufs.h | 10 ++++++++ 8 files changed, 124 insertions(+), 14 deletions(-) diff --git a/Documentation/scsi/ufs.txt b/Documentation/scsi/ufs.txt index 6c0e995..ed5768d 100644 --- a/Documentation/scsi/ufs.txt +++ b/Documentation/scsi/ufs.txt @@ -18,6 +18,7 @@ Contents 4. UFSHCD User Interface 4.1 UFS Query IOCTL 4.2 UFS Auto-Hibern8 IOCTL + 4.3 UFS Task Management IOCTL 1. Overview @@ -220,6 +221,40 @@ host and device using IOCTL interface. return error; } +4.3 UFS Task Management IOCTL + + This interface enables user to manage tasks on the device. It's meant + mainly for test and troubleshooting purposes. You can use following + snippet to comunicate with this interface: + + #include + #include + #include + + static int handleTask(int fd, uint8_t task_id, uint8_t task_func, + uint8_t *response) + { + ufs_ioctl_task_mgmt_data task_data; + int error; + + /* Task ID (normally in range 0-F) */ + task_data.task_id = task_id; + + /* Task Function (check ) */ + task_data.task_func = task_func; + + /* [fd] used here shall be opened UFS device */ + error = ioctl(fd, UFS_IOCTL_TASK_MANAGEMENT, &task_data); + + if (!error) + /* This will return task specific response */ + *response = task_data.response; + + return error; + } + + This one should be used with extreme care as it's more of a testing/vaidation + interface. UFS Specifications can be found at, diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 06da302..8bfa5f3 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -88,16 +88,6 @@ static inline bool ufs_is_valid_unit_desc_lun(u8 lun) * UFS Protocol Information Unit related definitions */ -/* Task management functions */ -enum { - UFS_ABORT_TASK = 0x01, - UFS_ABORT_TASK_SET = 0x02, - UFS_CLEAR_TASK_SET = 0x04, - UFS_LOGICAL_RESET = 0x08, - UFS_QUERY_TASK = 0x80, - UFS_QUERY_TASK_SET = 0x81, -}; - /* UTP UPIU Transaction Codes Initiator to Target */ enum { UPIU_TRANSACTION_NOP_OUT = 0x00, diff --git a/drivers/scsi/ufs/ufshcd-ioctl.c b/drivers/scsi/ufs/ufshcd-ioctl.c index 71f4026..afcb099 100644 --- a/drivers/scsi/ufs/ufshcd-ioctl.c +++ b/drivers/scsi/ufs/ufshcd-ioctl.c @@ -180,6 +180,7 @@ static int ufshcd_query_ioctl(struct ufs_hba *hba, u8 lun, void __user *buffer) goto out_release_mem; } + /* Prepare to handle query */ switch (ioctl_data->opcode) { case UPIU_QUERY_OPCODE_WRITE_DESC: write = true; @@ -329,6 +330,51 @@ static int ufshcd_auto_hibern8_ioctl(struct ufs_hba *hba, void __user *buffer) return err; } +static int ufshcd_task_mgmt_ioctl(struct ufs_hba *hba, u8 lun, + void __user *buffer) +{ + struct ufs_ioctl_task_mgmt_data *ioctl_data; + int err = 0; + + if (!buffer) + return -EINVAL; + + if (!ufs_is_valid_unit_desc_lun(lun)) + return -EINVAL; + + ioctl_data = kzalloc(sizeof(struct ufs_ioctl_task_mgmt_data), + GFP_KERNEL); + if (!ioctl_data) { + err = -ENOMEM; + goto out; + } + + /* Extract params from user buffer */ + if (copy_from_user(ioctl_data, buffer, sizeof(*ioctl_data))) { + err = -EFAULT; + goto out_release_mem; + } + + err = ufshcd_issue_tm_cmd(hba, lun, ioctl_data->task_id, + ioctl_data->task_func, &ioctl_data->response); + + if (err) + goto out_release_mem; + + /* Copy response to user */ + if (copy_to_user(buffer, ioctl_data, sizeof(*ioctl_data))) + err = -EFAULT; + +out_release_mem: + kfree(ioctl_data); +out: + if (err) + dev_err(hba->dev, "User Task Management failed (error: %d)", + err); + + return err; +} + /** * ufshcd_ioctl - ufs ioctl callback registered in scsi_host * @dev: scsi device required for per LUN queries @@ -338,6 +384,7 @@ static int ufshcd_auto_hibern8_ioctl(struct ufs_hba *hba, void __user *buffer) * Supported commands: * UFS_IOCTL_QUERY * UFS_IOCTL_AUTO_HIBERN8 + * UFS_IOCTL_TASK_MANAGEMENT */ int ufshcd_ioctl(struct scsi_device *dev, int cmd, void __user *buffer) { @@ -359,6 +405,12 @@ int ufshcd_ioctl(struct scsi_device *dev, int cmd, void __user *buffer) err = ufshcd_auto_hibern8_ioctl(hba, buffer); pm_runtime_put_sync(hba->dev); break; + case UFS_IOCTL_TASK_MANAGEMENT: + pm_runtime_get_sync(hba->dev); + err = ufshcd_task_mgmt_ioctl(hba, + ufshcd_scsi_to_upiu_lun(dev->lun), buffer); + pm_runtime_put_sync(hba->dev); + break; default: err = -EOPNOTSUPP; break; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6fcbeb5..6c52102 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5437,7 +5437,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) * * 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, +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; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 392f702..ef1607f 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -864,6 +864,10 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, void ufshcd_setup_auto_hibern8(struct ufs_hba *hba, u8 scale, u16 timer_val); u32 ufshcd_read_auto_hibern8_state(struct ufs_hba *hba); +/* Expose Task Management API */ +int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, + u8 tm_function, u8 *tm_response); + /* Wrapper functions for safely calling variant operations */ static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) { diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 43f87ad..b8e1006 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -255,7 +255,7 @@ static inline int scsi_is_wlun(u64 lun) * Here are some scsi specific ioctl commands which are sometimes useful. * * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395 - * include/uapi/scsi/ufs/ioctl.h defines 0x53A0 - 0x53A1 + * include/uapi/scsi/ufs/ioctl.h defines 0x53A0 - 0x53A2 */ /* Used to obtain PUN and LUN info. Conflicts with CDROMAUDIOBUFSIZ */ diff --git a/include/uapi/scsi/ufs/ioctl.h b/include/uapi/scsi/ufs/ioctl.h index f3583de..6b7e876 100644 --- a/include/uapi/scsi/ufs/ioctl.h +++ b/include/uapi/scsi/ufs/ioctl.h @@ -9,6 +9,7 @@ */ #define UFS_IOCTL_QUERY 0x53A0 #define UFS_IOCTL_AUTO_HIBERN8 0x53A1 +#define UFS_IOCTL_TASK_MANAGEMENT 0x53A2 /** * struct ufs_ioctl_query_data - used to transfer data to and from user via @@ -89,4 +90,21 @@ struct ufs_ioctl_auto_hibern8_data { __u16 timer_val; }; +/** + * struct ufs_ioctl_task_mgmt_data - used to perform Task Management specific + * functions + * + * @task_id: ID of a task to be managed + * @task_func: function to perform on managed task + * @response: Task Management response + * + * Submitted: task_id, task_func + * Received: response + */ +struct ufs_ioctl_task_mgmt_data { + __u8 task_id; + __u8 task_func; + __u8 response; +}; + #endif /* UAPI_UFS_IOCTL_H_ */ diff --git a/include/uapi/scsi/ufs/ufs.h b/include/uapi/scsi/ufs/ufs.h index 096ebea..9f93c9a 100644 --- a/include/uapi/scsi/ufs/ufs.h +++ b/include/uapi/scsi/ufs/ufs.h @@ -66,4 +66,14 @@ enum query_opcode { UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, }; +/* Task management functions */ +enum { + UFS_ABORT_TASK = 0x01, + UFS_ABORT_TASK_SET = 0x02, + UFS_CLEAR_TASK_SET = 0x04, + UFS_LOGICAL_RESET = 0x08, + UFS_QUERY_TASK = 0x80, + UFS_QUERY_TASK_SET = 0x81, +}; + #endif /* UAPI_UFS_H_ */