linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Avri Altman <avri.altman@wdc.com>
To: "James E . J . Bottomley" <jejb@linux.vnet.ibm.com>,
	"Martin K . Petersen" <martin.petersen@oracle.com>,
	linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Bart Van Assche <bvanassche@acm.org>,
	alim.akhtar@samsung.com, asutoshd@codeaurora.org,
	Zang Leigang <zangleigang@hisilicon.com>,
	Avi Shchislowski <avi.shchislowski@wdc.com>,
	Bean Huo <beanhuo@micron.com>,
	cang@codeaurora.org, stanley.chu@mediatek.com,
	MOHAMMED RAFIQ KAMAL BASHA <md.rafiq@samsung.com>,
	Sang-yoon Oh <sangyoon.oh@samsung.com>,
	yongmyung lee <ymhungry.lee@samsung.com>,
	Jinyoung CHOI <j-young.choi@samsung.com>,
	Avri Altman <avri.altman@wdc.com>
Subject: [RFC PATCH 02/13] scsi: ufshpb: Init part I - Read HPB config
Date: Fri, 15 May 2020 13:30:03 +0300	[thread overview]
Message-ID: <1589538614-24048-3-git-send-email-avri.altman@wdc.com> (raw)
In-Reply-To: <1589538614-24048-1-git-send-email-avri.altman@wdc.com>

The ufshpb module bear 2 main duties.  During initialization, it reads
the hpb configuration from the device.  Later on, during the scan host
phase, it attaches the scsi device and activates the scsi hpb device
handler.

The second duty mainly concern the HPB cache management and will be
dealt with in future patches.

This patch introduce an API to carry the first part of the
initialization: reading the HPB configuration.

At this point we introduce the key data structure of the ufshpb module -
ufshpb_lun.  It will bear some more duties in the future, so we will
elaborate it as we go.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 drivers/scsi/ufs/Kconfig  |  12 ++
 drivers/scsi/ufs/Makefile |   1 +
 drivers/scsi/ufs/ufshcd.c |   5 +
 drivers/scsi/ufs/ufshcd.h |  10 ++
 drivers/scsi/ufs/ufshpb.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufshpb.h |  22 ++++
 6 files changed, 368 insertions(+)
 create mode 100644 drivers/scsi/ufs/ufshpb.c
 create mode 100644 drivers/scsi/ufs/ufshpb.h

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index e2005ae..a540919 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -160,3 +160,15 @@ config SCSI_UFS_BSG
 
 	  Select this if you need a bsg device node for your UFS controller.
 	  If unsure, say N.
+
+config SCSI_UFS_HPB
+	bool "Support UFS Host Performance Booster (HPB)"
+        depends on SCSI_UFSHCD
+        help
+	  A UFS feature targeted to improve random read performance.  It uses
+	  the host’s system memory as a cache for L2P map data, so that both
+	  physical block address (PBA) and logical block address (LBA) can be
+	  delivered in HPB read command.
+
+          Select this to enable this feature.
+          If unsure, say N.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 94c6c5d..c38788a 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
 obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
 obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
+obj-$(CONFIG_SCSI_UFS_HPB) += ufshpb.o
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 426073a..bffe699 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -50,6 +50,7 @@
 #include "ufs_bsg.h"
 #include <asm/unaligned.h>
 #include <linux/blkdev.h>
+#include "ufshpb.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ufs.h>
@@ -7341,6 +7342,9 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
 		hba->clk_scaling.is_allowed = true;
 	}
 
+	if (ufshcd_is_hpb_supported(hba))
+		ufshpb_probe(hba);
+
 	ufs_bsg_probe(hba);
 	scsi_scan_host(hba->host);
 	pm_runtime_put_sync(hba->dev);
@@ -8608,6 +8612,7 @@ EXPORT_SYMBOL(ufshcd_shutdown);
 void ufshcd_remove(struct ufs_hba *hba)
 {
 	ufs_bsg_remove(hba);
+	ufshpb_remove(hba);
 	ufs_sysfs_remove_nodes(hba->dev);
 	blk_cleanup_queue(hba->tmf_queue);
 	blk_mq_free_tag_set(&hba->tmf_tag_set);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 23a434c..e7014a3 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -564,6 +564,11 @@ enum ufshcd_caps {
 	 * provisioned to be used. This would increase the write performance.
 	 */
 	UFSHCD_CAP_WB_EN				= 1 << 7,
+
+	/*
+	 * This capability indicates that the platform supports HPB
+	 */
+	UFSHCD_CAP_HPB 					= 1 << 8,
 };
 
 /**
@@ -791,6 +796,11 @@ static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
 	return hba->caps & UFSHCD_CAP_WB_EN;
 }
 
+static inline bool ufshcd_is_hpb_supported(struct ufs_hba *hba)
+{
+	return hba->caps & UFSHCD_CAP_HPB;
+}
+
 #define ufshcd_writel(hba, val, reg)	\
 	writel((val), (hba)->mmio_base + (reg))
 #define ufshcd_readl(hba, reg)	\
diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
new file mode 100644
index 0000000..181917f
--- /dev/null
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -0,0 +1,318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Host Performance Booster(HPB)
+ * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2018, Google, Inc.
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+#include <asm/unaligned.h>
+#include "ufshcd.h"
+#include "ufs.h"
+#include "ufshpb.h"
+
+#define UFSHPB_SPEC_VER (0x310)
+#define UFSHPB_MAX_LUNS (0x20)
+#define DEV_DESC_HPB_SIZE (0x53)
+#define GEO_DESC_HPB_SIZE (0x4D)
+#define UNIT_DESC_HPB_SIZE (0x29)
+
+enum ufshpb_control_modes {
+	UFSHPB_HOST_CONTROL,
+	UFSHPB_DEVICE_CONTROL
+};
+
+/**
+ * struct ufshpb_lun_conf - to hold hpb lun config from unit descriptor
+ * @lun - lun id
+ * @size - lun size = 2^bLogicalBlockSize x qLogicalBlockCount
+ * @max_active_regions - Maximum Number of Active HPB Regions for that LU
+ * @pinned_starting_idx - HPB Pinned Region Start Offset
+ * @pinned_count - Number of HPB Pinned Regions
+ */
+struct ufshpb_lun_config {
+	u8 lun;
+	u64 size;
+	u8 hpb_lun_idx;
+	u16 max_active_regions;
+	u16 pinned_starting_idx;
+	u16 pinned_count;
+};
+
+/**
+ * struct ufshpb_config - to hold hpb config supported by the device
+ * @version - HPB Specification Version
+ * @mode - hpb control mode
+ * @region_size - HPB Region size[B] = 512B x 2^bHPBRegionSize
+ * @max_luns - Maximum number of HPB LU supported by the device <= 0x20
+ * @subregion_size - HPB Sub-Region size[B] = 512B x 2^bHPBSubRegionSize
+ * @max_active_regions - Maximum number of Active HPB Regions
+ * @num_hpb_luns - hpb luns that are configured in the device
+ * @hpb_luns - to hold hpb lun config from unit descriptor
+ */
+struct ufshpb_config {
+	u16 version;
+	u8 mode;
+	u8 region_size;
+	u8 max_luns;
+	u8 subregion_size;
+	u16 max_active_regions;
+	u8 num_hpb_luns;
+};
+
+struct ufshpb_lun {
+	u8 lun;
+};
+
+
+struct ufshpb_config *ufshpb_conf;
+struct ufshpb_lun_config *ufshpb_luns_conf;
+struct ufshpb_lun *ufshpb_luns;
+static unsigned long ufshpb_lun_map[BITS_TO_LONGS(UFSHPB_MAX_LUNS)];
+static u8 ufshpb_lun_lookup[UFSHPB_MAX_LUNS];
+
+/**
+ * ufshpb_remove - ufshpb cleanup
+ *
+ * Should be called when unloading the driver.
+ */
+void ufshpb_remove(struct ufs_hba *hba)
+{
+	kfree(ufshpb_conf);
+	kfree(ufshpb_luns_conf);
+	kfree(ufshpb_luns);
+	ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+			  QUERY_FLAG_IDN_HPB_RESET, 0, NULL);
+}
+
+static int ufshpb_hpb_init(void)
+{
+	u8 num_hpb_luns = ufshpb_conf->num_hpb_luns;
+	int i;
+
+	ufshpb_luns = kcalloc(num_hpb_luns, sizeof(*ufshpb_luns), GFP_KERNEL);
+	if (!ufshpb_luns)
+		return -ENOMEM;
+
+	for (i = 0; i < num_hpb_luns; i++) {
+		struct ufshpb_lun *hpb = ufshpb_luns + i;
+
+		hpb->lun = (ufshpb_luns_conf + i)->lun;
+	}
+
+	return 0;
+}
+
+static inline bool ufshpb_desc_proper_sizes(struct ufs_hba *hba)
+{
+	return hba->desc_size.dev_desc >= DEV_DESC_HPB_SIZE &&
+		hba->desc_size.geom_desc >= GEO_DESC_HPB_SIZE &&
+		hba->desc_size.unit_desc >= UNIT_DESC_HPB_SIZE;
+}
+
+static int ufshpb_get_geo_config(struct ufs_hba *hba)
+{
+	int ret;
+	u8 *desc_buf;
+
+	desc_buf = kzalloc(GEO_DESC_HPB_SIZE, GFP_KERNEL);
+	if (!desc_buf)
+		return -ENOMEM;
+
+	ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
+				     desc_buf, GEO_DESC_HPB_SIZE);
+	if (ret)
+		goto free;
+
+	ufshpb_conf->region_size =
+			desc_buf[GEOMETRY_DESC_PARAM_HPB_REGION_SIZE];
+	ufshpb_conf->subregion_size =
+			desc_buf[GEOMETRY_DESC_PARAM_HPB_SUBREGION_SIZE];
+	ufshpb_conf->max_luns = desc_buf[GEOMETRY_DESC_PARAM_MAX_HPB_LUNS];
+
+	/* None of HPB geometrical parameters should be 0 */
+	if (!ufshpb_conf->max_luns || !ufshpb_conf->region_size ||
+	    !ufshpb_conf->subregion_size) {
+		ret = -EINVAL;
+		goto free;
+	}
+
+	ret = 0;
+
+free:
+	kfree(desc_buf);
+	return ret;
+}
+
+static int ufshpb_get_unit_config(struct ufs_hba *hba, u8 dev_num_luns)
+{
+	int ret;
+	struct ufshpb_lun_config *luns_conf;
+	u8 *desc_buf;
+	u8 num_hpb_luns = 0;
+	u16 max_active_regions = 0;
+	int i;
+
+	luns_conf = kcalloc(ufshpb_conf->max_luns, sizeof(*luns_conf),
+			    GFP_KERNEL);
+	if (!luns_conf)
+		return -ENOMEM;
+
+	desc_buf = kzalloc(UNIT_DESC_HPB_SIZE, GFP_KERNEL);
+	if (!desc_buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* iterate over all unit descriptors, look for hpb luns */
+	for (i = 0; i < dev_num_luns; i++) {
+		struct ufshpb_lun_config *lun_conf;
+		u64 block_count;
+		u8 block_size;
+
+		memset(desc_buf, 0x0, UNIT_DESC_HPB_SIZE);
+
+		ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, i, 0,
+					     desc_buf, UNIT_DESC_HPB_SIZE);
+		if (ret)
+			goto out;
+
+		if (desc_buf[UNIT_DESC_PARAM_LU_ENABLE] != UFS_LUN_HPB)
+			continue;
+
+		lun_conf = luns_conf + num_hpb_luns;
+
+		/* mark the hpb lun for future lookup */
+		ufshpb_lun_lookup[i] = num_hpb_luns;
+		lun_conf->lun = i;
+		lun_conf->hpb_lun_idx = num_hpb_luns;
+		set_bit(i, ufshpb_lun_map);
+		num_hpb_luns++;
+
+		block_count = get_unaligned_be64(
+			&desc_buf[UNIT_DESC_PARAM_LOGICAL_BLK_COUNT]);
+		block_size = desc_buf[UNIT_DESC_PARAM_LOGICAL_BLK_SIZE];
+		lun_conf->size = BIT(block_size) * block_count;
+
+		/* get ufshpb params */
+		lun_conf->max_active_regions = get_unaligned_be16(
+			&desc_buf[UNIT_DESC_PARAM_MAX_ACTIVE_HPBREGIONS]);
+
+		/*
+		 * wDeviceMaxActiveHPBRegions is redundant. Suffices to keep
+		 * track of sum of wLUMaxActiveHPBRegions over the luns.
+		 */
+		max_active_regions += lun_conf->max_active_regions;
+
+		lun_conf->pinned_count = get_unaligned_be16(
+			&desc_buf[UNIT_DESC_PARAM_HPB_PINNED_COUNT]);
+		if (lun_conf->pinned_count)
+			lun_conf->pinned_starting_idx = get_unaligned_be16(
+				&desc_buf[UNIT_DESC_PARAM_HPB_PINNED_OFFSET]);
+
+		/* there can be up to bHPBNumberLU HPB luns */
+		if (num_hpb_luns == ufshpb_conf->max_luns)
+			break;
+	}
+
+	if (!num_hpb_luns || !max_active_regions) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ufshpb_conf->num_hpb_luns = num_hpb_luns;
+	ufshpb_conf->max_active_regions = max_active_regions;
+	ufshpb_luns_conf = luns_conf;
+
+	ret = 0;
+
+out:
+	kfree(desc_buf);
+	if (ret)
+		kfree(luns_conf);
+	return ret;
+}
+
+/**
+ * ufshpb_probe - read hpb config from the device
+ * @hba: per adapter object
+ *
+ * Called during initial loading of the driver, and before scsi_scan_host.
+ */
+int ufshpb_probe(struct ufs_hba *hba)
+{
+	int ret = -EINVAL;
+	u16 spec_ver = 0;
+	u8 dev_num_luns = 0;
+	u8 *dev_desc = NULL;
+
+	/*
+	 * if the HPB database already exist, that's fine, leave it.
+	 * The device will signal should it needs to be reset.
+	 */
+	if (ufshpb_luns)
+		return 0;
+
+	if (!ufshpb_desc_proper_sizes(hba))
+		goto out;
+
+	dev_desc = kzalloc(DEV_DESC_HPB_SIZE, GFP_KERNEL);
+	if (!dev_desc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, dev_desc,
+				   DEV_DESC_HPB_SIZE))
+		goto out;
+
+	spec_ver = get_unaligned_be16(&dev_desc[DEVICE_DESC_PARAM_SPEC_VER]);
+	if (spec_ver < UFSHPB_SPEC_VER)
+		goto out;
+
+	if (!(dev_desc[DEVICE_DESC_PARAM_UFS_FEAT] & UFS_FEATURE_HPB))
+		goto out;
+
+	ufshpb_conf = kzalloc(sizeof(*ufshpb_conf), GFP_KERNEL);
+	if (!ufshpb_conf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ufshpb_conf->version =
+		get_unaligned_be16(&dev_desc[DEVICE_DESC_PARAM_HPBVER]);
+	ufshpb_conf->mode = dev_desc[DEVICE_DESC_PARAM_HPBCONTROL];
+
+	/* this driver supports only host control mode */
+	if (ufshpb_conf->mode != UFSHPB_HOST_CONTROL)
+		goto out;
+
+	/* bNumberLU does not include wluns which can't be hpb luns */
+	dev_num_luns = dev_desc[DEVICE_DESC_PARAM_NUM_LU];
+
+	ret = ufshpb_get_geo_config(hba);
+	if (ret)
+		goto out;
+
+	ret = ufshpb_get_unit_config(hba, dev_num_luns);
+	if (ret)
+		goto out;
+
+	ret = ufshpb_hpb_init();
+	if (ret)
+		goto out;
+
+out:
+	kfree(dev_desc);
+	if (ret) {
+		dev_err(hba->dev, "err %d while probing HPB\n", ret);
+		hba->caps &= ~UFSHCD_CAP_HPB;
+		ufshpb_remove(hba);
+	}
+
+	return ret;
+}
+
+MODULE_AUTHOR("Avri Altman <avri.altman@wdc.com>");
+MODULE_DESCRIPTION("UFS Host Performance Booster Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h
new file mode 100644
index 0000000..ee990f4
--- /dev/null
+++ b/drivers/scsi/ufs/ufshpb.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2017-2018 Samsung Electronics Co., Ltd.
+ * Copyright (C) 2018, Google, Inc.
+ * Copyright (C) 2019 Western Digital Corporation or its affiliates.
+ */
+#ifndef _UFSHPB_H
+#define _UFSHPB_H
+
+#include <linux/types.h>
+
+struct ufs_hba;
+
+#ifdef CONFIG_SCSI_UFS_HPB
+void ufshpb_remove(struct ufs_hba *hba);
+int ufshpb_probe(struct ufs_hba *hba);
+#else
+static inline void ufshpb_remove(struct ufs_hba *hba) {}
+static inline int ufshpb_probe(struct ufs_hba *hba) { return 0; }
+#endif
+
+#endif /* _UFSHPB_H */
-- 
2.7.4


  parent reply	other threads:[~2020-05-15 10:31 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-15 10:30 [RFC PATCH 00/13] scsi: ufs: Add HPB Support Avri Altman
2020-05-15 10:30 ` [RFC PATCH 01/13] scsi: ufs: Add HPB parameters Avri Altman
2020-05-15 10:30 ` Avri Altman [this message]
2020-05-15 15:33   ` [RFC PATCH 02/13] scsi: ufshpb: Init part I - Read HPB config Randy Dunlap
2020-05-16  1:46   ` Bart Van Assche
2020-05-16  1:57   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 03/13] scsi: scsi_dh: Introduce scsi_dh_ufshpb Avri Altman
2020-05-16  1:48   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 04/13] scsi: ufs: ufshpb: Init part II - Attach scsi device Avri Altman
2020-05-16  1:52   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 05/13] scsi: ufs: ufshpb: Disable HPB if no HPB-enabled luns Avri Altman
2020-05-16  2:02   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 06/13] scsi: scsi_dh: ufshpb: Prepare for L2P cache management Avri Altman
2020-05-16  2:13   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 07/13] scsi: scsi_dh: ufshpb: Add ufshpb state machine Avri Altman
2020-05-16  2:44   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 08/13] scsi: dh: ufshpb: Activate pinned regions Avri Altman
2020-05-15 10:30 ` [RFC PATCH 09/13] scsi: ufshpb: Add response API Avri Altman
2020-05-16  3:06   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 10/13] scsi: dh: ufshpb: Add ufshpb_set_params Avri Altman
2020-05-15 10:30 ` [RFC PATCH 11/13] scsi: Allow device handler set their own CDB Avri Altman
2020-05-16  3:19   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 12/13] scsi: dh: ufshpb: Add prep_fn handler Avri Altman
2020-05-16  3:40   ` Bart Van Assche
2020-05-15 10:30 ` [RFC PATCH 13/13] scsi: scsi_dh: ufshpb: Add "Cold" subregions timer Avri Altman
2020-05-16  3:50 ` [RFC PATCH 00/13] scsi: ufs: Add HPB Support Bart Van Assche
2020-05-16  9:14   ` Avri Altman
2020-05-16 17:14     ` Bart Van Assche
     [not found]     ` <CGME20200516171420epcas2p108c570904c5117c3654d71e0a2842faa@epcms2p7>
2020-05-19 22:31       ` Another approach of UFSHPB yongmyung lee
2020-05-20 17:55         ` Christoph Hellwig
2020-05-20 21:19           ` Bart Van Assche
2020-05-22 16:35             ` Bart Van Assche
2020-05-22 16:49         ` Bart Van Assche
     [not found]         ` <CGME20200516171420epcas2p108c570904c5117c3654d71e0a2842faa@epcms2p4>
2020-05-25  5:40           ` Daejun Park
2020-05-25 14:56             ` Bart Van Assche
2020-05-26  6:15               ` Avri Altman
2020-05-26 17:03                 ` Bart Van Assche
     [not found]                 ` <CGME20200516171420epcas2p108c570904c5117c3654d71e0a2842faa@epcms2p3>
2020-05-27  9:11                   ` Daejun Park
2020-05-27 11:46                     ` Bean Huo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1589538614-24048-3-git-send-email-avri.altman@wdc.com \
    --to=avri.altman@wdc.com \
    --cc=alim.akhtar@samsung.com \
    --cc=asutoshd@codeaurora.org \
    --cc=avi.shchislowski@wdc.com \
    --cc=beanhuo@micron.com \
    --cc=bvanassche@acm.org \
    --cc=cang@codeaurora.org \
    --cc=j-young.choi@samsung.com \
    --cc=jejb@linux.vnet.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=md.rafiq@samsung.com \
    --cc=sangyoon.oh@samsung.com \
    --cc=stanley.chu@mediatek.com \
    --cc=ymhungry.lee@samsung.com \
    --cc=zangleigang@hisilicon.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).