Skip to contentSkip to conversation

Add ioctl and debug utilities to UFS driver

PATCH Superseded Gilad Broner 4 participants 8 messages Apr 14, 2015 – Apr 29, 2015

Subsystems (4)

v8 of 9 Superseded Latest is v9 →

lore
Share & tools
lore
#0 lore raw

v8 cover Add ioctl and debug utilities to UFS driver

Changes from V7:
Fix handling of copy_from_user() result in case of incomplete copy in ufshcd_query_ioctl(). Fix ufs-debugfs build in case UFS is configured as a loadable kernel module.

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

 drivers/scsi/ufs/Makefile      |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 ++++++++++++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c    |  53 +++
 drivers/scsi/ufs/ufs.h         |  53 +--
 drivers/scsi/ufs/ufshcd.c      | 957 ++++++++++++++++++++++++++++++++++++++---
 drivers/scsi/ufs/ufshcd.h      | 110 +++++
 drivers/scsi/ufs/ufshci.h      |   3 +
 include/scsi/scsi.h            |   1 +
 include/trace/events/ufs.h     | 213 +++++++++
 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 +++
 14 files changed, 2368 insertions(+), 91 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
#1 lore raw

PATCH v8 1/3 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     | 219 +++++++++++++++++++++++++++++++++++++++++-
 include/scsi/scsi.h           |   1 +
 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 +++++++++++++
 7 files changed, 356 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
index 42c459a..1f023c4 100644
@@ -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 +217 -2

255 lines not on this page · raw message

include/scsi/scsi.h +1 -0
index d0a66aa..3feb501 100644
@@ -569,6 +569,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 0x5388
  */
 
 /* Used to obtain PUN and LUN info.  Conflicts with CDROMAUDIOBUFSIZ */
include/uapi/scsi/Kbuild +1 -0
index 75746d5..d404525 100644
@@ -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
new file mode 100644
index 0000000..cc3ef20
@@ -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
Reviewed-by on v8 1/3
#2 lore raw

Re: [PATCH v8 1/3] scsi: ufs: add ioctl interface for query request

Quoted 11 lines

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.

Quoted 14 lines
---
 drivers/scsi/ufs/ufs.h        |  53 +++-------
 drivers/scsi/ufs/ufshcd.c     | 219
+++++++++++++++++++++++++++++++++++++++++-
 include/scsi/scsi.h           |   1 +
 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 +++++++++++++
 7 files changed, 356 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

<snip many lines of code>

Quoted 9 lines
include/uapi/scsi/ufs/ufs.h new file +4 -1
+	UPIU_QUERY_OPCODE_CLEAR_FLAG	= 0x7,
+	UPIU_QUERY_OPCODE_TOGGLE_FLAG	= 0x8,
+};
+#endif /* UAPI_UFS_H_ */
--

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

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

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

#3 lore raw

PATCH v8 2/3 scsi: ufs: add debugfs for ufs

In reply to Gilad Broner

From: 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      |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 +++++++++++++++++++++++++++++++++++++++++
 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(+), 13 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
drivers/scsi/ufs/Makefile +2 -1
index 8303bcc..3291ce3 100644
@@ -1,5 +1,6 @@
 # UFSHCD makefile
+scsi_ufshcd_mod-y := ufshcd.o ufs-debugfs.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += scsi_ufshcd_mod.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
drivers/scsi/ufs/ufs-debugfs.c new file +901 -0

901 lines not on this page · raw message

drivers/scsi/ufs/ufs-debugfs.h new file +38 -0
new file mode 100644
index 0000000..7ed308d
@@ -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

400 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
index d572119..c8b178f 100644
@@ -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
Reviewed-by on v8 2/3
#4 lore raw

Re: [PATCH v8 2/3] scsi: ufs: add debugfs for ufs

Quoted 24 lines

From: 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

Quoted 12 lines
---
 drivers/scsi/ufs/Makefile      |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901
+++++++++++++++++++++++++++++++++++++++++
 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(+), 13 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

<snip many lines of code>

Quoted 14 lines
drivers/scsi/ufs/ufshci.h +2 -1
@@ -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 */
--

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

Quoted 5 lines

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

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

maintainer
#5 lore raw

Re: [PATCH v8 2/3] scsi: ufs: add debugfs for ufs

In reply to Gilad Broner
Quoted 19 lines · Gilad Broner

From: 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

Quoted 5 lines

Bloody test your damn changes. That means running them through a config options permutation when you introduce config dependencies.

This is what happens with CONFIG_DEBUG_FS=n:

drivers/scsi/ufs/ufshcd.c:92:9: warning: ‘struct scsi_cmd’ declared inside parameter list [enabled by default]
struct scsi_cmd *cmd)
^
drivers/scsi/ufs/ufshcd.c:92:9: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]

That's a typo inside the other branch of the #ifdef ... apparently none of your reviewers spotted it either.

drivers/scsi/ufs/ufs-debugfs.c: In function ‘ufsdbg_tag_stats_show’:
drivers/scsi/ufs/ufs-debugfs.c:60:18: error: ‘struct ufs_hba’ has no member named ‘ufs_stats’
ufs_stats = &hba->ufs_stats;
^
...

This lot is obvious: ufs-debufs should not be compiled at all if CONFIG_DEBUG_FS=n

From now on, I'm not taking your code unless it has an external reviewer who makes sure I don't keep running across crap like this.

James

#6 lore raw

PATCH v8 3/3 scsi: ufs: add trace events and dump prints for debug

In reply to Gilad Broner

Add 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  | 213 ++++++++++++++++++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h
drivers/scsi/ufs/ufs-qcom.c +53 -0
index 6652a81..68cbba4 100644
@@ -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;
@@ -995,6 +1003,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
  *
@@ -1012,5 +1064,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
index c8b178f..c5a0d19 100644
@@ -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 +213 -0

213 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
maintainer
#7 lore raw

Re: [RESEND/PATCH v8 3/3] scsi: ufs: add trace events and dump prints for debug

Quoted 38 lines · On Tue, 14 Apr 2015 14:51:21 +0300 Gilad Broner <[email protected]> wrote:
drivers/scsi/ufs/ufshcd.c +34 -0
+static const char *ufschd_uic_link_state_to_string(
+			enum uic_link_state state)
+{
+	switch (state) {
+	case UIC_LINK_OFF_STATE:	return "OFF";
+	case UIC_LINK_ACTIVE_STATE:	return "ACTIVE";
+	case UIC_LINK_HIBERN8_STATE:	return "HIBERN8";
+	default:			return "UNKNOWN";
+	}
+}
+
+static const char *ufschd_ufs_dev_pwr_mode_to_string(
+			enum ufs_dev_pwr_mode state)
+{
+	switch (state) {
+	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
+	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
+	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
+	default:			return "UNKNOWN";
+	}
+}
+
+static const char *ufschd_clk_gating_state_to_string(
+			enum clk_gating_state state)
+{
+	switch (state) {
+	case CLKS_OFF:		return "CLKS_OFF";
+	case CLKS_ON:		return "CLKS_ON";
+	case REQ_CLKS_OFF:	return "REQ_CLKS_OFF";
+	case REQ_CLKS_ON:	return "REQ_CLKS_ON";
+	default:		return "UNKNOWN_STATE";
+	}
+}
+
 static void ufshcd_ungate_work(struct work_struct *work)
 {
 	int ret;

drivers/scsi/ufs/ufshcd.c start: · line 824

Quoted 6 lines
drivers/scsi/ufs/ufshcd.c +3 -0
@@ -635,6 +819,9 @@ start:
 	case REQ_CLKS_OFF:
 		if (cancel_delayed_work(&hba->clk_gating.gate_work)) {
 			hba->clk_gating.state = CLKS_ON;
+			trace_ufshcd_clk_gating(dev_name(hba->dev),
+				ufschd_clk_gating_state_to_string(
+					hba->clk_gating.state));

Instead of wasting the ring buffer by writing the strings into the ring buffer directly, please just write the enum (4 bytes), and use __print_symbolic() to print out the string.

My 4.1 patch queue even has a way to convert the enum names that are exported to user space back into their numbers such that tools like perf and trace-cmd can still parse it.

Quoted 27 lines
drivers/scsi/ufs/ufshcd.c +14 -0
 			break;
 		}
 		/*
@@ -645,6 +832,9 @@ start:
 	case CLKS_OFF:
 		scsi_block_requests(hba->host);
 		hba->clk_gating.state = REQ_CLKS_ON;
+		trace_ufshcd_clk_gating(dev_name(hba->dev),
+			ufschd_clk_gating_state_to_string(
+				hba->clk_gating.state));
 		schedule_work(&hba->clk_gating.ungate_work);
 		/*
 		 * fall through to check if we should wait for this
 
 
+++ b/include/trace/events/ufs.h
@@ -0,0 +1,213 @@
+/*
+ * 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

drivers/scsi/ufs/ufshcd.c line 20

Quoted 10 lines
drivers/scsi/ufs/ufshcd.c +10 -0
+ * GNU General Public License for more details.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ufs
+
+#if !defined(_TRACE_UFS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_UFS_H
+
+#include <linux/tracepoint.h>
#define UFS_STATES \
	{ UIC_LINK_OFF_STATE,		"OFF" }, \
	{ UIC_LINK_ACTIVE_STATE,	"ACTIVE" }, \
	{ UIC_LINK_HIBERN8_STATE,	"HIBERN8" }, \
	{ UFS_ACTIVE_PWR_MODE,		"ACTIVE" }, \
	{ UFS_SLEEP_PWR_MODE,		"SLEEP" }, \
	{ UFS_POWERDOWN_PWR_MODE,	"POWERDOWN" }, \
	{ CLKS_OFF,			"CLKS_OFF" }, \
	{ CLKS_ON:		"CLKS_ON" }, \
	{ REQ_CLKS_OFF,		"REQ_CLKS_OFF"}, \
	{ REQ_CLKS_ON,		"REQ_CLKS_ON"}

include/trace/events/ufs.h line 23

Quoted 3 lines
include/trace/events/ufs.h new file +3 -0
+
+DECLARE_EVENT_CLASS(ufshcd_state_change_template,
+	TP_PROTO(const char *dev_name, const char *state),

TP_PROTO(const char *dev_nam, int state),

include/trace/events/ufs.h line 29

Quoted 6 lines
include/trace/events/ufs.h new file +6 -0
+
+	TP_ARGS(dev_name, state),
+
+	TP_STRUCT__entry(
+		__string(dev_name, dev_name)
+		__string(state, state)
	__field(int, state)

include/trace/events/ufs.h line 34

Quoted 5 lines
include/trace/events/ufs.h new file +5 -0
+	),
+
+	TP_fast_assign(
+		__assign_str(dev_name, dev_name);
+		__assign_str(state, state);
	__entry->state = state;

include/trace/events/ufs.h

Quoted 4 lines
include/trace/events/ufs.h new file +4 -0
+	),
+
+	TP_printk("%s: state changed to %s",
+		__get_str(dev_name),
		__print_symbolic(__entry->state, UFS_STATES)

Something like that. And after my patch set makes it into mainline during this merge window, you can then change the above to:

#define UFS_STATES \
	EM( UIC_LINK_OFF_STATE,		"OFF" ) \
	EM( UIC_LINK_ACTIVE_STATE,	"ACTIVE" ) \
	EM( UIC_LINK_HIBERN8_STATE,	"HIBERN8" ) \
	EM( UFS_ACTIVE_PWR_MODE,	"ACTIVE" ) \
	EM( UFS_SLEEP_PWR_MODE,		"SLEEP" ) \
	EM( UFS_POWERDOWN_PWR_MODE,	"POWERDOWN" ) \
	EM( CLKS_OFF,			"CLKS_OFF" ) \
	EM( CLKS_ON:			"CLKS_ON" ) \
	EM( REQ_CLKS_OFF,		"REQ_CLKS_OFF") \
	EMe(REQ_CLKS_ON,		"REQ_CLKS_ON")

#undef EM
#undef EMe
#define EM(a, b) TRACE_DEFINE_ENUM(a);
#define EMe(a, b) TRACE_DEFINE_ENUM(a);

UFS_STATES

#undef EM
#undef EMe
#define EM(a, b) { a, b },
#define EM(a, b) { a, b }

And then those enums will be converted to their actual values in the printk formats in the format files.

-- Steve

Quoted 175 lines
include/trace/events/ufs.h new file +175 -0
+);
+
+DEFINE_EVENT(ufshcd_state_change_template, ufshcd_clk_gating,
+	TP_PROTO(const char *dev_name, const char *state),
+	TP_ARGS(dev_name, state));
+DEFINE_EVENT(ufshcd_state_change_template, ufshcd_auto_bkops_state,
+	TP_PROTO(const char *dev_name, const char *state),
+	TP_ARGS(dev_name, state));
+
+TRACE_EVENT(ufshcd_clk_scaling,
+
+	TP_PROTO(const char *dev_name, const char *state, const char *clk,
+		u32 prev_state, u32 curr_state),
+
+	TP_ARGS(dev_name, state, clk, prev_state, curr_state),
+
+	TP_STRUCT__entry(
+		__string(dev_name, dev_name)
+		__string(state, state)
+		__string(clk, clk)
+		__field(u32, prev_state)
+		__field(u32, curr_state)
+	),
+
+	TP_fast_assign(
+		__assign_str(dev_name, dev_name);
+		__assign_str(state, state);
+		__assign_str(clk, clk);
+		__entry->prev_state = prev_state;
+		__entry->curr_state = curr_state;
+	),
+
+	TP_printk("%s: %s %s from %u to %u Hz",
+		__get_str(dev_name), __get_str(state), __get_str(clk),
+		__entry->prev_state, __entry->curr_state)
+);
+
+DECLARE_EVENT_CLASS(ufshcd_profiling_template,
+	TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
+		 int err),
+
+	TP_ARGS(dev_name, profile_info, time_us, err),
+
+	TP_STRUCT__entry(
+		__string(dev_name, dev_name)
+		__string(profile_info, profile_info)
+		__field(s64, time_us)
+		__field(int, err)
+	),
+
+	TP_fast_assign(
+		__assign_str(dev_name, dev_name);
+		__assign_str(profile_info, profile_info);
+		__entry->time_us = time_us;
+		__entry->err = err;
+	),
+
+	TP_printk("%s: %s: took %lld usecs, err %d",
+		__get_str(dev_name), __get_str(profile_info),
+		__entry->time_us, __entry->err)
+);
+
+DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_hibern8,
+	TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
+		 int err),
+	TP_ARGS(dev_name, profile_info, time_us, err));
+
+DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_clk_gating,
+	TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
+		 int err),
+	TP_ARGS(dev_name, profile_info, time_us, err));
+
+DEFINE_EVENT(ufshcd_profiling_template, ufshcd_profile_clk_scaling,
+	TP_PROTO(const char *dev_name, const char *profile_info, s64 time_us,
+		 int err),
+	TP_ARGS(dev_name, profile_info, time_us, err));
+
+DECLARE_EVENT_CLASS(ufshcd_template,
+	TP_PROTO(const char *dev_name, int err, s64 usecs,
+		 const char *dev_state, const char *link_state),
+
+	TP_ARGS(dev_name, err, usecs, dev_state, link_state),
+
+	TP_STRUCT__entry(
+		__field(s64, usecs)
+		__field(int, err)
+		__string(dev_name, dev_name)
+		__string(dev_state, dev_state)
+		__string(link_state, link_state)
+	),
+
+	TP_fast_assign(
+		__entry->usecs = usecs;
+		__entry->err = err;
+		__assign_str(dev_name, dev_name);
+		__assign_str(dev_state, dev_state);
+		__assign_str(link_state, link_state);
+	),
+
+	TP_printk(
+		"%s: took %lld usecs, dev_state: %s, link_state: %s, err %d",
+		__get_str(dev_name),
+		__entry->usecs,
+		__get_str(dev_state),
+		__get_str(link_state),
+		__entry->err
+	)
+);
+
+DEFINE_EVENT(ufshcd_template, ufshcd_system_suspend,
+	     TP_PROTO(const char *dev_name, int err, s64 usecs,
+		      const char *dev_state, const char *link_state),
+	     TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+DEFINE_EVENT(ufshcd_template, ufshcd_system_resume,
+	     TP_PROTO(const char *dev_name, int err, s64 usecs,
+		      const char *dev_state, const char *link_state),
+	     TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+DEFINE_EVENT(ufshcd_template, ufshcd_runtime_suspend,
+	     TP_PROTO(const char *dev_name, int err, s64 usecs,
+		      const char *dev_state, const char *link_state),
+	     TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+DEFINE_EVENT(ufshcd_template, ufshcd_runtime_resume,
+	     TP_PROTO(const char *dev_name, int err, s64 usecs,
+		      const char *dev_state, const char *link_state),
+	     TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+DEFINE_EVENT(ufshcd_template, ufshcd_init,
+	     TP_PROTO(const char *dev_name, int err, s64 usecs,
+		      const char *dev_state, const char *link_state),
+	     TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+TRACE_EVENT(ufshcd_command,
+	TP_PROTO(const char *dev_name, const char *str, unsigned int tag,
+			u32 doorbell, int transfer_len, u32 intr, u64 lba,
+			u8 opcode),
+
+	TP_ARGS(dev_name, str, tag, doorbell, transfer_len, intr, lba, opcode),
+
+	TP_STRUCT__entry(
+		__string(dev_name, dev_name)
+		__string(str, str)
+		__field(unsigned int, tag)
+		__field(u32, doorbell)
+		__field(int, transfer_len)
+		__field(u32, intr)
+		__field(u64, lba)
+		__field(u8, opcode)
+	),
+
+	TP_fast_assign(
+		__assign_str(dev_name, dev_name);
+		__assign_str(str, str);
+		__entry->tag = tag;
+		__entry->doorbell = doorbell;
+		__entry->transfer_len = transfer_len;
+		__entry->intr = intr;
+		__entry->lba = lba;
+		__entry->opcode = opcode;
+	),
+
+	TP_printk(
+		"%s: %s: tag: %u, DB: 0x%x, size: %d, IS: %u, LBA: %llu, opcode: 0x%x",
+		__get_str(str), __get_str(dev_name), __entry->tag,
+		__entry->doorbell, __entry->transfer_len,
+		__entry->intr, __entry->lba, (u32)__entry->opcode
+	)
+);
+
+#endif /* if !defined(_TRACE_UFS_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>