Received: by 10.223.176.5 with SMTP id f5csp2939203wra; Thu, 1 Feb 2018 08:19:40 -0800 (PST) X-Google-Smtp-Source: AH8x225drPcKtnssHtNPvrTQvlIdK1CIwCB4KCflq6xqmtmQx9ULkzEdk6KC0B4jl9G/DX6S6cgP X-Received: by 2002:a17:902:8607:: with SMTP id f7-v6mr32732492plo.273.1517501979958; Thu, 01 Feb 2018 08:19:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517501979; cv=none; d=google.com; s=arc-20160816; b=EqL/BUx2iDFcSxhumJNS0q58HhtBK1Kil2Dy82XQkOVtWkzH/WcGQdRSNnMMt2JiYa pj4qpOJsN6V+gU91I7VGXW7FfZFxcYysl8jr078GkGM+b70DGINYQZSx+vvCpIt+w1hP qyUu2tbAxHPr4HnDCYL3uEYg9EjeXLODEJwtzrWvKYZI9qm5eNwStQ6LghUsizA+mhzh 0rLtIodzxkbd6eAwlplV3TJiLtTicCG9GiZLRLSd+azgjQmNulN3mICDDS1X4a6Ul+fK ubMEig62AepK8WM0XetMyt4pecuTFDRYTJwIJfw8qEOPCQ1LzoEeWtsw1HWUeG0O7JR/ wcHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=S5uaNP7rHpBwJhF+fR/93roFyLBMimOhabNjNhB852Y=; b=gkaAxW2tYjquwtU22FrT+C9fJfwo4XPNuTXRl+t6oP/7D0PwCPCMDj7+z1O+h0p6AQ xom9RBFULEt836qT+5lIMtuwXSxMYXfSBPj0sPj9b+HXfGOJzHZPNNWPvtGdr5Ftqvad ot5311waDjC95V8w5eYeYJ3rM0FdyptxRzW2xD3vAqtwgQn3dfHnHl79BXBRveCpX3PF WV8//IlcL8uFi0lFHozSOxHjjAsPfY/SyrBsw+RrGRjMZWe2RUQXqLg8j9iNVm7nRMxK QJPPh/WnuCpXGXunRmUBESotsu2m7P5z/JDu436rhlHY7Jvolz5EQBGl2EU71pX7u862 nFlw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@wdc.com header.s=dkim.wdc.com header.b=DXCtE1DJ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o16si1538544pgd.125.2018.02.01.08.19.25; Thu, 01 Feb 2018 08:19:39 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@wdc.com header.s=dkim.wdc.com header.b=DXCtE1DJ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752674AbeBAQP7 (ORCPT + 99 others); Thu, 1 Feb 2018 11:15:59 -0500 Received: from esa6.hgst.iphmx.com ([216.71.154.45]:47147 "EHLO esa6.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752641AbeBAQPw (ORCPT ); Thu, 1 Feb 2018 11:15:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1517501753; x=1549037753; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=skB4JP56EMecV588DoFeXZ3smgWuxW1vzCleBiuvfdY=; b=DXCtE1DJzYSW7+VJc8BiqTPBKcLgoYv/BCnLOZSi0L2ZS6WoICWuZpWD ZHDTMukKp98nm0uZVmvp/k9o6hFYUSfTVtvpTT5HEQBU7Hu+WJXUp/8DY KS2d/cCQm/rW4f8SLRzMD6v422R7ZhrDGss0m+3unVn99Po9+0PPyNdPa P0iFoK2vLpbcBlALfNU/JNIEi9PcTyGs8vylTPyPT+LuM4Yvw8OSbEAe8 5baP/fRK3FtyMJwKAGg50Am9+OFSH4OKRUGxTQB5DbvQt+YIDSr4sLtiX L7o8OTlYIgfmtQh8V2XoUC4WA2G7fIXckLlcuPHE/hG6XsLci6cR2NGTF w==; X-IronPort-AV: E=Sophos;i="5.46,444,1511798400"; d="scan'208";a="70915260" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 02 Feb 2018 00:15:53 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 01 Feb 2018 08:10:54 -0800 Received: from ilb000042.sdcorp.global.sandisk.com ([10.0.231.79]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Feb 2018 08:15:49 -0800 From: Stanislav Nijnikov To: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org, jaegeuk@kernel.org Cc: alex.lemberg@wdc.com, Stanislav Nijnikov Subject: [PATCH v4 01/10] ufs: sysfs: attribute group for existing sysfs entries. Date: Thu, 1 Feb 2018 18:15:37 +0200 Message-Id: <1517501746-19075-2-git-send-email-stanislav.nijnikov@wdc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1517501746-19075-1-git-send-email-stanislav.nijnikov@wdc.com> References: <1517501746-19075-1-git-send-email-stanislav.nijnikov@wdc.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch introduces attribute group to show existing sysfs entries. Signed-off-by: Stanislav Nijnikov --- drivers/scsi/ufs/Makefile | 3 +- drivers/scsi/ufs/ufs-sysfs.c | 164 +++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-sysfs.h | 22 ++++++ drivers/scsi/ufs/ufshcd.c | 156 ++-------------------------------------- drivers/scsi/ufs/ufshcd.h | 2 + 5 files changed, 194 insertions(+), 153 deletions(-) create mode 100644 drivers/scsi/ufs/ufs-sysfs.c create mode 100644 drivers/scsi/ufs/ufs-sysfs.h diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 9310c6c..918f579 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o +ufshcd-core-objs := ufshcd.o ufs-sysfs.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c new file mode 100644 index 0000000..cc68a90 --- /dev/null +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -0,0 +1,164 @@ +//SPDX-License-Identifier: GPL-2.0-only +//Copyright (C) 2018 Western Digital Corporation +//This program is free software; you can redistribute it and/or modify it +//under the terms of the GNU General Public License as published by the +//Free Software Foundation; version 2. +// +//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 +#include + +#include "ufs-sysfs.h" + +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 inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count, + bool rpm) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned long flags, value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (value >= UFS_PM_LVL_MAX) + return -EINVAL; + + spin_lock_irqsave(hba->host->host_lock, flags); + if (rpm) + hba->rpm_lvl = value; + else + hba->spm_lvl = value; + spin_unlock_irqrestore(hba->host->host_lock, flags); + return count; +} + +static ssize_t rpm_lvl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int curr_len; + u8 lvl; + + curr_len = snprintf(buf, PAGE_SIZE, + "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n", + hba->rpm_lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->rpm_lvl].link_state)); + + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\nAll available Runtime PM levels info:\n"); + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n", + lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[lvl].link_state)); + + return curr_len; +} + +static ssize_t rpm_lvl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true); +} + +static ssize_t spm_lvl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int curr_len; + u8 lvl; + + curr_len = snprintf(buf, PAGE_SIZE, + "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n", + hba->spm_lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[hba->spm_lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[hba->spm_lvl].link_state)); + + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\nAll available System PM levels info:\n"); + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), + "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n", + lvl, + ufschd_ufs_dev_pwr_mode_to_string( + ufs_pm_lvl_states[lvl].dev_state), + ufschd_uic_link_state_to_string( + ufs_pm_lvl_states[lvl].link_state)); + + return curr_len; +} + +static ssize_t spm_lvl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false); +} + +static DEVICE_ATTR_RW(rpm_lvl); +static DEVICE_ATTR_RW(spm_lvl); + +static struct attribute *ufs_sysfs_ufshcd_attrs[] = { + &dev_attr_rpm_lvl.attr, + &dev_attr_spm_lvl.attr, + NULL +}; + +static const struct attribute_group ufs_sysfs_default_group = { + .attrs = ufs_sysfs_ufshcd_attrs, +}; + +static const struct attribute_group *ufs_sysfs_groups[] = { + &ufs_sysfs_default_group, + NULL, +}; + +void ufs_sysfs_add_nodes(struct device *dev) +{ + int ret; + + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups); + if (ret) + dev_err(dev, + "%s: sysfs groups creation failed (err = %d)\n", + __func__, ret); +} + +void ufs_sysfs_remove_nodes(struct device *dev) +{ + sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups); +} diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h new file mode 100644 index 0000000..c53c039 --- /dev/null +++ b/drivers/scsi/ufs/ufs-sysfs.h @@ -0,0 +1,22 @@ +/*SPDX-License-Identifier: GPL-2.0-only + *Copyright (C) 2018 Western Digital Corporation + *This program is free software; you can redistribute it and/or modify it + *under the terms of the GNU General Public License as published by the + *Free Software Foundation; version 2. + * + *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 __UFS_SYSFS_H__ +#define __UFS_SYSFS_H__ + +#include + +#include "ufshcd.h" + +void ufs_sysfs_add_nodes(struct device *dev); +void ufs_sysfs_remove_nodes(struct device *dev); +#endif diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a355d98..e7621a0a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -44,6 +44,7 @@ #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" +#include "ufs-sysfs.h" #define CREATE_TRACE_POINTS #include @@ -150,7 +151,7 @@ enum { #define ufshcd_is_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) -static struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { +struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE}, {UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE}, @@ -813,28 +814,6 @@ static inline bool ufshcd_is_hba_active(struct ufs_hba *hba) ? false : true; } -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"; - } -} - u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba) { /* HCI version 1.0 and 1.1 supports UniPro 1.41 */ @@ -7585,133 +7564,6 @@ int ufshcd_runtime_idle(struct ufs_hba *hba) } EXPORT_SYMBOL(ufshcd_runtime_idle); -static inline ssize_t ufshcd_pm_lvl_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count, - bool rpm) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - unsigned long flags, value; - - if (kstrtoul(buf, 0, &value)) - return -EINVAL; - - if (value >= UFS_PM_LVL_MAX) - return -EINVAL; - - spin_lock_irqsave(hba->host->host_lock, flags); - if (rpm) - hba->rpm_lvl = value; - else - hba->spm_lvl = value; - spin_unlock_irqrestore(hba->host->host_lock, flags); - return count; -} - -static ssize_t ufshcd_rpm_lvl_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->rpm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->rpm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available Runtime PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; -} - -static ssize_t ufshcd_rpm_lvl_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return ufshcd_pm_lvl_store(dev, attr, buf, count, true); -} - -static void ufshcd_add_rpm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->rpm_lvl_attr.show = ufshcd_rpm_lvl_show; - hba->rpm_lvl_attr.store = ufshcd_rpm_lvl_store; - sysfs_attr_init(&hba->rpm_lvl_attr.attr); - hba->rpm_lvl_attr.attr.name = "rpm_lvl"; - hba->rpm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, &hba->rpm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for rpm_lvl\n"); -} - -static ssize_t ufshcd_spm_lvl_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev); - int curr_len; - u8 lvl; - - curr_len = snprintf(buf, PAGE_SIZE, - "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n", - hba->spm_lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[hba->spm_lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[hba->spm_lvl].link_state)); - - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\nAll available System PM levels info:\n"); - for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) - curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len), - "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n", - lvl, - ufschd_ufs_dev_pwr_mode_to_string( - ufs_pm_lvl_states[lvl].dev_state), - ufschd_uic_link_state_to_string( - ufs_pm_lvl_states[lvl].link_state)); - - return curr_len; -} - -static ssize_t ufshcd_spm_lvl_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return ufshcd_pm_lvl_store(dev, attr, buf, count, false); -} - -static void ufshcd_add_spm_lvl_sysfs_nodes(struct ufs_hba *hba) -{ - hba->spm_lvl_attr.show = ufshcd_spm_lvl_show; - hba->spm_lvl_attr.store = ufshcd_spm_lvl_store; - sysfs_attr_init(&hba->spm_lvl_attr.attr); - hba->spm_lvl_attr.attr.name = "spm_lvl"; - hba->spm_lvl_attr.attr.mode = 0644; - if (device_create_file(hba->dev, &hba->spm_lvl_attr)) - dev_err(hba->dev, "Failed to create sysfs for spm_lvl\n"); -} - -static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba) -{ - ufshcd_add_rpm_lvl_sysfs_nodes(hba); - ufshcd_add_spm_lvl_sysfs_nodes(hba); -} - -static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba) -{ - device_remove_file(hba->dev, &hba->rpm_lvl_attr); - device_remove_file(hba->dev, &hba->spm_lvl_attr); -} - /** * ufshcd_shutdown - shutdown routine * @hba: per adapter instance @@ -7749,7 +7601,7 @@ EXPORT_SYMBOL(ufshcd_shutdown); */ void ufshcd_remove(struct ufs_hba *hba) { - ufshcd_remove_sysfs_nodes(hba); + ufs_sysfs_remove_nodes(hba->dev); scsi_remove_host(hba->host); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); @@ -7996,7 +7848,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufshcd_set_ufs_dev_active(hba); async_schedule(ufshcd_async_scan, hba); - ufshcd_add_sysfs_nodes(hba); + ufs_sysfs_add_nodes(hba->dev); return 0; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 1332e54..53e2779 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -985,4 +985,6 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) hba->vops->dbg_register_dump(hba); } +extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; + #endif /* End of Header */ -- 2.7.4