From: Hannes Reinecke <hare@suse.de>
To: James Smart <jsmart2021@gmail.com>, linux-scsi@vger.kernel.org
Cc: maier@linux.ibm.com, dwagner@suse.de, bvanassche@acm.org,
Ram Vegesna <ram.vegesna@broadcom.com>
Subject: Re: [PATCH v2 07/32] elx: libefc_sli: APIs to setup SLI library
Date: Wed, 8 Jan 2020 09:22:19 +0100 [thread overview]
Message-ID: <8fa86591-9c1f-9b64-3641-b8eddb2a5c62@suse.de> (raw)
In-Reply-To: <20191220223723.26563-8-jsmart2021@gmail.com>
On 12/20/19 11:36 PM, James Smart wrote:
> This patch continues the libefc_sli SLI-4 library population.
>
> This patch adds APIS to initialize the library, initialize
> the SLI Port, reset firmware, terminate the SLI Port, and
> terminate the library.
>
> Signed-off-by: Ram Vegesna <ram.vegesna@broadcom.com>
> Signed-off-by: James Smart <jsmart2021@gmail.com>
> ---
> drivers/scsi/elx/libefc_sli/sli4.c | 1222 ++++++++++++++++++++++++++++++++++++
> drivers/scsi/elx/libefc_sli/sli4.h | 552 +++++++++++++++-
> 2 files changed, 1773 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/elx/libefc_sli/sli4.c b/drivers/scsi/elx/libefc_sli/sli4.c
> index 3cdabb917df6..e2bea34b445a 100644
> --- a/drivers/scsi/elx/libefc_sli/sli4.c
> +++ b/drivers/scsi/elx/libefc_sli/sli4.c
> @@ -4524,3 +4524,1225 @@ sli_cqe_async(struct sli4 *sli4, void *buf)
>
> return rc;
> }
> +
> +/* Determine if the chip FW is in a ready state */
> +int
> +sli_fw_ready(struct sli4 *sli4)
> +{
> + u32 val;
> + /*
> + * Is firmware ready for operation? Check needed depends on IF_TYPE
> + */
> + val = sli_reg_read_status(sli4);
> + return (val & SLI4_PORT_STATUS_RDY) ? 1 : 0;
> +}
> +
boolean?
> +static int
> +sli_sliport_reset(struct sli4 *sli4)
> +{
> + u32 iter, val;
> + int rc = -1;
> +
> + val = SLI4_PORT_CTRL_IP;
> + /* Initialize port, endian */
> + writel(val, (sli4->reg[0] + SLI4_PORT_CTRL_REG));
> +
> + for (iter = 0; iter < 3000; iter++) {
> + mdelay(10); /* 10 ms */
> + if (sli_fw_ready(sli4) == 1) {
> + rc = 0;
> + break;
> + }
> + }
> +
> + if (rc != 0)
> + efc_log_crit(sli4, "port failed to become ready after initialization\n");
> +
> + return rc;
> +}
> +
Same here?
> +static bool
> +sli_wait_for_fw_ready(struct sli4 *sli4, u32 timeout_ms)
> +{
> + u32 iter = timeout_ms / (SLI4_INIT_PORT_DELAY_US / 1000);
> + bool ready = false;
> +
> + do {
> + iter--;
> + mdelay(10); /* 10 ms */
> + if (sli_fw_ready(sli4) == 1)
> + ready = true;
> + } while (!ready && (iter > 0));
> +
> + return ready;
> +}
> +
See? It doesn't even hurt ...
> +static int
> +sli_fw_init(struct sli4 *sli4)
> +{
> + bool ready;
> +
> + /*
> + * Is firmware ready for operation?
> + */
> + ready = sli_wait_for_fw_ready(sli4, SLI4_FW_READY_TIMEOUT_MSEC);
> + if (!ready) {
> + efc_log_crit(sli4, "FW status is NOT ready\n");
> + return -1;
> + }
> +
> + /*
> + * Reset port to a known state
> + */
> + if (sli_sliport_reset(sli4))
> + return -1;
> +
> + return 0;
> +}
> +
boolean?
[ .. ]
> +int
> +sli_init(struct sli4 *sli4)
> +{
> + if (sli4->has_extents) {
> + efc_log_info(sli4, "XXX need to implement extent allocation\n");
> + return -1;
> + }
> +
Ho-hum.
Maybe 'extend allocation not implemented' ?
[ .. ]
> +int
> +sli_resource_alloc(struct sli4 *sli4, enum sli4_resource rtype,
> + u32 *rid, u32 *index)
> +{
> + int rc = 0;
> + u32 size;
> + u32 extent_idx;
> + u32 item_idx;
> + u32 position;
> +
> + *rid = U32_MAX;
> + *index = U32_MAX;
> +
> + switch (rtype) {
> + case SLI_RSRC_VFI:
> + case SLI_RSRC_VPI:
> + case SLI_RSRC_RPI:
> + case SLI_RSRC_XRI:
> + position =
> + find_first_zero_bit(sli4->extent[rtype].use_map,
> + sli4->extent[rtype].map_size);
> + if (position >= sli4->extent[rtype].map_size) {
> + efc_log_err(sli4, "out of resource %d (alloc=%d)\n",
> + rtype, sli4->extent[rtype].n_alloc);
> + rc = -1;
> + break;
> + }
> + set_bit(position, sli4->extent[rtype].use_map);
> + *index = position;
> +
> + size = sli4->extent[rtype].size;
> +
> + extent_idx = *index / size;
> + item_idx = *index % size;
> +
> + *rid = sli4->extent[rtype].base[extent_idx] + item_idx;
> +
> + sli4->extent[rtype].n_alloc++;
> + break;
> + default:
> + rc = -1;
> + }
> +
> + return rc;
> +}
> +
Didn't you mention extent allocation is not implemented?
So is this a different type of extent?
> +int
> +sli_resource_free(struct sli4 *sli4,
> + enum sli4_resource rtype, u32 rid)
> +{
> + int rc = -1;
> + u32 x;
> + u32 size, *base;
> +
> + switch (rtype) {
> + case SLI_RSRC_VFI:
> + case SLI_RSRC_VPI:
> + case SLI_RSRC_RPI:
> + case SLI_RSRC_XRI:
> + /*
> + * Figure out which extent contains the resource ID. I.e. find
> + * the extent such that
> + * extent->base <= resource ID < extent->base + extent->size
> + */
> + base = sli4->extent[rtype].base;
> + size = sli4->extent[rtype].size;
> +
> + /*
> + * In the case of FW reset, this may be cleared
> + * but the force_free path will still attempt to
> + * free the resource. Prevent a NULL pointer access.
> + */
> + if (base) {
> + for (x = 0; x < sli4->extent[rtype].number;
> + x++) {
> + if (rid >= base[x] &&
> + (rid < (base[x] + size))) {
> + rid -= base[x];
> + clear_bit((x * size) + rid,
> + sli4->extent[rtype].use_map);
> + rc = 0;
> + break;
> + }
> + }
> + }
> + break;
> + default:
> + break;
> + }
> +
> + return rc;
> +}
> +
> +int
> +sli_resource_reset(struct sli4 *sli4, enum sli4_resource rtype)
> +{
> + int rc = -1;
> + u32 i;
> +
> + switch (rtype) {
> + case SLI_RSRC_VFI:
> + case SLI_RSRC_VPI:
> + case SLI_RSRC_RPI:
> + case SLI_RSRC_XRI:
> + for (i = 0; i < sli4->extent[rtype].map_size; i++)
> + clear_bit(i, sli4->extent[rtype].use_map);
> + rc = 0;
> + break;
> + default:
> + break;
> + }
> +
> + return rc;
> +}
> +
> +int sli_raise_ue(struct sli4 *sli4, u8 dump)
> +{
> + u32 val = 0;
> +#define FDD 2
Oh, come on.
You have defines for everything but the kitchen sink.
So why do you have to define this one inline?
> + if (dump == FDD) {
> + val = SLI4_PORT_CTRL_FDD | SLI4_PORT_CTRL_IP;
> + writel(val, (sli4->reg[0] + SLI4_PORT_CTRL_REG));
> + } else {
> + val = SLI4_PHYDEV_CTRL_FRST;
> +
> + if (dump == 1)
> + val |= SLI4_PHYDEV_CTRL_DD;
> + writel(val, (sli4->reg[0] + SLI4_PHYDEV_CTRL_REG));
> + }
> +
> + return 0;
> +}
> +
> +int sli_dump_is_ready(struct sli4 *sli4)
> +{
> + int rc = 0;
> + u32 port_val;
> + u32 bmbx_val;
> +
> + /*
> + * Ensure that the port is ready AND the mailbox is
> + * ready before signaling that the dump is ready to go.
> + */
> + port_val = sli_reg_read_status(sli4);
> + bmbx_val = readl(sli4->reg[0] + SLI4_BMBX_REG);
> +
> + if ((bmbx_val & SLI4_BMBX_RDY) &&
> + (port_val & SLI4_PORT_STATUS_RDY)) {
> + if (port_val & SLI4_PORT_STATUS_DIP)
> + rc = 1;
> + else if (port_val & SLI4_PORT_STATUS_FDP)
> + rc = 2;
> + }
> +
> + return rc;
> +}
> +
Please use defines for the return values here.
One has no idea why '1' or '2' is returned here.
At the very least some documentation.
> +int sli_dump_is_present(struct sli4 *sli4)
> +{
> + u32 val;
> + bool ready;
> +
> + /* If the chip is not ready, then there cannot be a dump */
> + ready = sli_wait_for_fw_ready(sli4, SLI4_INIT_PORT_DELAY_US);
> + if (!ready)
> + return 0;
> +
> + val = sli_reg_read_status(sli4);
> + if (val == U32_MAX) {
> + efc_log_err(sli4, "error reading SLIPORT_STATUS\n");
> + return -1;
> + } else {
> + return (val & SLI4_PORT_STATUS_DIP) ? 1 : 0;
> + }
> +}
> +
> +int sli_reset_required(struct sli4 *sli4)
> +{
> + u32 val;
> +
> + val = sli_reg_read_status(sli4);
> + if (val == U32_MAX) {
> + efc_log_err(sli4, "error reading SLIPORT_STATUS\n");
> + return -1;
> + } else {
> + return (val & SLI4_PORT_STATUS_RN) ? 1 : 0;
> + }
> +}
> +
> +int
> +sli_cmd_post_sgl_pages(struct sli4 *sli4, void *buf, size_t size,
> + u16 xri,
> + u32 xri_count, struct efc_dma *page0[],
> + struct efc_dma *page1[], struct efc_dma *dma)
> +{
> + struct sli4_rqst_post_sgl_pages *post = NULL;
> + u32 i;
> + __le32 req_len;
> +
> + post = sli_config_cmd_init(sli4, buf, size,
> + SLI_CONFIG_PYLD_LENGTH(post_sgl_pages),
> + dma);
> + if (!post)
> + return EFC_FAIL;
> +
> + /* payload size calculation */
> + /* 4 = xri_start + xri_count */
> + /* xri_count = # of XRI's registered */
> + /* sizeof(uint64_t) = physical address size */
> + /* 2 = # of physical addresses per page set */
> + req_len = cpu_to_le32(4 + (xri_count * (sizeof(uint64_t) * 2)));
> + sli_cmd_fill_hdr(&post->hdr, SLI4_OPC_POST_SGL_PAGES, SLI4_SUBSYSTEM_FC,
> + CMD_V0, req_len);
> + post->xri_start = cpu_to_le16(xri);
> + post->xri_count = cpu_to_le16(xri_count);
> +
> + for (i = 0; i < xri_count; i++) {
> + post->page_set[i].page0_low =
> + cpu_to_le32(lower_32_bits(page0[i]->phys));
> + post->page_set[i].page0_high =
> + cpu_to_le32(upper_32_bits(page0[i]->phys));
> + }
> +
> + if (page1) {
> + for (i = 0; i < xri_count; i++) {
> + post->page_set[i].page1_low =
> + cpu_to_le32(lower_32_bits(page1[i]->phys));
> + post->page_set[i].page1_high =
> + cpu_to_le32(upper_32_bits(page1[i]->phys));
> + }
> + }
> +
> + return EFC_SUCCESS;
> +}
> +
EFC_SUCCESS is back!
I've already missed them; none of the previous functions in this patch
use them.
Please fix.
[ .. ]
> +extern int
> +sli_cmd_unreg_vfi(struct sli4 *sli4, void *buf, size_t size,
> + u16 index, u32 which);
> +extern int
> +sli_cmd_common_nop(struct sli4 *sli4, void *buf, size_t size,
> + uint64_t context);
> +extern int
> +sli_cmd_common_get_resource_extent_info(struct sli4 *sli4, void *buf,
> + size_t size, u16 rtype);
> +extern int
> +sli_cmd_common_get_sli4_parameters(struct sli4 *sli4,
> + void *buf, size_t size);
> +extern int
> +sli_cmd_common_write_object(struct sli4 *sli4, void *buf, size_t size,
> + u16 noc, u16 eof, u32 desired_write_length,
> + u32 offset, char *object_name, struct efc_dma *dma);
> +extern int
> +sli_cmd_common_delete_object(struct sli4 *sli4, void *buf, size_t size,
> + char *object_name);
> +extern int
> +sli_cmd_common_read_object(struct sli4 *sli4, void *buf, size_t size,
> + u32 desired_read_length, u32 offset,
> + char *object_name, struct efc_dma *dma);
> +extern int
> +sli_cmd_dmtf_exec_clp_cmd(struct sli4 *sli4, void *buf, size_t size,
> + struct efc_dma *cmd, struct efc_dma *resp);
> +extern int
> +sli_cmd_common_set_dump_location(struct sli4 *sli4,
> + void *buf, size_t size, bool query,
> + bool is_buffer_list,
> + struct efc_dma *buffer, u8 fdb);
> +extern int
> +sli_cmd_common_set_features(struct sli4 *sli4, void *buf, size_t size,
> + u32 feature, u32 param_len,
> + void *parameter);
> +
> +int sli_cqe_mq(struct sli4 *sli4, void *buf);
> +int sli_cqe_async(struct sli4 *sli4, void *buf);
> +
> +extern int
> +sli_setup(struct sli4 *sli4, void *os, struct pci_dev *pdev,
> + void __iomem *reg[]);
> +void sli_calc_max_qentries(struct sli4 *sli4);
> +int sli_init(struct sli4 *sli4);
> +int sli_reset(struct sli4 *sli4);
> +int sli_fw_reset(struct sli4 *sli4);
> +int sli_teardown(struct sli4 *sli4);
> +extern int
> +sli_callback(struct sli4 *sli4, enum sli4_callback which,
> + void *func, void *arg);
> +extern int
> +sli_bmbx_command(struct sli4 *sli4);
> +extern int
> +__sli_queue_init(struct sli4 *sli4, struct sli4_queue *q,
> + u32 qtype, size_t size, u32 n_entries,
> + u32 align);
> +extern int
> +__sli_create_queue(struct sli4 *sli4, struct sli4_queue *q);
> +extern int
> +sli_eq_modify_delay(struct sli4 *sli4, struct sli4_queue *eq,
> + u32 num_eq, u32 shift, u32 delay_mult);
> +extern int
> +sli_queue_alloc(struct sli4 *sli4, u32 qtype,
> + struct sli4_queue *q, u32 n_entries,
> + struct sli4_queue *assoc);
> +extern int
> +sli_cq_alloc_set(struct sli4 *sli4, struct sli4_queue *qs[],
> + u32 num_cqs, u32 n_entries, struct sli4_queue *eqs[]);
> +extern int
> +sli_get_queue_entry_size(struct sli4 *sli4, u32 qtype);
> +extern int
> +sli_queue_free(struct sli4 *sli4, struct sli4_queue *q,
> + u32 destroy_queues, u32 free_memory);
> +extern int
> +sli_queue_eq_arm(struct sli4 *sli4, struct sli4_queue *q, bool arm);
> +extern int
> +sli_queue_arm(struct sli4 *sli4, struct sli4_queue *q, bool arm);
> +
> +extern int
> +sli_wq_write(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_mq_write(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_rq_write(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_eq_read(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_cq_read(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_mq_read(struct sli4 *sli4, struct sli4_queue *q,
> + u8 *entry);
> +extern int
> +sli_queue_index(struct sli4 *sli4, struct sli4_queue *q);
> +extern int
> +_sli_queue_poke(struct sli4 *sli4, struct sli4_queue *q,
> + u32 index, u8 *entry);
> +extern int
> +sli_queue_poke(struct sli4 *sli4, struct sli4_queue *q, u32 index,
> + u8 *entry);
> +extern int
> +sli_resource_alloc(struct sli4 *sli4, enum sli4_resource rtype,
> + u32 *rid, u32 *index);
> +extern int
> +sli_resource_free(struct sli4 *sli4, enum sli4_resource rtype,
> + u32 rid);
> +extern int
> +sli_resource_reset(struct sli4 *sli4, enum sli4_resource rtype);
> +extern int
> +sli_eq_parse(struct sli4 *sli4, u8 *buf, u16 *cq_id);
> +extern int
> +sli_cq_parse(struct sli4 *sli4, struct sli4_queue *cq, u8 *cqe,
> + enum sli4_qentry *etype, u16 *q_id);
> +
I guess you can reformat those; the linux line length is 80 characters,
and one really should use them ...
Cheers,
Hannes
--
Dr. Hannes Reinecke Teamlead Storage & Networking
hare@suse.de +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
next prev parent reply other threads:[~2020-01-08 8:22 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-20 22:36 [PATCH v2 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver James Smart
2019-12-20 22:36 ` [PATCH v2 01/32] elx: libefc_sli: SLI-4 register offsets and field definitions James Smart
2020-01-08 7:11 ` Hannes Reinecke
2020-01-09 0:59 ` James Smart
2019-12-20 22:36 ` [PATCH v2 02/32] elx: libefc_sli: SLI Descriptors and Queue entries James Smart
2020-01-08 7:24 ` Hannes Reinecke
2020-01-09 1:00 ` James Smart
2019-12-20 22:36 ` [PATCH v2 03/32] elx: libefc_sli: Data structures and defines for mbox commands James Smart
2020-01-08 7:32 ` Hannes Reinecke
2020-01-09 1:03 ` James Smart
2019-12-20 22:36 ` [PATCH v2 04/32] elx: libefc_sli: queue create/destroy/parse routines James Smart
2020-01-08 7:45 ` Hannes Reinecke
2020-01-09 1:04 ` James Smart
2019-12-20 22:36 ` [PATCH v2 05/32] elx: libefc_sli: Populate and post different WQEs James Smart
2020-01-08 7:54 ` Hannes Reinecke
2020-01-09 1:04 ` James Smart
2019-12-20 22:36 ` [PATCH v2 06/32] elx: libefc_sli: bmbx routines and SLI config commands James Smart
2020-01-08 8:05 ` Hannes Reinecke
2019-12-20 22:36 ` [PATCH v2 07/32] elx: libefc_sli: APIs to setup SLI library James Smart
2020-01-08 8:22 ` Hannes Reinecke [this message]
2020-01-09 1:29 ` James Smart
2019-12-20 22:36 ` [PATCH v2 08/32] elx: libefc: Generic state machine framework James Smart
2020-01-09 7:05 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 09/32] elx: libefc: Emulex FC discovery library APIs and definitions James Smart
2020-01-09 7:16 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 10/32] elx: libefc: FC Domain state machine interfaces James Smart
2020-01-09 7:27 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 11/32] elx: libefc: SLI and FC PORT " James Smart
2020-01-09 7:34 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 12/32] elx: libefc: Remote node " James Smart
2020-01-09 8:31 ` Hannes Reinecke
2020-01-09 9:57 ` Daniel Wagner
2019-12-20 22:37 ` [PATCH v2 13/32] elx: libefc: Fabric " James Smart
2020-01-09 8:34 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 14/32] elx: libefc: FC node ELS and state handling James Smart
2020-01-09 8:39 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 15/32] elx: efct: Data structures and defines for hw operations James Smart
2020-01-09 8:41 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 16/32] elx: efct: Driver initialization routines James Smart
2020-01-09 9:01 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 17/32] elx: efct: Hardware queues creation and deletion James Smart
2020-01-09 9:10 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 18/32] elx: efct: RQ buffer, memory pool allocation and deallocation APIs James Smart
2020-01-09 9:13 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 19/32] elx: efct: Hardware IO and SGL initialization James Smart
2020-01-09 9:22 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 20/32] elx: efct: Hardware queues processing James Smart
2020-01-09 9:24 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 21/32] elx: efct: Unsolicited FC frame processing routines James Smart
2020-01-09 9:26 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 22/32] elx: efct: Extended link Service IO handling James Smart
2020-01-09 9:38 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 23/32] elx: efct: SCSI IO handling routines James Smart
2020-01-09 9:41 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 24/32] elx: efct: LIO backend interface routines James Smart
2020-01-09 3:56 ` Bart Van Assche
2019-12-20 22:37 ` [PATCH v2 25/32] elx: efct: Hardware IO submission routines James Smart
2020-01-09 9:52 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 26/32] elx: efct: link statistics and SFP data James Smart
2020-01-09 10:12 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 27/32] elx: efct: xport and hardware teardown routines James Smart
2020-01-09 10:14 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 28/32] elx: efct: IO timeout handling routines James Smart
2020-01-09 11:27 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 29/32] elx: efct: Firmware update, async link processing James Smart
2020-01-09 11:45 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 30/32] elx: efct: scsi_transport_fc host interface support James Smart
2020-01-09 11:46 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 31/32] elx: efct: Add Makefile and Kconfig for efct driver James Smart
2019-12-20 23:17 ` Randy Dunlap
2020-01-09 11:47 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 32/32] elx: efct: Tie into kernel Kconfig and build process James Smart
2019-12-24 7:45 ` kbuild test robot
2019-12-24 21:01 ` Nathan Chancellor
2019-12-25 16:09 ` James Smart
2020-01-09 11:47 ` Hannes Reinecke
2019-12-29 18:27 ` [PATCH v2 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver Sebastian Herbszt
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=8fa86591-9c1f-9b64-3641-b8eddb2a5c62@suse.de \
--to=hare@suse.de \
--cc=bvanassche@acm.org \
--cc=dwagner@suse.de \
--cc=jsmart2021@gmail.com \
--cc=linux-scsi@vger.kernel.org \
--cc=maier@linux.ibm.com \
--cc=ram.vegesna@broadcom.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).