Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp3676104imm; Tue, 29 May 2018 11:23:10 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoiw17RokwMfPA+vjiIfhKOENhxkILHvvjPeau83V7xPuT4YkRIW5/yukfDCkwj/HcQtzQ2 X-Received: by 2002:a17:902:d90f:: with SMTP id c15-v6mr18486468plz.65.1527618190870; Tue, 29 May 2018 11:23:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527618190; cv=none; d=google.com; s=arc-20160816; b=cccuDYXPuHRYrBKv3DSngw9VJw6TKJ2mitV2A2sWub4Idzum8i8aLHMayo3urYDf8O f9YA+QmJOtgNofO406aqKi7ske04VFicqrSH6FUgnJSzcBtNXsVBPxA0pyN7Nc9EEUwn cupWHgfbzueGEMUYlB0Qqdt3T/0zeCeyBa1bLWmvfMrHAxaGO40hS+V8nV0HbncrYukB 2/mL9wdGu7AMrI+yrscmcP8wFuQxq+pSs88GZ8pagO78cV4AJWLAJUb1/TVz8X4byDPI YjosQrrrPAuXA70+NUFG8sAVLG3csiHws7pJcSZPQcTF6QmFGHwOI2exEUcO0Jz5/zkG fNKg== 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=/xwuva0m3EornI+dEwDFaHta5iifdYqbp+TTpTX98u8=; b=G6+aAeQyiB2cPwz+UWgej5u07GXPTvB/mtHNWff5Ek6h+qFciVOGq3myh5CNm8q9V4 v4MLJ85oUfHBphUp2xlstl5MTDoBC3ta5WmjdsLzK/EP5hqsGnAwtWCbQBWhv0epdULM tyzZtQehvcRfeNWYZfpAFGsPQCG9T4/iZbqqgWqFS822vrXYgGeNhRubwM3sh6zaMlyv KvrdXAj47BzQLJ4h2Cmu8ENpsTfHhaYvCtR/qemIPfcfeZpSSK4iRjz3Uv0+6+wyWXKB M1qgMMo5WKTX8/roqgrWxboOmHu088ntIr0tHsqJbPRpcieUhh5+lOGcUvgm+2B1pkZJ rV1g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=RfGegnOE; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k186-v6si10307790pge.375.2018.05.29.11.22.57; Tue, 29 May 2018 11:23:10 -0700 (PDT) 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=pass header.i=@chromium.org header.s=google header.b=RfGegnOE; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965953AbeE2SUc (ORCPT + 99 others); Tue, 29 May 2018 14:20:32 -0400 Received: from mail-pl0-f67.google.com ([209.85.160.67]:36032 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S936956AbeE2SSO (ORCPT ); Tue, 29 May 2018 14:18:14 -0400 Received: by mail-pl0-f67.google.com with SMTP id v24-v6so9427902plo.3 for ; Tue, 29 May 2018 11:18:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/xwuva0m3EornI+dEwDFaHta5iifdYqbp+TTpTX98u8=; b=RfGegnOE8Uj0NI//atS2HZ5adB888z5wHdA0s5dL2nb3WW92t5zhaxIj95JCiVjeS9 mKXN8kRUPj5xRcDuxRRSv/USMuEAgMMaG9Pbczg2QiKSU/R/oYGWNYHEia91zP2ZxH/+ D3n+xDLclXLW9TVvKf1rET+Ifhw1BIs9SKpG8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/xwuva0m3EornI+dEwDFaHta5iifdYqbp+TTpTX98u8=; b=dd7/tHC6X3J+FFSr99xqLm690MjWRqkWzb8dGk6fRsXrAtXFRH7D9r72tupVt6kP+f N0oownXoGx2zmjcFmN4FifrryZ1+0OpE8VFoTsoLiY3ZJggCFKbqow/dHWa9h+VZZtWo OcPZXp1GHjoGoA13TWMP7AdH2PTqLvUcj80iEia3zbvmbuwg/lxxN4mNNdkUq0dfCS79 mxxj+yY1zyvnI90knEiZVqIuhOIfjwtR2ehSap0OMu7ngVqpeVJD1jmQkRhYbG/zG3IC q9b+vboIBLaL8nJyUnc7eKnp7TzIjtyr1mtunfMAjObRHSpbVVrer0HrSmCUyv4/0vte pJXA== X-Gm-Message-State: ALKqPwc1QwvSvLqqsq9nGbU3Y8Jk2nN47K+r3AY70ogwdKwNJzzsw8Cj FNTCK81uAxlPdxlzqvuN1okJUg== X-Received: by 2002:a17:902:b701:: with SMTP id d1-v6mr18850837pls.121.1527617893876; Tue, 29 May 2018 11:18:13 -0700 (PDT) Received: from evgreen2.mtv.corp.google.com ([2620:0:1000:1511:116f:8bf3:133b:f7fd]) by smtp.gmail.com with ESMTPSA id b74-v6sm18255704pfl.138.2018.05.29.11.18.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 29 May 2018 11:18:12 -0700 (PDT) From: Evan Green To: Vinayak Holikatti , "James E.J. Bottomley" , "Martin K. Petersen" , Stanislav Nijnikov , linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org Cc: Gwendal Grignou , Evan Green Subject: [PATCH 1/7] scsi: ufs: Add Configuration Descriptor to sysfs Date: Tue, 29 May 2018 11:17:34 -0700 Message-Id: <20180529181740.195362-2-evgreen@chromium.org> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20180529181740.195362-1-evgreen@chromium.org> References: <20180529181740.195362-1-evgreen@chromium.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This change adds the configuration descriptor to the UFS sysfs interface. This is done in preparation for making the interface writable, which will enable provisioning UFS devices via Linux. The configuration descriptor is laid out as a header, then a set of (usually 8) copies of the same descriptor for each unit. Rather than creating 8 sets of the same attribute, this interface adds a cfg_unit file, which can be set as an index that defines which of the 8 configuration unit descriptors are being shown through sysfs. Signed-off-by: Evan Green --- In this change, I used cfg_unit as a selector because it matched the precedent set by rpm_lvl and spm_lvl, and was frankly the easiest option. It was pointed out to me that this creates a synchronization problem for user mode, as it means only one process can be safely using this interface at a time. If it's preferred, I can change the interface to enumerate a sysfs group for each unit descriptor in the config descriptor. The argument for keeping it the way it currently is goes like: 1) On the read side, all the information available here is available elsewhere in other descriptors. I suppose that doesn't stop apps from doing it anyway and interfering with a write. 2) On the write side, there's probably already something wrong if more than one process is trying to provision the disk. Let me know what you think. I think I'm leaning towards the dynamic groups, but I could be convinced either way. --- drivers/scsi/ufs/ufs-sysfs.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs.h | 29 +++++++++++++ drivers/scsi/ufs/ufshcd.h | 3 ++ 3 files changed, 129 insertions(+) diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index 8d9332bb7d0c..a7d65492832a 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -327,6 +327,102 @@ static const struct attribute_group ufs_sysfs_device_descriptor_group = { .attrs = ufs_sysfs_device_descriptor, }; +static ssize_t cfg_unit_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", hba->sysfs_config_unit); +} + +static ssize_t cfg_unit_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + unsigned long max_value, value; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + if (hba->desc_size.conf_desc < CONFIGURATION_DESC_PARAM_UNIT0) + return -EINVAL; + + max_value = (hba->desc_size.conf_desc - + CONFIGURATION_DESC_PARAM_UNIT0) / CONFIGURATION_UNIT_DESC_SIZE; + + if (value >= max_value) + return -EINVAL; + + hba->sysfs_config_unit = value; + return count; +} + +#define UFS_CONFIG_DESC_PARAM(_name, _uname, _size) \ + UFS_DESC_PARAM(cfg_##_name, _uname, CONFIGURATION, _size) + +#define UFS_CONFIG_UNIT_DESC_PARAM(_name, _uname, _size) \ +static ssize_t unit_##_name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct ufs_hba *hba = dev_get_drvdata(dev); \ + size_t offset = CONFIGURATION_DESC_PARAM_UNIT0 + \ + (hba->sysfs_config_unit * \ + CONFIGURATION_UNIT_DESC_SIZE) + \ + CONFIGURATION_UNIT_DESC_PARAM_##_uname; \ + if (offset + _size > hba->desc_size.conf_desc) { \ + return -EINVAL; \ + } \ + return ufs_sysfs_read_desc_param(hba, \ + QUERY_DESC_IDN_CONFIGURATION, 0, offset, buf, _size); \ +} \ +static DEVICE_ATTR_RO(unit_##_name) + +UFS_CONFIG_DESC_PARAM(number_of_luns, _NUM_LU, 1); +UFS_CONFIG_DESC_PARAM(boot_enable, _BOOT_ENBL, 1); +UFS_CONFIG_DESC_PARAM(descriptor_access_enable, _DESC_ACCSS_ENBL, 1); +UFS_CONFIG_DESC_PARAM(initial_power_mode, _INIT_PWR_MODE, 1); +UFS_CONFIG_DESC_PARAM(high_priority_lun, _HIGH_PR_LUN, 1); +UFS_CONFIG_DESC_PARAM(secure_removal_type, _SEC_RMV_TYPE, 1); +UFS_CONFIG_DESC_PARAM(init_active_icc_level, _ACTVE_ICC_LVL, 1); +UFS_CONFIG_DESC_PARAM(periodic_rtc_update, _FRQ_RTC, 2); +DEVICE_ATTR_RW(cfg_unit); +UFS_CONFIG_UNIT_DESC_PARAM(lu_enable, LU_ENABLE, 1); +UFS_CONFIG_UNIT_DESC_PARAM(boot_lun_id, BOOT_LUN_ID, 1); +UFS_CONFIG_UNIT_DESC_PARAM(lu_write_protect, LU_WR_PROTECT, 1); +UFS_CONFIG_UNIT_DESC_PARAM(memory_type, MEM_TYPE, 1); +UFS_CONFIG_UNIT_DESC_PARAM(allocation_units, NUM_ALLOC_UNITS, 4); +UFS_CONFIG_UNIT_DESC_PARAM(data_reliability, DATA_RELIABILITY, 1); +UFS_CONFIG_UNIT_DESC_PARAM(logical_block_size, LOGICAL_BLK_SIZE, 1); +UFS_CONFIG_UNIT_DESC_PARAM(provisioning_type, PROVISIONING_TYPE, 1); +UFS_CONFIG_UNIT_DESC_PARAM(context_capabilities, CTX_CAPABILITIES, 2); + +static struct attribute *ufs_sysfs_config_descriptor[] = { + &dev_attr_cfg_number_of_luns.attr, + &dev_attr_cfg_boot_enable.attr, + &dev_attr_cfg_descriptor_access_enable.attr, + &dev_attr_cfg_initial_power_mode.attr, + &dev_attr_cfg_high_priority_lun.attr, + &dev_attr_cfg_secure_removal_type.attr, + &dev_attr_cfg_init_active_icc_level.attr, + &dev_attr_cfg_periodic_rtc_update.attr, + &dev_attr_cfg_unit.attr, + &dev_attr_unit_lu_enable.attr, + &dev_attr_unit_boot_lun_id.attr, + &dev_attr_unit_lu_write_protect.attr, + &dev_attr_unit_memory_type.attr, + &dev_attr_unit_allocation_units.attr, + &dev_attr_unit_data_reliability.attr, + &dev_attr_unit_logical_block_size.attr, + &dev_attr_unit_provisioning_type.attr, + &dev_attr_unit_context_capabilities.attr, + NULL, +}; + +static const struct attribute_group ufs_sysfs_config_descriptor_group = { + .name = "config_descriptor", + .attrs = ufs_sysfs_config_descriptor, +}; + #define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size) \ UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size) @@ -713,6 +809,7 @@ static const struct attribute_group ufs_sysfs_attributes_group = { static const struct attribute_group *ufs_sysfs_groups[] = { &ufs_sysfs_default_group, &ufs_sysfs_device_descriptor_group, + &ufs_sysfs_config_descriptor_group, &ufs_sysfs_interconnect_descriptor_group, &ufs_sysfs_geometry_descriptor_group, &ufs_sysfs_health_descriptor_group, diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 14e5bf7af0bb..a5712b1a07ad 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -260,6 +260,35 @@ enum device_desc_param { DEVICE_DESC_PARAM_PRDCT_REV = 0x2A, }; +/* Configuration descriptor parameter offsets in bytes */ +enum configuration_desc_param { + CONFIGURATION_DESC_PARAM_LEN = 0x0, + CONFIGURATION_DESC_PARAM_TYPE = 0x1, + CONFIGURATION_DESC_PARAM_NUM_LU = 0x2, + CONFIGURATION_DESC_PARAM_BOOT_ENBL = 0x3, + CONFIGURATION_DESC_PARAM_DESC_ACCSS_ENBL = 0x4, + CONFIGURATION_DESC_PARAM_INIT_PWR_MODE = 0x5, + CONFIGURATION_DESC_PARAM_HIGH_PR_LUN = 0x6, + CONFIGURATION_DESC_PARAM_SEC_RMV_TYPE = 0x7, + CONFIGURATION_DESC_PARAM_ACTVE_ICC_LVL = 0x8, + CONFIGURATION_DESC_PARAM_FRQ_RTC = 0x9, + CONFIGURATION_DESC_PARAM_UNIT0 = 0x10, +}; + +/* Configuration unit descriptor parameter offsets in bytes */ +enum configuration_unit_desc_param { + CONFIGURATION_UNIT_DESC_PARAM_LU_ENABLE = 0x0, + CONFIGURATION_UNIT_DESC_PARAM_BOOT_LUN_ID = 0x1, + CONFIGURATION_UNIT_DESC_PARAM_LU_WR_PROTECT = 0x2, + CONFIGURATION_UNIT_DESC_PARAM_MEM_TYPE = 0x3, + CONFIGURATION_UNIT_DESC_PARAM_NUM_ALLOC_UNITS = 0x4, + CONFIGURATION_UNIT_DESC_PARAM_DATA_RELIABILITY = 0x8, + CONFIGURATION_UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0x9, + CONFIGURATION_UNIT_DESC_PARAM_PROVISIONING_TYPE = 0xA, + CONFIGURATION_UNIT_DESC_PARAM_CTX_CAPABILITIES = 0xB, + CONFIGURATION_UNIT_DESC_SIZE = 0x10, +}; + /* Interconnect descriptor parameters offsets in bytes*/ enum interconnect_desc_param { INTERCONNECT_DESC_PARAM_LEN = 0x0, diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8110dcd04d22..fb6dcc490f21 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -683,6 +683,9 @@ struct ufs_hba { struct rw_semaphore clk_scaling_lock; struct ufs_desc_size desc_size; + + /* Which unit descriptor is showing in the sysfs config descriptor. */ + int sysfs_config_unit; }; /* Returns true if clocks can be gated. Otherwise false */ -- 2.13.5