Add ioctl and debug utilities to UFS driver
Subsystems (5)
v4 cover Add ioctl and debug utilities to UFS driver
Changes from V3:
Changed tag statistics macros to functions and removed redundant call to ufsdbg_remove_debugfs().
Other minor changes fixing previous comments.
Dolev Raviv (1):
scsi: ufs: add ioctl interface for query request
Gilad Broner (1):
scsi: ufs: add trace events and dump prints for debug
Lee Susman (1):
scsi: ufs: add debugfs for ufs
Sujit Reddy Thumma (1):
scsi: ufs: inject errors to verify error handling
drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-debugfs.c | 1042 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-debugfs.h | 42 ++ drivers/scsi/ufs/ufs-qcom.c | 53 ++ drivers/scsi/ufs/ufs.h | 53 +- drivers/scsi/ufs/ufshcd.c | 965 +++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 115 +++++ drivers/scsi/ufs/ufshci.h | 3 + include/trace/events/ufs.h | 227 +++++++++ include/uapi/scsi/Kbuild | 1 + include/uapi/scsi/ufs/Kbuild | 3 + include/uapi/scsi/ufs/ioctl.h | 57 +++ include/uapi/scsi/ufs/ufs.h | 66 +++ lib/Kconfig.debug | 14 + 14 files changed, 2552 insertions(+), 90 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-debugfs.c create mode 100644 drivers/scsi/ufs/ufs-debugfs.h create mode 100644 include/trace/events/ufs.h create mode 100644 include/uapi/scsi/ufs/Kbuild create mode 100644 include/uapi/scsi/ufs/ioctl.h create mode 100644 include/uapi/scsi/ufs/ufs.h
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v4 1/4 scsi: ufs: add ioctl interface for query request
From: Dolev Raviv <[email protected]>
This patch exposes the ioctl interface for UFS driver via SCSI device ioctl interface. As of now UFS driver would provide the ioctl for query interface to connected UFS device.
--- drivers/scsi/ufs/ufs.h | 53 +++------- drivers/scsi/ufs/ufshcd.c | 225 +++++++++++++++++++++++++++++++++++++++++- include/uapi/scsi/Kbuild | 1 + include/uapi/scsi/ufs/Kbuild | 3 + include/uapi/scsi/ufs/ioctl.h | 57 +++++++++++ include/uapi/scsi/ufs/ufs.h | 66 +++++++++++++ 6 files changed, 361 insertions(+), 44 deletions(-) create mode 100644 include/uapi/scsi/ufs/Kbuild create mode 100644 include/uapi/scsi/ufs/ioctl.h create mode 100644 include/uapi/scsi/ufs/ufs.h
drivers/scsi/ufs/ufs.h +11 -42
@@ -38,6 +38,7 @@#include <linux/mutex.h> #include <linux/types.h> +#include <scsi/ufs/ufs.h> #define MAX_CDB_SIZE 16#define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum { UFS_UPIU_RPMB_WLUN = 0xC4, }; +/** +* ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor +* @lun: LU number to check +* @return: true if the lun has a matching unit descriptor, false otherwise +*/ +static inline bool ufs_is_valid_unit_desc_lun (u8 lun) +{ +return (lun ==UFS_UPIU_RPMB_WLUN || (lun <UFS_UPIU_MAX_GENERAL_LUN )); +} +/* * UFS Protocol Information Unit related definitions */
@@ -126,35 +137,6 @@ enum { UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81, }; -/* Flag idn for Query Requests*/ -enum flag_idn { -QUERY_FLAG_IDN_FDEVICEINIT =0x01 , -QUERY_FLAG_IDN_PWR_ON_WPE =0x03 , -QUERY_FLAG_IDN_BKOPS_EN =0x04 , -}; - -/* Attribute idn for Query requests */ -enum attr_idn { -QUERY_ATTR_IDN_ACTIVE_ICC_LVL =0x03 , -QUERY_ATTR_IDN_BKOPS_STATUS =0x05 , -QUERY_ATTR_IDN_EE_CONTROL =0x0D , -QUERY_ATTR_IDN_EE_STATUS =0x0E , -}; - -/* Descriptor idn for Query requests */ -enum desc_idn { -QUERY_DESC_IDN_DEVICE =0x0 , -QUERY_DESC_IDN_CONFIGURAION =0x1 , -QUERY_DESC_IDN_UNIT =0x2 , -QUERY_DESC_IDN_RFU_0 =0x3 , -QUERY_DESC_IDN_INTERCONNECT =0x4 , -QUERY_DESC_IDN_STRING =0x5 , -QUERY_DESC_IDN_RFU_1 =0x6 , -QUERY_DESC_IDN_GEOMETRY =0x7 , -QUERY_DESC_IDN_POWER =0x8 , -QUERY_DESC_IDN_MAX , -}; -enum desc_header_offset {QUERY_DESC_LENGTH_OFFSET =0x00 ,QUERY_DESC_DESC_TYPE_OFFSET =0x01 ,
@@ -247,19 +229,6 @@ enum bkops_status { BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, }; -/* UTP QUERY Transaction Specific Fields OpCode */ -enum query_opcode { -UPIU_QUERY_OPCODE_NOP =0x0 , -UPIU_QUERY_OPCODE_READ_DESC =0x1 , -UPIU_QUERY_OPCODE_WRITE_DESC =0x2 , -UPIU_QUERY_OPCODE_READ_ATTR =0x3 , -UPIU_QUERY_OPCODE_WRITE_ATTR =0x4 , -UPIU_QUERY_OPCODE_READ_FLAG =0x5 , -UPIU_QUERY_OPCODE_SET_FLAG =0x6 , -UPIU_QUERY_OPCODE_CLEAR_FLAG =0x7 , -UPIU_QUERY_OPCODE_TOGGLE_FLAG =0x8 , -}; -/* Query response result code */ enum {QUERY_RESULT_SUCCESS =0x00 ,
drivers/scsi/ufs/ufshcd.c +223 -2
261 lines not on this page · raw message
include/uapi/scsi/Kbuild +1 -0
@@ -1,5 +1,6 @@ # UAPI Header export list header-y += fc/ +header-y += ufs/ header-y += scsi_bsg_fc.h header-y += scsi_netlink.h header-y += scsi_netlink_fc.h
include/uapi/scsi/ufs/Kbuild new file +3 -0
@@ -0,0 +1,3 @@ +# UAPI Header export list +header-y += ioctl.h +header-y += ufs.h
include/uapi/scsi/ufs/ioctl.h new file +57 -0
57 lines not on this page · raw message
include/uapi/scsi/ufs/ufs.h new file +66 -0
66 lines not on this page · raw message
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v4 2/4 scsi: ufs: add debugfs for ufs
In reply to Gilad BronerFrom: Lee Susman <[email protected]>
Adding debugfs capability for ufshcd.
debugfs attributes introduced in this patch:
- View driver/controller runtime data
- Command tag statistics for performance analisis
- Dump device descriptor info
- Track recoverable errors statistics during runtime
- Change UFS power mode during runtime
entry a string in the format 'GGLLMM' where:
G - selected gear
L - number of lanes
M - power mode
(1=fast mode, 2=slow mode, 4=fast-auto mode,
5=slow-auto mode)
First letter is for RX, second is for TX.
- Get/set DME attributes
--- drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-debugfs.c | 902 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-debugfs.h | 38 ++ drivers/scsi/ufs/ufshcd.c | 229 ++++++++++- drivers/scsi/ufs/ufshcd.h | 65 +++ drivers/scsi/ufs/ufshci.h | 2 + 6 files changed, 1225 insertions(+), 12 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-debugfs.c create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
drivers/scsi/ufs/Makefile +1 -0
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o +obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
drivers/scsi/ufs/ufs-debugfs.c new file +902 -0
902 lines not on this page · raw message
drivers/scsi/ufs/ufs-debugfs.h new file +38 -0
@@ -0,0 +1,38 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* UFS debugfs - add debugfs interface to the ufshcd. +* This is currently used for statistics collection and exporting from the +* UFS driver. +* This infrastructure can be used for debugging or direct tweaking +* of the driver from userspace. +* +*/ + +#ifndef _UFS_DEBUGFS_H +#define _UFS_DEBUGFS_H + +#include <linux/debugfs.h> +#include "ufshcd.h" + +#ifdef CONFIG_DEBUG_FS +void ufsdbg_add_debugfs (struct ufs_hba *hba); +void ufsdbg_remove_debugfs (struct ufs_hba *hba); +#else +static inline void ufsdbg_add_debugfs (struct ufs_hba *hba) +{ +} +static inline void ufsdbg_remove_debugfs (struct ufs_hba *hba) +{ +} +#endif + +#endif /* End of Header */
drivers/scsi/ufs/ufshcd.c +217 -12
399 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.h +65 -0
99 lines not on this page · raw message
drivers/scsi/ufs/ufshci.h +2 -0
@@ -72,6 +72,8 @@ enum {REG_UIC_COMMAND_ARG_1 =0x94 ,REG_UIC_COMMAND_ARG_2 =0x98 ,REG_UIC_COMMAND_ARG_3 =0x9C , + + UFSHCI_REG_SPACE_SIZE = 0xA0, };/* Controller capability masks */
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v4 3/4 scsi: ufs: add trace events and dump prints for debug
In reply to Gilad BronerAdd trace events to driver to allow monitoring and profilig of activities such as PM suspend/resume, hibernate enter/exit, clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide detailed information in case of errors to assist in analysis of issues.
--- drivers/scsi/ufs/ufs-qcom.c | 53 +++++ drivers/scsi/ufs/ufshcd.c | 511 +++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/ufs/ufshcd.h | 49 ++++- drivers/scsi/ufs/ufshci.h | 1 + include/trace/events/ufs.h | 227 ++++++++++++++++++++ 5 files changed, 804 insertions(+), 37 deletions(-) create mode 100644 include/trace/events/ufs.h
drivers/scsi/ufs/ufs-qcom.c +53 -0
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, const char *speed_mode);static int ufs_qcom_set_bus_vote (struct ufs_qcom_host *host,int vote); +static void ufs_qcom_dump_regs (struct ufs_hba *hba,int offset,int len, +char *prefix) +{ +print_hex_dump (KERN_ERR , prefix, + len >4 ?DUMP_PREFIX_OFFSET :DUMP_PREFIX_NONE , +16 ,4 , hba->mmio_base + offset, len *4 , false); +} +static int ufs_qcom_get_connected_tx_lanes (struct ufs_hba *hba,u32 *tx_lanes) {int err =0 ;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba) dev_req_params->hs_rate); } +static void ufs_qcom_print_hw_debug_reg_all (struct ufs_hba *hba) +{ +u32 reg; + +ufs_qcom_dump_regs (hba,UFS_UFS_DBG_RD_REG_OCSC ,44 , +"UFS_UFS_DBG_RD_REG_OCSC " ); + + reg =ufshcd_readl (hba,REG_UFS_CFG1 ); + reg |=UFS_BIT (17 ); +ufshcd_writel (hba, reg,REG_UFS_CFG1 ); + +ufs_qcom_dump_regs (hba,UFS_UFS_DBG_RD_EDTL_RAM ,32 , +"UFS_UFS_DBG_RD_EDTL_RAM " ); +ufs_qcom_dump_regs (hba,UFS_UFS_DBG_RD_DESC_RAM ,128 , +"UFS_UFS_DBG_RD_DESC_RAM " ); +ufs_qcom_dump_regs (hba,UFS_UFS_DBG_RD_PRDT_RAM ,64 , +"UFS_UFS_DBG_RD_PRDT_RAM " ); + +ufshcd_writel (hba, (reg & ~UFS_BIT (17 )),REG_UFS_CFG1 ); + +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_UAWM ,4 , +"UFS_DBG_RD_REG_UAWM " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_UARM ,4 , +"UFS_DBG_RD_REG_UARM " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_TXUC ,48 , +"UFS_DBG_RD_REG_TXUC " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_RXUC ,27 , +"UFS_DBG_RD_REG_RXUC " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_DFC ,19 , +"UFS_DBG_RD_REG_DFC " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_TRLUT ,34 , +"UFS_DBG_RD_REG_TRLUT " ); +ufs_qcom_dump_regs (hba,UFS_DBG_RD_REG_TMRLUT ,9 , +"UFS_DBG_RD_REG_TMRLUT " ); +} + +static void ufs_qcom_dump_dbg_regs (struct ufs_hba *hba) +{ +ufs_qcom_dump_regs (hba,REG_UFS_SYS1CLK_1US ,5 , +"REG_UFS_SYS1CLK_1US " ); + +ufs_qcom_print_hw_debug_reg_all (hba); +} +/** * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .pwr_change_notify = ufs_qcom_pwr_change_notify, .suspend = ufs_qcom_suspend, .resume = ufs_qcom_resume, + .dbg_register_dump = ufs_qcom_dump_dbg_regs, };EXPORT_SYMBOL (ufs_hba_qcom_vops);
drivers/scsi/ufs/ufshcd.c +476 -35
915 lines not on this page · raw message
drivers/scsi/ufs/ufshcd.h +47 -2
95 lines not on this page · raw message
drivers/scsi/ufs/ufshci.h +1 -0
@@ -166,6 +166,7 @@ enum {/* UECPA - Host UIC Error Code PHY Adapter Layer 38h */ #define UIC_PHY_ADAPTER_LAYER_ERROR UFS_BIT(31)#define UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK 0x1F +#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF/* UECDL - Host UIC Error Code Data Link Layer 3Ch */ #define UIC_DATA_LINK_LAYER_ERROR UFS_BIT(31)
include/trace/events/ufs.h new file +227 -0
227 lines not on this page · raw message
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH v4 4/4 scsi: ufs: inject errors to verify error handling
In reply to Gilad BronerFrom: Sujit Reddy Thumma <[email protected]>
Use fault-injection framework to simulate error conditions in the controller and verify error handling mechanisms implemented in UFS host controller driver.
This is used only during development and hence guarded by CONFIG_UFS_FAULT_INJECTION debug config option.
--- drivers/scsi/ufs/ufs-debugfs.c | 140 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-debugfs.h | 4 ++ drivers/scsi/ufs/ufshcd.c | 2 + drivers/scsi/ufs/ufshcd.h | 5 ++ lib/Kconfig.debug | 14 +++++ 5 files changed, 165 insertions(+)
drivers/scsi/ufs/ufs-debugfs.c +140 -0
@@ -17,6 +17,7 @@* */ +#include <linux/random.h> #include "ufs-debugfs.h" #include "unipro.h"
@@ -41,6 +42,143 @@ struct desc_field_offset { } while (0)#define DOORBELL_CLR_TOUT_US (1000 * 1000)/* 1 sec */ +#ifdef CONFIG_UFS_FAULT_INJECTION + +#define INJECT_COMMAND_HANG (0x0) + +static DECLARE_FAULT_ATTR (fail_default_attr); +static char *fail_request; +module_param (fail_request, charp,0 ); + +static bool inject_fatal_err_tr (struct ufs_hba *hba,u8 ocs_err) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_reqs, hba->nutrs); +if (tag == hba->nutrs) +return 0 ; + +ufshcd_writel (hba, ~(1 << tag),REG_UTP_TRANSFER_REQ_LIST_CLEAR ); + (&hba->lrb[tag])->utr_descriptor_ptr->header.dword_2 = +cpu_to_be32 (ocs_err); + +/* fatal error injected */ +return 1 ; +} + +static bool inject_fatal_err_tm (struct ufs_hba *hba,u8 ocs_err) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_tasks, hba->nutmrs); +if (tag == hba->nutmrs) +return 0 ; + +ufshcd_writel (hba, ~(1 << tag),REG_UTP_TASK_REQ_LIST_CLEAR ); + (&hba->utmrdl_base_addr[tag])->header.dword_2 = +cpu_to_be32 (ocs_err); + +/* fatal error injected */ +return 1 ; +} + +static bool inject_cmd_hang_tr (struct ufs_hba *hba) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_reqs, hba->nutrs); +if (tag == hba->nutrs) +return 0 ; + +__clear_bit (tag, &hba->outstanding_reqs); + hba->lrb[tag].cmd =NULL ; +__clear_bit (tag, &hba->lrb_in_use); + +/* command hang injected */ +return 1 ; +} + +static int inject_cmd_hang_tm (struct ufs_hba *hba) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_tasks, hba->nutmrs); +if (tag == hba->nutmrs) +return 0 ; + +__clear_bit (tag, &hba->outstanding_tasks); +__clear_bit (tag, &hba->tm_slots_in_use); + +/* command hang injected */ +return 1 ; +} + +void ufsdbg_fail_request (struct ufs_hba *hba,u32 *intr_status) +{ +u8 ocs_err; +static const u32 errors[] = { +CONTROLLER_FATAL_ERROR , +SYSTEM_BUS_FATAL_ERROR , +INJECT_COMMAND_HANG , + }; + +if (!should_fail (&hba->debugfs_files.fail_attr,1 )) + goto out; + + *intr_status = errors[prandom_u32 () %ARRAY_SIZE (errors)]; +dev_info (hba->dev,"%s: fault-inject error: 0x%x\n" , + __func__, *intr_status); + +switch (*intr_status) { +case CONTROLLER_FATAL_ERROR :/* fall through */ + ocs_err =OCS_FATAL_ERROR ; + goto set_ocs; +case SYSTEM_BUS_FATAL_ERROR : + ocs_err =OCS_INVALID_CMD_TABLE_ATTR ; +set_ocs: +if (!inject_fatal_err_tr (hba, ocs_err)) +if (!inject_fatal_err_tm (hba, ocs_err)) + *intr_status =0 ; +break ; +case INJECT_COMMAND_HANG : +if (!inject_cmd_hang_tr (hba)) +inject_cmd_hang_tm (hba); +break ; +default : +BUG (); +/* some configurations ignore panics caused by BUG() */ +break ; + } +out: +return ; +} + +static void ufsdbg_setup_fault_injection (struct ufs_hba *hba) +{ + hba->debugfs_files.fail_attr = fail_default_attr; + +if (fail_request) +setup_fault_attr (&hba->debugfs_files.fail_attr, fail_request); + +/* suppress dump stack everytime failure is injected */ + hba->debugfs_files.fail_attr.verbose =0 ; + +if (IS_ERR (fault_create_debugfs_attr ("inject_fault" , + hba->debugfs_files.debugfs_root, + &hba->debugfs_files.fail_attr))) +dev_err (hba->dev,"%s: failed to create debugfs entry\n" , + __func__); +} +#else +void ufsdbg_fail_request (struct ufs_hba *hba,u32 *intr_status) +{ +} + +static void ufsdbg_setup_fault_injection (struct ufs_hba *hba) +{ +} +#endif /* CONFIG_UFS_FAULT_INJECTION */ +#define BUFF_LINE_CAPACITY 16#define TAB_CHARS 8
@@ -885,6 +1023,8 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba) goto err; } +ufsdbg_setup_fault_injection (hba); +return ; err:
drivers/scsi/ufs/ufs-debugfs.h +4 -0
@@ -26,6 +26,7 @@#ifdef CONFIG_DEBUG_FS void ufsdbg_add_debugfs (struct ufs_hba *hba);void ufsdbg_remove_debugfs (struct ufs_hba *hba); +void ufsdbg_fail_request (struct ufs_hba *hba,u32 *intr_status);#else static inline void ufsdbg_add_debugfs (struct ufs_hba *hba) {
@@ -33,6 +34,9 @@ static inline void ufsdbg_add_debugfs(struct ufs_hba *hba)static inline void ufsdbg_remove_debugfs (struct ufs_hba *hba) { } +static inline void ufsdbg_fail_request (struct ufs_hba *hba,u32 *intr_status) +{ +}#endif #endif /* End of Header */
drivers/scsi/ufs/ufshcd.c +2 -0
@@ -4009,6 +4009,8 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba)*/ static void ufshcd_sl_intr (struct ufs_hba *hba,u32 intr_status) { +ufsdbg_fail_request (hba, &intr_status); + hba->errors =UFSHCD_ERROR_MASK & intr_status;if (hba->errors)ufshcd_check_errors (hba);
drivers/scsi/ufs/ufshcd.h +5 -0
@@ -64,6 +64,8 @@#include <scsi/scsi_dbg.h> #include <scsi/scsi_eh.h> +#include <linux/fault-inject.h> +#include "ufs.h" #include "ufshci.h"
@@ -283,6 +285,9 @@ struct debugfs_files {struct dentry *dme_peer_read;u32 dme_local_attr_id;u32 dme_peer_attr_id; +#ifdef CONFIG_UFS_FAULT_INJECTION +struct fault_attr fail_attr; +#endif };/* tag stats statistics types */
lib/Kconfig.debug +14 -0
@@ -1432,6 +1432,20 @@ config FAIL_MMC_REQUEST and to test how the mmc host driver handles retries from the block device. +config UFS_FAULT_INJECTION + bool "Fault-injection capability for UFS IO" + select DEBUG_FS + depends on FAULT_INJECTION && SCSI_UFSHCD + help + Provide fault-injection capability for UFS IO. + This will make the UFS host controller driver to randomly + abort ongoing commands in the host controller, update OCS + field according to the injected fatal error and can also + forcefully hang the command indefinitely till upper layer + timeout occurs. This is useful to test error handling in + the UFS contoller driver and test how the driver handles + the retries from block/SCSI mid layer. + config FAULT_INJECTION_DEBUG_FS bool "Debugfs entries for fault-injection capabilities" depends on FAULT_INJECTION && SYSFS && DEBUG_FS
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v4 4/4] scsi: ufs: inject errors to verify error handling
2015-03-02 23:56 GMT+09:00 Gilad Broner <[email protected]>:
Quoted 8 lines
From: Sujit Reddy Thumma <[email protected]>
Use fault-injection framework to simulate error conditions in the controller and verify error handling mechanisms implemented in UFS host controller driver.
This is used only during development and hence guarded by
CONFIG_UFS_FAULT_INJECTIONdebug config option.
This feature looks useful, but I have a couple of comments and question.
drivers/scsi/ufs/ufs-debugfs.c struct desc_field_offset { · line 95
Quoted 11 lines
drivers/scsi/ufs/ufs-debugfs.c +11
-0+static bool inject_cmd_hang_tr (struct ufs_hba *hba) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_reqs, hba->nutrs); +if (tag == hba->nutrs) +return 0 ; + +__clear_bit (tag, &hba->outstanding_reqs); + hba->lrb[tag].cmd =NULL ; +__clear_bit (tag, &hba->lrb_in_use);
hba->lrb_in_use is a bitmap set by test_and_set_bit_lock(). So this should be cleared by clear_bit_unlock().
And as soon as the bit corresponds to this slot in hba->lrb_in_use is cleared, this slot could be reused. But if the request corresponds to the slot is not completed yet, it could sacrifice the new request, too. So should we only inject into the commands which have been completed like this?
tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
completed_reqs = tr_doorbell ^ hba->outstanding_reqs;
tag = find_first_bit(&completed_reqs, hba->nutrs);
...Or clear the corresponding bit in REG_UTP_TASK_REQ_LIST_CLEAR, just like what inject_fatal_err_tr() does?
Quoted 9 lines
drivers/scsi/ufs/ufs-debugfs.c +9
-0+ +/* command hang injected */ +return 1 ; +} + +static int inject_cmd_hang_tm (struct ufs_hba *hba) +{ +int tag; +
drivers/scsi/ufs/ufs-debugfs.c struct desc_field_offset { · line 114
Quoted 10 lines
drivers/scsi/ufs/ufs-debugfs.c +10
-0+ tag =find_first_bit (&hba->outstanding_tasks, hba->nutmrs); +if (tag == hba->nutmrs) +return 0 ; + +__clear_bit (tag, &hba->outstanding_tasks); +__clear_bit (tag, &hba->tm_slots_in_use); + +/* command hang injected */ +return 1 ; +}
The same goes for hba->tm_slots_in_use.
Re: [PATCH v4 4/4] scsi: ufs: inject errors to verify error handling
Quoted 6 lines
Quoted 6 lines
drivers/scsi/ufs/ufs-debugfs.c +6
-0+static bool inject_cmd_hang_tr (struct ufs_hba *hba) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_reqs, hba->nutrs); +if (tag == hba->nutrs)
Quoted 8 lines
drivers/scsi/ufs/ufs-debugfs.c struct desc_field_offset { · line 95
Quoted 5 lines
drivers/scsi/ufs/ufs-debugfs.c +5
-0+return 0 ; + +__clear_bit (tag, &hba->outstanding_reqs); + hba->lrb[tag].cmd =NULL ; +__clear_bit (tag, &hba->lrb_in_use);
hba->lrb_in_useis a bitmap set bytest_and_set_bit_lock(). So this should be cleared byclear_bit_unlock().
You are correct. Thanks.
Quoted 6 lines
And as soon as the bit corresponds to this slot in
hba->lrb_in_useis cleared, this slot could be reused. But if the request corresponds to the slot is not completed yet, it could sacrifice the new request, too. So should we only inject into the commands which have been completed like this?
Please note that we only clear the bit in hba->lrb_in_use. scsi_done is not called for this request. Therefore, the tag is not yet free in the block layer and next calls for queuecommand will not pass down this tag to be used in the UFS driver. So there is no danger of a new request being sacrificed.
On a different note, we are debating internally on a few other changes so until we consolidate those I will drop this patch with error injection.
Gilad.
Signature · 3 lines
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v4 4/4] scsi: ufs: inject errors to verify error handling
2015-03-10 19:20 GMT+09:00 Gilad Broner <[email protected]>:
Quoted 24 lines
Quoted 6 lines
Quoted 6 lines
drivers/scsi/ufs/ufs-debugfs.c +6
-0+static bool inject_cmd_hang_tr (struct ufs_hba *hba) +{ +int tag; + + tag =find_first_bit (&hba->outstanding_reqs, hba->nutrs); +if (tag == hba->nutrs)Quoted 8 lines
drivers/scsi/ufs/ufs-debugfs.c struct desc_field_offset { · line 95
Quoted 5 lines
drivers/scsi/ufs/ufs-debugfs.c +5
-0+return 0 ; + +__clear_bit (tag, &hba->outstanding_reqs); + hba->lrb[tag].cmd =NULL ; +__clear_bit (tag, &hba->lrb_in_use);
hba->lrb_in_useis a bitmap set bytest_and_set_bit_lock(). So this should be cleared byclear_bit_unlock().You are correct. Thanks.
Quoted 6 lines
And as soon as the bit corresponds to this slot in
hba->lrb_in_useis cleared, this slot could be reused. But if the request corresponds to the slot is not completed yet, it could sacrifice the new request, too. So should we only inject into the commands which have been completed like this?
Quoted 5 lines
Please note that we only clear the bit in
hba->lrb_in_use.scsi_doneis not called for this request. Therefore, the tag is not yet free in the block layer and next calls for queuecommand will not pass down this tag to be used in the UFS driver. So there is no danger of a new request being sacrificed.
OK, I see there is no danger as far as the commands are comming through queuecommand(). But what about the query requests? PATCH 1/4 in this series has added ioctl interface for query request which also acquires a tag in hba->lrb_in_use through ufshcd_get_dev_cmd_tag(). Although it is very difficult to happen, is it possible for new query requests to be clashed by inject_cmd_hang_tr() in the same way I described earlier?