diff options
| -rw-r--r-- | drivers/scsi/ufs/Makefile | 2 | ||||
| -rw-r--r-- | drivers/scsi/ufs/debugfs.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/ufs/qcom-debugfs.c | 98 | ||||
| -rw-r--r-- | drivers/scsi/ufs/qcom-debugfs.h | 24 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 16 | ||||
| -rw-r--r-- | include/linux/scsi/ufs/ufs-qcom.h | 18 | ||||
| -rw-r--r-- | include/linux/scsi/ufs/ufshcd.h | 6 |
7 files changed, 167 insertions, 4 deletions
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 535244fe714f..58ee7fef70b2 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs_quirks.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o obj-$(CONFIG_SCSI_UFS_TEST) += ufs_test.o -obj-$(CONFIG_DEBUG_FS) += debugfs.o +obj-$(CONFIG_DEBUG_FS) += debugfs.o qcom-debugfs.o diff --git a/drivers/scsi/ufs/debugfs.c b/drivers/scsi/ufs/debugfs.c index fd682fbdbc30..4fd197cace5c 100644 --- a/drivers/scsi/ufs/debugfs.c +++ b/drivers/scsi/ufs/debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* 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 @@ -1065,6 +1065,9 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba) ufsdbg_setup_fault_injection(hba); + if (hba->vops && hba->vops->add_debugfs) + hba->vops->add_debugfs(hba, hba->debugfs_files.debugfs_root); + return; err: @@ -1076,6 +1079,8 @@ err_no_root: void ufsdbg_remove_debugfs(struct ufs_hba *hba) { + if (hba->vops && hba->vops->remove_debugfs) + hba->vops->remove_debugfs(hba); debugfs_remove_recursive(hba->debugfs_files.debugfs_root); kfree(hba->ufs_stats.tag_stats); diff --git a/drivers/scsi/ufs/qcom-debugfs.c b/drivers/scsi/ufs/qcom-debugfs.c new file mode 100644 index 000000000000..24f164312c21 --- /dev/null +++ b/drivers/scsi/ufs/qcom-debugfs.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#include <linux/debugfs.h> +#include <linux/scsi/ufs/ufs-qcom.h> +#include "qcom-debugfs.h" + +static void ufs_qcom_dbg_remove_debugfs(struct ufs_qcom_host *host); + +static int ufs_qcom_dbg_print_en_read(void *data, u64 *attr_val) +{ + struct ufs_qcom_host *host = data; + + if (!host) + return -EINVAL; + + *attr_val = (u64)host->dbg_print_en; + return 0; +} + +static int ufs_qcom_dbg_print_en_set(void *data, u64 attr_id) +{ + struct ufs_qcom_host *host = data; + + if (!host) + return -EINVAL; + + if (attr_id & ~UFS_QCOM_DBG_PRINT_ALL) + return -EINVAL; + + host->dbg_print_en = (u32)attr_id; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(ufs_qcom_dbg_print_en_ops, + ufs_qcom_dbg_print_en_read, + ufs_qcom_dbg_print_en_set, + "%llu\n"); + + +void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root) +{ + struct ufs_qcom_host *host; + + if (!hba || !hba->priv) { + pr_err("%s: NULL host, exiting\n", __func__); + return; + } + + host = hba->priv; + host->debugfs_files.debugfs_root = debugfs_create_dir("qcom", root); + if (IS_ERR(host->debugfs_files.debugfs_root)) + /* Don't complain -- debugfs just isn't enabled */ + goto err_no_root; + if (!host->debugfs_files.debugfs_root) { + /* + * Complain -- debugfs is enabled, but it failed to + * create the directory + */ + dev_err(host->hba->dev, + "%s: NULL debugfs root directory, exiting", __func__); + goto err_no_root; + } + + host->debugfs_files.dbg_print_en = + debugfs_create_file("dbg_print_en", S_IRUSR | S_IWUSR, + host->debugfs_files.debugfs_root, host, + &ufs_qcom_dbg_print_en_ops); + if (!host->debugfs_files.dbg_print_en) { + dev_err(host->hba->dev, + "%s: failed to create dbg_print_en debugfs entry\n", + __func__); + goto err; + } + return; + +err: + ufs_qcom_dbg_remove_debugfs(host); +err_no_root: + dev_err(host->hba->dev, "%s: failed to initialize debugfs\n", __func__); +} + +static void ufs_qcom_dbg_remove_debugfs(struct ufs_qcom_host *host) +{ + debugfs_remove_recursive(host->debugfs_files.debugfs_root); + host->debugfs_files.debugfs_root = NULL; +} diff --git a/drivers/scsi/ufs/qcom-debugfs.h b/drivers/scsi/ufs/qcom-debugfs.h new file mode 100644 index 000000000000..03341711e11e --- /dev/null +++ b/drivers/scsi/ufs/qcom-debugfs.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef QCOM_DEBUGFS_H_ +#define QCOM_DEBUGFS_H_ + +#include <linux/scsi/ufs/ufshcd.h> + +#ifdef CONFIG_DEBUG_FS +void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root); +#endif + +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 1d47641a02f7..d7eafc3bb8ce 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -34,6 +34,9 @@ #include "ufs-qcom.h" #include "ufshci.h" #include "ufs-qcom-ice.h" +#include "qcom-debugfs.h" + +#define DEFAULT_UFS_QCOM_DBG_PRINT_EN UFS_QCOM_DBG_PRINT_REGS_EN static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; @@ -1268,6 +1271,8 @@ static int ufs_qcom_init(struct ufs_hba *hba) if (hba->dev->id < MAX_UFS_QCOM_HOSTS) ufs_qcom_hosts[hba->dev->id] = host; + host->dbg_print_en |= DEFAULT_UFS_QCOM_DBG_PRINT_EN; + goto out; out_disable_phy: @@ -1371,6 +1376,10 @@ out: static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba) { u32 reg; + struct ufs_qcom_host *host = hba->priv; + + if (!(host->dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN)) + return; ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44, "UFS_UFS_DBG_RD_REG_OCSC "); @@ -1406,8 +1415,8 @@ static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba) 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_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16, + "HCI Vendor Specific Registers "); ufs_qcom_print_hw_debug_reg_all(hba); } @@ -1437,6 +1446,9 @@ const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .crypto_engine_get_err = ufs_qcom_crypto_engine_get_err, .crypto_engine_reset_err = ufs_qcom_crypto_engine_reset_err, .dbg_register_dump = ufs_qcom_dump_dbg_regs, +#ifdef CONFIG_DEBUG_FS + .add_debugfs = ufs_qcom_dbg_add_debugfs, +#endif }; /** diff --git a/include/linux/scsi/ufs/ufs-qcom.h b/include/linux/scsi/ufs/ufs-qcom.h index dee92b9ee54f..e00f0b935227 100644 --- a/include/linux/scsi/ufs/ufs-qcom.h +++ b/include/linux/scsi/ufs/ufs-qcom.h @@ -15,6 +15,7 @@ #define UFS_QCOM_H_ #include <linux/phy/phy.h> +#include <linux/scsi/ufs/ufshcd.h> #define MAX_UFS_QCOM_HOSTS 1 #define MAX_U32 (~(u32)0) @@ -120,6 +121,11 @@ struct ufs_qcom_phy_vreg { bool enabled; }; +/* QCOM UFS debug print bit mask */ +#define UFS_QCOM_DBG_PRINT_REGS_EN BIT(0) + +#define UFS_QCOM_DBG_PRINT_ALL UFS_QCOM_DBG_PRINT_REGS_EN + static inline void ufs_qcom_get_controller_revision(struct ufs_hba *hba, u8 *major, u16 *minor, u16 *step) @@ -189,6 +195,13 @@ struct ufs_hw_version { u8 major; }; +#ifdef CONFIG_DEBUG_FS +struct qcom_debugfs_files { + struct dentry *debugfs_root; + struct dentry *dbg_print_en; +}; +#endif + struct ufs_qcom_host { /* * Set this capability if host controller supports the QUniPro mode @@ -213,6 +226,11 @@ struct ufs_qcom_host { void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; +#ifdef CONFIG_DEBUG_FS + struct qcom_debugfs_files debugfs_files; +#endif + /* Bitmask for enabling debug prints */ + u32 dbg_print_en; }; #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) diff --git a/include/linux/scsi/ufs/ufshcd.h b/include/linux/scsi/ufs/ufshcd.h index b4d7b5f60995..ad3d250a7018 100644 --- a/include/linux/scsi/ufs/ufshcd.h +++ b/include/linux/scsi/ufs/ufshcd.h @@ -312,6 +312,8 @@ struct ufs_pwr_mode_info { * @crypto_engine_reset_err: resets the saved error status of * the cryptographic engine * @dbg_register_dump: used to dump controller debug information + * @add_debugfs: used to add debugfs entries + * @remove_debugfs: used to remove debugfs entries */ struct ufs_hba_variant_ops { const char *name; @@ -340,6 +342,10 @@ struct ufs_hba_variant_ops { int (*crypto_engine_get_err)(struct ufs_hba *); void (*crypto_engine_reset_err)(struct ufs_hba *); void (*dbg_register_dump)(struct ufs_hba *hba); +#ifdef CONFIG_DEBUG_FS + void (*add_debugfs)(struct ufs_hba *hba, struct dentry *root); + void (*remove_debugfs)(struct ufs_hba *hba); +#endif }; /* clock gating state */ |
