From patchwork Mon Nov 7 13:10:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bean Huo X-Patchwork-Id: 16413 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2041320wru; Mon, 7 Nov 2022 05:13:44 -0800 (PST) X-Google-Smtp-Source: AA0mqf6uXe/T/1CwQ8E1F+PJct/Ad9uc9ARO94mAcarXirBygvzJr/LSKsVHcT9kmK6XMORfQlSA X-Received: by 2002:a17:906:18e2:b0:7ae:563c:7bf8 with SMTP id e2-20020a17090618e200b007ae563c7bf8mr9838112ejf.391.1667826823869; Mon, 07 Nov 2022 05:13:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667826823; cv=none; d=google.com; s=arc-20160816; b=NjcnfXRe8CvLj/VhyskaUQqpFw/3J8jeb702J+M2r4/tT2M5jwpELNZIzkMbBQy1Ma 6QMo7kup7BQFmXgApRaaLxrm5JnVAhWdGbK35HBvuE4hy6wCWqdGeGih0zbfXWkoJdC7 rt5U/gxC3Xn47JTZ1QTOUwdDqrhxykZmMr96uXOv0O3W5umFWrWCx1V9PTcPZrsbeB18 Blyx0e9BVgJZtdV2f7d6QoVkVcr/GeN859howviKjCu5gXmpcgtQEFqO/iRv+rTKI4QV EyFFsNN5wJotI6h1iVflVUeB15V3x4AILm3WY6CL+dNCypO0YY14loAyMgKZ4u/5vzr8 8C9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=x0ChwJ2vaiy1SWOkttW7ZHW/S8+rHXWSvSwa65vCkNw=; b=XWPsbNglfELJ5TSTZV3G2t6Y5QyuuGOAp4JwGCdi1MTrqibryoZCt+J+Qwivq82pjJ HfCgnN3FdI4gOXJ8l7TyMQXExuOqn4C4/XcXQhXcgHKQ0HiY1i9fxfdNHwodhLi4YGjt yVMsn3RUMxHXt+s5xnt0WPkFCyoqqUMR9dRy3dgw6pLiZI3kvayIUul5GGh02A9OHydI mspOi+KA6OlGg3fVv4XHQfmtoy1x15I9m6e2xPxefogq0iC0FJ/ya1o0h61T9UZ96Hie fzS26NCq4e+0NknBz08x+6/5uCB+yTQiHhTbJnc7fiF30jeX6fOoHd2sCtoo7O3pkWAC L6/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@iokpp.de header.s=strato-dkim-0002 header.b=dSEri47t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id u9-20020a170906124900b007ae4717bf0fsi7060574eja.158.2022.11.07.05.13.19; Mon, 07 Nov 2022 05:13:43 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@iokpp.de header.s=strato-dkim-0002 header.b=dSEri47t; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232236AbiKGNLL (ORCPT + 99 others); Mon, 7 Nov 2022 08:11:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50562 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232096AbiKGNLD (ORCPT ); Mon, 7 Nov 2022 08:11:03 -0500 Received: from mo4-p02-ob.smtp.rzone.de (mo4-p02-ob.smtp.rzone.de [85.215.255.81]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4BE11C924; Mon, 7 Nov 2022 05:11:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1667826655; s=strato-dkim-0002; d=iokpp.de; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=x0ChwJ2vaiy1SWOkttW7ZHW/S8+rHXWSvSwa65vCkNw=; b=dSEri47t1GEzZxTYXqvVC5tnr7NEBZL0M6SNWlSx2MmfyUSl+va+fNUI7TXCpwMm/9 fjL+8f2ceMZZU30OfpnTOCpd1mgsggupQXaCGBjSG+GWfcJS/Kx5M5BqRNz0HC6YysFG fTAuOoEzQrLk9Q0eW+9kNpdSK6/m9NPeYgPN/cx/U9QbeoDeZPzL1Le2MuQCtWeckAIR 97pwZf3bW+BCJanhZcU6A7o3XaHvLrGXt8ldu4J0Lmr6EIIavGYQM1qek2yYxwBmA9dn 2Vnr+t2NriWeNBOgxxrZwba634ZLFpHGymC/sFtS5jKtjNimwELrNtcJRN7AgjuCAo5w xA+g== Authentication-Results: strato.com; dkim=none X-RZG-AUTH: ":LmkFe0i9dN8c2t4QQyGBB/NDXvjDB6pBSedrgBzPc9DUyubU4DD1QLj68UeUr1+U1RvWtIeMr7Q/U8vM/+oObyVBycbphAC+CkWyag==" X-RZG-CLASS-ID: mo01 Received: from blinux.speedport.ip by smtp.strato.de (RZmta 48.2.1 AUTH) with ESMTPSA id z9cfbfyA7DAsjG9 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Mon, 7 Nov 2022 14:10:54 +0100 (CET) From: Bean Huo To: alim.akhtar@samsung.com, avri.altman@wdc.com, jejb@linux.ibm.com, martin.petersen@oracle.com, stanley.chu@mediatek.com, beanhuo@micron.com, bvanassche@acm.org, tomas.winkler@intel.com, daejun7.park@samsung.com, quic_cang@quicinc.com, quic_nguyenb@quicinc.com, quic_xiaosenh@quicinc.com, quic_richardp@quicinc.com, quic_asutoshd@quicinc.com, hare@suse.de Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH v1 1/2] ufs: core: Advanced RPMB detection Date: Mon, 7 Nov 2022 14:10:37 +0100 Message-Id: <20221107131038.201724-2-beanhuo@iokpp.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221107131038.201724-1-beanhuo@iokpp.de> References: <20221107131038.201724-1-beanhuo@iokpp.de> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_PASS,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748843179974812512?= X-GMAIL-MSGID: =?utf-8?q?1748843179974812512?= From: Bean Huo Check UFS Advanced RPMB LU enablement during ufshcd_lu_init(). Signed-off-by: Bean Huo --- drivers/ufs/core/ufshcd.c | 4 ++++ include/ufs/ufs.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index ee73d7036133..d49e7a0b82ca 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -4940,6 +4940,10 @@ static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev) desc_buf[UNIT_DESC_PARAM_LU_WR_PROTECT] == UFS_LU_POWER_ON_WP) hba->dev_info.is_lu_power_on_wp = true; + if (desc_buf[UNIT_DESC_PARAM_UNIT_INDEX] == UFS_RPMB_UNIT && + desc_buf[UNIT_DESC_PARAM_RPMB_REGION_EN] & 1 << 4) + hba->dev_info.b_advanced_rpmb_en = true; + kfree(desc_buf); set_qdepth: /* diff --git a/include/ufs/ufs.h b/include/ufs/ufs.h index 1bba3fead2ce..2e617ab87750 100644 --- a/include/ufs/ufs.h +++ b/include/ufs/ufs.h @@ -199,6 +199,7 @@ enum unit_desc_param { UNIT_DESC_PARAM_PSA_SENSITIVE = 0x7, UNIT_DESC_PARAM_MEM_TYPE = 0x8, UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9, + UNIT_DESC_PARAM_RPMB_REGION_EN = 0x9, UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB, UNIT_DESC_PARAM_ERASE_BLK_SIZE = 0x13, @@ -601,6 +602,8 @@ struct ufs_dev_info { bool b_rpm_dev_flush_capable; u8 b_presrv_uspc_en; + + bool b_advanced_rpmb_en; }; /* From patchwork Mon Nov 7 13:10:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bean Huo X-Patchwork-Id: 16414 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2041692wru; Mon, 7 Nov 2022 05:14:18 -0800 (PST) X-Google-Smtp-Source: AMsMyM4jI9eAaZ8pSqdpENsQW+I4W2hPSDEqhfPa+L1KXJdDHrKOTy36pzvfg8tHXJPTR01oSTcj X-Received: by 2002:aa7:ce16:0:b0:461:865a:ae44 with SMTP id d22-20020aa7ce16000000b00461865aae44mr49074920edv.280.1667826857913; Mon, 07 Nov 2022 05:14:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667826857; cv=none; d=google.com; s=arc-20160816; b=I6ACjkdFQSZV4Qdao54BDlq+qQmUbXqWOVqxFNOV92A1Z5hupq00agSR+DU2hl/l14 hREsxEN4BbXpCuEsHlqnaZawciEW9tD+nL2ilR3/pQLFTHYbC29Eo2kdLsQjKEypi0A5 PTBrv6YJkpb3lS7QkLVecLGFLORrnoM/zyEHKoBZ+D5jTbOM0MPVQnkoTsnhjhgJ9GRk VHKSOMF5lmLNHdiyTMNQZdslc24iqZx91vItTsOVmRjpOLmj5oJXpd8Fr49JJTnRVru4 YDjEdNFHqQeaqpJGjhqczhF+kMBfLCsmA/rgGaS5j0m1JKwclsh0aGP0rxTQ3c19laof ko3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=q1J6XpIe/9MO4lE/o05tOqolPRNB84M1cOMhaBrvy1I=; b=Cgn8fMdxKHBT/1ElXDorPkSN0LA41ULgoNYis6cQKdL+2NrRreCXNGZTwuZ/GETvEM EiHSMistW1Z+RS/7oKhsqM2ZsCWHDAtRbrYvfbVfdNz9VHRceroGqL3vPdBgJ9fKeRfw XMveX1PGyCFqNNcGFUk0vmo+mD71qxq3MUJieLZpKo3g9ZWeDrb5N8EVTQH6UA5AnSMy z7HVm5N3MLaOV3OO7snnl7OUTYrUK0rLLzUiNKyZfHaTDYw7lhCuXDl5Di0LghHbXgZ5 37c9lQcXS6AMFIXrf1C3Q0qtx96zaPjCFc6FdVk91ii7VFDjGDrX8+OUdmB0juMjLHCC JIaQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@iokpp.de header.s=strato-dkim-0002 header.b=bj9KSEKp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id cx24-20020a05640222b800b004615937b174si8968661edb.480.2022.11.07.05.13.54; Mon, 07 Nov 2022 05:14:17 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@iokpp.de header.s=strato-dkim-0002 header.b=bj9KSEKp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232266AbiKGNLO (ORCPT + 99 others); Mon, 7 Nov 2022 08:11:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50584 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232158AbiKGNLE (ORCPT ); Mon, 7 Nov 2022 08:11:04 -0500 Received: from mo4-p02-ob.smtp.rzone.de (mo4-p02-ob.smtp.rzone.de [85.215.255.84]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B4B9A1C921; Mon, 7 Nov 2022 05:11:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1667826655; s=strato-dkim-0002; d=iokpp.de; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=q1J6XpIe/9MO4lE/o05tOqolPRNB84M1cOMhaBrvy1I=; b=bj9KSEKpcack2YMlTpUcH/AIRIMFG8T2+OG1Vr5k7aj/3u5UNEa/V6xhg2EKHOcKH4 izY8GkEJW+J53jAheDT1QJRtTVMoNU89Z1He0No/+XNK5rfdh/U/KAynm/ER1r3hKy8Y hnud5sotul4hdhHD5KDY2Jk+5cg4OLzn5U33yV9WMN5mSM/wNB9udUZRiKiqqQGSZSak i9l0XcuAL8SXlSbiML68OMj7l7ad5SQ8MX0312YdvPS/vFfU68xgSFCi7SG6Fjgw2hc1 +vZvh0Ppx+OFgfGyLowrAQE4fUlyN+XaCDKQ2XC1jNRJhLMt9DTzBtJS5u5WO1W9fVnR meKw== Authentication-Results: strato.com; dkim=none X-RZG-AUTH: ":LmkFe0i9dN8c2t4QQyGBB/NDXvjDB6pBSedrgBzPc9DUyubU4DD1QLj68UeUr1+U1RvWtIeMr7Q/U8vM/+oObyVBycbphAC+CkWyag==" X-RZG-CLASS-ID: mo02 Received: from blinux.speedport.ip by smtp.strato.de (RZmta 48.2.1 AUTH) with ESMTPSA id z9cfbfyA7DAtjGB (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Mon, 7 Nov 2022 14:10:55 +0100 (CET) From: Bean Huo To: alim.akhtar@samsung.com, avri.altman@wdc.com, jejb@linux.ibm.com, martin.petersen@oracle.com, stanley.chu@mediatek.com, beanhuo@micron.com, bvanassche@acm.org, tomas.winkler@intel.com, daejun7.park@samsung.com, quic_cang@quicinc.com, quic_nguyenb@quicinc.com, quic_xiaosenh@quicinc.com, quic_richardp@quicinc.com, quic_asutoshd@quicinc.com, hare@suse.de Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org, Bean Huo Subject: [RFC PATCH v1 2/2] ufs: core: Add advanced RPMB support in ufs_bsg Date: Mon, 7 Nov 2022 14:10:38 +0100 Message-Id: <20221107131038.201724-3-beanhuo@iokpp.de> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221107131038.201724-1-beanhuo@iokpp.de> References: <20221107131038.201724-1-beanhuo@iokpp.de> MIME-Version: 1.0 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_PASS,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1748843215416107648?= X-GMAIL-MSGID: =?utf-8?q?1748843215416107648?= Add advanced RPMB support in ufs_bsg. For these reasons, we try to implement Advanced RPMB in ufs_bsg: 1. According to the UFS specification, only one RPMB operation can be performed at any time. We can ensure this by using reserved slot and its dev_cmd sync operation protection mechanism. 2. Fort the Advanced RPMB, RPMB metadata is packaged in an EHS (to device) of the UPIU, and the corresponding reply EHS (from the device) should also be returned to the user space. bsg_job->reuqest and bsg_job->reply allow us to pass and return EHS from/back to userspace. Compared to normal/legacy RPMB, the advantage of advanced RPMB are: 1. The data length in the RPBM data read/write command could be > 4KB. For the legacy RPMB, the data length in a single RPMB data transfer is 256 bytes. 2. All of the advanced RPMB operations will be a single command shot. but for the legacy RPBM, take the read write-counter value as an example, you need two commands(first SECURITY PROTOCOL OUT, then the second SECURITY PROTOCOL IN) Signed-off-by: Bean Huo --- drivers/ufs/core/ufs_bsg.c | 115 +++++++++++++--------- drivers/ufs/core/ufshcd.c | 157 ++++++++++++++++++++++++------- include/uapi/scsi/scsi_bsg_ufs.h | 30 +++++- include/ufs/ufshcd.h | 5 + 4 files changed, 226 insertions(+), 81 deletions(-) diff --git a/drivers/ufs/core/ufs_bsg.c b/drivers/ufs/core/ufs_bsg.c index b99e3f3dc4ef..6c6a27ad49d5 100644 --- a/drivers/ufs/core/ufs_bsg.c +++ b/drivers/ufs/core/ufs_bsg.c @@ -8,8 +8,10 @@ #include #include #include -#include "ufs_bsg.h" +#include #include + +#include "ufs_bsg.h" #include "ufshcd-priv.h" static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len, @@ -30,21 +32,6 @@ static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len, return 0; } -static int ufs_bsg_verify_query_size(struct ufs_hba *hba, - unsigned int request_len, - unsigned int reply_len) -{ - int min_req_len = sizeof(struct ufs_bsg_request); - int min_rsp_len = sizeof(struct ufs_bsg_reply); - - if (min_req_len > request_len || min_rsp_len > reply_len) { - dev_err(hba->dev, "not enough space assigned\n"); - return -EINVAL; - } - - return 0; -} - static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job, uint8_t **desc_buff, int *desc_len, enum query_opcode desc_op) @@ -83,23 +70,53 @@ static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job, return 0; } +static int ufshcd_exec_advanced_rpmb_req(struct ufs_hba *hba, struct bsg_job *job, + struct bsg_buffer *bbuf, int msgcode, int len) +{ + struct ufs_rpmb_request *rpmb_request = job->request; + struct ufs_rpmb_reply *rpmb_reply = job->reply; + enum dma_data_direction dir = DMA_NONE; + int mapped_sg_cnt; + int ret; + + if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en) + return -EINVAL; + + if (msgcode == UPIU_TRANSACTION_ARPMB_DATA_WRITE) + dir = DMA_TO_DEVICE; + else if (msgcode == UPIU_TRANSACTION_ARPMB_DATA_READ) + dir = DMA_FROM_DEVICE; + + if (dir != DMA_NONE && bbuf->sg_cnt) { + mapped_sg_cnt = dma_map_sg(hba->host->dma_dev, bbuf->sg_list, bbuf->sg_cnt, dir); + if (unlikely(!mapped_sg_cnt)) + return -ENOMEM; + } + + ret = ufshcd_advanced_rpmb_req_handler(hba, &rpmb_request->bsg_request.upiu_req, + &rpmb_reply->bsg_reply.upiu_rsp, &rpmb_request->ehs_req, + &rpmb_reply->ehs_rsp, mapped_sg_cnt, bbuf->sg_list, + dir, len); + + if (dir != DMA_NONE && bbuf->sg_cnt) + dma_unmap_sg(hba->host->dma_dev, bbuf->sg_list, bbuf->sg_cnt, dir); + + return ret; +} + 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; struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent)); - unsigned int req_len = job->request_len; - unsigned int reply_len = job->reply_len; struct uic_command uc = {}; int msgcode; - uint8_t *desc_buff = NULL; + uint8_t *buff = NULL; int desc_len = 0; enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP; int ret; - - ret = ufs_bsg_verify_query_size(hba, req_len, reply_len); - if (ret) - goto out; + struct bsg_buffer *bbuf = NULL; + bool rpmb = false; bsg_reply->reply_payload_rcv_len = 0; @@ -109,34 +126,52 @@ static int ufs_bsg_request(struct bsg_job *job) switch (msgcode) { case UPIU_TRANSACTION_QUERY_REQ: desc_op = bsg_request->upiu_req.qr.opcode; - ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff, + ret = ufs_bsg_alloc_desc_buffer(hba, job, &buff, &desc_len, desc_op); - if (ret) { - ufshcd_rpm_put_sync(hba); + if (ret) goto out; - } fallthrough; case UPIU_TRANSACTION_NOP_OUT: case UPIU_TRANSACTION_TASK_REQ: ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req, &bsg_reply->upiu_rsp, msgcode, - desc_buff, &desc_len, desc_op); + buff, &desc_len, desc_op); if (ret) - dev_err(hba->dev, - "exe raw upiu: error code %d\n", ret); + dev_err(hba->dev, "exe raw upiu: error code %d\n", ret); + else if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) + bsg_reply->reply_payload_rcv_len = + sg_copy_from_buffer(job->request_payload.sg_list, + job->request_payload.sg_cnt, buff, desc_len); break; case UPIU_TRANSACTION_UIC_CMD: memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE); ret = ufshcd_send_uic_cmd(hba, &uc); if (ret) - dev_err(hba->dev, - "send uic cmd: error code %d\n", ret); + dev_err(hba->dev, "send uic cmd: error code %d\n", ret); memcpy(&bsg_reply->upiu_rsp.uc, &uc, UIC_CMD_SIZE); break; + case UPIU_TRANSACTION_ARPMB_DATA_READ: + case UPIU_TRANSACTION_ARPMB_DATA_WRITE: + if (!job->request_payload.payload_len || job->request_payload.payload_len > 4096) { + ret = -EINVAL; + goto out; + } + bbuf = &job->request_payload; + fallthrough; + case UPIU_TRANSACTION_ARPMB_PROGRAM_KEY: + case UPIU_TRANSACTION_ARPMB_READ_COUNTER: + rpmb = true; + ret = ufshcd_exec_advanced_rpmb_req(hba, job, bbuf, msgcode, + job->request_payload.payload_len); + if (ret) + dev_err(hba->dev, "RPMB OP failed: error code %d\n", ret); + else if (msgcode == UPIU_TRANSACTION_ARPMB_READ_COUNTER) + bsg_reply->reply_payload_rcv_len = job->request_payload.payload_len; + break; default: ret = -ENOTSUPP; dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode); @@ -144,22 +179,12 @@ static int ufs_bsg_request(struct bsg_job *job) break; } +out: ufshcd_rpm_put_sync(hba); + kfree(buff); - if (!desc_buff) - goto out; - - if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) - bsg_reply->reply_payload_rcv_len = - sg_copy_from_buffer(job->request_payload.sg_list, - job->request_payload.sg_cnt, - desc_buff, desc_len); - - kfree(desc_buff); - -out: bsg_reply->result = ret; - job->reply_len = sizeof(struct ufs_bsg_reply); + job->reply_len = !rpmb ? sizeof(struct ufs_bsg_reply) : sizeof(struct ufs_rpmb_reply); /* complete the job here only if no error */ if (ret == 0) bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index d49e7a0b82ca..592ee3809c16 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -56,6 +56,9 @@ /* Query request timeout */ #define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */ +/* Advanced RPMB request timeout */ +#define ADVANCED_RPMB_REQ_TIMEOUT 4500 /* 3 seconds */ + /* Task management command timeout */ #define TM_CMD_TIMEOUT 100 /* msecs */ @@ -2399,40 +2402,32 @@ int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) } /** - * ufshcd_map_sg - Map scatter-gather list to prdt - * @hba: per adapter instance - * @lrbp: pointer to local reference block - * - * Returns 0 in case of success, non-zero value in case of failure + * ufshcd_sgl_to_prdt - SG list to PRTD (Physical Region Description Table, 4DW format) + * @hba: per-adapter instance + * @lrbp: pointer to local reference block + * @sg_entries: The number of sg lists actually used + * @sg_list: Pointer to SG list */ -static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int sg_entries, + struct scatterlist *sg_list) + { struct ufshcd_sg_entry *prd_table; struct scatterlist *sg; - struct scsi_cmnd *cmd; - int sg_segments; int i; - cmd = lrbp->cmd; - sg_segments = scsi_dma_map(cmd); - if (sg_segments < 0) - return sg_segments; - - if (sg_segments) { + if (sg_entries) { if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16((sg_segments * - sizeof(struct ufshcd_sg_entry))); + cpu_to_le16((sg_entries * sizeof(struct ufshcd_sg_entry))); else - lrbp->utr_descriptor_ptr->prd_table_length = - cpu_to_le16(sg_segments); + lrbp->utr_descriptor_ptr->prd_table_length = cpu_to_le16(sg_entries); prd_table = lrbp->ucd_prdt_ptr; - scsi_for_each_sg(cmd, sg, sg_segments, i) { + for_each_sg(sg_list, sg, sg_entries, i) { const unsigned int len = sg_dma_len(sg); - /* * From the UFSHCI spec: "Data Byte Count (DBC): A '0' * based value that indicates the length, in bytes, of @@ -2449,6 +2444,26 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) } else { lrbp->utr_descriptor_ptr->prd_table_length = 0; } +} + +/** + * ufshcd_map_sg - Map scatter-gather list to prdt + * @hba: per adapter instance + * @lrbp: pointer to local reference block + * + * Returns 0 in case of success, non-zero value in case of failure + */ +static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + struct scsi_cmnd *cmd; + int sg_segments; + + cmd = lrbp->cmd; + sg_segments = scsi_dma_map(cmd); + if (sg_segments < 0) + return sg_segments; + + ufshcd_sgl_to_prdt(hba, lrbp, sg_segments, scsi_sglist(cmd)); return 0; } @@ -2496,14 +2511,14 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs) } /** - * ufshcd_prepare_req_desc_hdr() - Fills the requests header - * descriptor according to request - * @lrbp: pointer to local reference block + * ufshcd_prepare_req_desc_hdr - Fills UTP Transfer request descriptor header according to request + * @lrbp: pointer to local reference block * @upiu_flags: flags required in the header - * @cmd_dir: requests data direction + * @cmd_dir: requests data direction + * @ehs_length: Total EHS Length (in 32‐bytes units of all Extra Header Segments) */ -static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, - u8 *upiu_flags, enum dma_data_direction cmd_dir) +static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, u8 *upiu_flags, + enum dma_data_direction cmd_dir, int ehs_length) { struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr; u32 data_direction; @@ -2522,8 +2537,9 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, *upiu_flags = UPIU_CMD_FLAGS_NONE; } - dword_0 = data_direction | (lrbp->command_type - << UPIU_COMMAND_TYPE_OFFSET); + dword_0 = data_direction | (lrbp->command_type << UPIU_COMMAND_TYPE_OFFSET) | + ehs_length << 8; + if (lrbp->intr_cmd) dword_0 |= UTP_REQ_DESC_INT_CMD; @@ -2546,8 +2562,7 @@ static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, } /** - * ufshcd_prepare_utp_scsi_cmd_upiu() - fills the utp_transfer_req_desc, - * for scsi commands + * ufshcd_prepare_utp_scsi_cmd_upiu() - fills the utp_transfer_req_desc for scsi commands * @lrbp: local reference block pointer * @upiu_flags: flags */ @@ -2578,8 +2593,7 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags) } /** - * ufshcd_prepare_utp_query_req_upiu() - fills the utp_transfer_req_desc, - * for query requsts + * ufshcd_prepare_utp_query_req_upiu() - fills the utp_transfer_req_desc for query requsts * @hba: UFS hba * @lrbp: local reference block pointer * @upiu_flags: flags @@ -2650,7 +2664,7 @@ static int ufshcd_compose_devman_upiu(struct ufs_hba *hba, else lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; - ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE); + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0); if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY) ufshcd_prepare_utp_query_req_upiu(hba, lrbp, upiu_flags); else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP) @@ -2679,7 +2693,7 @@ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) if (likely(lrbp->cmd)) { ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, - lrbp->cmd->sc_data_direction); + lrbp->cmd->sc_data_direction, 0); ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags); } else { ret = -EINVAL; @@ -2945,6 +2959,12 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) dev_err(hba->dev, "%s: Reject UPIU not fully implemented\n", __func__); break; + case UPIU_TRANSACTION_RESPONSE: + if (hba->dev_cmd.type != DEV_CMD_TYPE_RPMB) { + err = -EINVAL; + dev_err(hba->dev, "%s: unexpected response %x\n", __func__, resp); + } + break; default: err = -EINVAL; dev_err(hba->dev, "%s: Invalid device management cmd response: %x\n", @@ -6838,7 +6858,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, /* update the task tag in the request upiu */ req_upiu->header.dword_0 |= cpu_to_be32(tag); - ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE); + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0); /* just copy the upiu request as it is */ memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr)); @@ -6961,6 +6981,73 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, return err; } +int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req, + struct ufs_ehs *ehs_rsp, int sg_cnt, struct scatterlist *sg_list, + enum dma_data_direction dir, int len) +{ + DECLARE_COMPLETION_ONSTACK(wait); + const u32 tag = hba->reserved_slot; + struct ufshcd_lrb *lrbp; + int err = 0; + u8 upiu_flags; + + /* Protects use of hba->reserved_slot. */ + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); + down_read(&hba->clk_scaling_lock); + + lrbp = &hba->lrb[tag]; + WARN_ON(lrbp->cmd); + lrbp->cmd = NULL; + lrbp->task_tag = tag; + lrbp->lun = UFS_UPIU_RPMB_WLUN; + + lrbp->intr_cmd = true; + ufshcd_prepare_lrbp_crypto(NULL, lrbp); + hba->dev_cmd.type = DEV_CMD_TYPE_RPMB; + + lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; + + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, len/32); + + /* update the task tag and LUN in the request upiu */ + req_upiu->header.dword_0 |= cpu_to_be32(upiu_flags << 16 | UFS_UPIU_RPMB_WLUN << 8 | tag); + + /* copy the upiu request as it is */ + memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr)); + /* copy ehs */ + memcpy(lrbp->ucd_req_ptr + 1, ehs_req, sizeof(*ehs_req)); + + if (dir != DMA_NONE && sg_list) + ufshcd_sgl_to_prdt(hba, lrbp, sg_cnt, sg_list); + + + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); + + hba->dev_cmd.complete = &wait; + + ufshcd_send_command(hba, tag); + + err = ufshcd_wait_for_dev_cmd(hba, lrbp, ADVANCED_RPMB_REQ_TIMEOUT); + + if (!err) { + /* just copy the upiu response as it is */ + memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu)); + + u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + sizeof(*rsp_upiu); + u16 ehs_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) >> 24; + + if (ehs_len == 2 && ehs_rsp) + memcpy(ehs_rsp, descp, ehs_len * 32); + } + + up_read(&hba->clk_scaling_lock); + mutex_unlock(&hba->dev_cmd.lock); + ufshcd_release(hba); + return err; +} + /** * ufshcd_eh_device_reset_handler() - Reset a single logical unit. * @cmd: SCSI command pointer diff --git a/include/uapi/scsi/scsi_bsg_ufs.h b/include/uapi/scsi/scsi_bsg_ufs.h index d55f2176dfd4..a79adbc89cc0 100644 --- a/include/uapi/scsi/scsi_bsg_ufs.h +++ b/include/uapi/scsi/scsi_bsg_ufs.h @@ -14,7 +14,16 @@ */ #define UFS_CDB_SIZE 16 -#define UPIU_TRANSACTION_UIC_CMD 0x1F + +enum ufs_bsg_msg_code { + UPIU_TRANSACTION_UIC_CMD = 0x1F, + UPIU_TRANSACTION_ARPMB_DATA_WRITE, + UPIU_TRANSACTION_ARPMB_DATA_READ, + UPIU_TRANSACTION_ARPMB_PROGRAM_KEY, + UPIU_TRANSACTION_ARPMB_READ_COUNTER, + +}; + /* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */ #define UIC_CMD_SIZE (sizeof(__u32) * 4) @@ -79,6 +88,14 @@ struct utp_upiu_req { }; }; +struct ufs_ehs { + __u8 blenght; + __u8 lehs_type; + __u16 wehssub_type; + __u8 meta[28]; + __u8 mac_key[32]; +}; + /* request (CDB) structure of the sg_io_v4 */ struct ufs_bsg_request { __u32 msgcode; @@ -102,4 +119,15 @@ struct ufs_bsg_reply { struct utp_upiu_req upiu_rsp; }; + +struct ufs_rpmb_request { + struct ufs_bsg_request bsg_request; + struct ufs_ehs ehs_req; +}; + +struct ufs_rpmb_reply { + struct ufs_bsg_reply bsg_reply; + struct ufs_ehs ehs_rsp; +}; + #endif /* UFS_BSG_H */ diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 96538eb3a6c0..59906cc7d8d3 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -30,6 +30,7 @@ struct ufs_hba; enum dev_cmd_type { DEV_CMD_TYPE_NOP = 0x0, DEV_CMD_TYPE_QUERY = 0x1, + DEV_CMD_TYPE_RPMB = 0x2, }; enum ufs_event_type { @@ -1208,6 +1209,10 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, u8 *desc_buff, int *buff_len, enum query_opcode desc_op); +int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, + struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req, + struct ufs_ehs *ehs_rsp, int sg_cnt, struct scatterlist *sg_list, + enum dma_data_direction dir, int len); int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable); int ufshcd_wb_toggle_buf_flush(struct ufs_hba *hba, bool enable); int ufshcd_suspend_prepare(struct device *dev);