Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp1920527imm; Thu, 14 Jun 2018 06:05:45 -0700 (PDT) X-Google-Smtp-Source: ADUXVKK3+aFZAr6r060mTh+PkIuW1CJ3an2W2ZSlqy5jkixKLUxmHdN49ysXMt/9S5bzgnKv1mEd X-Received: by 2002:a17:902:8d85:: with SMTP id v5-v6mr2974119plo.93.1528981545357; Thu, 14 Jun 2018 06:05:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528981545; cv=none; d=google.com; s=arc-20160816; b=o1LLI69Ush9hVX7JdgNBAcDou52rEn74PqvkeDhUyaYT7bU6xL93siQLAFnPWVwYU9 Ze7xlRmXr/vGmaw0eonGL+KS+0ZJCyvg0JheY8Dk3s6dkSUvEwNfFl8yWMeSK+3iJRBc ot7eGRU06m+c0YPBbSxg3IYRz9Dw0iYQ/5Y0j3OMEd+6i+quXb3NDz/DhCFy8cbgnbXV OPASn4kKr8m5YwB4tvxphwrr7o91o3L3rmnGGNNuc4CsTEOFHIo9b+mKPGy0uahI3Ea3 Q1V3ZLANsjknwwI74JaJm1II2WWsXuSw/yR5oER3+ujXTx6BCluvUiwMWeVhSA4Lahi8 o1IA== 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:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=3jz+qg6bidlkY3ZYaNR91bkejp9SH6IQLwmiISoFlmE=; b=eZYKNwM3WLxZR0Tz2TLEPc+Vegni7pHJgSuwuPpoiM5pIdG+Q8dBkpZkNnPqOSUlFD MGK4V4l4Evg43bbtRE29+0VZl2hONQYH8Vw/a947ebzBqvgyR9MD/xUIRpYX0r536PSX S4tSv2mEwbRa5HL4MJfyG8/Nb/t0HyUZAAsBrdQxEigouNRqhk0ubS+syCqe//wHH0th FRrAP7F9cEpTAO1xq5P2Qtw5mBRfCeYca5kzCdPKNk/LXvy1LbdMPKT3cSKkERhmitxP z/DQVnqhrZqhNRbPVOwuYtbP1O95BXNGeLF1Fm9ncnhMYcZYzLPJqd2e/kVexbC60Dii Cm2Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=kehe09E1; dkim=pass header.i=@codeaurora.org header.s=default header.b=fV4IJ9m7; 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 c3-v6si5265030pld.87.2018.06.14.06.05.31; Thu, 14 Jun 2018 06:05:45 -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=@codeaurora.org header.s=default header.b=kehe09E1; dkim=pass header.i=@codeaurora.org header.s=default header.b=fV4IJ9m7; 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 S1755307AbeFNNEv (ORCPT + 99 others); Thu, 14 Jun 2018 09:04:51 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:55818 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755225AbeFNNEr (ORCPT ); Thu, 14 Jun 2018 09:04:47 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 5BFE8602FC; Thu, 14 Jun 2018 13:04:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1528981487; bh=W/+jE4ymyTlGslI275VqEsWyr8EWzzwylFHdMzwr3rI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kehe09E1FeMSEdxPTTLhA0xl44pprqQeXdjecqqPAr//hr9FD5k7h/JMZbPG0lVGW 69obKMMm4nUrZzsR3wjyCOpnkIlBlcA5+Q75+sttWn3bQgnbA+lxXrvz5hrCqJxnJ2 b5RH8sjiQBgFWQGrH9vNegEloaJyYU8IBUtoRBz0= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from sayalil-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: sayalil@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 504F96055D; Thu, 14 Jun 2018 13:04:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1528981485; bh=W/+jE4ymyTlGslI275VqEsWyr8EWzzwylFHdMzwr3rI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fV4IJ9m7a7Ou8jMp0C+1OmyoqfFlwE5/O+5jMJJHWqRo1yZIerWLPDRBzGfRwH3eP 4p6WMu7lHlQHi+qses8ynlBKHI24iJ8zsq4HYLsj+JTL/lybhY4sZcWG0JE6oaQWip BK1dv94MPdTl38H/G0eRSShmMSOiet37w2xaB1Sw= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 504F96055D Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=sayalil@codeaurora.org From: Sayali Lokhande To: subhashj@codeaurora.org, cang@codeaurora.org, vivek.gautam@codeaurora.org, rnayak@codeaurora.org, vinholikatti@gmail.com, jejb@linux.vnet.ibm.com, martin.petersen@oracle.com, asutoshd@codeaurora.org, evgreen@chromium.org, riteshh@codeaurora.org Cc: linux-scsi@vger.kernel.org, Sayali Lokhande , linux-kernel@vger.kernel.org (open list) Subject: [PATCH V3 3/3] scsi: ufs: Add configfs support for ufs provisioning Date: Thu, 14 Jun 2018 18:33:52 +0530 Message-Id: <1528981432-23065-4-git-send-email-sayalil@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1528981432-23065-1-git-send-email-sayalil@codeaurora.org> References: <1528981432-23065-1-git-send-email-sayalil@codeaurora.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add configfs support to provision ufs device at runtime. Usage: echo > /config/ufshcd/ufs_provision To check provisioning status: cat /config/ufshcd/ufs_provision 1 -> Success (Reboot device to check updated provisioning) Signed-off-by: Sayali Lokhande --- Documentation/ABI/testing/configfs-driver-ufs | 14 ++ drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-configfs.c | 191 ++++++++++++++++++++++++++ drivers/scsi/ufs/ufs.h | 2 + drivers/scsi/ufs/ufshcd.c | 2 + drivers/scsi/ufs/ufshcd.h | 7 + 6 files changed, 217 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-driver-ufs create mode 100644 drivers/scsi/ufs/ufs-configfs.c diff --git a/Documentation/ABI/testing/configfs-driver-ufs b/Documentation/ABI/testing/configfs-driver-ufs new file mode 100644 index 0000000..a17fe15 --- /dev/null +++ b/Documentation/ABI/testing/configfs-driver-ufs @@ -0,0 +1,14 @@ +What: /config/ufshcd/ufs_provision +Date: Jun 2018 +KernelVersion: 4.14 +Description: + This file shows the status of runtime ufs provisioning. + This can be used to provision ufs device if bConfigDescrLock is 0. + Configuration buffer needs to be written in space separated format + specificied as: + echo + + + + + > /config/ufshcd/ufs_provision diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 918f579..d438e74 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-d obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-objs := ufshcd.o ufs-sysfs.o +obj-$(CONFIG_CONFIGFS_FS) += ufs-configfs.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-configfs.c b/drivers/scsi/ufs/ufs-configfs.c new file mode 100644 index 0000000..7655e6b --- /dev/null +++ b/drivers/scsi/ufs/ufs-configfs.c @@ -0,0 +1,191 @@ +/* + * drivers/scsi/ufs/ufs-configfs.c + * + * Copyright (c) 2018, Qualcomm Technologies, Inc. + * + */ + +#include +#include +#include +#include + +#include "ufs.h" +#include "ufshcd.h" + +struct ufs_hba *hba; + +static ssize_t ufs_provision_show(struct config_item *item, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "provision_enabled = %x\n", + hba->provision_enabled); +} + +ssize_t ufshcd_desc_configfs_store(const char *buf, size_t count) +{ + struct ufs_config_descr *cfg = &hba->cfgs; + char *strbuf; + char *strbuf_copy; + int desc_buf[count]; + int *pt; + char *token; + int i, ret; + int value, commit = 0; + int num_luns = 0; + int KB_per_block = 4; + + /* reserve one byte for null termination */ + strbuf = kmalloc(count + 1, GFP_KERNEL); + if (!strbuf) + return -ENOMEM; + + strbuf_copy = strbuf; + strlcpy(strbuf, buf, count + 1); + memset(desc_buf, 0, count); + + /* Just return if bConfigDescrLock is already set */ + ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_CONF_DESC_LOCK, 0, 0, &cfg->bConfigDescrLock); + if (ret) { + dev_err(hba->dev, "%s: Failed reading bConfigDescrLock %d, cannot re-provision device!\n", + __func__, ret); + hba->provision_enabled = 0; + goto out; + } + if (cfg->bConfigDescrLock == 1) { + dev_err(hba->dev, "%s: bConfigDescrLock already set to %u, cannot re-provision device!\n", + __func__, cfg->bConfigDescrLock); + hba->provision_enabled = 0; + goto out; + } + + for (i = 0; i < count; i++) { + token = strsep(&strbuf, " "); + if (!token && i) { + num_luns = desc_buf[i-1]; + dev_dbg(hba->dev, "%s: token %s, num_luns %d\n", + __func__, token, num_luns); + if (num_luns > 8) { + dev_err(hba->dev, "%s: Invalid num_luns %d\n", + __func__, num_luns); + hba->provision_enabled = 0; + goto out; + } + break; + } + + ret = kstrtoint(token, 0, &value); + if (ret) { + dev_err(hba->dev, "%s: kstrtoint failed %d %s\n", + __func__, ret, token); + break; + } + desc_buf[i] = value; + dev_dbg(hba->dev, " desc_buf[%d] 0x%x", i, desc_buf[i]); + } + + /* Fill in the descriptors with parsed configuration data */ + pt = desc_buf; + cfg->bNumberLU = *pt++; + cfg->bBootEnable = *pt++; + cfg->bDescrAccessEn = *pt++; + cfg->bInitPowerMode = *pt++; + cfg->bHighPriorityLUN = *pt++; + cfg->bSecureRemovalType = *pt++; + cfg->bInitActiveICCLevel = *pt++; + cfg->wPeriodicRTCUpdate = *pt++; + cfg->bConfigDescrLock = *pt++; + dev_dbg(hba->dev, "%s: %u %u %u %u %u %u %u %u %u\n", __func__, + cfg->bNumberLU, cfg->bBootEnable, cfg->bDescrAccessEn, + cfg->bInitPowerMode, cfg->bHighPriorityLUN, cfg->bSecureRemovalType, + cfg->bInitActiveICCLevel, cfg->wPeriodicRTCUpdate, + cfg->bConfigDescrLock); + + for (i = 0; i < num_luns; i++) { + cfg->unit[i].LUNum = *pt++; + cfg->unit[i].bLUEnable = *pt++; + cfg->unit[i].bBootLunID = *pt++; + /* dNumAllocUnits = size_in_kb/KB_per_block */ + cfg->unit[i].dNumAllocUnits = (u32)(*pt++ / KB_per_block); + cfg->unit[i].bDataReliability = *pt++; + cfg->unit[i].bLUWriteProtect = *pt++; + cfg->unit[i].bMemoryType = *pt++; + cfg->unit[i].bLogicalBlockSize = *pt++; + cfg->unit[i].bProvisioningType = *pt++; + cfg->unit[i].wContextCapabilities = *pt++; + } + + cfg->lun_to_grow = *pt++; + commit = *pt++; + cfg->num_luns = *pt; + dev_dbg(hba->dev, "%s: lun_to_grow %u, commit %u num_luns %u\n", + __func__, cfg->lun_to_grow, commit, cfg->num_luns); + if (commit == 1) { + ret = ufshcd_do_config_device(hba); + if (!ret) { + hba->provision_enabled = 1; + dev_err(hba->dev, + "%s: UFS Provisioning completed,num_luns %u, reboot now !\n", + __func__, cfg->num_luns); + } + } else + dev_err(hba->dev, "%s: Invalid commit %u\n", __func__, commit); +out: + kfree(strbuf_copy); + return count; +} + +static ssize_t ufs_provision_store(struct config_item *item, + const char *buf, size_t count) +{ + return ufshcd_desc_configfs_store(buf, count); +} + +static struct configfs_attribute ufshcd_attr_provision = { + .ca_name = "ufs_provision", + .ca_mode = S_IRUGO | S_IWUGO, + .ca_owner = THIS_MODULE, + .show = ufs_provision_show, + .store = ufs_provision_store, +}; + +static struct configfs_attribute *ufshcd_attrs[] = { + &ufshcd_attr_provision, + NULL, +}; + +static struct config_item_type ufscfg_type = { + .ct_attrs = ufshcd_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem ufscfg_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "ufshcd", + .ci_type = &ufscfg_type, + }, + }, +}; + +int ufshcd_configfs_init(struct ufs_hba *hba_ufs) +{ + int ret; + struct configfs_subsystem *subsys = &ufscfg_subsys; + hba = hba_ufs; + + config_group_init(&subsys->su_group); + mutex_init(&subsys->su_mutex); + ret = configfs_register_subsystem(subsys); + if (ret) { + pr_err("Error %d while registering subsystem %s\n", + ret, + subsys->su_group.cg_item.ci_namebuf); + } + return ret; +} + +void ufshcd_configfs_exit(void) +{ + configfs_unregister_subsystem(&ufscfg_subsys); +} \ No newline at end of file diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 1f99904..0b497fc 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -427,6 +427,7 @@ enum { }; struct ufs_unit_desc { + u8 LUNum; u8 bLUEnable; /* 1 for enabled LU */ u8 bBootLunID; /* 0 for using this LU for boot */ u8 bLUWriteProtect; /* 1 = power on WP, 2 = permanent WP */ @@ -451,6 +452,7 @@ struct ufs_config_descr { u32 qVendorConfigCode; /* Vendor specific configuration code */ struct ufs_unit_desc unit[8]; u8 lun_to_grow; + u8 num_luns; }; /* Task management service response */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c0235a4..63d6532 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7854,6 +7854,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) void ufshcd_remove(struct ufs_hba *hba) { ufs_sysfs_remove_nodes(hba->dev); + ufshcd_configfs_exit(); scsi_remove_host(hba->host); /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); @@ -8107,6 +8108,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) async_schedule(ufshcd_async_scan, hba); ufs_sysfs_add_nodes(hba->dev); + ufshcd_configfs_init(hba); return 0; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 816b674..fb254c8 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -550,6 +551,7 @@ struct ufs_hba { bool is_irq_enabled; u32 dev_ref_clk_freq; struct ufs_config_descr cfgs; + bool provision_enabled; /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1 @@ -867,7 +869,12 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, int ufshcd_hold(struct ufs_hba *hba, bool async); void ufshcd_release(struct ufs_hba *hba); + +/* Expose UFS configfs API's */ int ufshcd_do_config_device(struct ufs_hba *hba); +ssize_t ufshcd_desc_configfs_store(const char *buf, size_t count); +int ufshcd_configfs_init(struct ufs_hba *hba_ufs); +void ufshcd_configfs_exit(void); int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, int *desc_length); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project