From patchwork Wed Jul 26 14:55:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Potomski, MichalX" X-Patchwork-Id: 9865229 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 02DF6602B1 for ; Wed, 26 Jul 2017 14:54:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0622E2861B for ; Wed, 26 Jul 2017 14:54:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EF0A228643; Wed, 26 Jul 2017 14:54:02 +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 9A04328628 for ; Wed, 26 Jul 2017 14:54:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751827AbdGZOyA (ORCPT ); Wed, 26 Jul 2017 10:54:00 -0400 Received: from mga09.intel.com ([134.134.136.24]:21949 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751571AbdGZOx5 (ORCPT ); Wed, 26 Jul 2017 10:53:57 -0400 Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Jul 2017 07:53:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,415,1496127600"; d="scan'208";a="131503146" Received: from mpotom-tieto.ir.intel.com ([10.103.116.137]) by fmsmga005.fm.intel.com with ESMTP; 26 Jul 2017 07:53:55 -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, szymonx.mielczarek@intel.com Subject: [RESEND][PATCH v3 1/2] scsi: ufs: Use DEVICE_ATTR_RW macros and sdev_attrs structure Date: Wed, 26 Jul 2017 16:55:02 +0200 Message-Id: <20170726145503.15339-2-michalx.potomski@intel.com> X-Mailer: git-send-email 2.13.0.67.g10c78a1 In-Reply-To: <20170726145503.15339-1-michalx.potomski@intel.com> References: <20170726145503.15339-1-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 Previous implementation was obsolete and needed to be updated. Additionally device_create_file() call occurs after a UFS device has been made visible in sysfs and hence will cause trouble (race condition) if a udev rule tries to set this attribute from inside a rule that is triggered by device creation. Signed-off-by: Michał Potomski Reviewed-by: Bart Van Assche --- drivers/scsi/ufs/ufshcd.c | 232 ++++++++++++++++++++-------------------------- 1 file changed, 103 insertions(+), 129 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5bc9dc14e075..5e0fee6ab0db 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6490,6 +6490,108 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) return found ? BLK_EH_NOT_HANDLED : BLK_EH_RESET_TIMER; } +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 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 ufshcd_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 ufshcd_pm_lvl_store(dev, attr, buf, count, false); +} + +static DEVICE_ATTR_RW(rpm_lvl); +static DEVICE_ATTR_RW(spm_lvl); + +static struct device_attribute *ufshcd_dev_attrs[] = { + &dev_attr_rpm_lvl, + &dev_attr_spm_lvl, + NULL, +}; + static struct scsi_host_template ufshcd_driver_template = { .module = THIS_MODULE, .name = UFSHCD, @@ -6509,6 +6611,7 @@ static struct scsi_host_template ufshcd_driver_template = { .can_queue = UFSHCD_CAN_QUEUE, .max_host_blocked = 1, .track_queue_depth = 1, + .sdev_attrs = ufshcd_dev_attrs, }; static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, @@ -7578,133 +7681,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 @@ -7742,7 +7718,6 @@ EXPORT_SYMBOL(ufshcd_shutdown); */ void ufshcd_remove(struct ufs_hba *hba) { - ufshcd_remove_sysfs_nodes(hba); scsi_remove_host(hba->host); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); @@ -7989,7 +7964,6 @@ 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); return 0;