From: Alexander Kozyrev <akozyrev@nvidia.com>
To: <dev@dpdk.org>
Cc: <rasland@nvidia.com>, <viacheslavo@nvidia.com>,
<matan@nvidia.com>, <hamdani@nvidia.com>, <valex@nvidia.com>,
<dsosnowski@nvidia.com>, <orika@nvidia.com>, <bingz@nvidia.com>,
<suanmingm@nvidia.com>
Subject: [PATCH 1/5] net/mlx5/hws: introduce new matcher type
Date: Tue, 15 Oct 2024 19:35:53 +0300 [thread overview]
Message-ID: <20241015163557.581447-1-akozyrev@nvidia.com> (raw)
From: Hamdan Igbaria <hamdani@nvidia.com>
introduce STE array matcher, where this matcher can only
be isolated under a parent table and not chained to the
table matchers chain.
Signed-off-by: Hamdan Igbaria <hamdani@nvidia.com>
---
drivers/net/mlx5/hws/mlx5dr.h | 13 +++++-
drivers/net/mlx5/hws/mlx5dr_debug.c | 12 +++++-
drivers/net/mlx5/hws/mlx5dr_matcher.c | 58 +++++++++++++++++++++++--
drivers/net/mlx5/hws/mlx5dr_matcher.h | 6 +++
drivers/net/mlx5/hws/mlx5dr_rule.c | 2 +-
drivers/net/mlx5/hws/mlx5dr_table.c | 61 +++++++++++++++++++--------
drivers/net/mlx5/hws/mlx5dr_table.h | 8 +++-
drivers/net/mlx5/mlx5_flow_hw.c | 2 +
8 files changed, 135 insertions(+), 27 deletions(-)
diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index 0fe39e9c76..8a1a389a3f 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -130,6 +130,14 @@ enum mlx5dr_matcher_distribute_mode {
MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR = 0x1,
};
+/* Match mode describes the behavior of the matcher STE's when a packet arrives */
+enum mlx5dr_matcher_match_mode {
+ /* Packet arriving at this matcher STE's will match according it's tag and match definer */
+ MLX5DR_MATCHER_MATCH_MODE_DEFAULT = 0x0,
+ /* Packet arriving at this matcher STE's will always hit and perform the actions */
+ MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT = 0x1,
+};
+
enum mlx5dr_rule_hash_calc_mode {
MLX5DR_RULE_HASH_CALC_MODE_RAW,
MLX5DR_RULE_HASH_CALC_MODE_IDX,
@@ -144,11 +152,14 @@ struct mlx5dr_matcher_attr {
enum mlx5dr_matcher_resource_mode mode;
/* Optimize insertion in case packet origin is the same for all rules */
enum mlx5dr_matcher_flow_src optimize_flow_src;
- /* Define the insertion and distribution modes for this matcher */
+ /* Define the insertion, distribution and match modes for this matcher */
enum mlx5dr_matcher_insert_mode insert_mode;
enum mlx5dr_matcher_distribute_mode distribute_mode;
+ enum mlx5dr_matcher_match_mode match_mode;
/* Define whether the created matcher supports resizing into a bigger matcher */
bool resizable;
+ /* This will imply that this matcher is not part of the matchers chain of parent table */
+ bool isolated;
union {
struct {
uint8_t sz_row_log;
diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.c b/drivers/net/mlx5/hws/mlx5dr_debug.c
index 741a725842..f15ad96598 100644
--- a/drivers/net/mlx5/hws/mlx5dr_debug.c
+++ b/drivers/net/mlx5/hws/mlx5dr_debug.c
@@ -182,7 +182,7 @@ mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher_attr *attr = &matcher->attr;
int ret;
- ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d\n",
+ ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
MLX5DR_DEBUG_RES_TYPE_MATCHER_ATTR,
(uint64_t)(uintptr_t)matcher,
attr->priority,
@@ -192,7 +192,9 @@ mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher)
attr->optimize_using_rule_idx,
attr->optimize_flow_src,
attr->insert_mode,
- attr->distribute_mode);
+ attr->distribute_mode,
+ attr->match_mode,
+ attr->isolated);
if (ret < 0) {
rte_errno = EINVAL;
return rte_errno;
@@ -377,6 +379,12 @@ static int mlx5dr_debug_dump_table(FILE *f, struct mlx5dr_table *tbl)
return ret;
}
+ LIST_FOREACH(matcher, &tbl->isolated_matchers, next) {
+ ret = mlx5dr_debug_dump_matcher(f, matcher);
+ if (ret)
+ return ret;
+ }
+
return 0;
out_err:
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c
index dfa2cd435c..54460cc82b 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
@@ -198,6 +198,18 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher *tmp_matcher;
int ret;
+ if (matcher->attr.isolated) {
+ LIST_INSERT_HEAD(&tbl->isolated_matchers, matcher, next);
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(tbl, matcher->end_ft,
+ tbl->default_miss.miss_tbl);
+ if (ret) {
+ DR_LOG(ERR, "Failed to connect the new matcher to the miss_tbl");
+ goto remove_from_list;
+ }
+
+ return 0;
+ }
+
/* Find location in matcher list */
if (LIST_EMPTY(&tbl->head)) {
LIST_INSERT_HEAD(&tbl->head, matcher, next);
@@ -230,7 +242,7 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
}
} else {
/* Connect last matcher to next miss_tbl if exists */
- ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
if (ret) {
DR_LOG(ERR, "Failed connect new matcher to miss_tbl");
goto remove_from_list;
@@ -284,6 +296,11 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
struct mlx5dr_matcher *next;
int ret;
+ if (matcher->attr.isolated) {
+ LIST_REMOVE(matcher, next);
+ return 0;
+ }
+
prev_ft = tbl->ft;
prev_matcher = LIST_FIRST(&tbl->head);
LIST_FOREACH(tmp_matcher, &tbl->head, next) {
@@ -309,7 +326,7 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
goto matcher_reconnect;
}
} else {
- ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
if (ret) {
DR_LOG(ERR, "Failed to disconnect last matcher");
goto matcher_reconnect;
@@ -518,14 +535,17 @@ static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
}
} else if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
- rtc_attr.num_hash_definer = 1;
if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
/* Hash Split Table */
+ if (mlx5dr_matcher_is_always_hit(matcher))
+ rtc_attr.num_hash_definer = 1;
+
rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH;
rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
/* Linear Lookup Table */
+ rtc_attr.num_hash_definer = 1;
rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR;
rtc_attr.match_definer_0 = ctx->caps->linear_match_definer;
}
@@ -973,10 +993,17 @@ mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
/* Hash Split Table */
- if (!caps->rtc_hash_split_table) {
+ if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT &&
+ !caps->rtc_hash_split_table) {
DR_LOG(ERR, "FW doesn't support insert by index and hash distribute");
goto not_supported;
}
+
+ if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_DEFAULT &&
+ !attr->isolated) {
+ DR_LOG(ERR, "STE array matcher supported only as an isolated matcher");
+ goto not_supported;
+ }
} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
/* Linear Lookup Table */
if (!caps->rtc_linear_lookup_table ||
@@ -991,6 +1018,12 @@ mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX);
goto not_supported;
}
+
+ if (attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT) {
+ DR_LOG(ERR, "Linear lookup tables will always hit, given match mode is not supported %d\n",
+ attr->match_mode);
+ goto not_supported;
+ }
} else {
DR_LOG(ERR, "Matcher has unsupported distribute mode");
goto not_supported;
@@ -1032,6 +1065,11 @@ mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
DR_LOG(ERR, "Root matcher does not support resizing");
goto not_supported;
}
+ if (attr->isolated) {
+ DR_LOG(ERR, "Root matcher can not be isolated");
+ goto not_supported;
+ }
+
return 0;
}
@@ -1045,6 +1083,18 @@ mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH)
attr->table.sz_col_log = mlx5dr_matcher_rules_to_tbl_depth(attr->rule.num_log);
+ if (attr->isolated) {
+ if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_INDEX ||
+ attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH ||
+ attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_DEFAULT) {
+ DR_LOG(ERR, "Isolated matcher only supported for STE array matcher");
+ goto not_supported;
+ }
+
+ /* We reach here only in case of STE array */
+ matcher->flags |= MLX5DR_MATCHER_FLAGS_STE_ARRAY;
+ }
+
matcher->flags |= attr->resizable ? MLX5DR_MATCHER_FLAGS_RESIZABLE : 0;
return mlx5dr_matcher_check_attr_sz(caps, attr);
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.h b/drivers/net/mlx5/hws/mlx5dr_matcher.h
index ca6a5298d9..ef42b7de6b 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.h
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.h
@@ -28,6 +28,7 @@ enum mlx5dr_matcher_flags {
MLX5DR_MATCHER_FLAGS_COLLISION = 1 << 2,
MLX5DR_MATCHER_FLAGS_RESIZABLE = 1 << 3,
MLX5DR_MATCHER_FLAGS_COMPARE = 1 << 4,
+ MLX5DR_MATCHER_FLAGS_STE_ARRAY = 1 << 5,
};
struct mlx5dr_match_template {
@@ -146,6 +147,11 @@ static inline bool mlx5dr_matcher_is_insert_by_idx(struct mlx5dr_matcher *matche
return matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX;
}
+static inline bool mlx5dr_matcher_is_always_hit(struct mlx5dr_matcher *matcher)
+{
+ return matcher->attr.match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT;
+}
+
int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
uint32_t fw_ft_type,
enum mlx5dr_table_type type,
diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.c b/drivers/net/mlx5/hws/mlx5dr_rule.c
index 5d66d81ea5..519328ccf3 100644
--- a/drivers/net/mlx5/hws/mlx5dr_rule.c
+++ b/drivers/net/mlx5/hws/mlx5dr_rule.c
@@ -539,7 +539,7 @@ static int mlx5dr_rule_create_hws(struct mlx5dr_rule *rule,
* will always match and perform the specified actions, which
* makes the tag irrelevant.
*/
- if (likely(!mlx5dr_matcher_is_insert_by_idx(matcher) && !is_update))
+ if (likely(!mlx5dr_matcher_is_always_hit(matcher) && !is_update))
mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz,
(uint8_t *)dep_wqe->wqe_data.action);
else if (unlikely(is_update))
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c b/drivers/net/mlx5/hws/mlx5dr_table.c
index ab73017ade..634b484a94 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -429,7 +429,7 @@ int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
{
struct mlx5dr_context *ctx = tbl->ctx;
pthread_spin_lock(&ctx->ctrl_lock);
- if (!LIST_EMPTY(&tbl->head)) {
+ if (!LIST_EMPTY(&tbl->head) || !LIST_EMPTY(&tbl->isolated_matchers)) {
DR_LOG(ERR, "Cannot destroy table containing matchers");
rte_errno = EBUSY;
goto unlock_err;
@@ -531,7 +531,7 @@ int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
return 0;
LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) {
- ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl, false);
if (ret) {
DR_LOG(ERR, "Failed to update source miss table, unexpected behavior");
return ret;
@@ -541,34 +541,32 @@ int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
return 0;
}
-int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
- struct mlx5dr_table *dst_tbl)
+int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_devx_obj *ft,
+ struct mlx5dr_table *dst_tbl)
{
- struct mlx5dr_devx_obj *last_ft;
struct mlx5dr_matcher *matcher;
int ret;
- last_ft = mlx5dr_table_get_last_ft(src_tbl);
-
if (dst_tbl) {
if (LIST_EMPTY(&dst_tbl->head)) {
- /* Connect src_tbl last_ft to dst_tbl start anchor */
- ret = mlx5dr_table_ft_set_next_ft(last_ft,
+ /* Connect src_tbl ft to dst_tbl start anchor */
+ ret = mlx5dr_table_ft_set_next_ft(ft,
src_tbl->fw_ft_type,
dst_tbl->ft->id);
if (ret)
return ret;
- /* Reset last_ft RTC to default RTC */
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ /* Reset ft RTC to default RTC */
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
NULL, NULL);
if (ret)
return ret;
} else {
- /* Connect src_tbl last_ft to first matcher RTC */
+ /* Connect src_tbl ft to first matcher RTC */
matcher = LIST_FIRST(&dst_tbl->head);
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
matcher->match_ste.rtc_0,
matcher->match_ste.rtc_1);
@@ -576,24 +574,51 @@ int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
return ret;
/* Reset next miss FT to default */
- ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+ ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
if (ret)
return ret;
}
} else {
/* Reset next miss FT to default */
- ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, last_ft);
+ ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
if (ret)
return ret;
- /* Reset last_ft RTC to default RTC */
- ret = mlx5dr_table_ft_set_next_rtc(last_ft,
+ /* Reset ft RTC to default RTC */
+ ret = mlx5dr_table_ft_set_next_rtc(ft,
src_tbl->fw_ft_type,
NULL, NULL);
if (ret)
return ret;
}
+ return 0;
+}
+
+int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_table *dst_tbl,
+ bool only_update_last_ft)
+{
+ struct mlx5dr_matcher *matcher;
+ struct mlx5dr_devx_obj *ft;
+ int ret;
+
+ /* Connect last FT in the src_tbl matchers chain */
+ ft = mlx5dr_table_get_last_ft(src_tbl);
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
+ if (ret)
+ return ret;
+
+ if (!only_update_last_ft) {
+ /* Connect isolated matchers FT */
+ LIST_FOREACH(matcher, &src_tbl->isolated_matchers, next) {
+ ft = matcher->end_ft;
+ ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
+ if (ret)
+ return ret;
+ }
+ }
+
src_tbl->default_miss.miss_tbl = dst_tbl;
return 0;
@@ -633,7 +658,7 @@ int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
pthread_spin_lock(&ctx->ctrl_lock);
old_miss_tbl = tbl->default_miss.miss_tbl;
- ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl);
+ ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl, false);
if (ret)
goto out;
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.h b/drivers/net/mlx5/hws/mlx5dr_table.h
index b2fbb47416..32f2574a97 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.h
+++ b/drivers/net/mlx5/hws/mlx5dr_table.h
@@ -23,6 +23,7 @@ struct mlx5dr_table {
uint32_t fw_ft_type;
uint32_t level;
LIST_HEAD(matcher_head, mlx5dr_matcher) head;
+ LIST_HEAD(isolated_matchers_head, mlx5dr_matcher) isolated_matchers;
LIST_ENTRY(mlx5dr_table) next;
struct mlx5dr_default_miss default_miss;
};
@@ -54,7 +55,8 @@ void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
struct mlx5dr_devx_obj *ft_obj);
int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
- struct mlx5dr_table *dst_tbl);
+ struct mlx5dr_table *dst_tbl,
+ bool only_update_last_ft);
int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl);
@@ -66,4 +68,8 @@ int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
struct mlx5dr_devx_obj *rtc_0,
struct mlx5dr_devx_obj *rtc_1);
+int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
+ struct mlx5dr_devx_obj *ft,
+ struct mlx5dr_table *dst_tbl);
+
#endif /* MLX5DR_TABLE_H_ */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index c5ddd1d404..b9807f347d 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -5157,6 +5157,8 @@ flow_hw_table_create(struct rte_eth_dev *dev,
matcher_attr.optimize_using_rule_idx = true;
matcher_attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_RULE;
matcher_attr.insert_mode = flow_hw_matcher_insert_mode_get(attr->insertion_type);
+ if (matcher_attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
+ matcher_attr.match_mode = MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT;
if (attr->hash_func == RTE_FLOW_TABLE_HASH_FUNC_CRC16) {
DRV_LOG(ERR, "16-bit checksum hash type is not supported");
rte_errno = ENOTSUP;
--
2.18.2
next reply other threads:[~2024-10-15 16:36 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-15 16:35 Alexander Kozyrev [this message]
2024-10-15 16:35 ` [PATCH 2/5] net/mlx5/hws: introduce jump to matcher action Alexander Kozyrev
2024-10-15 16:35 ` [PATCH 3/5] net/mlx5: create array ste matcher Alexander Kozyrev
2024-10-15 16:35 ` [PATCH 4/5] net/mlx5: add flow rule insertion by index with pattern Alexander Kozyrev
2024-10-15 16:35 ` [PATCH 5/5] net/mlx5: implement jump to table index action Alexander Kozyrev
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=20241015163557.581447-1-akozyrev@nvidia.com \
--to=akozyrev@nvidia.com \
--cc=bingz@nvidia.com \
--cc=dev@dpdk.org \
--cc=dsosnowski@nvidia.com \
--cc=hamdani@nvidia.com \
--cc=matan@nvidia.com \
--cc=orika@nvidia.com \
--cc=rasland@nvidia.com \
--cc=suanmingm@nvidia.com \
--cc=valex@nvidia.com \
--cc=viacheslavo@nvidia.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).