From patchwork Sun Jul 29 13:33:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548251 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 7E0DE139A for ; Sun, 29 Jul 2018 13:34:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6C2E72A4F9 for ; Sun, 29 Jul 2018 13:34:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 603612A4FD; Sun, 29 Jul 2018 13:34:59 +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 68DC42A4F9 for ; Sun, 29 Jul 2018 13:34:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726751AbeG2PF0 (ORCPT ); Sun, 29 Jul 2018 11:05:26 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:25577 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726461AbeG2PF0 (ORCPT ); Sun, 29 Jul 2018 11:05:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871297; x=1564407297; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Mi5uq22bK8X8H25hOLrxNOX3B79/gAKRFMEjdk9AJk8=; b=QyScs8nMWZNY+DOM4bU62nX45TscCZAtLrJxiKvbZRWMfVdVYthU3QMt 286s0MYBSbUaCmhcSapHu9CEfx/nsICbcRUC8urO5wgW7IYkr5Ksf4Voy XSqfA3J/apSmTInZ5gtl4y0eFt6LBtkMs8VFSRTnSYW0+3++xrAbxuo0F 2hLxjOobtgi/ZE7ypjSBuxHe6CLdADa1I71P+LG6jIcHq1GlLT0fn1Jjg fr5ZzeZCgRQtqXXBwfIMpeZU7kTs4HTx5khtLYJSYZN4wg/zS9/B/SJTb SW+XLcpRTFYHXNjE8+3VonrVyvHtUhTuYae79y2sDogWoCr6YIPJXcJ+R Q==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="85332496" 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; 29 Jul 2018 21:34:57 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 29 Jul 2018 06:23:27 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:34:55 -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: [RFC 1/6] scsi: Add ufs transport class Date: Sun, 29 Jul 2018 16:33:21 +0300 Message-Id: <1532871206-6311-2-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 | 337 ++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_ufs.h | 40 +++++ 4 files changed, 391 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..62aec49 --- /dev/null +++ b/drivers/scsi/scsi_transport_ufs.c @@ -0,0 +1,337 @@ +// 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 +#include +#include +#include + + +#define UFS_HOST_ATTRS 0 +#define UFS_PORT_ATTRS 0 + +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; +}; +#define to_ufs_internal(tmpl) container_of(tmpl, struct ufs_internal, t) + +struct ufs_host_attrs { + atomic_t next_port_id; +}; +#define to_ufs_host_attrs(x) ((struct ufs_host_attrs *)(x)->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, NULL); + 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->next_port_id, 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); + + 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 = atomic_inc_return(&ufs_host->next_port_id); + + 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..483bce4 --- /dev/null +++ b/include/scsi/scsi_transport_ufs.h @@ -0,0 +1,40 @@ +/* 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 + + +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; +}; +#define dev_to_ufs_port(d) \ + 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 Jul 29 13:33:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548253 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 596A1A753 for ; Sun, 29 Jul 2018 13:35:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48CAD2A4F9 for ; Sun, 29 Jul 2018 13:35:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3C9972A4FD; Sun, 29 Jul 2018 13:35:13 +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 5970D2A4F9 for ; Sun, 29 Jul 2018 13:35:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726751AbeG2PFk (ORCPT ); Sun, 29 Jul 2018 11:05:40 -0400 Received: from esa6.hgst.iphmx.com ([216.71.154.45]:8942 "EHLO esa6.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726461AbeG2PFk (ORCPT ); Sun, 29 Jul 2018 11:05:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871312; x=1564407312; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Z7lXHUnbqYa8XVdDTs4bx78LrY+s0p3Gqyqb7MhBnv0=; b=oHko8WXnzRYC8MtO2qAM+ZnaZ8C0pA6TBPZUpuC0ZFffSMOjvfK6V6Zm KZDtO50DOEN5lDWgBL+0/XHzWPdeW4s+46SJ/I0fCfU45DYIqNcN//J6S PFIIoPsxOAXERNlbIAG2oFb0fgI/McdDYVmrqCqXWcARfA/eI7a0TQ0qd UEZ8/hi4ZK4RVQcKZgtb4llIDHDK5PNkYTjSYCiDXbLZvVojZH7e8U3e0 tqQ3n3BZ+L5qxTvOmqcwsnnp3iAG8jSuIT8ZEY4J9H7fZQNsTxrfGuR8r vIsa9cw2tzkTi7nEbRmLoJNAdMk0BoU59EoE5YOO6UxmAV+alg3ZnNTUk w==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="86762656" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 29 Jul 2018 21:35:12 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 29 Jul 2018 06:23:41 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:35:08 -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: [RFC 2/6] scsi: ufs: Add ufs-bsg module Date: Sun, 29 Jul 2018 16:33:22 +0300 Message-Id: <1532871206-6311-3-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 | 74 +++++++++++++++++++++++ include/uapi/scsi/scsi_bsg_ufs.h | 56 +++++++++++++++++ 4 files changed, 258 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..71826ba --- /dev/null +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SSCSI 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..de5511f --- /dev/null +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -0,0 +1,74 @@ +/* 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 dwards of uic command */ + struct utp_upiu_query uc; + } tsf; + uint8_t data[0]; +} __packed; + + +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 recevied ? */ + 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; + uint8_t data[0]; +}; + +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 Jul 29 13:33:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548255 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 D1C8FA753 for ; Sun, 29 Jul 2018 13:35:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C15E72A4F9 for ; Sun, 29 Jul 2018 13:35:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B47172A4FD; Sun, 29 Jul 2018 13:35:21 +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 476FB2A4F9 for ; Sun, 29 Jul 2018 13:35:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726802AbeG2PFt (ORCPT ); Sun, 29 Jul 2018 11:05:49 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:46967 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726461AbeG2PFt (ORCPT ); Sun, 29 Jul 2018 11:05:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871320; x=1564407320; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=HlBZSg1Ho1g642lfUKwy6VA0T1WUVCxgEMNyHE6kVAw=; b=ZJZqliNfX3La0YWS85sCLRsRm+2AZehiY23ymMxnPL2kdMS0LHyiEvAH E9UAd9GKsq4/7KpPVtaLOH+vzgEQX48lU2dDrt/58eXn8p/KQaJoNroKP cdnDWirnYNRXYoNRlpKGlbuQn4g68Uefyc28+Tz0jXV1G4P4XK3KzT2xi 58soVo3FgiAoIgvJ47Sq0l5UBxsjBBPC8sVrpXSTjgZ8RGTJpkCGY8x7u EK86HTG8Y1ZUCirAYE6W9+88jToI5/UtXFTiS8jAJ4yF/zWnzQCZDw+PU mWN+hyTn5pP1O8dBcHnYNxYTxPwDdxgD/HnxEUOQZgrLY4ccJOvgH16Be Q==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="189069448" 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; 29 Jul 2018 21:35:19 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 29 Jul 2018 06:23:17 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:35:17 -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: [RFC 3/6] scsi: ufs: Instantiate a ufs transport if its available Date: Sun, 29 Jul 2018 16:33:23 +0300 Message-Id: <1532871206-6311-4-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 Jul 29 13:33:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548257 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 7275C139A for ; Sun, 29 Jul 2018 13:35:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 622672A4F9 for ; Sun, 29 Jul 2018 13:35:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55BDE2A4FD; Sun, 29 Jul 2018 13:35:38 +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 8CE182A4F9 for ; Sun, 29 Jul 2018 13:35:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726802AbeG2PGG (ORCPT ); Sun, 29 Jul 2018 11:06:06 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:3996 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726461AbeG2PGG (ORCPT ); Sun, 29 Jul 2018 11:06:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871337; x=1564407337; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=s7+3XzeFjWYCBO+p9vTc/9dEmBcf892pEaDLTyIpsEw=; b=Kvt+a/H3on3Gw59qOEXDl0HO6cBmrCHJa/B1kIjfZyT5nhKcAjm3ELIo 7SO4PdbRij4sVpJPLEZnEr0aEQmfLIZH25GAbsSPGhk7nNCuoQjHUWQjL mEFKbcv3XukLHjmHAdnltwNMLNNQYuO/da95WMyon2ALzPbJZhzJVrSJa D1EPs7EDieV3Tc+Ylj0P+QOrm1egtlYXYnH3v8ZbFcWwTKBc26gpUW/IC evlcuJX6Z+anVDHjWkj3DlY9Hv980YyHCGTglR1GhNvB63RiLzRWqfJro rsXWCgzx2ToiETAkEJusHJM5+We15hDUIBsZxfrEFv/JzZ16KlOyvXXfQ A==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="88809334" 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; 29 Jul 2018 21:35:28 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 29 Jul 2018 06:23:24 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:35:24 -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: [RFC 4/6] scsi: ufs: Add API to execute raw upiu commands Date: Sun, 29 Jul 2018 16:33:24 +0300 Message-Id: <1532871206-6311-5-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 | 225 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 4 + 2 files changed, 229 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c2ae406..5abf697 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; @@ -3106,6 +3108,229 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, EXPORT_SYMBOL(ufshcd_map_desc_id_to_length); /** + * ufshcd_issue_tm_upiu_cmd - API for sending "utmrd" requests + * @hba - UFS hba + * @req_upiu - bsg request + * @rsp_upiu - bsg reply + * + * Those requests uses UTP Task Management Request Descriptor - utmrd. + * Therefore, it "rides" the task management infrastructure: uses its tag and + * tasks work queues. + */ +static int ufshcd_issue_tm_upiu_cmd(struct ufs_hba *hba, + __be32 *req_upiu, + __be32 *rsp_upiu) +{ + struct utp_task_req_desc *task_req_descp; + struct Scsi_Host *host = hba->host; + unsigned long flags; + int free_slot; + u8 tm_response = 0xF; + int err; + int task_tag; + + wait_event(hba->tm_tag_wq, ufshcd_get_tm_free_slot(hba, &free_slot)); + ufshcd_hold(hba, false); + + spin_lock_irqsave(host->host_lock, flags); + + task_req_descp = hba->utmrdl_base_addr; + task_req_descp += free_slot; + + 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_tag = hba->nutrs + free_slot; + + req_upiu[0] |= cpu_to_be32(task_tag); + + /* just copy the upiu request as it is */ + memcpy(task_req_descp->task_req_upiu, req_upiu, + GENERAL_UPIU_REQUEST_SIZE); + + /* send command to the controller */ + __set_bit(free_slot, &hba->outstanding_tasks); + + /* Make sure descriptors are ready before ringing the task doorbell */ + wmb(); + + ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL); + /* Make sure that doorbell is committed immediately */ + wmb(); + + spin_unlock_irqrestore(host->host_lock, flags); + + /* wait until the task management command is completed */ + err = wait_event_timeout(hba->tm_wq, + test_bit(free_slot, &hba->tm_condition), + msecs_to_jiffies(TM_CMD_TIMEOUT)); + if (!err) { + dev_err(hba->dev, "%s: bsg task management cmd timed-out\n", + __func__); + if (ufshcd_clear_tm_cmd(hba, free_slot)) + dev_WARN(hba->dev, + "%s: unable clear tm cmd (slot %d) timeout\n", + __func__, free_slot); + err = -ETIMEDOUT; + } else { + err = ufshcd_task_req_compl(hba, free_slot, &tm_response); + } + + /* just copy the upiu response as it is */ + memcpy(rsp_upiu, task_req_descp->task_rsp_upiu, + GENERAL_UPIU_REQUEST_SIZE); + + clear_bit(free_slot, &hba->tm_condition); + ufshcd_put_tm_slot(hba, free_slot); + wake_up(&hba->tm_tag_wq); + + ufshcd_release(hba); + return err; +} + +/** + * ufshcd_issue_devman_upiu_cmd - API for sending "utrd" type requests + * @hba: per-adapter instance + * @req_upiu: upiu request - 8 dwards + * @rsp_upiu: upiu reply - 8 dwards + * @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. + */ +static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, + __be32 *req_upiu, __be32 *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_20) ? + UTP_CMD_TYPE_UFS_STORAGE : + UTP_CMD_TYPE_DEV_MANAGE; + lrbp->intr_cmd = true; + hba->dev_cmd.type = cmd_type; + + /* update the task tag in the request upiu */ + req_upiu[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 - 8 dwards + * @rsp_upiu: upiu reply - 8 dwards + * @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, + __be32 *req_upiu, __be32 *rsp_upiu, + int msgcode, + u8 *desc_buff, int *buff_len, int rw) +{ + int err; + int cmd_type = DEV_CMD_TYPE_QUERY; + + 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_upiu_cmd(hba, req_upiu, rsp_upiu); + + break; + default: + err = -EINVAL; + + break; + } + +out: + return err; +} + +/** * ufshcd_read_desc_param - read the specified descriptor parameter * @hba: Pointer to adapter instance * @desc_id: descriptor idn value diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 33fdd3f..1895834 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -892,6 +892,10 @@ 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, + __be32 *req_upiu, __be32 *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 Jul 29 13:33:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548261 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 D1584A754 for ; Sun, 29 Jul 2018 13:35:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C0E182A4F9 for ; Sun, 29 Jul 2018 13:35:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B55872A4FC; Sun, 29 Jul 2018 13:35:40 +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 46AD32A4FF for ; Sun, 29 Jul 2018 13:35:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726914AbeG2PGI (ORCPT ); Sun, 29 Jul 2018 11:06:08 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:3996 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726461AbeG2PGI (ORCPT ); Sun, 29 Jul 2018 11:06:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871340; x=1564407340; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=nB7cImn/NJu797a6AYylBJ2gHVmRcZ1P4giJa2YMzL4=; b=dsuDfvV9mVGq6CFD2LHFdwdOBGzxj0lDIgxRAJ3BcHNanK2G1nhB1NPt t4wTAIQcgxNa0CMoHPEE6qRw0uSgcOyzLpcLumLKQZ0SL3WX03YAT1ljA qd/p6HHnSeiFbUfOBu0b4eXejFmlZyOI1Rg/wUNhUInoTOdT+U2uxRTra IkCygbSqUq5ktrpMkOu2LcdPii7TSUOwNX0l5gVPYWK8wL9P4e43ShYnd 5A1WmZF8uMgzH9T9QPTjXLArHm6EHL2wh6gGlF1q3CuT6S/nKO7lkDmqq GnE/nF3qCs19FJRDQBJgtjE5My7+wx04krqAvc9xgX7dn0Z7F5YBSwKUg A==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="88809354" 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; 29 Jul 2018 21:35:32 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 29 Jul 2018 06:23:29 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:35:29 -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: [RFC 5/6] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request() Date: Sun, 29 Jul 2018 16:33:25 +0300 Message-Id: <1532871206-6311-6-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 | 119 +++++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufs_bsg.h | 1 + 2 files changed, 116 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index 71826ba..d077e42 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -19,18 +19,129 @@ struct ufs_bsg { .bsg_request = ufs_bsg_request, }; +static int ufs_bsg_get_query_desc_size(struct utp_upiu_query *qr, + int *buff_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, buff_len); + + if (ret || !buff_len) + return -EINVAL; + + *buff_len = min_t(int, *buff_len, desc_size); + + return ret; +} + +static int ufs_bsg_verify_query_size(unsigned int request_len, + unsigned int reply_len, + int rw, int buff_len) +{ + int min_req_len = sizeof(struct ufs_bsg_request); + int min_rsp_len = sizeof(struct ufs_bsg_reply); + + if (rw == UFS_BSG_NOP) + goto null_buff; + + if (rw == WRITE) + min_req_len += buff_len; + +null_buff: + 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; + __be32 *req_upiu = NULL; + __be32 *rsp_upiu = NULL; + int msgcode; + uint8_t *desc_buff = NULL; + int buff_len = 0; + int rw = UFS_BSG_NOP; + int ret; + ret = ufs_bsg_verify_query_size(request_len, reply_len, rw, buff_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, &buff_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 || buff_len) { + ret = ufs_bsg_verify_query_size(request_len, reply_len, + rw, buff_len); + if (ret) { + dev_err(job->dev, + "not enough space assigned\n"); + goto out; + } + } + + req_upiu = (__be32 *)&bsg_request->header; + rsp_upiu = (__be32 *)&bsg_reply->header; + ret = ufshcd_exec_raw_upiu_cmd(bsg_host->hba, + req_upiu, rsp_upiu, msgcode, + desc_buff, &buff_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; + } + + bsg_reply->reply_payload_rcv_len = buff_len; +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 de5511f..0fd2859 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 Jul 29 13:33:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10548259 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 4ACC8139A for ; Sun, 29 Jul 2018 13:35:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3B16D2A4F9 for ; Sun, 29 Jul 2018 13:35:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2F9502A4FD; Sun, 29 Jul 2018 13:35:40 +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 C2A2F2A4F9 for ; Sun, 29 Jul 2018 13:35:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726899AbeG2PGI (ORCPT ); Sun, 29 Jul 2018 11:06:08 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:62617 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726826AbeG2PGI (ORCPT ); Sun, 29 Jul 2018 11:06:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=sandisk.com; i=@sandisk.com; q=dns/txt; s=dkim.sandisk.com; t=1532871340; x=1564407340; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=HT1hjg73VI2m7Cib9TrD6PJF9eXNxGsDdm0NUh5SFag=; b=StgfAqtZLdAstgmA1Ny6RsAyZ2A71e017ztlTw0ZuZ1LOJqUAWAeHz22 epFwuiicux52LpAPsY7Vd0cmme4Mj+9JudcZsA4r/gPhNt6oTl5lIKvVT Msl4+/kq2eDWCF/MkWXjuJhN3/N75lRYKmANxfQbXeY1F0UPrK8EhhKxp rwHZvMSibKSWEdQBNQhVnutBRTY7OEGgQv7YcHfjUUr1E+wF2mPV+SVeC ZaNyjobTpDobbVbpdPdRzifwPAUOK03cvS1UrMqtlrJiWqJKKUS2uw9Dg w6XwEToIKuwfjSyYUNt9a+GLZeWrsfIX2Qc0pAVNY/Sde73yUr8+TQM6G A==; X-IronPort-AV: E=Sophos;i="5.51,418,1526313600"; d="scan'208";a="88809357" 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; 29 Jul 2018 21:35:37 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP; 29 Jul 2018 06:23:34 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip01.wdc.com with ESMTP; 29 Jul 2018 06:35:34 -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: [RFC 6/6] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request() Date: Sun, 29 Jul 2018 16:33:26 +0300 Message-Id: <1532871206-6311-7-git-send-email-avri.altman@sandisk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532871206-6311-1-git-send-email-avri.altman@sandisk.com> References: <1532871206-6311-1-git-send-email-avri.altman@sandisk.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 | 1 + 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index d077e42..441d096 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -63,6 +63,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; @@ -70,6 +119,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 = {0}; __be32 *req_upiu = NULL; __be32 *rsp_upiu = NULL; int msgcode; @@ -124,7 +174,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 0fd2859..651ffb3 100644 --- a/drivers/scsi/ufs/ufs_bsg.h +++ b/drivers/scsi/ufs/ufs_bsg.h @@ -15,6 +15,7 @@ #define UFS_BSG_NOP (-1) #define UPIU_TRANSACTION_UIC_CMD 0x1F +#define UIC_CMD_SIZE (sizeof(u32) * 4) enum { REQ_UPIU_SIZE_DWORDS = 8,