From nobody Tue Apr 21 14:39:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776662993; cv=none; d=zohomail.com; s=zohoarc; b=DDXyLEilKeO6aV0c2X1M5aqWceJutPI1l9+PN39Ta/3uAImIVUf2WISWO0Plx42kzD2upvDyvZayflbPX06a9Aq3jo+kqmpz09c/4huUZxWIy+NQTODmi3a52i9LzW7Plk8g+smsX1SXQpZfWMkOiMbfHJxDltpvWj+KdGI8xC4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776662993; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=nEvvbdwpOxSnYp5j1qxcKcTTJ9o9BYKzkXwsXDSeBbU=; b=mSX+ze8dGoafBtsygx5ZBy9fwaidNG6cK/WvhkmATe2WUtrYwdgWsCnZha5MUSuzifuv4l/7owdRfvpoEPHDIeL2wTOOfHpDbk0V3ZC5lQ8w5dnPVRbIIA/aOzWpoX0d1MC9E/1X90kLPCEbx1dYqGQv3UFJYqKOscr8MfDYdN0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177666299395354.07807549895176; Sun, 19 Apr 2026 22:29:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wEhCF-0008Hi-W0; Mon, 20 Apr 2026 01:29:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wEhC6-0008F0-RS for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:19 -0400 Received: from mail-pj1-x102a.google.com ([2607:f8b0:4864:20::102a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wEhBz-0007zf-Nv for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:13 -0400 Received: by mail-pj1-x102a.google.com with SMTP id 98e67ed59e1d1-36143b0dbdbso1387005a91.2 for ; Sun, 19 Apr 2026 22:29:05 -0700 (PDT) Received: from [172.17.0.5] ([168.126.243.22]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab3ad18sm93099675ad.71.2026.04.19.22.29.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 22:29:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776662944; x=1777267744; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=nEvvbdwpOxSnYp5j1qxcKcTTJ9o9BYKzkXwsXDSeBbU=; b=fWFghWUMehs+oG/hY5z/K75s8F8m8LF4t9MNwLw8ciVa0bUKIwsvFOhv8zfZay+Tpv MhJuJPHQBILb3TKxrfNl/qX8xzW6SKsE6mcz68HxKGUyaH2NnAZqFyCHPo+waf1cePMp s0XpYzV3OmboT0G54m5okaAifcXLSek9psBln1f4DYNk2vdG8f3pZfZt1+oi1hRI4B3F gtkVjkgETmQrw+bqDI9vO1qvrz5K9FlDAgzJbVh/MtJdRPAtxKWNkkioIJaLOef6YTEu 2uz3GkuIVUfy44Tk6FG+J/pUOYita0aHjtKUkUVbO7y7OCZ5pKdlhxl+bzfqJxtRJX8h X7JA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776662944; x=1777267744; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=nEvvbdwpOxSnYp5j1qxcKcTTJ9o9BYKzkXwsXDSeBbU=; b=oE8YXrWAqn7gLYhIwijZRguCht+6ExSPgz0fPcbf9HvGY42LDPLYjvRXPOEqwm/gBu vurzW6LlXs1auZFQP2BNSkGyOJoIg2I3Q5HoqjEV0+0tA7hFx3AlCZ+x7QeL3if65MvX rR9xMPeXeQFEiSC8Y/bggltonudtKmYGIv1hw6o7J+BcrcpUwaZd/zxCKf1gWYjQWp0j 09FptfkKFBnVkbG/OD2aWyolY7h0uwn7FkI5rOWBSlWaNKV5ft6KQ9i0Sx8eE9YvYH8F cW0bpP5KbvGhpWNDom40oZE6u8A+fTI79AX215E993NSdF6rvU049btKqLWTsicHrjCA UHUA== X-Gm-Message-State: AOJu0YyHcdkk4cdVMOCa/x5fTCQ4jmm1iK/RUECjOnRKffy+oOCVrUJh flgVLJgvQaOQNh+sJqNEe77hvNTJeicRJIuCzLMlw1ChBRkFmtAl3DvCLsm+ORLcQqk= X-Gm-Gg: AeBDievESjqyYSr4zsNe4mXyIpGFPuWxf2m7p9Jil/xHY5kmvOJmrkVTQtWJoCqujIB oK/P02gHVycBvPL/ZpA6mJccvcK3mDH2YR9KUhQS4HIinYlzaiAj5mi440GUqsH1HzAzaQL9nao yPr+SgUUliYYkFM3839aPqBMu7R0a3tme25HqmZf8vBPCCQAsfkZyw07vkycQye1k/yLBLoKJtE tuOrcEswfRxXoZkV1CLxNOeidtfqP+hb2/iLpYdcpbyPSqeED+AIhxdBOI4J9dkmci9Vtps/D+Y hGeHCJSHqhaYt/T9Z61uxY8yVgb9nM9Z4Q92gUq0vsov5CtLsRxm4BBYagn2W2GS838efet0our TMFKEEQOSiDBb0srky199oKW3pQq0dOnmv0xPr+0aMiRc5j6oFyHEujINsncWTt2g8yuMLjTpSo etMs0QaZsbzdGB4QgSmbdIgxu/gwe9WgEy0ltefTr3/7dAGC3ghEs= X-Received: by 2002:a17:90b:6cd:b0:35d:ac4d:3cb6 with SMTP id 98e67ed59e1d1-361403b790dmr12186040a91.5.1776662944459; Sun, 19 Apr 2026 22:29:04 -0700 (PDT) From: Jaemyung Lee X-Google-Original-From: Jaemyung Lee Date: Mon, 20 Apr 2026 14:28:49 +0900 Subject: [PATCH v6 1/5] hw/ufs: Apply UFS 4.1 Specification MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260420-write_booster-v6-1-8c49acba03d4@samsung.com> References: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> In-Reply-To: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> To: qemu-devel@nongnu.org Cc: Jeuk Kim , Kevin Wolf , Hanna Reitz , qemu-block@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Jaemyung Lee X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1776662940; l=12799; i=jaemyung.lee@samsung.com; s=20260402; h=from:subject:message-id; bh=CgN8ljzeml1hAPWOnqVTo/m8W7lnE0WV5YXREroYZ/Q=; b=ExRBbRtUvl15p7Hj6pGLNsh/hGdutDCkEYFZvXmAumpJe8jORzvL/C8Qfo+10fhHKjA+n7h0I tw38NVKUAFCCK88epKx73ud1r8zfio0hDPma8TL/VSvFr2apLdvO8+w X-Developer-Key: i=jaemyung.lee@samsung.com; a=ed25519; pk=bZPd7A/kteUO62FfUM6IrI1LuBPe5QrcqfvsitM1ZjE= Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::102a; envelope-from=ldc.jml@gmail.com; helo=mail-pj1-x102a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776662996139154100 Apply current UFS 4.1 Specification to QEMU-UFS. QEMU-UFS device emulates operation via UFS 4.0 Specification, but current latest Spec. version is UFS 4.1. So extent internal DESCRIPTOR/FLAG/ATTRIBUTE declaration to follow UFS 4.1 Spec. It does not implement any actual functionallity, but only adds minimum supportability for further implementation. Signed-off-by: Jaemyung Lee --- hw/ufs/ufs.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++= +--- include/block/ufs.h | 59 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 6 deletions(-) diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index cb74cb56bc15ec6fb873097ccb1b6e5694639bd9..b2b70c8b38ebecd8d49ecce2886= 14d55efd90f2e 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -9,7 +9,7 @@ */ =20 /** - * Reference Specs: https://www.jedec.org/, 4.0 + * Reference Specs: https://www.jedec.org/, 4.1 * * Usage * ----- @@ -29,8 +29,8 @@ #include "trace.h" #include "ufs.h" =20 -/* The QEMU-UFS device follows spec version 4.0 */ -#define UFS_SPEC_VER 0x0400 +/* The QEMU-UFS device follows spec version 4.1 */ +#define UFS_SPEC_VER 0x0410 #define UFS_MAX_NUTRS 32 #define UFS_MAX_NUTMRS 8 #define UFS_MCQ_QCFGPTR 2 @@ -1000,6 +1000,7 @@ static const int flag_permission[UFS_QUERY_FLAG_IDN_C= OUNT] =3D { [UFS_QUERY_FLAG_IDN_WB_EN] =3D UFS_QUERY_FLAG_READ, [UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN] =3D UFS_QUERY_FLAG_READ, [UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8] =3D UFS_QUERY_FLAG_R= EAD, + [UFS_QUERY_FLAG_IDN_UNPIN_EN] =3D UFS_QUERY_FLAG_READ, }; =20 static inline QueryRespCode ufs_flag_check_idn_valid(uint8_t idn, int op) @@ -1057,10 +1058,31 @@ static const int attr_permission[UFS_QUERY_ATTR_IDN= _COUNT] =3D { [UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_EXT_IID_EN] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_HOST_HINT_CACHE_SIZE] =3D UFS_QUERY_ATTR_READ, /* refresh operation is not supported */ [UFS_QUERY_ATTR_IDN_REFRESH_STATUS] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_REFRESH_FREQ] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_REFRESH_UNIT] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_TIMESTAMP] =3D UFS_QUERY_ATTR_WRITE, + [UFS_QUERY_ATTR_IDN_DEVICE_LEVEL_EXCEPTION_ID] =3D UFS_QUERY_ATTR_READ, + /* host initiated defragmentation is not supported */ + [UFS_QUERY_ATTR_IDN_DEFRAG_OP] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_HID_SIZE] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_HID_PROG_RATIO] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_HID_STATE] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_HINT] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_STATUS] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATTR_REA= D, + [UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATTR= _READ, + [UFS_QUERY_ATTR_IDN_CURR_FIFO_WB_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATT= R_READ, + [UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_CURR_ALLOC_UNITS] =3D UFS_QUERY_ATT= R_READ, + [UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_AVAIL_PERCENT] =3D UFS_QUERY_ATTR_R= EAD, + [UFS_QUERY_ATTR_IDN_PINNED_WB_CUMM_WRITTEN_SIZE] =3D UFS_QUERY_ATTR_RE= AD, + [UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS] =3D UFS_QUERY_A= TTR_READ, }; =20 static inline QueryRespCode ufs_attr_check_idn_valid(uint8_t idn, int op) @@ -1194,12 +1216,50 @@ static uint32_t ufs_read_attr_value(UfsHc *u, uint8= _t idn) return u->attributes.wb_buffer_life_time_est; case UFS_QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE: return be32_to_cpu(u->attributes.current_wb_buffer_size); + case UFS_QUERY_ATTR_IDN_EXT_IID_EN: + return u->attributes.ext_iid_en; + case UFS_QUERY_ATTR_IDN_HOST_HINT_CACHE_SIZE: + return be16_to_cpu(u->attributes.host_hint_cache_size); case UFS_QUERY_ATTR_IDN_REFRESH_STATUS: return u->attributes.refresh_status; case UFS_QUERY_ATTR_IDN_REFRESH_FREQ: return u->attributes.refresh_freq; case UFS_QUERY_ATTR_IDN_REFRESH_UNIT: return u->attributes.refresh_unit; + case UFS_QUERY_ATTR_IDN_DEVICE_LEVEL_EXCEPTION_ID: + return be64_to_cpu(u->attributes.device_level_exception_id); + case UFS_QUERY_ATTR_IDN_DEFRAG_OP: + return u->attributes.defrag_op; + case UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE: + return be32_to_cpu(u->attributes.hid_avail_size); + case UFS_QUERY_ATTR_IDN_HID_SIZE: + return be32_to_cpu(u->attributes.hid_size); + case UFS_QUERY_ATTR_IDN_HID_PROG_RATIO: + return u->attributes.hid_prog_ratio; + case UFS_QUERY_ATTR_IDN_HID_STATE: + return u->attributes.hid_state; + case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_HINT: + return u->attributes.wb_buffer_resize_hint; + case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN: + return u->attributes.wb_buffer_resize_en; + case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_STATUS: + return u->attributes.wb_buffer_resize_status; + case UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE: + return u->attributes.wb_buffer_partial_flush_mode; + case UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE: + return be32_to_cpu(u->attributes.max_fifo_wb_partial_flush_mode); + case UFS_QUERY_ATTR_IDN_CURR_FIFO_WB_PARTIAL_FLUSH_MODE: + return be32_to_cpu(u->attributes.curr_fifo_wb_partial_flush_mode); + case UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_CURR_ALLOC_UNITS: + return be32_to_cpu(u->attributes.pinned_wb_buffer_curr_alloc_units= ); + case UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_AVAIL_PERCENT: + return u->attributes.pinned_wb_buffer_avail_percent; + case UFS_QUERY_ATTR_IDN_PINNED_WB_CUMM_WRITTEN_SIZE: + return be32_to_cpu(u->attributes.pinned_wb_cumm_written_size); + case UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS: + return be32_to_cpu(u->attributes.pinned_wb_num_alloc_units); + case UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS: + return be32_to_cpu(u->attributes.non_pinned_wb_min_num_alloc_units= ); } return 0; } @@ -1237,6 +1297,9 @@ static QueryRespCode ufs_write_attr_value(UfsHc *u, u= int8_t idn, uint32_t value) case UFS_QUERY_ATTR_IDN_PSA_DATA_SIZE: u->attributes.psa_data_size =3D cpu_to_be32(value); break; + case UFS_QUERY_ATTR_IDN_TIMESTAMP: + u->attributes.timestamp =3D cpu_to_be64(value); + break; } return UFS_QUERY_RESULT_SUCCESS; } diff --git a/include/block/ufs.h b/include/block/ufs.h index 04cb24324d7c5585be9df596738183e1924403fb..4dacfb776f947a285d86018add8= 2115f148b7dd9 100644 --- a/include/block/ufs.h +++ b/include/block/ufs.h @@ -294,7 +294,8 @@ typedef struct QEMU_PACKED DeviceDescriptor { uint32_t psa_max_data_size; uint8_t psa_state_timeout; uint8_t product_revision_level; - uint8_t reserved[36]; + uint8_t reserved[34]; + uint16_t extended_wb_support; uint32_t extended_ufs_features_support; uint8_t write_booster_buffer_preserve_user_space_en; uint8_t write_booster_buffer_type; @@ -342,6 +343,8 @@ typedef struct QEMU_PACKED GeometryDescriptor { uint8_t write_booster_buffer_cap_adj_fac; uint8_t supported_write_booster_buffer_user_space_reduction_types; uint8_t supported_write_booster_buffer_types; + uint8_t reserved3[17]; + uint8_t cap_adj_fac_representation; } GeometryDescriptor; =20 #define UFS_GEOMETRY_CAPACITY_SHIFT 9 @@ -437,6 +440,8 @@ typedef struct QEMU_PACKED Flags { uint8_t wb_buffer_flush_en; uint8_t wb_buffer_flush_during_hibernate; uint8_t reserved4[2]; + uint8_t unpin_en; + uint8_t reserved5[235]; } Flags; =20 typedef struct Attributes { @@ -457,6 +462,8 @@ typedef struct Attributes { uint16_t exception_event_status; uint32_t seconds_passed; uint16_t context_conf; + uint8_t obsolete; + uint8_t reserved2[2]; uint8_t device_ffu_status; uint8_t psa_state; uint32_t psa_data_size; @@ -469,10 +476,34 @@ typedef struct Attributes { uint8_t available_wb_buffer_size; uint8_t wb_buffer_life_time_est; uint32_t current_wb_buffer_size; + uint8_t reserved3[10]; + uint8_t ext_iid_en; + uint16_t host_hint_cache_size; uint8_t refresh_status; uint8_t refresh_freq; uint8_t refresh_unit; uint8_t refresh_method; + uint64_t timestamp; + uint8_t reserved4[3]; + uint64_t device_level_exception_id; + uint8_t defrag_op; + uint32_t hid_avail_size; + uint32_t hid_size; + uint8_t hid_prog_ratio; + uint8_t hid_state; + uint8_t reserved5[2]; + uint8_t wb_buffer_resize_hint; + uint8_t wb_buffer_resize_en; + uint8_t wb_buffer_resize_status; + uint8_t wb_buffer_partial_flush_mode; + uint32_t max_fifo_wb_partial_flush_mode; + uint32_t curr_fifo_wb_partial_flush_mode; + uint32_t pinned_wb_buffer_curr_alloc_units; + uint8_t pinned_wb_buffer_avail_percent; + uint32_t pinned_wb_cumm_written_size; + uint32_t pinned_wb_num_alloc_units; + uint32_t non_pinned_wb_min_num_alloc_units; + uint8_t reserved6[184]; } Attributes; =20 #define UFS_TRANSACTION_SPECIFIC_FIELD_SIZE 20 @@ -856,6 +887,7 @@ enum flag_idn { UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8 =3D 0x10, UFS_QUERY_FLAG_IDN_HPB_RESET =3D 0x11, UFS_QUERY_FLAG_IDN_HPB_EN =3D 0x12, + UFS_QUERY_FLAG_IDN_UNPIN_EN =3D 0x13, UFS_QUERY_FLAG_IDN_COUNT, }; =20 @@ -893,9 +925,29 @@ enum attr_idn { UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE =3D 0x1D, UFS_QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST =3D 0x1E, UFS_QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE =3D 0x1F, + UFS_QUERY_ATTR_IDN_EXT_IID_EN =3D 0x2A, + UFS_QUERY_ATTR_IDN_HOST_HINT_CACHE_SIZE =3D 0x2B, UFS_QUERY_ATTR_IDN_REFRESH_STATUS =3D 0x2C, UFS_QUERY_ATTR_IDN_REFRESH_FREQ =3D 0x2D, UFS_QUERY_ATTR_IDN_REFRESH_UNIT =3D 0x2E, + UFS_QUERY_ATTR_IDN_TIMESTAMP =3D 0x30, + UFS_QUERY_ATTR_IDN_DEVICE_LEVEL_EXCEPTION_ID =3D 0x34, + UFS_QUERY_ATTR_IDN_DEFRAG_OP =3D 0x35, + UFS_QUERY_ATTR_IDN_HID_AVAIL_SIZE =3D 0x36, + UFS_QUERY_ATTR_IDN_HID_SIZE =3D 0x37, + UFS_QUERY_ATTR_IDN_HID_PROG_RATIO =3D 0x38, + UFS_QUERY_ATTR_IDN_HID_STATE =3D 0x39, + UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_HINT =3D 0x3C, + UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN =3D 0x3D, + UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_STATUS =3D 0x3E, + UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE =3D 0x3F, + UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE =3D 0x40, + UFS_QUERY_ATTR_IDN_CURR_FIFO_WB_PARTIAL_FLUSH_MODE =3D 0x41, + UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_CURR_ALLOC_UNITS =3D 0x42, + UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_AVAIL_PERCENT =3D 0x43, + UFS_QUERY_ATTR_IDN_PINNED_WB_CUMM_WRITTEN_SIZE =3D 0x44, + UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS =3D 0x45, + UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS =3D 0x46, UFS_QUERY_ATTR_IDN_COUNT, }; =20 @@ -1005,6 +1057,7 @@ enum device_desc_param { UFS_DEVICE_DESC_PARAM_PRDCT_REV =3D 0x2A, UFS_DEVICE_DESC_PARAM_HPB_VER =3D 0x40, UFS_DEVICE_DESC_PARAM_HPB_CONTROL =3D 0x42, + UFS_DEVICE_DESC_PARAM_EXT_WB_SUP =3D 0x4D, UFS_DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP =3D 0x4F, UFS_DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN =3D 0x53, UFS_DEVICE_DESC_PARAM_WB_TYPE =3D 0x54, @@ -1208,14 +1261,14 @@ static inline void _ufs_check_size(void) QEMU_BUILD_BUG_ON(sizeof(UfsMcqCqIntReg) !=3D 12); QEMU_BUILD_BUG_ON(sizeof(UfsMcqOpReg) !=3D 48); QEMU_BUILD_BUG_ON(sizeof(DeviceDescriptor) !=3D 89); - QEMU_BUILD_BUG_ON(sizeof(GeometryDescriptor) !=3D 87); + QEMU_BUILD_BUG_ON(sizeof(GeometryDescriptor) !=3D 105); QEMU_BUILD_BUG_ON(sizeof(UnitDescriptor) !=3D 45); QEMU_BUILD_BUG_ON(sizeof(RpmbUnitDescriptor) !=3D 35); QEMU_BUILD_BUG_ON(sizeof(PowerParametersDescriptor) !=3D 98); QEMU_BUILD_BUG_ON(sizeof(InterconnectDescriptor) !=3D 6); QEMU_BUILD_BUG_ON(sizeof(StringDescriptor) !=3D 254); QEMU_BUILD_BUG_ON(sizeof(DeviceHealthDescriptor) !=3D 45); - QEMU_BUILD_BUG_ON(sizeof(Flags) !=3D 0x13); + QEMU_BUILD_BUG_ON(sizeof(Flags) !=3D 0xFF); QEMU_BUILD_BUG_ON(sizeof(UtpUpiuHeader) !=3D 12); QEMU_BUILD_BUG_ON(sizeof(UtpUpiuQuery) !=3D 276); QEMU_BUILD_BUG_ON(sizeof(UtpUpiuCmd) !=3D 20); --=20 2.48.1 From nobody Tue Apr 21 14:39:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776663051; cv=none; d=zohomail.com; s=zohoarc; b=byHb9W4Ig0xw+7cFk6MZDEXspuljar6JLaZJ+kkefZ3exaEiEs/r5mQc8TMZMcPglfdFqWcbbajgjeJkZnfYCQUsOitjmk9Kff64tDvQK2mRojuSA9KCL9gmxD1xVd63DTkv23ViPXfzYLA5i12g0bSA02Y+9Yp0eXggK3bZxx0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776663051; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=wp610CTuY5BtVJCvmliEvcgHSUgtMv4PTZfRqvUtBfw=; b=koGvq1jXSTVwfilNlMqlDQI4LkBYRcXqqbMCk02CrhCtUVGAwyN07ab8abo7MGCHFQsz2CnGx+nTpJkMdH19LmbQErsTT8AGPeCzvBzfEJ9hXOQuzofcxfFPuCDWgpQPRpDQsMpGz+FPFLVc2y+pCQssiFyCpy/C4bsdbRWRYqY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776663051259999.8598516455689; Sun, 19 Apr 2026 22:30:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wEhCE-0008H8-Vk; Mon, 20 Apr 2026 01:29:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wEhC8-0008FD-9R for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:19 -0400 Received: from mail-pl1-x629.google.com ([2607:f8b0:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wEhC1-00081Y-HG for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:16 -0400 Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-2ab46931cf1so25501385ad.0 for ; Sun, 19 Apr 2026 22:29:07 -0700 (PDT) Received: from [172.17.0.5] ([168.126.243.22]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab3ad18sm93099675ad.71.2026.04.19.22.29.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 22:29:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776662946; x=1777267746; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=wp610CTuY5BtVJCvmliEvcgHSUgtMv4PTZfRqvUtBfw=; b=jeLH97LyFbduKLDPkKipdbVIdXeU+56SKNeGnHC+zjAfHJOR3/3cIdW3aR5e7y92bR ByS6SWTox9UevU0nxGZQ3nZzs9zXFTVL5u2Gw9qHl6F3Eh3AJF3lZuHKmHr/mcenLZmp J94YTGjH3QLa0R6IsT/uCnD5js5UnjCfUmiLzihHg4YlYiufgk575TGgi6rT++OSLOx7 I6rDjIPU65/bG6v6duG8CqaVr0ajJKAnbFpI30wN7LrvtbImsX4pksCLWsHqUehPxP23 2lS4pX1+WRg5j1wGjmQDmd8Tg8aZHGWsd5Ca6apOEVydn3KJoHzMUQLOlg7U8bLpS8sw +eCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776662946; x=1777267746; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=wp610CTuY5BtVJCvmliEvcgHSUgtMv4PTZfRqvUtBfw=; b=ldAMnaaNeDKyrJv4qCrChv8Li9rfH0nRaU1gFKCNEJj8iusFCpwFtQ38GZYyyHV8SZ j0P3bd+T1uxpwoH6bt04wxW16ZJS/87a/4wifAxo0R8fwXFcwWOoMXS/klqdKsAAs4se d7C6PvQ46a5Y/te6ffGb1VznZHc1wtOj7T3BnQkm9xu8JWTReoZ7GM4YvudJtqZXNjKF hVh5o5BRs5z2YTT9gEMMShXVHOI/ouFMPEaPMWVJeUSDHfPyljjBRDtjD2kIA+FkKwjM /oVu7miVsuvXn186aPf4nVi87E1uVROVFuctHKy6LIdSikDaCejCjPZFuKvWWIqd0kbS uFoQ== X-Gm-Message-State: AOJu0YzKK3y2B75Mmdw0wTI3EicLxv7UYG3msii6Fu+IdZSmIgX/u8vN 1xGV5IhjZRjaIdzAHR85Hb5ibMkCIesVeOuGyok2602TK/M8Vi2FHW/j5bmC1Qlb/hM= X-Gm-Gg: AeBDieteAELdMHvgkjL0lzB1UFsnkO7izxzCv3mAGb57QKqp53FjutuFii747suXFnU BHp0cmd0ENpsGlNWyTpgjGDv6bDCwieC0w4hqJEt87rGQ9zDkuP4caeUNvscojaFbe1R1ICGmCg wrFB5FgsvMmbkEv9jMoK5nCjgVLY6j3SjH2t1qkzDQHkfiSFrRHuxvRSJrPfg8x4yzH+c11qoXe FFDjW6XU9KpNXcWPjO8V1bWNMTsuqBSYF20Ng9StNCEh94Xe4ptDnV33lHb4i101ry/bEp/RZrR GHa3Y6tvzVvbpgZd5iD6IuHjEhrOTMCbGkLqyU5lJMztnNN7Pxl9j/Ln9UFZJAYXIcmqouQgcbL pisbOFzbRs8yAILyGNxVHRB6GJUHNDZoLKcjsGJd2xU/reekDP+3+ToU9iI2eHwOgEHQe0x7aua yVQTwI1ttBphM53zPApu3t/4vOgIGzGeCFmtD+Jkeb X-Received: by 2002:a17:903:1b2b:b0:2b4:6529:7b9e with SMTP id d9443c01a7336-2b5f9e145a1mr104966805ad.12.1776662946523; Sun, 19 Apr 2026 22:29:06 -0700 (PDT) From: Jaemyung Lee X-Google-Original-From: Jaemyung Lee Date: Mon, 20 Apr 2026 14:28:50 +0900 Subject: [PATCH v6 2/5] hw/ufs: Modify flag handling operation MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260420-write_booster-v6-2-8c49acba03d4@samsung.com> References: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> In-Reply-To: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> To: qemu-devel@nongnu.org Cc: Jeuk Kim , Kevin Wolf , Hanna Reitz , qemu-block@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Jaemyung Lee X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1776662940; l=6656; i=jaemyung.lee@samsung.com; s=20260402; h=from:subject:message-id; bh=UwQldvutZu9HqLXksjdiAk3IKzXkRCngBaBlZ026a4E=; b=tuskH5PQ6UR//7Os4QA0q+v5qBzNMJHYk3iAWX6w94e+yKKjRhr6YFfVqRUhHUNtjz+aG3wF1 eHE8DhY3fvXDN4/v8EZttpecJcaHGGPojDdF94Au0ENvIlY/N6Th/5B X-Developer-Key: i=jaemyung.lee@samsung.com; a=ed25519; pk=bZPd7A/kteUO62FfUM6IrI1LuBPe5QrcqfvsitM1ZjE= Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::629; envelope-from=ldc.jml@gmail.com; helo=mail-pl1-x629.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776663052372158500 Change internal flag handling operation same as attribute's In UFS device, some flag queries directly trigger specific device behaviour like attribute's, not only changes the internal values. So restructure flag query processing functions same as attribute processing, to facilitate linking detailed implementations based on individual flag value changes. Signed-off-by: Jaemyung Lee --- hw/ufs/ufs.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 119 insertions(+), 33 deletions(-) diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index b2b70c8b38ebecd8d49ecce288614d55efd90f2e..69f82ab462d135fe6cda479891f= 9d8f26d19be9a 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -1021,6 +1021,122 @@ static inline QueryRespCode ufs_flag_check_idn_vali= d(uint8_t idn, int op) return UFS_QUERY_RESULT_SUCCESS; } =20 +static uint32_t ufs_read_flag_value(UfsHc *u, uint8_t idn) +{ + switch (idn) { + case UFS_QUERY_FLAG_IDN_FDEVICEINIT: + return u->flags.device_init; + case UFS_QUERY_FLAG_IDN_PERMANENT_WPE: + return u->flags.permanent_wp_en; + case UFS_QUERY_FLAG_IDN_PWR_ON_WPE: + return u->flags.power_on_wp_en; + case UFS_QUERY_FLAG_IDN_BKOPS_EN: + return u->flags.background_ops_en; + case UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE: + return u->flags.device_life_span_mode_en; + case UFS_QUERY_FLAG_IDN_PURGE_ENABLE: + return u->flags.purge_enable; + case UFS_QUERY_FLAG_IDN_REFRESH_ENABLE: + return u->flags.refresh_enable; + case UFS_QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL: + return u->flags.phy_resource_removal; + case UFS_QUERY_FLAG_IDN_BUSY_RTC: + return u->flags.busy_rtc; + case UFS_QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE: + return u->flags.permanently_disable_fw_update; + case UFS_QUERY_FLAG_IDN_WB_EN: + return u->flags.wb_en; + case UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN: + return u->flags.wb_buffer_flush_en; + case UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8: + return u->flags.wb_buffer_flush_during_hibernate; + case UFS_QUERY_FLAG_IDN_UNPIN_EN: + return u->flags.unpin_en; + default: + g_assert_not_reached(); + return 0; + } +} + +static QueryRespCode ufs_write_flag_value(UfsHc *u, uint8_t idn, uint8_t v= alue) +{ + switch (idn) { + case UFS_QUERY_FLAG_IDN_FDEVICEINIT: + u->flags.device_init =3D 0; + break; + case UFS_QUERY_FLAG_IDN_PERMANENT_WPE: + u->flags.permanent_wp_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_PWR_ON_WPE: + u->flags.power_on_wp_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_BKOPS_EN: + u->flags.background_ops_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE: + u->flags.device_life_span_mode_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_PURGE_ENABLE: + u->flags.purge_enable =3D value; + break; + case UFS_QUERY_FLAG_IDN_REFRESH_ENABLE: + u->flags.refresh_enable =3D value; + break; + case UFS_QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL: + u->flags.phy_resource_removal =3D value; + break; + case UFS_QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE: + u->flags.permanently_disable_fw_update =3D value; + break; + case UFS_QUERY_FLAG_IDN_WB_EN: + u->flags.wb_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN: + u->flags.wb_buffer_flush_en =3D value; + break; + case UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8: + u->flags.wb_buffer_flush_during_hibernate =3D value; + break; + default: + return UFS_QUERY_RESULT_INVALID_VALUE; + } + + return UFS_QUERY_RESULT_SUCCESS; +} + +static QueryRespCode ufs_exec_query_flag(UfsRequest *req, int op) +{ + UfsHc *u =3D req->hc; + uint8_t idn =3D req->req_upiu.qr.idn; + uint8_t value; + QueryRespCode ret; + + ret =3D ufs_flag_check_idn_valid(idn, op); + if (ret) { + return ret; + } + + if (op =3D=3D UFS_QUERY_FLAG_READ) { + value =3D ufs_read_flag_value(u, idn); + ret =3D UFS_QUERY_RESULT_SUCCESS; + } else if (op =3D=3D UFS_QUERY_FLAG_SET) { + value =3D 1; + ret =3D ufs_write_flag_value(u, idn, value); + } else if (op =3D=3D UFS_QUERY_FLAG_CLEAR) { + value =3D 0; + ret =3D ufs_write_flag_value(u, idn, value); + } else if (op =3D=3D UFS_QUERY_FLAG_TOGGLE) { + value =3D !(ufs_read_flag_value(u, idn)); + ret =3D ufs_write_flag_value(u, idn, value); + } else { + trace_ufs_err_query_invalid_opcode(op); + return UFS_QUERY_RESULT_INVALID_OPCODE; + } + + req->rsp_upiu.qr.value =3D cpu_to_be32(value); + return ret; +} + static const int attr_permission[UFS_QUERY_ATTR_IDN_COUNT] =3D { /* booting is not supported */ [UFS_QUERY_ATTR_IDN_BOOT_LU_EN] =3D UFS_QUERY_ATTR_READ, @@ -1103,39 +1219,6 @@ static inline QueryRespCode ufs_attr_check_idn_valid= (uint8_t idn, int op) return UFS_QUERY_RESULT_SUCCESS; } =20 -static QueryRespCode ufs_exec_query_flag(UfsRequest *req, int op) -{ - UfsHc *u =3D req->hc; - uint8_t idn =3D req->req_upiu.qr.idn; - uint32_t value; - QueryRespCode ret; - - ret =3D ufs_flag_check_idn_valid(idn, op); - if (ret) { - return ret; - } - - if (idn =3D=3D UFS_QUERY_FLAG_IDN_FDEVICEINIT) { - value =3D 0; - } else if (op =3D=3D UFS_QUERY_FLAG_READ) { - value =3D *(((uint8_t *)&u->flags) + idn); - } else if (op =3D=3D UFS_QUERY_FLAG_SET) { - value =3D 1; - } else if (op =3D=3D UFS_QUERY_FLAG_CLEAR) { - value =3D 0; - } else if (op =3D=3D UFS_QUERY_FLAG_TOGGLE) { - value =3D *(((uint8_t *)&u->flags) + idn); - value =3D !value; - } else { - trace_ufs_err_query_invalid_opcode(op); - return UFS_QUERY_RESULT_INVALID_OPCODE; - } - - *(((uint8_t *)&u->flags) + idn) =3D value; - req->rsp_upiu.qr.value =3D cpu_to_be32(value); - return UFS_QUERY_RESULT_SUCCESS; -} - static inline uint8_t ufs_read_device_temp(UfsHc *u) { uint8_t feat_sup =3D u->device_desc.ufs_features_support; @@ -1300,6 +1383,9 @@ static QueryRespCode ufs_write_attr_value(UfsHc *u, u= int8_t idn, uint32_t value) case UFS_QUERY_ATTR_IDN_TIMESTAMP: u->attributes.timestamp =3D cpu_to_be64(value); break; + default: + g_assert_not_reached(); + return 0; } return UFS_QUERY_RESULT_SUCCESS; } --=20 2.48.1 From nobody Tue Apr 21 14:39:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776663035; cv=none; d=zohomail.com; s=zohoarc; b=Yf1GjmCSJxRqA7qXEdQv02efqBi0iEHWV3LNhpccnbDbeWhFLT16tsAuBBHCiNkMHx/NsANOpW3+kvdR5UaBuUrhosJCMoRWscegTpy6q7lB9BTYHJYWsk95BJ+m0nd9+t2ZYw+xl3IMG+g0uLVor93rs36OdgH+mO18JMZwmE0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776663035; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=s7rduMfdSHBv6Dm+D3nhuA8gVs+ENlu+IzPYpxEzuEI=; b=c8yPTqLBFbB8J2Ah3LEBgI2RPitOaPBnihUnBoWFvvdO0GbufjUbWL6o5JQzST+IZIMzPbk8fcqm63rQorJDU/QkyGj/SQe8V7myVERPgYLc9DW2gU7pm1RPK0H+NM2rpzzFwBriWkfWdHyZrp1MO4HFSNgUzE+TV9Xh0ELUz2U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776663035552773.2559824850792; Sun, 19 Apr 2026 22:30:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wEhCE-0008H7-R3; Mon, 20 Apr 2026 01:29:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wEhC9-0008FF-JR for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:19 -0400 Received: from mail-pl1-x631.google.com ([2607:f8b0:4864:20::631]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wEhC6-000822-Ib for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:17 -0400 Received: by mail-pl1-x631.google.com with SMTP id d9443c01a7336-2b461310af5so9659565ad.1 for ; Sun, 19 Apr 2026 22:29:09 -0700 (PDT) Received: from [172.17.0.5] ([168.126.243.22]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab3ad18sm93099675ad.71.2026.04.19.22.29.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 22:29:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776662948; x=1777267748; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=s7rduMfdSHBv6Dm+D3nhuA8gVs+ENlu+IzPYpxEzuEI=; b=lBQbAOZ6rRELHmy76wyujcvzttFXlWf52u+vQvpkcJ30AN+J6zjiGMck7wuT3PhsAu n10DJbpK03BKQvhjJLxfAYB+xohGUtb2bUA3tzDvu3zhvgEYJ5DiKiLvfFW0S6I7Qu4i 9sdtnD7Sk/ILCMIINLsYVrJYYhZe+O59u7plaCcH2s6ynEwFGaoRkFKzsLizjS1GOap/ h90aJptmNXj88GSq0SFy4ipw4cP5TeS7I8sm/+gsd1auHKI2LRCQDiKF5DQv/ZpeWdE0 eNOu8steUKtC6WPt/2VRx7xSs7C5zzHym8A+U6IIMeMevyIUVcugNVFv92TrL/MHKq9y UHKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776662948; x=1777267748; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=s7rduMfdSHBv6Dm+D3nhuA8gVs+ENlu+IzPYpxEzuEI=; b=BiB2hO8DZhAVF2X3EN5Mvys3E5dM2ThyTUIftB5mzNrwu7q/LmWvW9MuEYE91ATo9h 9X+ZVZ5S23HdDehoT2B4KdeoAndhgLkGJaLisZEuyp+RhF85dt20nk9Tg8T8v1gRTsx0 2fozK/aj4mJ6Fo9e2Cfrdm3pDOPGbwqbreEHmVOxtOM1gfAXGQTnGrIFXFqfN4pUU+hU dJAau2OyQf6CtanacWbfsz/ElW3LPfjJq4X6IHqgkJBXz5zBc0oLAahij00mpn3y/h0K ecg6GXCFA90UJNsHb5HBcL9N+Nkv1MxfjF2bLlboOMGMPNApcNdv+6VUBUsiASkCNFEg /x0g== X-Gm-Message-State: AOJu0YxqVGoIN9MQZyv7g908HHdj0moUVtigBUoJqCa1F/J2oJvLEIuE aVQgMWIzySp2EL/XWmzkKk5JERLEcLxwdnA0qRk2bSHMDmJ9xL2cvhKjeCsWhgJkTpc= X-Gm-Gg: AeBDietx3jqABv2EEvwpHSzDeqY+purcXNuuw7WKVSmtVF6irRbUCugdPMADjehQ4dE Vk2FYtIdlTS3EI0LksCs8kYSIGrWU1ZgACk7udbd1NUJxjpmQQ5jTMr7C2z8sLlTzJEXy3MXfJR tts7ragrZnnwetiALeeDKClJsQkHCvtTHuiQI6EPjpaxi4DBH6FOpo2POgmd8P0hG+rGR1d49aR 4L4A83VwVSNIiKQ/ymA0fho8d8CVzt3A1kpWV9/I6cV2hpr5/yVhWiw0i+uG7XAtQhog3kc/4ND fp1DFc5s0ksPCSrGYILQi6TYtGe75WMXTBCcqW8nDmzL+y5euQHSn6yV2tirzNJbeIsG7K6yFVE WPWYvxpU2jWMmGXCpIbX2J8EFMJX2LfpIGua+MYlqp4OwVhOADMfrM4+HdYI6owMA38ifQ3P3iX Ns7JBPN4KP4IvFtuXsLnCzcXWbm+4jV8K2Xi4ce3E2 X-Received: by 2002:a17:902:9002:b0:2b0:91e6:bc18 with SMTP id d9443c01a7336-2b5f9e7bb41mr69449905ad.14.1776662948556; Sun, 19 Apr 2026 22:29:08 -0700 (PDT) From: Jaemyung Lee X-Google-Original-From: Jaemyung Lee Date: Mon, 20 Apr 2026 14:28:51 +0900 Subject: [PATCH v6 3/5] hw/ufs: Add idle operation MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260420-write_booster-v6-3-8c49acba03d4@samsung.com> References: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> In-Reply-To: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> To: qemu-devel@nongnu.org Cc: Jeuk Kim , Kevin Wolf , Hanna Reitz , qemu-block@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Jaemyung Lee X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1776662940; l=3493; i=jaemyung.lee@samsung.com; s=20260402; h=from:subject:message-id; bh=U1I7iR9KAXBx24tNL1R8hKu0trzHrSPwvB+dS7OpoRs=; b=HXEFZhSf5rng3vs9GzL1pBfJNw1EAHYTMz2xmn2rK6fprhAI3TE+UAwnbHrXkSS0Bp1isTZZ1 +/iRdmYb/uYB/J1NpvTsMmzKyEW2390WM+euWlVVy1hXpxyeNT8k9v9 X-Developer-Key: i=jaemyung.lee@samsung.com; a=ed25519; pk=bZPd7A/kteUO62FfUM6IrI1LuBPe5QrcqfvsitM1ZjE= Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::631; envelope-from=ldc.jml@gmail.com; helo=mail-pl1-x631.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776663038332158500 When no I/O occurs, the UFS Device performs various internal operations. To emulate this, adds a timer that periodically checks the current I/O status of the device and call the ufs_process_idle() function when idle. Signed-off-by: Jaemyung Lee --- hw/ufs/ufs.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/ufs/ufs.h | 2 ++ 2 files changed, 73 insertions(+) diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index 69f82ab462d135fe6cda479891f9d8f26d19be9a..c504a0d7e3fb89eb5558cfd9c41= 0cda9396bc3b4 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -1801,6 +1801,71 @@ static void ufs_sendback_req(void *opaque) ufs_irq_check(u); } =20 +static void ufs_process_idle(UfsHc *u) +{ + /* Currently do nothing */ + return; +} + +static inline bool ufs_check_idle(UfsHc *u) +{ + return !u->reg.utrldbr; +} + +static inline bool ufs_mcq_check_idle(UfsHc *u) +{ + if (!u->params.mcq) { + return true; + } + + for (int qid =3D 0; qid < ARRAY_SIZE(u->sq); qid++) { + if (!u->sq[qid]) { + continue; + } + + if (!ufs_mcq_sq_empty(u, qid)) { + return false; + } + + /* internal ongoing MCQ request check */ + UfsSq *sq =3D u->sq[qid]; + for (int i =3D 0; i < sq->size; i++) { + if (sq->req[i].state !=3D UFS_REQUEST_IDLE) { + return false; + } + } + } + + for (int qid =3D 0; qid < ARRAY_SIZE(u->cq); qid++) { + if (!u->cq[qid]) { + continue; + } + + if (!ufs_mcq_cq_empty(u, qid)) { + return false; + } + + if (!QTAILQ_EMPTY(&u->cq[qid]->req_list)) { + return false; + } + } + + return true; +} + +#define UFS_IDLE_TIMER_TICK 100 /* 0.1s */ +static void ufs_idle_timer_cb(void *opaque) +{ + UfsHc *u =3D opaque; + int64_t now =3D qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT); + + if (ufs_check_idle(u) && ufs_mcq_check_idle(u)) { + ufs_process_idle(u); + } + + timer_mod(&u->idle_timer, now + UFS_IDLE_TIMER_TICK); +} + static bool ufs_check_constraints(UfsHc *u, Error **errp) { if (u->params.nutrs > UFS_MAX_NUTRS) { @@ -1863,6 +1928,7 @@ static void ufs_init_hc(UfsHc *u) uint32_t cap =3D 0; uint32_t mcqconfig =3D 0; uint32_t mcqcap =3D 0; + int64_t now =3D qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT); =20 u->reg_size =3D pow2ceil(ufs_reg_size(u)); =20 @@ -1959,6 +2025,9 @@ static void ufs_init_hc(UfsHc *u) * dynamically */ u->temperature =3D UFS_TEMPERATURE; + + timer_init_ms(&u->idle_timer, QEMU_CLOCK_VIRTUAL_RT, ufs_idle_timer_cb= , u); + timer_mod(&u->idle_timer, now + UFS_IDLE_TIMER_TICK); } =20 static void ufs_realize(PCIDevice *pci_dev, Error **errp) @@ -1986,6 +2055,8 @@ static void ufs_exit(PCIDevice *pci_dev) { UfsHc *u =3D UFS(pci_dev); =20 + timer_del(&u->idle_timer); + qemu_free_irq(u->irq); =20 qemu_bh_delete(u->doorbell_bh); diff --git a/hw/ufs/ufs.h b/hw/ufs/ufs.h index 13d964c5ae5ec430a98b2ef71987cb9279e9a317..b5f040302129f4d02732ddd20ef= 82eb33c41922a 100644 --- a/hw/ufs/ufs.h +++ b/hw/ufs/ufs.h @@ -148,6 +148,8 @@ typedef struct UfsHc { UfsCq *cq[UFS_MAX_MCQ_QNUM]; =20 uint8_t temperature; + + QEMUTimer idle_timer; } UfsHc; =20 static inline uint32_t ufs_mcq_sq_tail(UfsHc *u, uint32_t qid) --=20 2.48.1 From nobody Tue Apr 21 14:39:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776663090; cv=none; d=zohomail.com; s=zohoarc; b=IvFJsKC2q8eyalcNMkzMUf1NoujWxmbAm9SaLZRd1HawXyNvo/r927kX9Lsfxz6PUXrx4YBP5lKvIUGRm75Ksl1pH23fY+ucWuEs+tqApbHa2TFXxYgrTFOwRWbmJ/mV5i5pR4yUbwmKk81/T9bEWSMydTCirzGCfTO96eTlzUA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776663090; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8O87Untgd2ja5zoymtIHsPWYco5t+oSB6+mY+a9OYMM=; b=PKpEFXb9Rts5L+kPFqGqLsTqlk3tPyl8MxaooLlx+BuWS2PEpvg3pIReuANMFm0ic3j2O9aNM7OH9FeT9XjWCWD77U2/XZCluM75ZQRCEvRW5C+L1jTz6a2D6NiQgGBWuKc3Q3azvK9Bo5mRfuCsGN41r6XK/ISIUUUS8oN83rw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776663090296547.7090417078997; Sun, 19 Apr 2026 22:31:30 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wEhCH-0008IF-7f; Mon, 20 Apr 2026 01:29:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wEhCC-0008Fb-41 for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:20 -0400 Received: from mail-pj1-x102b.google.com ([2607:f8b0:4864:20::102b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wEhC6-00082R-JY for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:19 -0400 Received: by mail-pj1-x102b.google.com with SMTP id 98e67ed59e1d1-35d965648a2so2235351a91.0 for ; Sun, 19 Apr 2026 22:29:12 -0700 (PDT) Received: from [172.17.0.5] ([168.126.243.22]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab3ad18sm93099675ad.71.2026.04.19.22.29.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 22:29:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776662951; x=1777267751; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=8O87Untgd2ja5zoymtIHsPWYco5t+oSB6+mY+a9OYMM=; b=YwHnR6K38s49WXTWIaOlLNJ+6RMg+kX3xrKzxCmvhM7Xy01xjRdcv6p7ZYh4BNkB0x FIOeAvCU22L/gbLls0+8DU3mErTRSFHj5N2S094JFyuK4LRibnv3aMDqRs3ZZEtxlGRX UMmqtjGvKnTtzBeZJDkN9kV1yzcgIHEQ/UN1tDizFePXH7VaTujvM5QhJYp8B542rmXp djhXs/EUtQng7ImfOm67CrSf/Kv+Hq2+Phpn8TE3yywps/nG//rrnLCr/rIaTIJCbltY ckeugzsywR6hzhMxzM9bZtbVjRpUCAE0VO96AQ4bRxA/IKOPnXaUADaqjpLJUaNBBu4i RXAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776662951; x=1777267751; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=8O87Untgd2ja5zoymtIHsPWYco5t+oSB6+mY+a9OYMM=; b=WM8VVsDWUmT4RGV5U8+5Q2zKbw8r08EIJBSuGNkxKLT4qxmyKKXHQBJ4HrHPP95uTF OnKh8YorjSZ/t63eXWxvp/6XvYXFmnkMNs2EJ7wKefrfQM9TXLH18k/yDJTPQM1c41sL 9j1ZQ8jBeXSdcmoBwu64cMmizMcTKRVWK0rIaCOmNd2MEiNcDXRDnXA9h4W3pcXjaA+4 s85wxvnWHCQJ/Lc6itI86d5j+pe+P9yc7Pbi9nPtuNiACYgR7WmcRa/y8aHQrSfJJSbF psp3zIodMq2hqcBQiVb/X8NfIEr+kn476I0Dw1keYR4kNX7oLth29dk+47ceG7wdxZz5 ibOQ== X-Gm-Message-State: AOJu0YzQvWtkGziwT5g52iRPw53y/4tVA/PkhnxViYzhSYS1sJ+Ez8uH lSTLXIfEyq0qMMf79iZzdY/i7oWSSAuByInhgzESFwNYTKY4u+dJyThGg0EFDFkCZsg= X-Gm-Gg: AeBDietlBmfXubzjsXK2ZvmjuQg3Bip1NQ+1UIeSXypuVx8eBU6ogc/isMlVNGtxeS5 E+e63otom0E0+6+NsqctLn90QGO16PuijEjj0sjB+jSM19cKmiQpykrs4NGzTv/iqKd2bFc1ALl WlF6PCE0zjn67oyR4MNJQbto5Gbcr9ZgBYgvl4B6kM5JWMNT6yJmHCClRugx3zR9Z3yHUT7wngw 66DZW6paOmcjXbHIuj3WRDJjhP8771jlG23qncGl5221bxfqz2vvyjZYtMD1Sn3txeTBtBPaZVf Q1k3UPMP6OFO2lW/tHOOEsIbTInPXd2j8HWf4J0zZEYDkFAkbi24+iim62gANeRuT6a+/vKPPmr SVxezvCRjF9V9fHM2w0BN79OiYWjvt05Mmr79Mat2kKqffZ7G5UvByHn5YIFIjhYY6QZkdgzqwg kn+Y+r50gCTN9yFNaKsVa+b5pOAqXOVpGIc4zjoCsM X-Received: by 2002:a17:90b:2785:b0:35d:9efd:7956 with SMTP id 98e67ed59e1d1-361403f0fa6mr13478949a91.11.1776662950734; Sun, 19 Apr 2026 22:29:10 -0700 (PDT) From: Jaemyung Lee X-Google-Original-From: Jaemyung Lee Date: Mon, 20 Apr 2026 14:28:52 +0900 Subject: [PATCH v6 4/5] hw/ufs: Add UFS Write Booster Support MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260420-write_booster-v6-4-8c49acba03d4@samsung.com> References: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> In-Reply-To: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> To: qemu-devel@nongnu.org Cc: Jeuk Kim , Kevin Wolf , Hanna Reitz , qemu-block@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Jaemyung Lee X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1776662940; l=26500; i=jaemyung.lee@samsung.com; s=20260402; h=from:subject:message-id; bh=yFMWzjnf+Mp6Xk3PRYRL+yNQ2lD5iySwbfTktOCYeBA=; b=V/cMvrb+wKCxUSToQACQe9BvheUi32hIVmh5QZPDKF7yC6pQaTTQTgyJfyiQ7/fu0wE/xnlan G8vg6L6IRt6D7NU7K535S6keXSRhwy1SBGmeeItIBg0F7XQ4PxeQElW X-Developer-Key: i=jaemyung.lee@samsung.com; a=ed25519; pk=bZPd7A/kteUO62FfUM6IrI1LuBPe5QrcqfvsitM1ZjE= Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::102b; envelope-from=ldc.jml@gmail.com; helo=mail-pj1-x102b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776663092568158500 Add UFS Write Booster implementation which follows UFS 4.1 Spec. Signed-off-by: Jaemyung Lee --- hw/ufs/lu.c | 97 ++++++++++++++- hw/ufs/ufs.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++++= +--- hw/ufs/ufs.h | 47 +++++++ include/block/ufs.h | 51 ++++++++ 4 files changed, 524 insertions(+), 16 deletions(-) diff --git a/hw/ufs/lu.c b/hw/ufs/lu.c index 3f3c9589cee57ae3e77e2f486476d5fcec204d80..fd8c9ef6007c2b093a1594a6aaa= 35f98a5fefdea 100644 --- a/hw/ufs/lu.c +++ b/hw/ufs/lu.c @@ -58,13 +58,108 @@ static void ufs_build_scsi_response_upiu(UfsRequest *r= eq, uint8_t *sense, status, data_segment_length); } =20 +#define UFS_GROUP_NUMBER_MASK 0x1F +#define UFS_WB_GROUP_NUMBER_DEFAULT 0x00 /* 00000b */ +#define UFS_WB_GROUP_NUMBER_PINNED 0x18 /* 11000b */ +static bool ufs_wb_check_write_pinned(UfsHc *u, UfsRequest *req) +{ + uint8_t cmd =3D req->req_upiu.sc.cdb[0]; + uint8_t group_number =3D UFS_WB_GROUP_NUMBER_DEFAULT; + + if (u->attributes.wb_buffer_partial_flush_mode !=3D UFS_WB_FLUSH_PINNE= D) { + return false; + } + + if (cmd =3D=3D WRITE_16) { + group_number =3D req->req_upiu.sc.cdb[14] & UFS_GROUP_NUMBER_MASK; + + } else if (cmd =3D=3D WRITE_10) { + group_number =3D req->req_upiu.sc.cdb[6] & UFS_GROUP_NUMBER_MASK; + } + + return (group_number =3D=3D UFS_WB_GROUP_NUMBER_PINNED); +} + +#define UFS_WB_TOTAL_WRITTEN_DIV (10 * 1024 * 1024) /* 10MiB */ +static void ufs_wb_process_write_pinned(UfsHc *u, uint32_t transfered_len) +{ + UfsWb *wb =3D &u->wb; + uint64_t remain_bytes, remain_data; + uint32_t total_written; + + if (!wb->pinned_curr_bytes) { + return; + } + + if (wb->pinned_used_bytes >=3D wb->pinned_curr_bytes) { + return; + } + + remain_bytes =3D wb->pinned_curr_bytes - wb->pinned_used_bytes; + if (remain_bytes >=3D transfered_len) { + wb->pinned_total_written_bytes +=3D transfered_len; + wb->pinned_used_bytes +=3D transfered_len; + remain_data =3D 0; + + } else { + wb->pinned_total_written_bytes +=3D remain_bytes; + wb->pinned_used_bytes +=3D remain_bytes; + remain_data =3D transfered_len - remain_bytes; + } + + total_written =3D wb->pinned_total_written_bytes / UFS_WB_TOTAL_WRITTE= N_DIV; + u->attributes.pinned_wb_cumm_written_size =3D cpu_to_be32(total_writte= n); + + remain_bytes =3D wb->curr_bytes - wb->used_bytes; + wb->used_bytes +=3D MIN(remain_bytes, remain_data); +} + +static void ufs_wb_process_write_normal(UfsHc *u, uint32_t transfered_len) +{ + UfsWb *wb =3D &u->wb; + uint64_t curr_bytes, used_bytes, remain_bytes; + + if (!wb->curr_bytes) { + return; + } + + curr_bytes =3D wb->curr_bytes - wb->pinned_curr_bytes; + used_bytes =3D wb->used_bytes - wb->pinned_used_bytes; + + if (used_bytes >=3D curr_bytes) { + return; + } + + remain_bytes =3D curr_bytes - used_bytes; + wb->used_bytes +=3D MIN(remain_bytes, transfered_len); +} + +static void ufs_wb_process_write_req(UfsRequest *req, uint32_t transfered_= len) +{ + UfsHc *u =3D req->hc; + + if (!u->flags.wb_en || !ufs_is_write_req(req)) { + return; + } + + if (ufs_wb_check_write_pinned(u, req)) { + ufs_wb_process_write_pinned(u, transfered_len); + } else { + ufs_wb_process_write_normal(u, transfered_len); + } +} + static void ufs_scsi_command_complete(SCSIRequest *scsi_req, size_t resid) { UfsRequest *req =3D scsi_req->hba_private; int16_t status =3D scsi_req->status; - uint32_t transfered_len =3D scsi_req->cmd.xfer - resid; =20 + /* WB accounting should only happen for successful commands */ + if (status =3D=3D GOOD) { + ufs_wb_process_write_req(req, transfered_len); + } + ufs_build_scsi_response_upiu(req, scsi_req->sense, scsi_req->sense_len, transfered_len, status); =20 diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index c504a0d7e3fb89eb5558cfd9c410cda9396bc3b4..c26a906d4bb445cde9c754427be= db2b53f4effee 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -996,11 +996,15 @@ static const int flag_permission[UFS_QUERY_FLAG_IDN_C= OUNT] =3D { [UFS_QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL] =3D UFS_QUERY_FLAG_READ, [UFS_QUERY_FLAG_IDN_BUSY_RTC] =3D UFS_QUERY_FLAG_READ, [UFS_QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE] =3D UFS_QUERY_FLAG_= READ, - /* Write Booster is not supported */ - [UFS_QUERY_FLAG_IDN_WB_EN] =3D UFS_QUERY_FLAG_READ, - [UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN] =3D UFS_QUERY_FLAG_READ, + [UFS_QUERY_FLAG_IDN_WB_EN] =3D UFS_QUERY_FLAG_READ | UFS_QUERY_FLAG_SE= T | + UFS_QUERY_FLAG_CLEAR | UFS_QUERY_FLAG_TOG= GLE, + [UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN] =3D + UFS_QUERY_FLAG_READ | UFS_QUERY_FLAG_SET | UFS_QUERY_FLAG_CLEAR | + UFS_QUERY_FLAG_TOGGLE, [UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8] =3D UFS_QUERY_FLAG_R= EAD, - [UFS_QUERY_FLAG_IDN_UNPIN_EN] =3D UFS_QUERY_FLAG_READ, + [UFS_QUERY_FLAG_IDN_UNPIN_EN] =3D UFS_QUERY_FLAG_READ | UFS_QUERY_FLAG= _SET | + UFS_QUERY_FLAG_CLEAR | + UFS_QUERY_FLAG_TOGGLE, }; =20 static inline QueryRespCode ufs_flag_check_idn_valid(uint8_t idn, int op) @@ -1097,6 +1101,9 @@ static QueryRespCode ufs_write_flag_value(UfsHc *u, u= int8_t idn, uint8_t value) case UFS_QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8: u->flags.wb_buffer_flush_during_hibernate =3D value; break; + case UFS_QUERY_FLAG_IDN_UNPIN_EN: + u->flags.unpin_en =3D value; + break; default: return UFS_QUERY_RESULT_INVALID_VALUE; } @@ -1189,16 +1196,20 @@ static const int attr_permission[UFS_QUERY_ATTR_IDN= _COUNT] =3D { [UFS_QUERY_ATTR_IDN_HID_PROG_RATIO] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_HID_STATE] =3D UFS_QUERY_ATTR_READ, [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_HINT] =3D UFS_QUERY_ATTR_READ, - [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN] =3D UFS_QUERY_ATTR_READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN] =3D UFS_QUERY_ATTR_WRITE, [UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_STATUS] =3D UFS_QUERY_ATTR_READ, - [UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATTR_REA= D, - [UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATTR= _READ, + [UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE] =3D + UFS_QUERY_ATTR_READ | UFS_QUERY_ATTR_WRITE, + [UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE] =3D + UFS_QUERY_ATTR_READ | UFS_QUERY_ATTR_WRITE, [UFS_QUERY_ATTR_IDN_CURR_FIFO_WB_PARTIAL_FLUSH_MODE] =3D UFS_QUERY_ATT= R_READ, [UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_CURR_ALLOC_UNITS] =3D UFS_QUERY_ATT= R_READ, [UFS_QUERY_ATTR_IDN_PINNED_WB_BUFF_AVAIL_PERCENT] =3D UFS_QUERY_ATTR_R= EAD, [UFS_QUERY_ATTR_IDN_PINNED_WB_CUMM_WRITTEN_SIZE] =3D UFS_QUERY_ATTR_RE= AD, - [UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS] =3D UFS_QUERY_ATTR_READ, - [UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS] =3D UFS_QUERY_A= TTR_READ, + [UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS] =3D + UFS_QUERY_ATTR_READ | UFS_QUERY_ATTR_WRITE, + [UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS] =3D + UFS_QUERY_ATTR_READ | UFS_QUERY_ATTR_WRITE, }; =20 static inline QueryRespCode ufs_attr_check_idn_valid(uint8_t idn, int op) @@ -1238,6 +1249,31 @@ static inline uint8_t ufs_read_device_temp(UfsHc *u) return 0; } =20 +static inline uint32_t ufs_wb_read_flush_status(UfsHc *u) +{ + uint32_t value =3D u->attributes.wb_buffer_flush_status; + + if (value =3D=3D UFS_WB_FLUSH_SUSPENDED || + value =3D=3D UFS_WB_FLUSH_COMPLETED || + value =3D=3D UFS_WB_FLUSH_FAILED) { + u->attributes.wb_buffer_flush_status =3D UFS_WB_FLUSH_IDLE; + } + + return value; +} + +static inline uint32_t ufs_wb_read_resize_status(UfsHc *u) +{ + uint32_t value =3D u->attributes.wb_buffer_resize_status; + + if (value =3D=3D UFS_WB_RESIZE_COMPLETED || + value =3D=3D UFS_WB_RESIZE_FAILED) { + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_IDLE; + } + + return value; +} + static uint32_t ufs_read_attr_value(UfsHc *u, uint8_t idn) { switch (idn) { @@ -1292,7 +1328,7 @@ static uint32_t ufs_read_attr_value(UfsHc *u, uint8_t= idn) case UFS_QUERY_ATTR_IDN_THROTTLING_STATUS: return u->attributes.throttling_status; case UFS_QUERY_ATTR_IDN_WB_FLUSH_STATUS: - return u->attributes.wb_buffer_flush_status; + return ufs_wb_read_flush_status(u); case UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE: return u->attributes.available_wb_buffer_size; case UFS_QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST: @@ -1323,10 +1359,8 @@ static uint32_t ufs_read_attr_value(UfsHc *u, uint8_= t idn) return u->attributes.hid_state; case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_HINT: return u->attributes.wb_buffer_resize_hint; - case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN: - return u->attributes.wb_buffer_resize_en; case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_STATUS: - return u->attributes.wb_buffer_resize_status; + return ufs_wb_read_resize_status(u); case UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE: return u->attributes.wb_buffer_partial_flush_mode; case UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE: @@ -1347,6 +1381,32 @@ static uint32_t ufs_read_attr_value(UfsHc *u, uint8_= t idn) return 0; } =20 +static void ufs_wb_resize_op(UfsHc *u, uint32_t value) +{ + if (u->attributes.wb_buffer_resize_status =3D=3D UFS_WB_RESIZE_IN_PROG= RESS) { + return; + } + + u->attributes.wb_buffer_resize_en =3D value; + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_IN_PROGRESS; +} + +static void ufs_wb_pinned_max_size(UfsHc *u, uint32_t value) +{ + UfsWb *wb =3D &u->wb; + + u->attributes.pinned_wb_num_alloc_units =3D cpu_to_be32(value); + wb->pinned_max_bytes =3D ufs_unit_to_byte(u, value); +} + +static void ufs_wb_pinned_min_size(UfsHc *u, uint32_t value) +{ + UfsWb *wb =3D &u->wb; + + u->attributes.non_pinned_wb_min_num_alloc_units =3D cpu_to_be32(value); + wb->pinned_min_bytes =3D ufs_unit_to_byte(u, value); +} + static QueryRespCode ufs_write_attr_value(UfsHc *u, uint8_t idn, uint32_t = value) { switch (idn) { @@ -1383,6 +1443,30 @@ static QueryRespCode ufs_write_attr_value(UfsHc *u, = uint8_t idn, uint32_t value) case UFS_QUERY_ATTR_IDN_TIMESTAMP: u->attributes.timestamp =3D cpu_to_be64(value); break; + case UFS_QUERY_ATTR_IDN_WB_BUFF_RESIZE_EN: + if (value >=3D UFS_WB_RESIZE_OP_MAX) { + return UFS_QUERY_RESULT_INVALID_VALUE; + } + ufs_wb_resize_op(u, value); + break; + case UFS_QUERY_ATTR_IDN_WB_BUFF_PARTIAL_FLUSH_MODE: + if (value >=3D UFS_WB_FLUSH_MODE_MAX) { + return UFS_QUERY_RESULT_INVALID_VALUE; + } + u->attributes.wb_buffer_partial_flush_mode =3D value; + break; + case UFS_QUERY_ATTR_IDN_MAX_FIFO_WB_PARTIAL_FLUSH_MODE: + if (value > u->params.wb_max_size) { + return UFS_QUERY_RESULT_INVALID_VALUE; + } + u->attributes.max_fifo_wb_partial_flush_mode =3D cpu_to_be32(value= ); + break; + case UFS_QUERY_ATTR_IDN_PINNED_WB_NUM_ALLOC_UNITS: + ufs_wb_pinned_max_size(u, value); + break; + case UFS_QUERY_ATTR_IDN_NON_PINNED_WB_MIN_NUM_ALLOC_UNITS: + ufs_wb_pinned_min_size(u, value); + break; default: g_assert_not_reached(); return 0; @@ -1801,9 +1885,177 @@ static void ufs_sendback_req(void *opaque) ufs_irq_check(u); } =20 +static inline void ufs_wb_update_avail_buffer(UfsHc *u) +{ + UfsWb *wb =3D &u->wb; + uint64_t non_pinned_curr_bytes, non_pinned_used_bytes; + uint32_t units; + + units =3D ufs_byte_to_unit(u, wb->pinned_curr_bytes); + u->attributes.pinned_wb_buffer_curr_alloc_units =3D cpu_to_be32(units); + + if (!wb->pinned_curr_bytes) + u->attributes.pinned_wb_buffer_avail_percent =3D 0; + else + u->attributes.pinned_wb_buffer_avail_percent =3D + (wb->pinned_curr_bytes - wb->pinned_used_bytes) * 10 / + wb->pinned_curr_bytes; + + non_pinned_curr_bytes =3D wb->curr_bytes - wb->pinned_curr_bytes; + non_pinned_used_bytes =3D wb->used_bytes - wb->pinned_used_bytes; + + units =3D ufs_byte_to_unit(u, non_pinned_curr_bytes); + u->attributes.current_wb_buffer_size =3D cpu_to_be32(units); + + if (!non_pinned_curr_bytes) + u->attributes.available_wb_buffer_size =3D 0; + else + u->attributes.available_wb_buffer_size =3D + (non_pinned_curr_bytes - non_pinned_used_bytes) * 10 / + non_pinned_curr_bytes; +} + +static inline bool ufs_wb_is_flush_needed(UfsHc *u, uint64_t *no_flush_byt= es) +{ + UfsWb *wb =3D &u->wb; + uint32_t max_unit; + + switch (u->attributes.wb_buffer_partial_flush_mode) { + case UFS_WB_FLUSH_NONE: + *no_flush_bytes =3D 0; + break; + case UFS_WB_FLUSH_FIFO: + max_unit =3D be32_to_cpu(u->attributes.max_fifo_wb_partial_flush_m= ode); + *no_flush_bytes =3D ufs_unit_to_byte(u, max_unit); + break; + case UFS_WB_FLUSH_PINNED: + *no_flush_bytes =3D (u->flags.unpin_en) ? 0 : wb->pinned_used_byte= s; + break; + default: + g_assert_not_reached(); + break; + } + + return wb->used_bytes > *no_flush_bytes; +} + +#define UFS_WB_FLUSH_BYTES (4096 * 1024) +static void ufs_wb_process_flush(UfsHc *u) +{ + UfsWb *wb =3D &u->wb; + uint64_t flush_bytes, no_flush_bytes; + + switch (u->attributes.wb_buffer_flush_status) { + case UFS_WB_FLUSH_IDLE: + if (u->flags.wb_buffer_flush_en && + ufs_wb_is_flush_needed(u, &no_flush_bytes)) { + u->attributes.wb_buffer_flush_status =3D UFS_WB_FLUSH_IN_PROGR= ESS; + } + + break; + case UFS_WB_FLUSH_IN_PROGRESS: + if (!u->flags.wb_buffer_flush_en) { + u->attributes.wb_buffer_flush_status =3D UFS_WB_FLUSH_SUSPENDE= D; + + } else if (!ufs_wb_is_flush_needed(u, &no_flush_bytes)) { + u->attributes.wb_buffer_flush_status =3D UFS_WB_FLUSH_COMPLETE= D; + + } else if (wb->pinned_used_bytes && u->flags.unpin_en) { + flush_bytes =3D MIN(wb->pinned_used_bytes, UFS_WB_FLUSH_BYTES); + wb->pinned_used_bytes -=3D flush_bytes; + wb->used_bytes -=3D flush_bytes; + + } else { + flush_bytes =3D MIN(wb->used_bytes - no_flush_bytes, UFS_WB_FL= USH_BYTES); + wb->used_bytes -=3D flush_bytes; + } + + break; + case UFS_WB_FLUSH_COMPLETED: + if (ufs_wb_is_flush_needed(u, &no_flush_bytes)) { + u->attributes.wb_buffer_flush_status =3D + (u->flags.wb_buffer_flush_en) ? UFS_WB_FLUSH_IN_PROGRESS : + UFS_WB_FLUSH_IDLE; + } + } +} + +static void ufs_wb_process_resize(UfsHc *u) +{ + UfsWb *wb =3D &u->wb; + + if (u->attributes.wb_buffer_resize_status !=3D UFS_WB_RESIZE_IN_PROGRE= SS) { + return; + } + + switch (u->attributes.wb_buffer_resize_en) { + case UFS_WB_DECREASE: + if (wb->curr_bytes <=3D wb->min_bytes) { + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_FAILED; + return; + + } else if (wb->curr_bytes <=3D wb->used_bytes) { + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_FAILED; + return; + } + + if (wb->curr_bytes - wb->used_bytes >=3D wb->resize_bytes) { + wb->curr_bytes -=3D wb->resize_bytes; + } else { + wb->curr_bytes =3D wb->used_bytes; + } + + if (wb->curr_bytes < wb->min_bytes) { + wb->curr_bytes =3D wb->min_bytes; + } + + break; + case UFS_WB_INCREASE: + if (wb->curr_bytes >=3D wb->max_bytes) { + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_FAILED; + return; + } + + wb->curr_bytes +=3D wb->resize_bytes; + if (wb->curr_bytes >=3D wb->max_bytes) { + wb->curr_bytes =3D wb->max_bytes; + } + + break; + default: + g_assert_not_reached(); + break; + } + + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_COMPLETED; +} + +static void ufs_wb_process_pinned(UfsHc *u) +{ + UfsWb *wb =3D &u->wb; + uint64_t avail_bytes; + + avail_bytes =3D wb->curr_bytes - wb->used_bytes + wb->pinned_used_byte= s; + + if ((u->attributes.wb_buffer_partial_flush_mode !=3D UFS_WB_FLUSH_PINN= ED) || + (wb->curr_bytes <=3D wb->pinned_min_bytes)) { + wb->pinned_curr_bytes =3D 0; + wb->pinned_used_bytes =3D 0; + + } else if (avail_bytes <=3D wb->pinned_max_bytes) { + wb->pinned_curr_bytes =3D avail_bytes; + + } else { + wb->pinned_curr_bytes =3D wb->pinned_max_bytes; + } +} + static void ufs_process_idle(UfsHc *u) { - /* Currently do nothing */ + ufs_wb_process_flush(u); + ufs_wb_process_resize(u); + ufs_wb_process_pinned(u); + ufs_wb_update_avail_buffer(u); return; } =20 @@ -1885,6 +2137,11 @@ static bool ufs_check_constraints(UfsHc *u, Error **= errp) return false; } =20 + if (u->params.wb_min_size > u->params.wb_max_size) { + error_setg(errp, "wb-min-size must be less than or equal wb-max-si= ze"); + return false; + } + return true; } =20 @@ -1923,11 +2180,47 @@ static void ufs_init_state(UfsHc *u) } } =20 +static void ufs_wb_init(UfsHc *u) +{ + UfsWb *wb =3D &u->wb; + uint32_t max_units =3D u->params.wb_max_size; + + wb->max_bytes =3D ufs_unit_to_byte(u, max_units); + wb->min_bytes =3D ufs_unit_to_byte(u, max_units); + + wb->curr_bytes =3D wb->max_bytes; + wb->used_bytes =3D 0; + wb->resize_bytes =3D (wb->max_bytes - wb->min_bytes) / 10; + + u->attributes.wb_buffer_flush_status =3D UFS_WB_FLUSH_IDLE; + u->attributes.available_wb_buffer_size =3D 0xA; + u->attributes.wb_buffer_life_time_est =3D 0x1; + u->attributes.current_wb_buffer_size =3D cpu_to_be32(max_units); + + u->attributes.wb_buffer_resize_hint =3D UFS_WB_HINT_KEEP; + u->attributes.wb_buffer_resize_status =3D UFS_WB_RESIZE_IDLE; + + u->attributes.wb_buffer_partial_flush_mode =3D UFS_WB_FLUSH_NONE; + + u->attributes.max_fifo_wb_partial_flush_mode =3D cpu_to_be32(max_units= ); + u->attributes.pinned_wb_num_alloc_units =3D cpu_to_be32(max_units); + u->attributes.non_pinned_wb_min_num_alloc_units =3D 0; + + wb->pinned_curr_bytes =3D 0; + wb->pinned_used_bytes =3D 0; + wb->pinned_min_bytes =3D 0; + wb->pinned_total_written_bytes =3D 0; +} + static void ufs_init_hc(UfsHc *u) { uint32_t cap =3D 0; uint32_t mcqconfig =3D 0; uint32_t mcqcap =3D 0; + uint32_t ext_wb_sup =3D WB_RESIZE | WB_FIFO | WB_PINNED; + uint32_t ext_ufs_feat_sup =3D UFS_DEV_WB_SUPPORT | + UFS_DEV_HIGH_TEMP_NOTIF | + UFS_DEV_LOW_TEMP_NOTIF; int64_t now =3D qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT); =20 u->reg_size =3D pow2ceil(ufs_reg_size(u)); @@ -1989,8 +2282,13 @@ static void ufs_init_hc(UfsHc *u) UFS_DEV_LOW_TEMP_NOTIF; u->device_desc.queue_depth =3D u->params.nutrs; u->device_desc.product_revision_level =3D 0x04; + u->device_desc.extended_wb_support |=3D cpu_to_be16(ext_wb_sup); u->device_desc.extended_ufs_features_support =3D - cpu_to_be32(UFS_DEV_HIGH_TEMP_NOTIF | UFS_DEV_LOW_TEMP_NOTIF); + cpu_to_be32((ext_ufs_feat_sup)); + u->device_desc.write_booster_buffer_preserve_user_space_en =3D 0x01; + u->device_desc.write_booster_buffer_type =3D 0x01; + u->device_desc.num_shared_write_booster_buffer_alloc_units =3D + cpu_to_be32(u->params.wb_max_size); =20 memset(&u->geometry_desc, 0, sizeof(GeometryDescriptor)); u->geometry_desc.length =3D sizeof(GeometryDescriptor); @@ -2006,6 +2304,16 @@ static void ufs_init_hc(UfsHc *u) 0x0; /* out-of-order data transfer is not supported */ u->geometry_desc.max_context_id_number =3D 0x5; u->geometry_desc.supported_memory_types =3D cpu_to_be16(0x8001); + u->geometry_desc.write_booster_buffer_max_n_alloc_units =3D + cpu_to_be32(u->params.wb_max_size); + u->geometry_desc.device_max_write_booster_l_us =3D + u->params.wb_max_lus; + u->geometry_desc.write_booster_buffer_cap_adj_fac =3D + u->params.wb_cap_adj_fac; + u->geometry_desc.supported_write_booster_buffer_user_space_reduction_t= ypes =3D + u->params.wb_reduction; + u->geometry_desc.supported_write_booster_buffer_types =3D + 0x1; /* lu-dedicated buffer type is not supported */ =20 memset(&u->attributes, 0, sizeof(u->attributes)); u->attributes.max_data_in_size =3D 0x08; @@ -2020,6 +2328,8 @@ static void ufs_init_hc(UfsHc *u) memset(&u->flags, 0, sizeof(u->flags)); u->flags.permanently_disable_fw_update =3D 1; =20 + ufs_wb_init(u); + /* * The temperature value is fixed to UFS_TEMPERATURE and does not chan= ge * dynamically @@ -2085,6 +2395,11 @@ static const Property ufs_props[] =3D { DEFINE_PROP_UINT8("nutmrs", UfsHc, params.nutmrs, 8), DEFINE_PROP_BOOL("mcq", UfsHc, params.mcq, false), DEFINE_PROP_UINT8("mcq-maxq", UfsHc, params.mcq_maxq, 2), + DEFINE_PROP_UINT32("wb-max-size", UfsHc, params.wb_max_size, 0x400), + DEFINE_PROP_UINT32("wb-min-size", UfsHc, params.wb_min_size, 0x100), + DEFINE_PROP_UINT8("wb-max-lus", UfsHc, params.wb_max_lus, 1), + DEFINE_PROP_UINT8("wb-cap-adj-fac", UfsHc, params.wb_cap_adj_fac, 3), + DEFINE_PROP_UINT8("wb-reduction", UfsHc, params.wb_reduction, 1), }; =20 static const VMStateDescription ufs_vmstate =3D { diff --git a/hw/ufs/ufs.h b/hw/ufs/ufs.h index b5f040302129f4d02732ddd20ef82eb33c41922a..42a20245128a765afc256034213= 5ced81dcc684c 100644 --- a/hw/ufs/ufs.h +++ b/hw/ufs/ufs.h @@ -91,6 +91,11 @@ typedef struct UfsParams { bool mcq; /* Multiple Command Queue support */ uint8_t mcq_qcfgptr; /* MCQ Queue Configuration Pointer in MCQCAP */ uint8_t mcq_maxq; /* MCQ Maximum number of Queues */ + uint32_t wb_max_size; /* WB Maximum allocation units */ + uint32_t wb_min_size; /* WB Minimum allocation units */ + uint8_t wb_max_lus; /* WB Maximum number of LUs */ + uint8_t wb_cap_adj_fac; /* WB Capacity Adjustment Factor */ + uint8_t wb_reduction; /* WB User Space Reduction */ } UfsParams; =20 /* @@ -118,6 +123,24 @@ typedef struct UfsCq { QTAILQ_HEAD(, UfsRequest) req_list; } UfsCq; =20 +/* + * Extended features + */ +typedef struct UfsWb { + struct UfsHc *u; + uint64_t max_bytes; + uint64_t min_bytes; + uint64_t curr_bytes; + uint64_t used_bytes; + uint64_t resize_bytes; + + uint64_t pinned_max_bytes; + uint64_t pinned_min_bytes; + uint64_t pinned_curr_bytes; + uint64_t pinned_used_bytes; + uint64_t pinned_total_written_bytes; +} UfsWb; + typedef struct UfsHc { PCIDevice parent_obj; UfsBus bus; @@ -147,6 +170,9 @@ typedef struct UfsHc { UfsSq *sq[UFS_MAX_MCQ_QNUM]; UfsCq *cq[UFS_MAX_MCQ_QNUM]; =20 + /* Extended features */ + UfsWb wb; + uint8_t temperature; =20 QEMUTimer idle_timer; @@ -211,6 +237,27 @@ static inline bool ufs_mcq_cq_full(UfsHc *u, uint32_t = qid) return tail =3D=3D ufs_mcq_cq_head(u, qid); } =20 +static inline uint64_t ufs_unit_to_byte(UfsHc *u, uint32_t unit) +{ + return (uint64_t)unit * u->geometry_desc.allocation_unit_size * + be32_to_cpu(u->geometry_desc.segment_size) * BDRV_SECTOR_SIZE; +} + +static inline uint32_t ufs_byte_to_unit(UfsHc *u, uint64_t byte) +{ + return byte / BDRV_SECTOR_SIZE / + be32_to_cpu(u->geometry_desc.segment_size) / + u->geometry_desc.allocation_unit_size; +} + +static inline bool ufs_is_write_req(UfsRequest *req) +{ + uint8_t cmd =3D req->req_upiu.sc.cdb[0]; + + /* UFS 4.1 Specifiaction doesn't support WRITE_12 */ + return (cmd =3D=3D WRITE_6) || (cmd =3D=3D WRITE_10) || (cmd =3D=3D WR= ITE_16); +} + #define TYPE_UFS "ufs" #define UFS(obj) OBJECT_CHECK(UfsHc, (obj), TYPE_UFS) =20 diff --git a/include/block/ufs.h b/include/block/ufs.h index 4dacfb776f947a285d86018add82115f148b7dd9..aa0dde805826d0b06ab80fb7403= 4192ba06c2045 100644 --- a/include/block/ufs.h +++ b/include/block/ufs.h @@ -1126,11 +1126,24 @@ enum health_desc_param { UFS_HEALTH_DESC_PARAM_LIFE_TIME_EST_B =3D 0x4, }; =20 +/* Possible values for bUFSFeaturesSupport */ enum { UFS_DEV_HIGH_TEMP_NOTIF =3D BIT(4), UFS_DEV_LOW_TEMP_NOTIF =3D BIT(5), }; =20 +/* Possible values for dExtendedWriteBoosterSupport */ +enum { + WB_RESIZE =3D BIT(0), + WB_FIFO =3D BIT(1), + WB_PINNED =3D BIT(2), +}; + +/* Possible values for dExtendedUFSFeaturesSupport */ +enum { + UFS_DEV_WB_SUPPORT =3D BIT(8), +}; + /* WriteBooster buffer mode */ enum { UFS_WB_BUF_MODE_LU_DEDICATED =3D 0x0, @@ -1207,6 +1220,44 @@ enum ufs_dev_pwr_mode { UFS_DEEPSLEEP_PWR_MODE =3D 4, }; =20 +/* UFS Write Booster */ +enum ufs_wb_flush_status { + UFS_WB_FLUSH_IDLE =3D 0, + UFS_WB_FLUSH_IN_PROGRESS =3D 1, + UFS_WB_FLUSH_SUSPENDED =3D 2, + UFS_WB_FLUSH_COMPLETED =3D 3, + UFS_WB_FLUSH_FAILED =3D 4, + UFS_WB_FLUSH_STATUS_MAX, +}; + +enum ufs_wb_flush_mode { + UFS_WB_FLUSH_NONE =3D 0, + UFS_WB_FLUSH_FIFO =3D 1, + UFS_WB_FLUSH_PINNED =3D 2, + UFS_WB_FLUSH_MODE_MAX, +}; + +enum ufs_wb_resize_hint { + UFS_WB_HINT_KEEP =3D 0, + UFS_WB_HINT_DECREASE =3D 1, + UFS_WB_HINT_ENCREASE =3D 2, + UFS_WB_RESIZE_HINT_MAX, +}; + +enum ufs_wb_resize_op { + UFS_WB_DECREASE =3D 0, + UFS_WB_INCREASE =3D 1, + UFS_WB_RESIZE_OP_MAX, +}; + +enum ufs_wb_resize_status { + UFS_WB_RESIZE_IDLE =3D 0, + UFS_WB_RESIZE_IN_PROGRESS =3D 1, + UFS_WB_RESIZE_COMPLETED =3D 2, + UFS_WB_RESIZE_FAILED =3D 3, + UFS_WB_RESIZE_STATUS_MAX, +}; + /* * struct UtpCmdRsp - Response UPIU structure * @residual_transfer_count: Residual transfer count DW-3 --=20 2.48.1 From nobody Tue Apr 21 14:39:41 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1776663067; cv=none; d=zohomail.com; s=zohoarc; b=P9wdW47h1lHhA7naG4lIbe1156sTwoWnpcVesa1BNDY/R+Zq11QhvHKumTG9RknjVV7PS5duuFIEB49egkUTlQ3jOkeDYDB9qaOzvmabHq1BDfljW96D0Hz4dMSW25VI7ARp8DtaID1g1oqxsDXjrGbQZVttSN+w5lLDGUxqjv0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1776663067; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=UvnDam+RI7xNOArU3spJiI07Kx70RBnYFEvTvltBdIM=; b=UE8Q4VCUzMIEm4duHKwNdfRcIBvH2dhB+tVm33ThGuti8AwLF+9m64xfH1VNtgPm+dDZ7dPZVXGemcyrCC6eDasbUPOJaFBehOn/n2l7N7jF4iybaoZM62TwcHfhAaGoAEJrNUcnd7hhEmAheHGCEQWhjFVpu32zd/ODw7NjlZg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1776663067388782.6744691267869; Sun, 19 Apr 2026 22:31:07 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wEhCH-0008IQ-Af; Mon, 20 Apr 2026 01:29:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wEhCC-0008FZ-4r for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:20 -0400 Received: from mail-pj1-x1034.google.com ([2607:f8b0:4864:20::1034]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wEhC6-00082r-JJ for qemu-devel@nongnu.org; Mon, 20 Apr 2026 01:29:17 -0400 Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-35f9ab079bdso1578967a91.2 for ; Sun, 19 Apr 2026 22:29:13 -0700 (PDT) Received: from [172.17.0.5] ([168.126.243.22]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fab3ad18sm93099675ad.71.2026.04.19.22.29.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Apr 2026 22:29:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776662953; x=1777267753; darn=nongnu.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=UvnDam+RI7xNOArU3spJiI07Kx70RBnYFEvTvltBdIM=; b=jfoBZXp8oXEimEdtXmCutrViDXfJp4mq05XgwH6yGn6W41WHP/j1a5BR1gM51bVY/1 ieyWm5e7PuVP3tc4hZ2/9Ewoc4VQ87YRr3AtZJNEB5BV+bcCWFzt6EYLdKw0SRSOa0xF M4cHZUGJqx3p3FsT6ZLhHO41kGmzVQDV4XGgPS6gBeqP2xHE67jV6ZpiEJwA9lxbBPJE 4DE4HaV4tACxr1UqshGK5pZjo79l1J9RsfYhoRY7p8kCf9ZS9inzVWrClMHPoz2ZLDAb ceGv6YxFVmedjFilsxhqYrxyF8QiAHzmZ4dV3NzPeukxWJZXT/i7yWdYLG6NoDJNUC/k J4oQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776662953; x=1777267753; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=UvnDam+RI7xNOArU3spJiI07Kx70RBnYFEvTvltBdIM=; b=eg64EahrgZ8tPuQkWniZoEiQhh3yj4wjOVYgz7JRcYi5Q+Ih/BxPJmr1AipuBJJMZJ Bh4YbciSJBbAtFVq3CvTB97zuYLHw7982gcbXtvQPtLkB+JmKxA37hM6p82YDvYFSUS2 iWaoGJr/oWvVtCNVDdo+wO2AQSjdXgctuDoPRC/2Z83n9rZuqsAkmp6xJXaDvU1Hee55 D5uO36fSUTu19G90LXWOpZhCgBCrRuSf6/7l8ktB8H+JVp8S1e4mXd7HrNLl417nufEQ CqCECCBMieeqmVSJnEQM6e5xGbHayZJWvQjEwaVNZxuemkFeXZDDsTopYFFpsShsOr1O 0fLQ== X-Gm-Message-State: AOJu0YyL2pGbJ224S52vICK7+J8DlbIbA2WoV4Q6pnPNoms4bbZ2XOGt 1Ay6N7eyj/ElYPkKi9o9nUFKpJXoVEndwZ5ABSHxusS0npsHhg786fXIHmG9X9JzdA0= X-Gm-Gg: AeBDievWDze3hdgSPHMbYPI+DnyOZNX0FPhVUH9xmllkNpb4AhtT4kMmTWZ+KFG+i9D pTZ0mfThU9sCzjDCbntbPH+wkMdTWBuN82brKY+uqJLrAQuW2/bZeP81QsQrIG100muJPBxFBdX 70AfjGOH6c2VB8aOOtKiz14pjYPwW56UKmCoB8N1VGp0S5VQfVoeGd9eZg9u+G1b8WzHeIw0tVT 5ATcqenLKNVIwVqT3Op6gcZbK1LZizrRW5JwG60vFwREeCd8TOpExy4KP0LcmqPZxFKtva6r51D Ac+KwEYlYvNxejuG0EvjyMBJhu9d7CdUMF58zPJHhhr1MxzstHA7Bw+lVaaR9RTDy1sZ+WnaOvN zgI+80MqgfuPqDxpRR+KRiU0MvM/F2bPgdQaY4lLuG7lBny6fV/g3hMQckw4GvGq0XCvmEATDUv Jhc1Ztbau7LV4T6aqD5MOLWPN+fQnIVJehdd07fQFWxZ7u64D0Mg4= X-Received: by 2002:a17:903:1b6f:b0:2b2:4cd2:e16c with SMTP id d9443c01a7336-2b5f9f3c58amr118027145ad.20.1776662952815; Sun, 19 Apr 2026 22:29:12 -0700 (PDT) From: Jaemyung Lee X-Google-Original-From: Jaemyung Lee Date: Mon, 20 Apr 2026 14:28:53 +0900 Subject: [PATCH v6 5/5] tests/qtest: Add UFS Write Booster QTest MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260420-write_booster-v6-5-8c49acba03d4@samsung.com> References: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> In-Reply-To: <20260420-write_booster-v6-0-8c49acba03d4@samsung.com> To: qemu-devel@nongnu.org Cc: Jeuk Kim , Kevin Wolf , Hanna Reitz , qemu-block@nongnu.org, Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Jaemyung Lee X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1776662940; l=8918; i=jaemyung.lee@samsung.com; s=20260402; h=from:subject:message-id; bh=rU67KxRcVLL6ZVBVhiBQ/INRn8llY3KXffQmzbO047E=; b=f8YXU4vN/4n731hESBmuMmgJJ0TK+3IzIUik2wf7twoNcpfLGNC4/GnsbAsHjkI/ybLL3v0/4 O05I4HXQ0nUA3Ou/w5OwT4y75EuKcS/gkqwdFGv6r0Uj/XLGq8F3rSt X-Developer-Key: i=jaemyung.lee@samsung.com; a=ed25519; pk=bZPd7A/kteUO62FfUM6IrI1LuBPe5QrcqfvsitM1ZjE= Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1034; envelope-from=ldc.jml@gmail.com; helo=mail-pj1-x1034.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1776663068881154100 It adds 'wb-init' and 'wb-read-write' TCs into tests/qtest/ufs-test.c. 'wb-init' tests that the WB support is properly initialized with UFS device and 'wb-read-write' tests that WB can be enabled and WRITE I/O can be handled/buffered as a WB command. Signed-off-by: Jaemyung Lee --- tests/qtest/ufs-test.c | 176 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 176 insertions(+) diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index 7f999441552a105987aaaf8e2b976f4a05f953ed..253fea27a5e52619f433d150755= 00a566eddeccc 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -1182,6 +1182,173 @@ static void ufstest_query_desc_request(void *obj, v= oid *data, ufs_exit(ufs, alloc); } =20 +static void ufstest_wb_init(void *obj, void *data, QGuestAllocator *alloc) +{ + QUfs *ufs =3D obj; + enum UtpOcsCodes ocs; + UtpUpiuRsp rsp_upiu; + uint8_t *desc; + uint32_t value; + + ufs_init(ufs, alloc); + + /* Read Device Descriptor */ + ocs =3D ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, + UFS_UPIU_QUERY_OPCODE_READ_DESC, + UFS_QUERY_DESC_IDN_DEVICE, 0, 0, 0, &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.response, =3D=3D, UFS_COMMAND_RESULT_= SUCCESS); + g_assert_cmpuint(rsp_upiu.qr.opcode, =3D=3D, UFS_UPIU_QUERY_OPCODE_REA= D_DESC); + g_assert_cmpuint(rsp_upiu.qr.idn, =3D=3D, UFS_QUERY_DESC_IDN_DEVICE); + g_assert_cmpuint(rsp_upiu.qr.data[0], =3D=3D, sizeof(DeviceDescriptor)= ); + g_assert_cmpuint(rsp_upiu.qr.data[1], =3D=3D, UFS_QUERY_DESC_IDN_DEVIC= E); + + /* Check Write Booster Supportability */ + desc =3D rsp_upiu.qr.data; + + value =3D *(uint16_t *)(desc + UFS_DEVICE_DESC_PARAM_EXT_WB_SUP); + value =3D be16_to_cpu(value); + g_assert_cmpuint(value, =3D=3D, WB_RESIZE | WB_FIFO | WB_PINNED); + + value =3D *(uint32_t *)(desc + UFS_DEVICE_DESC_PARAM_EXT_UFS_FEATURE_S= UP); + value =3D be32_to_cpu(value); + g_assert_cmpuint(value & UFS_DEV_WB_SUPPORT, =3D=3D, UFS_DEV_WB_SUPPOR= T); + + /* Read Geometry Descriptor */ + ocs =3D ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, + UFS_UPIU_QUERY_OPCODE_READ_DESC, + UFS_QUERY_DESC_IDN_GEOMETRY, 0, 0, 0, &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.response, =3D=3D, UFS_COMMAND_RESULT_= SUCCESS); + g_assert_cmpuint(rsp_upiu.qr.data[0], =3D=3D, sizeof(GeometryDescripto= r)); + g_assert_cmpuint(rsp_upiu.qr.data[1], =3D=3D, UFS_QUERY_DESC_IDN_GEOME= TRY); + + /* Check Write Booster Configuration */ + desc =3D rsp_upiu.qr.data; + + value =3D *(uint32_t *)(desc + UFS_GEOMETRY_DESC_PARAM_WB_MAX_ALLOC_UN= ITS); + value =3D be32_to_cpu(value); + g_assert_cmpuint(value, =3D=3D, 1024); + + value =3D desc[UFS_GEOMETRY_DESC_PARAM_WB_MAX_WB_LUNS]; + g_assert_cmpuint(value, =3D=3D, 1); + + value =3D desc[UFS_GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ]; + g_assert_cmpuint(value, =3D=3D, 3); + + value =3D desc[UFS_GEOMETRY_DESC_PARAM_WB_SUP_RED_TYPE]; + g_assert_cmpuint(value, =3D=3D, 1); + + value =3D desc[UFS_GEOMETRY_DESC_PARAM_WB_SUP_WB_TYPE]; + g_assert_cmpuint(value, =3D=3D, 1); + + ufs_exit(ufs, alloc); +} + +static void ufstest_wb_read_write(void *obj, void *data, QGuestAllocator *= alloc) +{ + QUfs *ufs =3D obj; + uint8_t read_buf[4096] =3D { 0 }; + uint8_t write_buf[4096] =3D { 0 }; + const uint8_t read_capacity_cdb[UFS_CDB_SIZE] =3D { + /* allocation length 4096 */ + SERVICE_ACTION_IN_16, + SAI_READ_CAPACITY_16, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x00 + }; + const uint8_t request_sense_cdb[UFS_CDB_SIZE] =3D { + REQUEST_SENSE, + }; + const uint8_t write_cdb[UFS_CDB_SIZE] =3D { + /* WRITE(10) to LBA 0, transfer length 1 */ + WRITE_10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 + }; + uint32_t block_size; + enum UtpOcsCodes ocs; + UtpUpiuRsp rsp_upiu; + const int test_lun =3D 1; + uint64_t end_time; + + ufs_init(ufs, alloc); + + /* Clear Unit Attention */ + ocs =3D ufs_send_scsi_command(ufs, test_lun, request_sense_cdb, NULL, = 0, + read_buf, sizeof(read_buf), &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.scsi_status, =3D=3D, CHECK_CONDITION); + + /* Read capacity */ + ocs =3D ufs_send_scsi_command(ufs, test_lun, read_capacity_cdb, NULL, = 0, + read_buf, sizeof(read_buf), &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.scsi_status, =3D=3D, + UFS_COMMAND_RESULT_SUCCESS); + block_size =3D ldl_be_p(&read_buf[8]); + g_assert_cmpuint(block_size, =3D=3D, 4096); + + /* Check available buffer size */ + ocs =3D ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQUEST, + UFS_UPIU_QUERY_OPCODE_READ_ATTR, + UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE, 0, 0, 0, &= rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.response, =3D=3D, UFS_COMMAND_RESULT_= SUCCESS); + g_assert_cmpuint(rsp_upiu.qr.opcode, =3D=3D, UFS_UPIU_QUERY_OPCODE_REA= D_ATTR); + g_assert_cmpuint(rsp_upiu.qr.idn, =3D=3D, UFS_QUERY_ATTR_IDN_AVAIL_WB_= BUFF_SIZE); + g_assert_cmpuint(rsp_upiu.qr.value, =3D=3D, cpu_to_be32(0xA)); + + /* Enable WB */ + ocs =3D ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST, + UFS_UPIU_QUERY_OPCODE_SET_FLAG, + UFS_QUERY_FLAG_IDN_WB_EN, 0, 0, 0, + &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.response, =3D=3D, UFS_COMMAND_RESULT_= SUCCESS); + g_assert_cmpuint(rsp_upiu.qr.value, =3D=3D, be32_to_cpu(1)); + + /* Write data */ + for (int i =3D 0; i < 256; i++) { + memset(write_buf, 0xab, block_size); + ocs =3D ufs_send_scsi_command(ufs, test_lun, write_cdb, write_buf, + block_size, NULL, 0, &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.scsi_status, =3D=3D, + UFS_COMMAND_RESULT_SUCCESS); + } + + end_time =3D g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SE= COND; + do { + qtest_clock_step(ufs->dev.bus->qts, 100); + + /* Check available buffer size */ + ocs =3D ufs_send_query(ufs, UFS_UPIU_QUERY_FUNC_STANDARD_READ_REQU= EST, + UFS_UPIU_QUERY_OPCODE_READ_ATTR, + UFS_QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE, 0, 0, = 0, + &rsp_upiu); + g_assert_cmpuint(ocs, =3D=3D, UFS_OCS_SUCCESS); + g_assert_cmpuint(rsp_upiu.header.response, =3D=3D, UFS_COMMAND_RES= ULT_SUCCESS); + g_assert_cmpuint(rsp_upiu.qr.opcode, =3D=3D, UFS_UPIU_QUERY_OPCODE= _READ_ATTR); + g_assert_cmpuint(rsp_upiu.qr.idn, =3D=3D, UFS_QUERY_ATTR_IDN_AVAIL= _WB_BUFF_SIZE); + } while (rsp_upiu.qr.value =3D=3D cpu_to_be32(0xA) && g_get_monotonic_= time() < end_time); + + /* Check available buffer size */ + g_assert_cmpuint(rsp_upiu.qr.value, =3D=3D, cpu_to_be32(0x9)); + + ufs_exit(ufs, alloc); +} + static void drive_destroy(void *path) { unlink(path); @@ -1234,6 +1401,13 @@ static void ufs_register_nodes(void) .edge.extra_device_opts =3D "mcq=3Dtrue,mcq-maxq=3D1" }; =20 + QOSGraphTestOptions wb_test_opts =3D { .before =3D ufs_blk_test_setup, + .edge.extra_device_opts =3D + "mcq=3Dfalse,nutrs=3D32,nutmr= s=3D8," + "wb-max-size=3D1024,wb-min-si= ze=3D256," + "wb-max-lus=3D1,wb-cap-adj-fa= c=3D3," + "wb-reduction=3D1" }; + add_qpci_address(&edge_opts, &(QPCIAddress){ .devfn =3D QPCI_DEVFN(4, = 0) }); =20 qos_node_create_driver("ufs", ufs_create); @@ -1262,6 +1436,8 @@ static void ufs_register_nodes(void) &io_test_opts); qos_add_test("query-desciptor", "ufs", ufstest_query_desc_request, &io_test_opts); + qos_add_test("wb-init", "ufs", ufstest_wb_init, &wb_test_opts); + qos_add_test("wb-read-write", "ufs", ufstest_wb_read_write, &wb_test_o= pts); } =20 libqos_init(ufs_register_nodes); --=20 2.48.1