From patchwork Sun Aug 5 11:39:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB13E157B for ; Sun, 5 Aug 2018 11:40:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C630B2991F for ; Sun, 5 Aug 2018 11:40:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA6C02993B; Sun, 5 Aug 2018 11:40:30 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 C8A902991F for ; Sun, 5 Aug 2018 11:40:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726159AbeHENoq (ORCPT ); Sun, 5 Aug 2018 09:44:46 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:63955 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENoq (ORCPT ); Sun, 5 Aug 2018 09:44:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469226; x=1565005226; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WdSEcLyTThMDOVovVsPFMMdayWz4vnbXBguKGlRP1Zk=; b=VSJpEtjdqY5YIOdRhpEbvfe/U4Qo2CU+Rf7lYSxyCfLWcCmH6q9e1Kvo oPyiDRl8QUTVDHbIkcTiRsTTJaj5qEMeLRsmveIiaufix702EsJl/ygvo jiHLkKLFGqDJOyNxZJbOqu1CPQLQcxJmKuoXqIfRCiuCBl70lLfBBRKHa 9lohekAcVJN/u7TdzhDDQFW2xplkCnq/VipNDcAEvT+Wjdcfnbgc1ChTs laHc5CuS4k/NXyQB21Q5wgthcjkbzsH5+TWfUJFOrq20IZPjNBwDjLBh2 YlVVHH9sEaoh3YIsUImc7R7rxKT/Ewi6w1icNOJo0cOJUgEZnYOia4bWJ Q==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="87459763" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:40:26 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 05 Aug 2018 04:28:44 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:40:23 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 1/8] scsi: Add ufs transport class Date: Sun, 5 Aug 2018 14:39:49 +0300 Message-Id: <1533469196-300-2-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.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 Scsi transport is a framework that allow to send scsi commands to a non-scsi devices. Still, it is flexible enough to allow sending non-scsi commands as well. We will use this framework to manage ufs devices by sending UPIU transactions. In addition to the basic SCSI core objects this transport class introduces two additional (currently empty) class objects: “ufs-host” and “ufs-port”. There is only one “ufs-host” in the system, but can be more-than-one “ufs-ports”. Those classes are left empty for now, as ufs-sysfs already contains an abundant amount of attributes. A “ufs-port” is purely a software object. Evidently, the function template takes no port as an argument, as the driver has no concept of "port". We only need it as a hanging point in the bsg device tree, so maybe a more appropriate term would be: "ufs-bsg-dev-node". The ufs-port has a pretty lean structure. This is because we are using upiu transactions that contains the outmost detailed info, so we don't really need complex constructs to support it. The transport will keep track of its ufs-ports via its scsi host. Signed-off-by: Avri Altman --- drivers/scsi/Kconfig | 13 ++ drivers/scsi/Makefile | 1 + drivers/scsi/scsi_transport_ufs.c | 354 ++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_ufs.h | 44 +++++ 4 files changed, 412 insertions(+) create mode 100644 drivers/scsi/scsi_transport_ufs.c create mode 100644 include/scsi/scsi_transport_ufs.h diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8fc851a..9e99275 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -290,6 +290,19 @@ config SCSI_SAS_ATTRS If you wish to export transport-specific information about each attached SAS device to sysfs, say Y. +config SCSI_UFS_ATTRS + tristate "UFS Transport Attributes" + depends on SCSI + select BLK_DEV_BSGLIB + help + Scsi transport is a framework that allow to send scsi commands to + a non-scsi devices. Still, it is flexible enough to allow sending + non-scsi commands as well. We will use this framework to manage + ufs devices by sending UPIU transactions. + + If you wish to export transport-specific information about + each attached UFS device to sysfs, say Y. + source "drivers/scsi/libsas/Kconfig" config SCSI_SRP_ATTRS diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index d1bad43..e0efc06 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o +obj-$(CONFIG_SCSI_UFS_ATTRS) += scsi_transport_ufs.o obj-$(CONFIG_SCSI_DH) += device_handler/ obj-$(CONFIG_LIBFC) += libfc/ diff --git a/drivers/scsi/scsi_transport_ufs.c b/drivers/scsi/scsi_transport_ufs.c new file mode 100644 index 0000000..06349c6 --- /dev/null +++ b/drivers/scsi/scsi_transport_ufs.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCSI UFS transport class + * + * Copyright (C) 2018 Western Digital Corporation + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define UFS_HOST_ATTRS 0 +#define UFS_PORT_ATTRS 0 + +#define MAX_PORTS 256 +static DEFINE_IDA(ufs_ida); + +struct ufs_internal { + struct scsi_transport_template t; + struct ufs_function_template *f; + + struct device_attribute *host_attrs[UFS_HOST_ATTRS + 1]; + struct device_attribute *port_attrs[UFS_PORT_ATTRS + 1]; + struct transport_container port_attr_cont; +}; + +static inline struct ufs_internal * +to_ufs_internal(struct scsi_transport_template *tmpl) +{ + return container_of(tmpl, struct ufs_internal, t); +} + +struct ufs_host_attrs { + atomic_t active_ports; +}; + +static inline struct ufs_host_attrs * +to_ufs_host_attrs(struct Scsi_Host *shost) +{ + return (struct ufs_host_attrs *)shost->shost_data; +} + +static int ufs_bsg_dispatch(struct bsg_job *job) +{ + struct Scsi_Host *shost = dev_to_shost(job->dev); + struct ufs_internal *i = to_ufs_internal(shost->transportt); + + /* check for payload_len when we'll support data transfer upiu */ + + return i->f->bsg_request(job); +} + +static int ufs_bsg_initialize(struct Scsi_Host *shost, struct ufs_port *port) +{ + struct request_queue *q; + struct ufs_internal *i = to_ufs_internal(shost->transportt); + + if (!i->f->bsg_request) { + pr_info("%s can't handle ufs requests\n", shost->hostt->name); + return 0; + } + + q = bsg_setup_queue(&port->dev, dev_name(&port->dev), + ufs_bsg_dispatch, 0); + if (IS_ERR(q)) + return PTR_ERR(q); + port->q = q; + + return 0; +} + +static int ufs_host_setup(struct transport_container *tc, struct device *dev, + struct device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct ufs_host_attrs *ufs_host = to_ufs_host_attrs(shost); + + atomic_set(&ufs_host->active_ports, 0); + + return 0; +} + +static DECLARE_TRANSPORT_CLASS(ufs_host_class, "ufs_host", ufs_host_setup, + NULL, NULL); + +static DECLARE_TRANSPORT_CLASS(ufs_port_class, "ufs_ports", + NULL, NULL, NULL); + +static int ufs_host_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct ufs_internal *i; + + if (!scsi_is_host_device(dev)) + return 0; + + shost = dev_to_shost(dev); + if (!shost->transportt) + return 0; + + if (shost->transportt->host_attrs.ac.class != &ufs_host_class.class) + return 0; + + i = to_ufs_internal(shost->transportt); + + return &i->t.host_attrs.ac == cont; +} + +static void ufs_port_release(struct device *dev) +{ + struct ufs_port *port = dev_to_ufs_port(dev); + struct Scsi_Host *shost = dev_to_shost(dev->parent); + struct ufs_host_attrs *ufs_host = to_ufs_host_attrs(shost); + + ida_simple_remove(&ufs_ida, port->id); + atomic_dec(&ufs_host->active_ports); + put_device(dev->parent); + kfree(port); +} + +static inline int scsi_is_ufs_port(const struct device *dev) +{ + return dev->release == ufs_port_release; +} + +static int ufs_port_match(struct attribute_container *cont, struct device *dev) +{ + struct Scsi_Host *shost; + struct ufs_internal *i; + + if (!scsi_is_ufs_port(dev)) + return 0; + + shost = dev_to_shost(dev->parent); + + if (!shost->transportt) + return 0; + + if (shost->transportt->host_attrs.ac.class != &ufs_host_class.class) + return 0; + + i = to_ufs_internal(shost->transportt); + return &i->port_attr_cont.ac == cont; +} + +/** + * ufs_attach_transport - instantiate UFS transport template + * @ft: UFS transport class function template + */ +struct scsi_transport_template * +ufs_attach_transport(struct ufs_function_template *ft) +{ + struct ufs_internal *i = kzalloc(sizeof(struct ufs_internal), + GFP_KERNEL); + + if (unlikely(!i)) + return NULL; + + i->f = ft; + i->t.host_attrs.ac.attrs = &i->host_attrs[0]; + i->t.host_attrs.ac.class = &ufs_host_class.class; + i->t.host_attrs.ac.match = ufs_host_match; + i->t.host_size = sizeof(struct ufs_host_attrs); + i->host_attrs[0] = NULL; + transport_container_register(&i->t.host_attrs); + + i->port_attr_cont.ac.class = &ufs_port_class.class; + i->port_attr_cont.ac.attrs = &i->port_attrs[0]; + i->port_attr_cont.ac.match = ufs_port_match; + i->port_attrs[0] = NULL; + transport_container_register(&i->port_attr_cont); + + return &i->t; +} +EXPORT_SYMBOL(ufs_attach_transport); + +/** + * ufs_release_transport - release UFS transport template instance + * @t: transport template instance + */ +void ufs_release_transport(struct scsi_transport_template *t) +{ + struct ufs_internal *i = to_ufs_internal(t); + + transport_container_unregister(&i->t.host_attrs); + transport_container_unregister(&i->port_attr_cont); + kfree(i); +} +EXPORT_SYMBOL(ufs_release_transport); + +/** ufs_port_alloc - allocate and initialize a UFS port structure + * @shost: scsi host that the port is attached to + * + * Allocates a UFS port structure. It will be added to the device tree + * below the device specified by its Scsi_Host parent. + * Returns %NULL on error + */ +struct ufs_port *ufs_port_alloc(struct Scsi_Host *shost) +{ + struct ufs_port *port; + struct device *parent = &shost->shost_gendev; + struct ufs_host_attrs *ufs_host = to_ufs_host_attrs(shost); + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return NULL; + + port->id = ida_simple_get(&ufs_ida, 0, MAX_PORTS, GFP_KERNEL); + if (port->id < 0) + return NULL; + atomic_inc(&ufs_host->active_ports); + + device_initialize(&port->dev); + + port->dev.parent = get_device(parent); + port->dev.release = ufs_port_release; + + dev_set_name(&port->dev, "ufs-port-%d:%d", shost->host_no, port->id); + + transport_setup_device(&port->dev); + + return port; +} +EXPORT_SYMBOL(ufs_port_alloc); + +/** + * ufs_port_add - add a UFS port to the device hierarchy + * @port: port to be added + * + * publishes a port to the rest of the system + */ +int ufs_port_add(struct ufs_port *port) +{ + struct device *dev = &port->dev; + struct Scsi_Host *shost = dev_to_shost(dev->parent); + int error; + + if (!port) { + pr_err("%s failed with null port\n", __func__); + return -EINVAL; + } + + error = device_add(dev); + + if (error) + return error; + + transport_add_device(dev); + transport_configure_device(dev); + + if (ufs_bsg_initialize(shost, port)) + dev_err(dev, "fail to initialize a bsg dev %d\n", + shost->host_no); + + return 0; +} +EXPORT_SYMBOL(ufs_port_add); + +/** + * ufs_port_free - free a ufs port + * @port: ufs port to free + * + * Frees the specified ufs port. Should be called on ufs_port_add() failure. + */ +void ufs_port_free(struct ufs_port *port) +{ + transport_destroy_device(&port->dev); + put_device(&port->dev); +} +EXPORT_SYMBOL(ufs_port_free); + +/** + * ufs_port_delete - remove a ufs port + * @port: ufs port to remove + * + */ +void ufs_port_delete(struct ufs_port *port) +{ + struct device *dev = &port->dev; + + if (port->q) + bsg_unregister_queue(port->q); + + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); + + put_device(dev); +} +EXPORT_SYMBOL(ufs_port_delete); + +static int do_ufs_port_del(struct device *dev, void *data) +{ + if (scsi_is_ufs_port(dev)) + ufs_port_delete(dev_to_ufs_port(dev)); + + return 0; +} + +/** + * ufs_remove_host - tear down a ufs port devices + * @shost: the scsi host which is parenting the ufs port objects + * + * Removes all ufs port devices. + * Unharm Other devices that are attached to that host. + */ +void ufs_remove_host(struct Scsi_Host *shost) +{ + device_for_each_child(&shost->shost_gendev, NULL, do_ufs_port_del); +} +EXPORT_SYMBOL_GPL(ufs_remove_host); + +static __init int ufs_transport_init(void) +{ + int error; + + error = transport_class_register(&ufs_host_class); + if (error) + goto out; + + error = transport_class_register(&ufs_port_class); + if (error) + goto out_unregister_transport; + + return 0; + +out_unregister_transport: + transport_class_unregister(&ufs_host_class); +out: + return error; +} + +static void __exit ufs_transport_exit(void) +{ + transport_class_unregister(&ufs_host_class); + transport_class_unregister(&ufs_port_class); +} + +MODULE_AUTHOR("WDC"); +MODULE_DESCRIPTION("UFS Transport Attributes"); +MODULE_LICENSE("GPL"); + +module_init(ufs_transport_init); +module_exit(ufs_transport_exit); diff --git a/include/scsi/scsi_transport_ufs.h b/include/scsi/scsi_transport_ufs.h new file mode 100644 index 0000000..c45dfb8 --- /dev/null +++ b/include/scsi/scsi_transport_ufs.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Western Digital Corporation + */ + +#ifndef SCSI_TRANSPORT_UFS_H +#define SCSI_TRANSPORT_UFS_H + +#include +#include +#include +#include + + +struct ufs_function_template { + int (*bsg_request)(struct bsg_job *job); +}; + +/* One might expect a more complex structure – + * some representation of a list containing all the luns of the systems, + * including the w-luns. However, as we are using upiu transactions that + * contains the lun index in its header, we need not to have its representation + * in the device tree. + */ +struct ufs_port { + struct device dev; + int id; + struct request_queue *q; +}; + +static inline struct ufs_port *dev_to_ufs_port(struct device *d) +{ + return container_of(d, struct ufs_port, dev); +} + +struct scsi_transport_template * +ufs_attach_transport(struct ufs_function_template *ft); +void ufs_release_transport(struct scsi_transport_template *t); +struct ufs_port *ufs_port_alloc(struct Scsi_Host *shost); +int ufs_port_add(struct ufs_port *port); +void ufs_port_free(struct ufs_port *port); +void ufs_port_delete(struct ufs_port *port); +void ufs_remove_host(struct Scsi_Host *shost); +#endif From patchwork Sun Aug 5 11:39:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556117 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77ACD157B for ; Sun, 5 Aug 2018 11:40:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61AAB2991F for ; Sun, 5 Aug 2018 11:40:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 540CE2993B; Sun, 5 Aug 2018 11:40:43 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 9F53D2991F for ; Sun, 5 Aug 2018 11:40:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726159AbeHENo7 (ORCPT ); Sun, 5 Aug 2018 09:44:59 -0400 Received: from esa6.hgst.iphmx.com ([216.71.154.45]:54198 "EHLO esa6.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENo7 (ORCPT ); Sun, 5 Aug 2018 09:44:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469242; x=1565005242; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=QP7N0igCd4rkEav5kJAu1cLyFbDhodF9dxnRf/9BBW0=; b=p7Mq+v7gfm0jlcwyRT3MhL+EVUZM9P7lj/6DNW91wc91pyzZeuxZVZRX jSHZKr4FNfB4IDTzH4VblzsKpEtYUoNl9hIsNnsWS3z/aHUMPRSngIMMy AAMujyOpvtfPGi5ypxdMZyf/jt9QK1oiwvOAwAhn9tko4KV84nl1lf9oc 4W4yokzeKPhzb1AZcefSlFt6XAAzVlTEQNUltWQwdpZUtGJuAAEcjeQHe qnvtiolaUav8Ri8scVlqbwRxIi+AHZp05Att8zc41gY8bhx7G2WTczZcf CoRDvM0r4Vv3p4uDNSpSgtjIn2yiM55LMcM+SkHVS3qhAz7lsI2vSGSXL A==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="88071632" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:40:41 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 05 Aug 2018 04:28:23 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:40:37 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 2/8] scsi: ufs: Add ufs-bsg module Date: Sun, 5 Aug 2018 14:39:50 +0300 Message-Id: <1533469196-300-3-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.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 A LLD companion for the ufs scsi transport. For now, just provide an API to instantiate the ufs transport, allocating and removing ufs-ports. As we are attaching the transport template to the scsi host that was already alocated for the ufs hba, we'll need to pay extra attention on where to call the provided API from ufshcd. For the time being, implements an empty bsg_request() - will add some more functionality in coming patches. Nonetheless, we reveal here the protocol we are planning to use: UFS Transport Protocol Transactions. UFS transactions consist of packets called UFS Protocol Information Units (UPIU). There are UPIU’s defined for UFS SCSI commands, responses, data in and data out, task management, utility functions, vendor functions, transaction synchronization and control, and more. By using UPIUs, we get access to the most fine-grained internals of this protocol, and able to communicate with the device in ways, that are sometimes beyond the capacity of the ufs driver. Signed-off-by: Avri Altman --- drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs_bsg.c | 127 +++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs_bsg.h | 72 ++++++++++++++++++++++ include/uapi/scsi/scsi_bsg_ufs.h | 56 +++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 drivers/scsi/ufs/ufs_bsg.c create mode 100644 drivers/scsi/ufs/ufs_bsg.h create mode 100644 include/uapi/scsi/scsi_bsg_ufs.h diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 2c50f03..5227bfb 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -8,3 +8,4 @@ ufshcd-core-objs := ufshcd.o ufs-sysfs.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o +obj-$(CONFIG_SCSI_UFS_ATTRS) += ufs_bsg.o diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c new file mode 100644 index 0000000..6f1941b --- /dev/null +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SCSI transport companion for UFS HBA + * + * Copyright (C) 2018 Western Digital Corporation + */ +#include "ufs_bsg.h" + +struct ufs_bsg { + struct ufs_hba *hba; + struct ufs_port *port; +}; +static struct ufs_bsg *bsg_host; + +static int ufs_bsg_request(struct bsg_job *job); + +static struct scsi_transport_template *ufs_transport_template; +static struct ufs_function_template ufs_transport_functions = { + .bsg_request = ufs_bsg_request, +}; + +static int ufs_bsg_request(struct bsg_job *job) +{ + struct ufs_bsg_request *bsg_request = job->request; + struct ufs_bsg_reply *bsg_reply = job->reply; + int ret = -ENOTSUPP; + + bsg_reply->reply_payload_rcv_len = 0; + + /* Do Nothing for now */ + dev_err(job->dev, "unsupported message_code 0x%x\n", + bsg_request->msgcode); + + bsg_reply->result = ret; + if (ret) + job->reply_len = sizeof(uint32_t); + else + job->reply_len = sizeof(struct ufs_bsg_reply) + + bsg_reply->reply_payload_rcv_len; + + bsg_job_done(job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + + return ret; +} + +/** + * ufs_bsg_attach_transport - instantiate UFS transport template + * @hba: hba to attach the transport template to + * + * Call this before scsi_add_host() publishes it to the scsi midlayer + */ +void ufs_bsg_attach_transport(struct ufs_hba *hba) +{ + ufs_transport_template = + ufs_attach_transport(&ufs_transport_functions); + if (!ufs_transport_template) + return; + + hba->host->transportt = ufs_transport_template; +} + +/** + * ufs_bsg_remove - detach and remove the added ufs-ports + * @shost: scsi host that is parenting the ufs-ports + * + * Should be called when unloading the driver. + */ +void ufs_bsg_remove(struct Scsi_Host *shost) +{ + if (!bsg_host) + return; + + ufs_remove_host(shost); + + if (ufs_transport_template) { + ufs_release_transport(ufs_transport_template); + ufs_transport_template = NULL; + } + + kfree(bsg_host); +} + +/** + * ufs_bsg_probe - Add and report ufs device to ufs transport + * @hba: per adapter object + * + * Called during initial loading of the driver, and before scsi_scan_host. + * Should be called only if the attach phase was successful + */ + +int ufs_bsg_probe(struct ufs_hba *hba) +{ + struct ufs_port *port; + int ret; + + if (WARN_ON(!ufs_transport_template)) + return -ENODEV; + + bsg_host = kzalloc(sizeof(*bsg_host), GFP_KERNEL); + if (!bsg_host) { + ret = -ENOMEM; + goto out; + } + + port = ufs_port_alloc(hba->host); + if (!port) { + ret = -ENOMEM; + goto out_free_bsg_host; + } + + ret = ufs_port_add(port); + if (ret) + goto out_free_port; + + bsg_host->port = port; + bsg_host->hba = hba; + + return 0; + +out_free_port: + ufs_port_free(port); +out_free_bsg_host: + kfree(bsg_host); +out: + ufs_transport_template = NULL; + return ret; +} diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h new file mode 100644 index 0000000..4a391b2 --- /dev/null +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Western Digital Corporation + */ +#ifndef UFS_BSG_H +#define UFS_BSG_H + +#include +#include +#include + +#include +#include "ufshcd.h" +#include "ufs.h" + +#define UPIU_TRANSACTION_UIC_CMD 0x1F + +enum { + REQ_UPIU_SIZE_DWORDS = 8, + RSP_UPIU_SIZE_DWORDS = 8, +}; + +struct ufs_bsg_request { + uint32_t msgcode; + struct utp_upiu_header header; + union { + struct utp_upiu_query qr; + struct utp_upiu_task_req tr; + /* use utp_upiu_query to host the 4 dwords of uic command */ + struct utp_upiu_query uc; + } tsf; +}; + + +struct ufs_bsg_reply { + /* + * The completion result. Result exists in two forms: + * if negative, it is an -Exxx system errno value. There will + * be no further reply information supplied. + * else, it's the 4-byte scsi error result, with driver, host, + * msg and status fields. The per-msgcode reply structure + * will contain valid data. + */ + uint32_t result; + + /* If there was reply_payload, how much was received? */ + uint32_t reply_payload_rcv_len; + + struct utp_upiu_header header; + union { + struct utp_upiu_query qr; + struct utp_upiu_task_rsp tr; + struct utp_upiu_query uc; + } tsf; +}; + +struct ufs_bsg_raw_upiu { + struct ufs_bsg_upiu request; + struct ufs_bsg_upiu reply; +}; + +#ifdef CONFIG_SCSI_UFS_ATTRS +void ufs_bsg_attach_transport(struct ufs_hba *hba); +void ufs_bsg_remove(struct Scsi_Host *shost); +int ufs_bsg_probe(struct ufs_hba *hba); +#else +static inline void ufs_bsg_attach_transport(struct ufs_hba *hba) {} +static inline void ufs_bsg_remove(struct Scsi_Host *shost) {} +static inline int ufs_bsg_probe(struct ufs_hba *hba) {return 0; } +#endif + +#endif /* UFS_BSG_H */ diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h new file mode 100644 index 0000000..5fb37be --- /dev/null +++ b/include/uapi/scsi/scsi_bsg_ufs.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * UFS Transport SGIO v4 BSG Message Support + * + * Copyright (C) 2018 Western Digital Corporation + */ +#ifndef SCSI_BSG_UFS_H +#define SCSI_BSG_UFS_H + +/* + * This file intended to be included by both kernel and user space + */ + + +/** + * struct ufs_bsg_upiu - upiu transaction structure + * + * @header: upiu header + * @tsf: Transaction Specific Fields + * @data: payload pointer + * + * This structure supports all ufs transaction types per JEDEC UFSv2.1 + * paragraph 10.7 + */ +struct ufs_bsg_upiu { + uint32_t header[3]; + uint32_t tsf[5]; + uint8_t data[0]; +}; + +/* request (CDB) structure of the sg_io_v4 */ +struct ufs_bsg_upiu_request { + uint32_t msgcode; + struct ufs_bsg_upiu upiu; +} __packed; + +/* response (request sense data) structure of the sg_io_v4 */ +struct ufs_bsg_upiu_reply { + /* + * The completion result. Result exists in two forms: + * if negative, it is an -Exxx system errno value. There will + * be no further reply information supplied. + * else, it's the 4-byte scsi error result, with driver, host, + * msg and status fields. The per-msgcode reply structure + * will contain valid data. + */ + uint32_t result; + + /* If there was reply_payload, how much was recevied ? */ + uint32_t reply_payload_rcv_len; + + struct ufs_bsg_upiu upiu; + +}; + +#endif /* SCSI_BSG_UFS_H */ From patchwork Sun Aug 5 11:39:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556119 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 45A491708 for ; Sun, 5 Aug 2018 11:40:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 31D602991F for ; Sun, 5 Aug 2018 11:40:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 25AC82993B; Sun, 5 Aug 2018 11:40:54 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 CA7212991F for ; Sun, 5 Aug 2018 11:40:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726165AbeHENpK (ORCPT ); Sun, 5 Aug 2018 09:45:10 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:63977 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENpK (ORCPT ); Sun, 5 Aug 2018 09:45:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469253; x=1565005253; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=SyEtLiUmTj4lO8w09I083Z02AOIq1i+ir9/+CIcOkO4=; b=qGtRY+agnYRpjLZW/TiuVV4JHTJtQdwRRuseaPc8FKZ/ISJ3Sio3mgZZ 8NECjfsXqrD1TGScWKj4iU/VRozbpV2liLSUXiSbtK0WUyTsc4l7UupYZ /YcgNqzB6+NFoO0rWKDn2uwlN+d7ttJAi6UssyjdNvV448avrwK/FqkFN qngkJ/5Sioe1Wq/55mPO5n27xZKqsILkWY+gkqD3YJDdd5zgH/D1doyOY LeSq0W5tFTcfqwOT3WPfWSwM0Bw6Epi2ibAoGuWC8x9NCQYL0PQBa93aj qsGtV2sm3bYpn6XfwcLMvWerYWpQsQVN0/CLCB/ESfZYWavcuze2x0bXl w==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="87459831" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:40:52 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 05 Aug 2018 04:29:11 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:40:49 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 3/8] scsi: ufs: Instantiate a ufs transport if its available Date: Sun, 5 Aug 2018 14:39:51 +0300 Message-Id: <1533469196-300-4-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 Call the Attach/Probe/Remove APIs. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufshcd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 3560185..c2ae406 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -46,6 +46,7 @@ #include "ufs_quirks.h" #include "unipro.h" #include "ufs-sysfs.h" +#include "ufs_bsg.h" #define CREATE_TRACE_POINTS #include @@ -6651,6 +6652,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) hba->clk_scaling.is_allowed = true; } + if (hba->host->transportt) + ufs_bsg_probe(hba); + scsi_scan_host(hba->host); pm_runtime_put_sync(hba->dev); } @@ -7874,6 +7878,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) */ void ufshcd_remove(struct ufs_hba *hba) { + ufs_bsg_remove(hba->host); ufs_sysfs_remove_nodes(hba->dev); scsi_remove_host(hba->host); /* disable interrupts */ @@ -8067,6 +8072,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) hba->is_irq_enabled = true; } + ufs_bsg_attach_transport(hba); + err = scsi_add_host(host, hba->dev); if (err) { dev_err(hba->dev, "scsi_add_host failed\n"); From patchwork Sun Aug 5 11:39:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556121 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D51551708 for ; Sun, 5 Aug 2018 11:41:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C354B2991F for ; Sun, 5 Aug 2018 11:41:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B6FB82993B; Sun, 5 Aug 2018 11:41:01 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 582362991F for ; Sun, 5 Aug 2018 11:41:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726166AbeHENpS (ORCPT ); Sun, 5 Aug 2018 09:45:18 -0400 Received: from esa6.hgst.iphmx.com ([216.71.154.45]:54212 "EHLO esa6.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENpS (ORCPT ); Sun, 5 Aug 2018 09:45:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469261; x=1565005261; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=sWKFFQ0+0PKZB5rValJpSeMVWO0psLQEnyDK4SBkv2M=; b=LjiIvQbxVB8+zu78Q/Bl/LtcDI5+lSpU+EVpYhhb/JO8nTxqpVR2yq3T Iwh+WEOYKzAYp5/1p4ElRq+by7Q/2rXS8QF3aklonVI5O14l8PQxYeI7J AtMnKmdos2t/LsFUdmSblbDZSUR3O7vuupEcekc7tSkrbaij/8YXjXE6D ElktIFDqd7BEoAOuoQsn5PYyzGsz8Ryk4D+MYRmgsYWDKHsco6DBi+0Hz 5PY4O13/KpIklLlO1RSYHJ7ojL+9jhV/PPG76bRLXMXw+WrNt8mmSyEie 7OZ4taNwPWiVY/mfZsuOFxvIG2I3pWGNDL/0XPy/gwM93iUB3eIJ6PaHg Q==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="88071645" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:41:01 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 05 Aug 2018 04:28:43 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:40:57 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 4/8] scsi: ufs: Add fill task management request Date: Sun, 5 Aug 2018 14:39:52 +0300 Message-Id: <1533469196-300-5-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 Do that in preparation to re-use ufshcd_issue_tm_cmd code. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufshcd.c | 50 +++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c2ae406..4206bab 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5597,6 +5597,32 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) return err; } +static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp, + int lun_id, int task_id, u8 tm_function, + int task_tag) +{ + struct utp_upiu_task_req *task_req_upiup; + + /* Configure task request descriptor */ + task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); + task_req_descp->header.dword_2 = + cpu_to_le32(OCS_INVALID_COMMAND_STATUS); + + task_req_upiup = + (struct utp_upiu_task_req *)task_req_descp->task_req_upiu; + task_req_upiup->header.dword_0 = + UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0, lun_id, + task_tag); + task_req_upiup->header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, + 0); + /* + * The host shall provide the same value for LUN field in the basic + * header and for Input Parameter. + */ + task_req_upiup->input_param1 = cpu_to_be32(lun_id); + task_req_upiup->input_param2 = cpu_to_be32(task_id); +} + /** * ufshcd_issue_tm_cmd - issues task management commands to controller * @hba: per adapter instance @@ -5611,7 +5637,6 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, u8 tm_function, u8 *tm_response) { struct utp_task_req_desc *task_req_descp; - struct utp_upiu_task_req *task_req_upiup; struct Scsi_Host *host; unsigned long flags; int free_slot; @@ -5631,27 +5656,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, spin_lock_irqsave(host->host_lock, flags); task_req_descp = hba->utmrdl_base_addr; task_req_descp += free_slot; - - /* Configure task request descriptor */ - task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD); - task_req_descp->header.dword_2 = - cpu_to_le32(OCS_INVALID_COMMAND_STATUS); - - /* Configure task request UPIU */ - task_req_upiup = - (struct utp_upiu_task_req *) task_req_descp->task_req_upiu; task_tag = hba->nutrs + free_slot; - task_req_upiup->header.dword_0 = - UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0, - lun_id, task_tag); - task_req_upiup->header.dword_1 = - UPIU_HEADER_DWORD(0, tm_function, 0, 0); - /* - * The host shall provide the same value for LUN field in the basic - * header and for Input Parameter. - */ - task_req_upiup->input_param1 = cpu_to_be32(lun_id); - task_req_upiup->input_param2 = cpu_to_be32(task_id); + + ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function, + task_tag); ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); From patchwork Sun Aug 5 11:39:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556123 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AFCD4157B for ; Sun, 5 Aug 2018 11:41:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D24B2991F for ; Sun, 5 Aug 2018 11:41:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8F36F2993B; Sun, 5 Aug 2018 11:41:16 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 257E62991F for ; Sun, 5 Aug 2018 11:41:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726180AbeHENpd (ORCPT ); Sun, 5 Aug 2018 09:45:33 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:4547 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENpc (ORCPT ); Sun, 5 Aug 2018 09:45:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469275; x=1565005275; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=KaEkKc7fCZERQBUQRMM1HKSJz0h6nEFOo7T73MJtbrU=; b=ZsffqbAEb9xfpvq5MCEFkBX2n1xsWqoaxmNrs3oLPukQwEOo/sKZHwdL e0cx0w2KDTLLSvU7CS252tFjcKxfh3wDERCD3ZG7u8j8N6tco7Ph/jMqd 505ZVkv1lQV78cbrbmQd6xzcW2eSMryly37/1RIDHDFHDmQyj8JEJMOkT cgjzQSsxyf5SvIHDZCPoXZHooE/SGBuIy3nx5WSDrWC1QSUN9jPFwxxti dqzVq/MSzDgHIZi4OFe8L1prfY0fMcBa4cAlp/6W0JJzmYjyhnO4Jpmoi puhpfyMrZaqyYoMdxpD5V+Y3DXB8nR/Dl5Jln9wvCO3ie+2NAw+u2fFE4 A==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="86611446" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:41:15 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 05 Aug 2018 04:29:33 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:41:12 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 5/8] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius Date: Sun, 5 Aug 2018 14:39:53 +0300 Message-Id: <1533469196-300-6-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 Do that in order to re-use its code if the task request and response UPIUs are given externally. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufshcd.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 4206bab..2df87e0 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5598,6 +5598,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) } static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp, + struct utp_upiu_task_req *raw_task_req_upiup, int lun_id, int task_id, u8 tm_function, int task_tag) { @@ -5608,6 +5609,13 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp, task_req_descp->header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS); + if (raw_task_req_upiup) { + raw_task_req_upiup->header.dword_0 |= cpu_to_be32(task_tag); + memcpy(task_req_descp->task_req_upiu, raw_task_req_upiup, + GENERAL_UPIU_REQUEST_SIZE); + return; + } + task_req_upiup = (struct utp_upiu_task_req *)task_req_descp->task_req_upiu; task_req_upiup->header.dword_0 = @@ -5633,8 +5641,11 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp, * * Returns non-zero value on error, zero on success. */ -static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, - u8 tm_function, u8 *tm_response) +static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, + struct utp_upiu_task_req *raw_task_req_upiup, + struct utp_upiu_task_req *raw_task_rsp_upiup, + int lun_id, int task_id, u8 tm_function, + u8 *tm_response) { struct utp_task_req_desc *task_req_descp; struct Scsi_Host *host; @@ -5658,8 +5669,8 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, task_req_descp += free_slot; task_tag = hba->nutrs + free_slot; - ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function, - task_tag); + ufshcd_fill_tm_req(task_req_descp, raw_task_req_upiup, lun_id, task_id, + tm_function, task_tag); ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); @@ -5691,6 +5702,10 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, err = -ETIMEDOUT; } else { err = ufshcd_task_req_compl(hba, free_slot, tm_response); + if (raw_task_rsp_upiup) + memcpy(raw_task_rsp_upiup, + task_req_descp->task_rsp_upiu, + GENERAL_UPIU_REQUEST_SIZE); ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete"); } @@ -5725,7 +5740,8 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) tag = cmd->request->tag; lrbp = &hba->lrb[tag]; - err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp); + err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0, + UFS_LOGICAL_RESET, &resp); if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) { if (!err) err = resp; @@ -5855,8 +5871,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) } for (poll_cnt = 100; poll_cnt; poll_cnt--) { - err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag, - UFS_QUERY_TASK, &resp); + err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, + lrbp->task_tag, UFS_QUERY_TASK, + &resp); if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) { /* cmd pending in the device */ dev_err(hba->dev, "%s: cmd pending in the device. tag = %d\n", @@ -5894,8 +5911,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto out; } - err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag, - UFS_ABORT_TASK, &resp); + err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag, + UFS_ABORT_TASK, &resp); if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) { if (!err) { err = resp; /* service response error */ From patchwork Sun Aug 5 11:39:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556125 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A908A157B for ; Sun, 5 Aug 2018 11:41:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 962902991F for ; Sun, 5 Aug 2018 11:41:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 89DA42993B; Sun, 5 Aug 2018 11:41:28 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 DE4B22991F for ; Sun, 5 Aug 2018 11:41:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726191AbeHENpo (ORCPT ); Sun, 5 Aug 2018 09:45:44 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:20478 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENpo (ORCPT ); Sun, 5 Aug 2018 09:45:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469286; x=1565005286; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=TB8TcUmtjn8W9PlosLzLijAt5+2nVrsH+66cXroDOmg=; b=D9K8fUTJp58nMZFELhMSHJMHU1bogrNFopI/YBYmzNe1gdyoAj5d1SGX yfssE9wjmkk22D4yo694Hm3j+sGAOacKIDnG1NDMliAQQHDdgfjwYlHr0 FxAE9W4AYoqmJAyMOjqk/VMTUSCkHgqeDjYafY9Y6ZdPKWo1ICOX5ccA6 VbiTovvGaz5vI+oBWC3dvkVJVg/XJxyfo45Yt1ClI3MCD4q8VofN3ik3D 10U6/dkqcGwOWxil0Ix0kfiXPtcFCsySU28jpQ25qiIstyHs/VTRyeZuf wY9OqkN3XrDRQz01ptztjIhEGTCcqnzM5RrEu9jkRYxPquu3oFgLld8hP A==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="190442255" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:41:26 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 05 Aug 2018 04:29:09 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:41:23 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 6/8] scsi: ufs: Add API to execute raw upiu commands Date: Sun, 5 Aug 2018 14:39:54 +0300 Message-Id: <1533469196-300-7-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 The UFS host software uses a combination of a host register set, and Transfer Request Descriptors in system memory to communicate with host controller hardware. In its mmio space, a separate places are assigned to UTP Transfer Request Descriptor ("utrd") list, and to UTP Task Management Request Descriptor ("utmrd") list. The provided API supports utrd-typed requests: nop out and device management commands. It also supports utmrd-type requests: task management requests. Other UPIU types are not supported for now. We utilize the already existing code for tag and task work queues. That is, all utrd-typed UPIUs are "disguised" as device management commands. Similarly, the utmrd-typed UPUIs uses the task management infrastructure. It is up to the caller to fill the upiu request properly, as it will be copied without any further input validations. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufshcd.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 6 ++ 2 files changed, 160 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2df87e0..24f8a03 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -257,6 +257,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, static irqreturn_t ufshcd_intr(int irq, void *__hba); static int ufshcd_change_power_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *pwr_mode); +static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp); + static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { return tag >= 0 && tag < hba->nutrs; @@ -5718,6 +5720,158 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, } /** + * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests + * @hba: per-adapter instance + * @req_upiu: upiu request + * @rsp_upiu: upiu reply + * @msgcode: message code, one of UPIU Transaction Codes Initiator to Target + * @desc_buff: pointer to descriptor buffer, NULL if NA + * @buff_len: descriptor size, 0 if NA + * @rw: either READ or WRITE + * + * Those type of requests uses UTP Transfer Request Descriptor - utrd. + * Therefore, it "rides" the device management infrastructure: uses its tag and + * tasks work queues. + * + * Since there is only one available tag for device management commands, + * the caller is expected to hold the hba->dev_cmd.lock mutex. + */ +static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, + struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, + u8 *desc_buff, int *buff_len, + int cmd_type, int rw) +{ + struct ufshcd_lrb *lrbp; + int err = 0; + int tag; + struct completion wait; + unsigned long flags; + u32 upiu_flags; + u8 *descp; + + down_read(&hba->clk_scaling_lock); + + wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, &tag)); + + init_completion(&wait); + lrbp = &hba->lrb[tag]; + WARN_ON(lrbp->cmd); + + lrbp->cmd = NULL; + lrbp->sense_bufflen = 0; + lrbp->sense_buffer = NULL; + lrbp->task_tag = tag; + lrbp->lun = 0; + lrbp->command_type = (hba->ufs_version == UFSHCI_VERSION_10 || + hba->ufs_version == UFSHCI_VERSION_11) ? + UTP_CMD_TYPE_DEV_MANAGE : + UTP_CMD_TYPE_UFS_STORAGE; + lrbp->intr_cmd = true; + hba->dev_cmd.type = cmd_type; + + /* update the task tag in the request upiu */ + req_upiu->header.dword_0 |= cpu_to_be32(tag); + + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE); + + /* just copy the upiu request as it is */ + memcpy(lrbp->ucd_req_ptr, req_upiu, GENERAL_UPIU_REQUEST_SIZE); + + if (desc_buff && rw == WRITE) { + descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE; + memcpy(descp, desc_buff, *buff_len); + *buff_len = 0; + } + + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); + + hba->dev_cmd.complete = &wait; + + /* Make sure descriptors are ready before ringing the doorbell */ + wmb(); + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_send_command(hba, tag); + spin_unlock_irqrestore(hba->host->host_lock, flags); + + /* + * ignore the returning value here - ufshcd_check_query_response is + * bound to fail since dev_cmd.query and dev_cmd.type were left empty. + * read the response directly ignoring all errors. + */ + ufshcd_wait_for_dev_cmd(hba, lrbp, QUERY_REQ_TIMEOUT); + + /* just copy the upiu request as it is */ + memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, GENERAL_UPIU_REQUEST_SIZE); + + ufshcd_put_dev_cmd_tag(hba, tag); + wake_up(&hba->dev_cmd.tag_wq); + up_read(&hba->clk_scaling_lock); + return err; +} + +/** + * ufshcd_exec_raw_upiu_cmd - API function for sending raw upiu commands + * @hba: per-adapter instance + * @req_upiu: upiu request + * @rsp_upiu: upiu reply - only 8 DW as we do not support scsi commands + * @msgcode: message code, one of UPIU Transaction Codes Initiator to Target + * @desc_buff: pointer to descriptor buffer, NULL if NA + * @buff_len: descriptor size, 0 if NA + * @rw: either READ or WRITE + * + * Supports UTP Transfer requests (nop and query), and UTP Task + * Management requests. + * It is up to the caller to fill the upiu conent properly, as it will + * be copied without any further input validations. + */ +int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, + struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, + int msgcode, + u8 *desc_buff, int *buff_len, int rw) +{ + int err; + int cmd_type = DEV_CMD_TYPE_QUERY; + u8 resp = 0xF; + + if (desc_buff && rw == READ) { + err = -ENOTSUPP; + goto out; + } + + switch (msgcode) { + case UPIU_TRANSACTION_NOP_OUT: + cmd_type = DEV_CMD_TYPE_NOP; + /* fall through */ + case UPIU_TRANSACTION_QUERY_REQ: + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); + err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu, + desc_buff, buff_len, + cmd_type, rw); + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); + + break; + case UPIU_TRANSACTION_TASK_REQ: + err = ufshcd_issue_tm_cmd(hba, + (struct utp_upiu_task_req *)req_upiu, + (struct utp_upiu_task_req *)rsp_upiu, + 0, 0, 0, &resp); + + break; + default: + err = -EINVAL; + + break; + } + +out: + return err; +} + +/** * ufshcd_eh_device_reset_handler - device reset handler registered to * scsi layer. * @cmd: SCSI command pointer diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 33fdd3f..0e8e50a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -892,6 +892,12 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id, u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba); +int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, + struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, + int msgcode, + u8 *desc_buff, int *buff_len, int rw); + /* Wrapper functions for safely calling variant operations */ static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) { From patchwork Sun Aug 5 11:39:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556129 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6CC681822 for ; Sun, 5 Aug 2018 11:41:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C0F829924 for ; Sun, 5 Aug 2018 11:41:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 505C92996E; Sun, 5 Aug 2018 11:41:45 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 D4C5529969 for ; Sun, 5 Aug 2018 11:41:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726261AbeHENqB (ORCPT ); Sun, 5 Aug 2018 09:46:01 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:64022 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726091AbeHENqB (ORCPT ); Sun, 5 Aug 2018 09:46:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469304; x=1565005304; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=YeFq5rEL2SvyNqQ/bQo+Qb7Up8PS/xgx2jabEvEIvr0=; b=mL5Mfdupkk7GTgTITwdIlPb3WZnG/vQnpcgiV6qD7gK0EB8RR3MwBuI8 98FKSsCFJ1YzEYelcbsVs3ZSC6kfcn2m8t/XJK5kW+O0aoUtuELZhGSQ5 bHU7uYlOXY8vSOP/ICI457hTVYjBVI/6WlLrNXP/Po5CTp0CQPaIW43GJ b1qr2y3JH+8pXXmbeg34hHQ7l5Xfuw2QmTJLuzX4fFeIRoV+3vZF5kP+M j5bmc8fIMQVD44mwvZP2h3iJoUXuf2Pc4PeyBsMlREfULyf9bPgKM5wYn lmP+UlHlY5Cw/WO4SwuFo4S3tO7t2lQYQPtzC/baQL6PQbkyBwtWNJQAF Q==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="87459862" Received: from h199-255-45-14.hgst.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:41:35 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 05 Aug 2018 04:29:53 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:41:32 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 7/8] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request() Date: Sun, 5 Aug 2018 14:39:55 +0300 Message-Id: <1533469196-300-8-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 Do that for the currently supported UPIUs: query, nop out, and task management. We do not support UPIU of type scsi command yet, while we are using the job's request and reply pointers to hold the payload. We will look into it in later patches. We might need to elaborate the raw upiu api for that. We also still not supporting uic commands: For first phase, we plan to use the existing api, and send only uic commands that are already supported. Anyway, all that will come in the next patch. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufs_bsg.c | 118 +++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufs_bsg.h | 1 + 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index 6f1941b..f4986f0 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -19,18 +19,128 @@ struct ufs_bsg { .bsg_request = ufs_bsg_request, }; +static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr, + int *desc_len) +{ + int desc_size = be16_to_cpu(qr->length); + int desc_id = qr->idn; + int ret = 0; + + if (qr->opcode != UPIU_QUERY_OPCODE_WRITE_DESC || desc_size <= 0) + return -EINVAL; + + ret = ufshcd_map_desc_id_to_length(bsg_host->hba, desc_id, desc_len); + + if (ret || !(*desc_len)) + return -EINVAL; + + *desc_len = min_t(int, *desc_len, desc_size); + + return ret; +} + +static int ufs_bsg_verify_query_size(unsigned int request_len, + unsigned int reply_len, + int rw, int desc_len) +{ + int min_req_len = sizeof(struct ufs_bsg_request); + int min_rsp_len = sizeof(struct ufs_bsg_reply); + + if (rw == WRITE) + min_req_len += desc_len; + + if (min_req_len > request_len) + return -EINVAL; + + if (min_rsp_len > reply_len) + return -EINVAL; + + return 0; +} + static int ufs_bsg_request(struct bsg_job *job) { struct ufs_bsg_request *bsg_request = job->request; struct ufs_bsg_reply *bsg_reply = job->reply; - int ret = -ENOTSUPP; + unsigned int request_len = job->request_len; + unsigned int reply_len = job->reply_len; + struct utp_upiu_query *qr; + struct utp_upiu_req *req_upiu = NULL; + struct utp_upiu_req *rsp_upiu = NULL; + int msgcode; + uint8_t *desc_buff = NULL; + int desc_len = 0; + int rw = UFS_BSG_NOP; + int ret; + ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, desc_len); + if (ret) { + dev_err(job->dev, "not enough space assigned\n"); + goto out; + } bsg_reply->reply_payload_rcv_len = 0; - /* Do Nothing for now */ - dev_err(job->dev, "unsupported message_code 0x%x\n", - bsg_request->msgcode); + msgcode = bsg_request->msgcode; + switch (msgcode) { + case UPIU_TRANSACTION_QUERY_REQ: + qr = &bsg_request->tsf.qr; + if (qr->opcode == UPIU_QUERY_OPCODE_READ_DESC) + goto not_supported; + + if (ufs_bsg_get_query_desc_size(qr, &desc_len)) + goto null_desc_buff; + + if (qr->opcode == UPIU_QUERY_OPCODE_WRITE_DESC) { + rw = WRITE; + desc_buff = ((uint8_t *)bsg_request) + + sizeof(struct ufs_bsg_request); + } + +null_desc_buff: + /* fall through */ + case UPIU_TRANSACTION_NOP_OUT: + case UPIU_TRANSACTION_TASK_REQ: + /* Now that we know if its a read or write, verify again */ + if (rw != UFS_BSG_NOP || desc_len) { + ret = ufs_bsg_verify_query_size(request_len, reply_len, + rw, desc_len); + if (ret) { + dev_err(job->dev, + "not enough space assigned\n"); + goto out; + } + } + + req_upiu = (struct utp_upiu_req *)&bsg_request->header; + rsp_upiu = (struct utp_upiu_req *)&bsg_reply->header; + ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba, + req_upiu, rsp_upiu, msgcode, + desc_buff, &desc_len, rw); + + break; + case UPIU_TRANSACTION_UIC_CMD: + /* later */ + case UPIU_TRANSACTION_COMMAND: + case UPIU_TRANSACTION_DATA_OUT: +not_supported: + /* for the time being, we do not support data transfer upiu */ + ret = -ENOTSUPP; + dev_err(job->dev, "unsupported msgcode 0x%x\n", msgcode); + + break; + default: + ret = -EINVAL; + + break; + } + + /* + * As we do not support read descriptor, the returning + * reply_payload_rcv_len is always 0. + */ + bsg_reply->reply_payload_rcv_len = 0; +out: bsg_reply->result = ret; if (ret) job->reply_len = sizeof(uint32_t); diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h index 4a391b2..876de9f 100644 --- a/drivers/scsi/ufs/ufs_bsg.h +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -13,6 +13,7 @@ #include "ufshcd.h" #include "ufs.h" +#define UFS_BSG_NOP (-1) #define UPIU_TRANSACTION_UIC_CMD 0x1F enum { From patchwork Sun Aug 5 11:39:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10556127 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3A7621708 for ; Sun, 5 Aug 2018 11:41:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 29C3A29924 for ; Sun, 5 Aug 2018 11:41:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1E47329970; Sun, 5 Aug 2018 11:41:45 +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=-7.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 B191E29924 for ; Sun, 5 Aug 2018 11:41:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726251AbeHENqB (ORCPT ); Sun, 5 Aug 2018 09:46:01 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:20495 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726191AbeHENqB (ORCPT ); Sun, 5 Aug 2018 09:46:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1533469303; x=1565005303; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=CdElE7RvKLDV82smDwZT5UN6i0W0AWLaxMtoJ6smoKQ=; b=WZnyhy63rYfd6N/REbaS7tY9MTHmDv0Il0Ha88UsEx4L3Fut3V0mq+mj 1OM/VLsi8bdWlnQvXs7NJ9/O1hKEwe4ZC5gvRZHSuqi/fXxDfBqq9hl3h yF1atwJZapdxfN33Q+s0lcp5KPVQe/R/gJ+CARV9r9XQkqDH+jgMGpIpW SG5WFU52FJlGbWebjT8YUNBnwVuXrxdXUYHJ5sbi+tAgJUgn49nT/GbK5 vCzIqwE1P0eoJGA6p9Uq8LCvookbZojFrlWrerOSIG6wQCzesPKTllEQ6 S0cj6l/LSl/NO2+v83zSLdK9gDa40dg88RpyGMDGAtCgSZTzBBSE3+0YA Q==; X-IronPort-AV: E=Sophos;i="5.51,447,1526313600"; d="scan'208";a="190442302" Received: from h199-255-45-15.hgst.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 05 Aug 2018 19:41:43 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 05 Aug 2018 04:29:27 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 05 Aug 2018 04:41:40 -0700 From: Avri Altman To: Christoph Hellwig , Johannes Thumshirn , Hannes Reinecke , Bart Van Assche , "James E.J. Bottomley" , "Martin K. Petersen" , linux-scsi@vger.kernel.org Cc: Stanislav Nijnikov , Avi Shchislowski , Alex Lemberg , Subhash Jadavani , Vinayak Holikatti , Avri Altman Subject: [PATCH v2 8/8] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request() Date: Sun, 5 Aug 2018 14:39:56 +0300 Message-Id: <1533469196-300-9-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533469196-300-1-git-send-email-avri.altman@wdc.com> References: <1533469196-300-1-git-send-email-avri.altman@wdc.com> 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 Add support to those uic commands, that are currently supported by ufshcd api: the variants of dme_{peer}_{set_get}. At this point better not to add any new api, as careless uic command may turn the device into a brick. Signed-off-by: Avri Altman --- drivers/scsi/ufs/ufs_bsg.c | 56 +++++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/ufs/ufs_bsg.h | 2 ++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index f4986f0..b2e48ad 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -58,6 +58,55 @@ static int ufs_bsg_verify_query_size(unsigned int request_len, return 0; } +static int ufs_bsg_exec_uic_cmd(struct uic_command *uc) +{ + u32 attr_sel = uc->argument1; + u8 attr_set = (uc->argument2 >> 16) & 0xff; + u32 mib_val = uc->argument3; + int cmd = uc->command; + int ret = 0; + + switch (cmd) { + case UIC_CMD_DME_GET: + ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel, + &mib_val, DME_LOCAL); + break; + case UIC_CMD_DME_SET: + ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set, + mib_val, DME_LOCAL); + break; + case UIC_CMD_DME_PEER_GET: + ret = ufshcd_dme_get_attr(bsg_host->hba, attr_sel, + &mib_val, DME_PEER); + break; + case UIC_CMD_DME_PEER_SET: + ret = ufshcd_dme_set_attr(bsg_host->hba, attr_sel, attr_set, + mib_val, DME_PEER); + break; + case UIC_CMD_DME_POWERON: + case UIC_CMD_DME_POWEROFF: + case UIC_CMD_DME_ENABLE: + case UIC_CMD_DME_RESET: + case UIC_CMD_DME_END_PT_RST: + case UIC_CMD_DME_LINK_STARTUP: + case UIC_CMD_DME_HIBER_ENTER: + case UIC_CMD_DME_HIBER_EXIT: + case UIC_CMD_DME_TEST_MODE: + ret = -ENOTSUPP; + pr_err("%s unsupported command 0x%x\n", __func__, cmd); + break; + default: + ret = -EINVAL; + } + + if (ret) + pr_err("%s error in command 0x%x\n", __func__, cmd); + + uc->argument3 = mib_val; + + return ret; +} + static int ufs_bsg_request(struct bsg_job *job) { struct ufs_bsg_request *bsg_request = job->request; @@ -65,6 +114,7 @@ static int ufs_bsg_request(struct bsg_job *job) unsigned int request_len = job->request_len; unsigned int reply_len = job->reply_len; struct utp_upiu_query *qr; + struct uic_command uc = {}; struct utp_upiu_req *req_upiu = NULL; struct utp_upiu_req *rsp_upiu = NULL; int msgcode; @@ -119,7 +169,11 @@ static int ufs_bsg_request(struct bsg_job *job) break; case UPIU_TRANSACTION_UIC_CMD: - /* later */ + memcpy(&uc, &bsg_request->tsf.uc, UIC_CMD_SIZE); + ret = ufs_bsg_exec_uic_cmd(&uc); + memcpy(&bsg_reply->tsf.uc, &uc, UIC_CMD_SIZE); + + break; case UPIU_TRANSACTION_COMMAND: case UPIU_TRANSACTION_DATA_OUT: not_supported: diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h index 876de9f..b9c8dc5 100644 --- a/drivers/scsi/ufs/ufs_bsg.h +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -15,6 +15,8 @@ #define UFS_BSG_NOP (-1) #define UPIU_TRANSACTION_UIC_CMD 0x1F +/* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */ +#define UIC_CMD_SIZE (sizeof(u32) * 4) enum { REQ_UPIU_SIZE_DWORDS = 8,