From patchwork Wed Aug 1 08:04:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551815 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 35CA8157D for ; Wed, 1 Aug 2018 08:06:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25AB52AC3D for ; Wed, 1 Aug 2018 08:06:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 183C72ADEA; Wed, 1 Aug 2018 08:06: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 279A02AC3D for ; Wed, 1 Aug 2018 08:06:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387494AbeHAJuj (ORCPT ); Wed, 1 Aug 2018 05:50:39 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:24004 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733173AbeHAJui (ORCPT ); Wed, 1 Aug 2018 05:50:38 -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=1533110771; x=1564646771; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Q+qj+Ll1s8heN4QLieALYFAkriJgMcH2UPKmg0a1Y9c=; b=o+aP7nDr5e9q9L6VJr2BotMsO9lqb6ijbTBSXdW91aoc5pC89dbCNnzC ntdBfEkSDrx0MuedcW5EWLSLFgCi+SLCGaVzMv8sHXzMteIqLcsx+UlN2 6rA3ia25NYNFwdvNzpoCUcYwQc+59YiCB4BoANFLLIX2Ka8pycB+IkXBT n9PLeMN2tNpN1fsQmYGbQBAZ+MnxkcmrGt8hykE/C367NhgtA/INFVJUS KSVQ584JUJBzxjdmtyENoBoH/8GpHJqFY5Q7T5fQQGeZV2alVe28W5J4u cV/goJGQPa4xZjYvRolMcJXqdgt03E7QGccULeroF5sjtdcainWUeHAnj g==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="189560853" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 01 Aug 2018 16:06:10 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 01 Aug 2018 00:54:36 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:06: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: [PATCH 1/6] scsi: Add ufs transport class Date: Wed, 1 Aug 2018 11:04:27 +0300 Message-Id: <1533110672-12785-2-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 | 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 Wed Aug 1 08:04:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551817 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 5EF3A157D for ; Wed, 1 Aug 2018 08:06:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50D5E2AC3D for ; Wed, 1 Aug 2018 08:06:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 43A0D2ADEA; Wed, 1 Aug 2018 08:06:31 +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 885E42AC3D for ; Wed, 1 Aug 2018 08:06:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387509AbeHAJu5 (ORCPT ); Wed, 1 Aug 2018 05:50:57 -0400 Received: from esa4.hgst.iphmx.com ([216.71.154.42]:37492 "EHLO esa4.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733173AbeHAJu5 (ORCPT ); Wed, 1 Aug 2018 05:50:57 -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=1533110791; x=1564646791; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GhfA0xbpJm3eJ+VE3vsJLVvALcEJmc0jvnv5jf67KJ4=; b=Pfx7GbWsxEXabSuO4bqrp/hVTXrDKM8rSiUrmSwMdi23AbgQzbgk33us t4jbqiqM336QiDDMu9EdXrTfcscnSBbzGz7Y8rOQelu8KPJa1UWCxBQCE t3M1dwj8w2gmsyNt5olknpo9A8WWs17JFwMT6340slYOyWlsUXRx4Mur0 mmyzBz1RnIEURuCejBzIj+K9nYyP5RxFpLf9LFKlRuZQYbnE3mWFLoqp6 VTiVHMoeva0VIlL4PaScKnGoQFw7iHqPrtCTn/i2FbcRGC02LnVfwZaC1 DcnxFBRAYgCkeuTwUzBc9qgWKR/pd1P6gbnWkHB/0CgKbXjJwdnH9eaAQ Q==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="85780136" 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; 01 Aug 2018 16:06:30 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 01 Aug 2018 00:54:19 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:06:27 -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 2/6] scsi: ufs: Add ufs-bsg module Date: Wed, 1 Aug 2018 11:04:28 +0300 Message-Id: <1533110672-12785-3-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 | 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 Wed Aug 1 08:04:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551819 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 1E7E4174A for ; Wed, 1 Aug 2018 08:06:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0FE302AC3D for ; Wed, 1 Aug 2018 08:06:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 03CCE2ADEA; Wed, 1 Aug 2018 08:06:42 +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 E75142AC3D for ; Wed, 1 Aug 2018 08:06:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387541AbeHAJvI (ORCPT ); Wed, 1 Aug 2018 05:51:08 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:48839 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733173AbeHAJvH (ORCPT ); Wed, 1 Aug 2018 05:51:07 -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=1533110800; x=1564646800; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=89cYVZS4qL6sS2V0Wnn5npADmWtPx5MvXwYP86Nk6I8=; b=d+AebaiMRkxwinYvzsk9ovl+FXBjutOrgupqTyx5gKOegGCaZihDWAfG 11cs6pjNRA5jx08JdD9nDQFBILPzEWc7cly5AFGzwK+13qpCYUnNbql07 hZEMwpm6PzcDTEFjfgZJMIhO7fwQQ7rqwUy4ucagRDtxR8GMHasF0QF/I clmDLpzfDVizKHWvnWTISbXaKKxk3bbukNVBg773Y1+R/gWr6nMRArkR2 Hc/YcA09cDQwkRWF2Ph8UfbPUMjP1fUS46zY4oU5OGe+yQEWI3GTxsFSd 23UI7Q+uMSnXEs30U8h4fulZHX50O2Ee2XJeg+WgRKljVBep2Y0h0hh+m Q==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="189560969" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 01 Aug 2018 16:06:39 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 01 Aug 2018 00:55:05 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:06: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 3/6] scsi: ufs: Instantiate a ufs transport if its available Date: Wed, 1 Aug 2018 11:04:29 +0300 Message-Id: <1533110672-12785-4-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 Wed Aug 1 08:04:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551821 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 227FD174A for ; Wed, 1 Aug 2018 08:06:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 147022AC3D for ; Wed, 1 Aug 2018 08:06:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 05FE22ADEA; Wed, 1 Aug 2018 08:06:55 +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 4C6C12AC3D for ; Wed, 1 Aug 2018 08:06:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387544AbeHAJvV (ORCPT ); Wed, 1 Aug 2018 05:51:21 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:38804 "EHLO esa5.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733173AbeHAJvV (ORCPT ); Wed, 1 Aug 2018 05:51:21 -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=1533110814; x=1564646814; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=mu/KClEC2mhYz9r7rIW5BzU9ZAnaCMmM5ocwKsb66Ns=; b=K66kFVdYjt4qJTqqfE8TxevXuYDq1yoGXNNbguJXCS0eyMznq2kSsyKl 0P1DmFwuT2nhu/DMH1ZYspHIM34evb5STi5xLYAo07x9YucOqN3BpArgs 5Mb2bZMNDd4jOQlQSXeStVDsgucDTIhD/LiPLX2bhjL5Tq85IjJxPJhin 7ae5QXIHJKYE8jrSFdPrWF/VQH9xm/RXbgSzZUXjjKDZfxIAEnzLAZQXM IZugk5HKeiaJ/dlwMKWfZQOQxoNz2KrfXbvPwvmDU0WsVRih2/hVHxbUQ ybRbRy0qLIV860YJqgwf9rmNOi+F34nRjB4/yOnzSx6p642Z0sOtdD6l7 g==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="86616345" 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; 01 Aug 2018 16:06:53 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 01 Aug 2018 00:55:18 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:06:50 -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 4/6] scsi: ufs: Add API to execute raw upiu commands Date: Wed, 1 Aug 2018 11:04:30 +0300 Message-Id: <1533110672-12785-5-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 | 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 Wed Aug 1 08:04:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551823 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 1C54D157D for ; Wed, 1 Aug 2018 08:07:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0E2522AC3D for ; Wed, 1 Aug 2018 08:07:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01A202ADEA; Wed, 1 Aug 2018 08:07:07 +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 7622F2AC3D for ; Wed, 1 Aug 2018 08:07:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387695AbeHAJvd (ORCPT ); Wed, 1 Aug 2018 05:51:33 -0400 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:27468 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733173AbeHAJvd (ORCPT ); Wed, 1 Aug 2018 05:51:33 -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=1533110826; x=1564646826; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=ZrCAGyLsJa5ghhNMPPCMlYgQQbG4WlWT+IZ0MFHYvII=; b=ieA/lA+WdX0zM/VzXnBn9zR0oYeJDJcCV/yqljR4Ws5Vjeb1luEMTzc7 JKaG+4h6aSoLLF+t2GRUFM1Gekh7MuTvlXRrJk4Yhoy5Mx9+elnfbp5D3 hk/q2CqCisRHarz5jpTQaPf1nDU76qOQy+zKnEzuRYGGo3tI0dB0viR1p uQZ1YA86MI7bipU2zENhyhGvUbBQN5AuFho6gzRyuntwJvKYI2tYpwP+0 6W3EUxvysxmigJIIvt6Y+gZY15EzpdB/45h1FCJj9zJzTep7XpdqYf31q erBD3ACs69lDkt+K+zqe1VGNUf4ySz/k4VDzA/o42dIWXpZSMp2etIk41 g==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="89335955" 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; 01 Aug 2018 16:07:05 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep02.wdc.com with ESMTP; 01 Aug 2018 00:54:55 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:07:02 -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 5/6] scsi: ufs-bsg: Add support for raw upiu in ufs_bsg_request() Date: Wed, 1 Aug 2018 11:04:31 +0300 Message-Id: <1533110672-12785-6-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 | 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 Wed Aug 1 08:04:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avri Altman X-Patchwork-Id: 10551825 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 6DD72157D for ; Wed, 1 Aug 2018 08:07:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 60EC52AC3D for ; Wed, 1 Aug 2018 08:07:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5512E2ADEA; Wed, 1 Aug 2018 08:07:26 +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 E5F7D2AC3D for ; Wed, 1 Aug 2018 08:07:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387706AbeHAJvx (ORCPT ); Wed, 1 Aug 2018 05:51:53 -0400 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:4343 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387697AbeHAJvw (ORCPT ); Wed, 1 Aug 2018 05:51:52 -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=1533110845; x=1564646845; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=QdahtqsDaHOqHwNstEbtJ5vDM8QggQ+fOq6q0wCTV0g=; b=a7nOlCFuN2ow3qKbcmjdHYDAHwpdlKyK10fPb4UkG3QweOgKx8lZrmMa BUNHAKq44Y50p7hkR+HnIcq0h/fcfvB7JBjjfQv10iWWh9KAn0PiYKG5h rJBsAwkxy8Eod3LWl8O9CWGn+2pSJzb5O7XEHBSnaalaqWNb3KNNb3cRN rqxzSmbTOXzeDMd5b9KXm8OG/+aKDtj1I7NaOoWZcqtXSzFaeZthVGELf kG8j4YMj3+wk8nxJovjBtBP998k/UEFvy4FSDNpTczSxG0pjAVryEzKPD zFmuk2xUyDtUVZgbI7Ffo04dFzJpWUeQ3fFxhZK4RpQvsXvvjaQB9znNT Q==; X-IronPort-AV: E=Sophos;i="5.51,431,1526313600"; d="scan'208";a="189561065" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 01 Aug 2018 16:07:14 +0800 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP; 01 Aug 2018 00:55:40 -0700 Received: from kfae422988.sdcorp.global.sandisk.com ([10.0.231.37]) by uls-op-cesaip02.wdc.com with ESMTP; 01 Aug 2018 01:07: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 6/6] scsi: ufs-bsg: Add support for uic commands in ufs_bsg_request() Date: Wed, 1 Aug 2018 11:04:32 +0300 Message-Id: <1533110672-12785-7-git-send-email-avri.altman@wdc.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1533110672-12785-1-git-send-email-avri.altman@wdc.com> References: <1533110672-12785-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 | 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,