All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tyler Baicar <tbaicar@codeaurora.org>
To: mchehab@osg.samsung.com, linux-edac@vger.kernel.org,
	astone@redhat.com, fu.wei@linaro.org, shiju.jose@huawei.com
Cc: Tyler Baicar <tbaicar@codeaurora.org>
Subject: [V2,1/2] rasdaemon: add support for non standard CPER section events
Date: Fri,  2 Jun 2017 15:40:32 -0600	[thread overview]
Message-ID: <1496439633-23155-2-git-send-email-tbaicar@codeaurora.org> (raw)

Add support to handle the non standard CPER section kernel trace
events which cover RAS errors who's section type is unknown.

Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Cc: Shiju Jose <shiju.jose@huawei.com>
---
 Makefile.am                |   3 +
 configure.ac               |   9 +++
 ras-events.c               |  15 +++++
 ras-events.h               |   8 +++
 ras-non-standard-handler.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
 ras-non-standard-handler.h |  26 ++++++++
 ras-record.c               |  59 ++++++++++++++++++
 ras-record.h               |  15 +++++
 ras-report.c               |  82 +++++++++++++++++++++++++
 ras-report.h               |  18 +++++-
 10 files changed, 381 insertions(+), 1 deletion(-)
 create mode 100644 ras-non-standard-handler.c
 create mode 100644 ras-non-standard-handler.h

diff --git a/Makefile.am b/Makefile.am
index c9e4481..1bc25e4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,9 @@ endif
 if WITH_AER
    rasdaemon_SOURCES += ras-aer-handler.c
 endif
+if WITH_NON_STANDARD
+   rasdaemon_SOURCES += ras-non-standard-handler.c
+endif
 if WITH_MCE
    rasdaemon_SOURCES += ras-mce-handler.c mce-intel.c mce-amd-k8.c \
 			mce-intel-p4-p6.c mce-intel-nehalem.c \
diff --git a/configure.ac b/configure.ac
index 559f70a..2adb798 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,15 @@ AS_IF([test "x$enable_aer" = "xyes"], [
 ])
 AM_CONDITIONAL([WITH_AER], [test x$enable_aer = xyes])
 
+AC_ARG_ENABLE([non_standard],
+    AS_HELP_STRING([--enable-non-standard], [enable NON_STANDARD events (currently experimental)]))
+
+AS_IF([test "x$enable_non_standard" = "xyes"], [
+  AC_DEFINE(HAVE_NON_STANDARD,1,"have UNKNOWN_SEC events collect")
+  AC_SUBST([WITH_NON_STANDARD])
+])
+AM_CONDITIONAL([WITH_NON_STANDARD], [test x$enable_non_standard = xyes])
+
 AC_ARG_ENABLE([mce],
     AS_HELP_STRING([--enable-mce], [enable MCE events (currently experimental)]))
 
diff --git a/ras-events.c b/ras-events.c
index 0be7c3f..96aa6f1 100644
--- a/ras-events.c
+++ b/ras-events.c
@@ -29,6 +29,7 @@
 #include "libtrace/event-parse.h"
 #include "ras-mc-handler.h"
 #include "ras-aer-handler.h"
+#include "ras-non-standard-handler.h"
 #include "ras-mce-handler.h"
 #include "ras-extlog-handler.h"
 #include "ras-record.h"
@@ -208,6 +209,10 @@ int toggle_ras_mc_event(int enable)
 	rc |= __toggle_ras_mc_event(ras, "ras", "extlog_mem_event", enable);
 #endif
 
+#ifdef HAVE_NON_STANDARD
+	rc |= __toggle_ras_mc_event(ras, "ras", "non_standard_event", enable);
+#endif
+
 free_ras:
 	free(ras);
 	return rc;
@@ -676,6 +681,16 @@ int handle_ras_events(int record_events)
 		    "ras", "aer_event");
 #endif
 
+#ifdef HAVE_NON_STANDARD
+        rc = add_event_handler(ras, pevent, page_size, "ras", "non_standard_event",
+                               ras_non_standard_event_handler);
+        if (!rc)
+                num_events++;
+        else
+                log(ALL, LOG_ERR, "Can't get traces from %s:%s\n",
+                    "ras", "non_standard_event");
+#endif
+
 	cpus = get_num_cpus(ras);
 
 #ifdef HAVE_MCE
diff --git a/ras-events.h b/ras-events.h
index 64e045a..3e1008f 100644
--- a/ras-events.h
+++ b/ras-events.h
@@ -68,6 +68,14 @@ enum hw_event_mc_err_type {
 	HW_EVENT_ERR_INFO,
 };
 
+/* Should match the code at Kernel's include/acpi/ghes.h */
+enum ghes_severity {
+	GHES_SEV_NO,
+	GHES_SEV_CORRECTED,
+	GHES_SEV_RECOVERABLE,
+	GHES_SEV_PANIC,
+};
+
 /* Function prototypes */
 int toggle_ras_mc_event(int enable);
 int handle_ras_events(int record_events);
diff --git a/ras-non-standard-handler.c b/ras-non-standard-handler.c
new file mode 100644
index 0000000..72e0798
--- /dev/null
+++ b/ras-non-standard-handler.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "libtrace/kbuffer.h"
+#include "ras-non-standard-handler.h"
+#include "ras-record.h"
+#include "ras-logger.h"
+#include "ras-report.h"
+
+void print_le_hex(struct trace_seq *s, const uint8_t *buf, int index) {
+	trace_seq_printf(s, "%02x%02x%02x%02x", buf[index+3], buf[index+2], buf[index+1], buf[index]);
+}
+
+static char *uuid_le(const char *uu)
+{
+	static char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+	char *p = uuid;
+	int i;
+	static const unsigned char le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
+
+	for (i = 0; i < 16; i++) {
+		p += sprintf(p, "%.2x", uu[le[i]]);
+		switch (i) {
+		case 3:
+		case 5:
+		case 7:
+		case 9:
+			*p++ = '-';
+			break;
+		}
+	}
+
+	*p = 0;
+
+	return uuid;
+}
+
+int ras_non_standard_event_handler(struct trace_seq *s,
+			 struct pevent_record *record,
+			 struct event_format *event, void *context)
+{
+	int len, i, line_count;
+	unsigned long long val;
+	struct ras_events *ras = context;
+	time_t now;
+	struct tm *tm;
+	struct ras_non_standard_event ev;
+
+	/*
+	 * Newer kernels (3.10-rc1 or upper) provide an uptime clock.
+	 * On previous kernels, the way to properly generate an event would
+	 * be to inject a fake one, measure its timestamp and diff it against
+	 * gettimeofday. We won't do it here. Instead, let's use uptime,
+	 * falling-back to the event report's time, if "uptime" clock is
+	 * not available (legacy kernels).
+	 */
+
+	if (ras->use_uptime)
+		now = record->ts/user_hz + ras->uptime_diff;
+	else
+		now = time(NULL);
+
+	tm = localtime(&now);
+	if (tm)
+		strftime(ev.timestamp, sizeof(ev.timestamp),
+			 "%Y-%m-%d %H:%M:%S %z", tm);
+	trace_seq_printf(s, "%s ", ev.timestamp);
+
+	if (pevent_get_field_val(s, event, "sev", record, &val, 1) < 0)
+		return -1;
+	switch (val) {
+	case GHES_SEV_NO:
+		ev.severity = "Informational";
+		break;
+	case GHES_SEV_CORRECTED:
+		ev.severity = "Corrected";
+		break;
+	case GHES_SEV_RECOVERABLE:
+		ev.severity = "Recoverable";
+		break;
+	default:
+	case GHES_SEV_PANIC:
+		ev.severity = "Fatal";
+	}
+	trace_seq_puts(s, ev.severity);
+
+	ev.sec_type = pevent_get_field_raw(s, event, "sec_type", record, &len, 1);
+	if(!ev.sec_type)
+		return -1;
+	trace_seq_printf(s, "\n section type: %s", uuid_le(ev.sec_type));
+	ev.fru_text = pevent_get_field_raw(s, event, "fru_text",
+						record, &len, 1);
+	ev.fru_id = pevent_get_field_raw(s, event, "fru_id",
+						record, &len, 1);
+	trace_seq_printf(s, " fru text: %s fru id: %s ",
+				ev.fru_text,
+				uuid_le(ev.fru_id));
+
+	if (pevent_get_field_val(s, event, "len", record, &val, 1) < 0)
+		return -1;
+	ev.length = val;
+	trace_seq_printf(s, "\n length: %d\n", ev.length);
+
+	ev.error = pevent_get_field_raw(s, event, "buf", record, &len, 1);
+	if(!ev.error)
+		return -1;
+	len = ev.length;
+	i = 0;
+	line_count = 0;
+	trace_seq_printf(s, " error:\n  %08x: ", i);
+	while(len >= 4) {
+		print_le_hex(s, ev.error, i);
+		i+=4;
+		len-=4;
+		if(++line_count == 4) {
+			trace_seq_printf(s, "\n  %08x: ", i);
+			line_count = 0;
+		} else
+			trace_seq_printf(s, " ");
+	}
+
+	/* Insert data into the SGBD */
+#ifdef HAVE_SQLITE3
+	ras_store_non_standard_record(ras, &ev);
+#endif
+
+#ifdef HAVE_ABRT_REPORT
+	/* Report event to ABRT */
+	ras_report_non_standard_record(ras, &ev);
+#endif
+
+	return 0;
+}
diff --git a/ras-non-standard-handler.h b/ras-non-standard-handler.h
new file mode 100644
index 0000000..2b5ac35
--- /dev/null
+++ b/ras-non-standard-handler.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __RAS_NON_STANDARD_HANDLER_H
+#define __RAS_NON_STANDARD_HANDLER_H
+
+#include "ras-events.h"
+#include "libtrace/event-parse.h"
+
+int ras_non_standard_event_handler(struct trace_seq *s,
+			 struct pevent_record *record,
+			 struct event_format *event, void *context);
+
+void print_le_hex(struct trace_seq *s, const uint8_t *buf, int index);
+
+#endif
diff --git a/ras-record.c b/ras-record.c
index 3dc4493..357ab61 100644
--- a/ras-record.c
+++ b/ras-record.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -157,6 +158,57 @@ int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev)
 }
 #endif
 
+/*
+ * Table and functions to handle ras:non standard
+ */
+
+#ifdef HAVE_NON_STANDARD
+static const struct db_fields non_standard_event_fields[] = {
+		{ .name="id",			.type="INTEGER PRIMARY KEY" },
+		{ .name="timestamp",		.type="TEXT" },
+		{ .name="sec_type",		.type="BLOB" },
+		{ .name="fru_id",		.type="BLOB" },
+		{ .name="fru_text",		.type="TEXT" },
+		{ .name="severity",		.type="TEXT" },
+		{ .name="error",		.type="BLOB" },
+};
+
+static const struct db_table_descriptor non_standard_event_tab = {
+	.name = "non_standard_event",
+	.fields = non_standard_event_fields,
+	.num_fields = ARRAY_SIZE(non_standard_event_fields),
+};
+
+int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev)
+{
+	int rc;
+	struct sqlite3_priv *priv = ras->db_priv;
+
+	if (!priv || !priv->stmt_non_standard_record)
+		return 0;
+	log(TERM, LOG_INFO, "non_standard_event store: %p\n", priv->stmt_non_standard_record);
+
+	sqlite3_bind_text (priv->stmt_non_standard_record,  1, ev->timestamp, -1, NULL);
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  2, ev->sec_type, -1, NULL);
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  3, ev->fru_id, 16, NULL);
+	sqlite3_bind_text (priv->stmt_non_standard_record,  4, ev->fru_text, -1, NULL);
+	sqlite3_bind_text (priv->stmt_non_standard_record,  5, ev->severity, -1, NULL);
+	sqlite3_bind_blob (priv->stmt_non_standard_record,  6, ev->error, ev->length, NULL);
+
+	rc = sqlite3_step(priv->stmt_non_standard_record);
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
+		log(TERM, LOG_ERR,
+		    "Failed to do non_standard_event step on sqlite: error = %d\n", rc);
+	rc = sqlite3_reset(priv->stmt_non_standard_record);
+	if (rc != SQLITE_OK && rc != SQLITE_DONE)
+		log(TERM, LOG_ERR,
+		    "Failed reset non_standard_event on sqlite: error = %d\n", rc);
+	log(TERM, LOG_INFO, "register inserted at db\n");
+
+	return rc;
+}
+#endif
+
 #ifdef HAVE_EXTLOG
 static const struct db_fields extlog_event_fields[] = {
 		{ .name="id",			.type="INTEGER PRIMARY KEY" },
@@ -450,6 +502,13 @@ int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras)
 					 &mce_record_tab);
 #endif
 
+#ifdef HAVE_NON_STANDARD
+	rc = ras_mc_create_table(priv, &non_standard_event_tab);
+	if (rc == SQLITE_OK)
+		rc = ras_mc_prepare_stmt(priv, &priv->stmt_non_standard_record,
+					&non_standard_event_tab);
+#endif
+
 		ras->db_priv = priv;
 	return 0;
 }
diff --git a/ras-record.h b/ras-record.h
index 5d84297..473ae40 100644
--- a/ras-record.h
+++ b/ras-record.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,9 +57,18 @@ struct ras_extlog_event {
 	unsigned short cper_data_length;
 };
 
+struct ras_non_standard_event {
+	char timestamp[64];
+	const char *sec_type, *fru_id, *fru_text;
+	const char *severity;
+	const uint8_t *error;
+	uint32_t length;
+};
+
 struct ras_mc_event;
 struct ras_aer_event;
 struct ras_extlog_event;
+struct ras_non_standard_event;
 struct mce_event;
 
 #ifdef HAVE_SQLITE3
@@ -77,6 +87,9 @@ struct sqlite3_priv {
 #ifdef HAVE_EXTLOG
 	sqlite3_stmt	*stmt_extlog_record;
 #endif
+#ifdef HAVE_NON_STANDARD
+	sqlite3_stmt	*stmt_non_standard_record;
+#endif
 };
 
 int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras);
@@ -84,6 +97,7 @@ int ras_store_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
 int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
 int ras_store_mce_record(struct ras_events *ras, struct mce_event *ev);
 int ras_store_extlog_mem_record(struct ras_events *ras, struct ras_extlog_event *ev);
+int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev);
 
 #else
 static inline int ras_mc_event_opendb(unsigned cpu, struct ras_events *ras) { return 0; };
@@ -91,6 +105,7 @@ static inline int ras_store_mc_event(struct ras_events *ras, struct ras_mc_event
 static inline int ras_store_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
 static inline int ras_store_mce_record(struct ras_events *ras, struct mce_event *ev) { return 0; };
 static inline int ras_store_extlog_mem_record(struct ras_events *ras, struct ras_extlog_event *ev) { return 0; };
+static inline int ras_store_non_standard_record(struct ras_events *ras, struct ras_non_standard_event *ev) { return 0; };
 
 #endif
 
diff --git a/ras-report.c b/ras-report.c
index 0a05732..3e508a5 100644
--- a/ras-report.c
+++ b/ras-report.c
@@ -1,3 +1,16 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
@@ -196,6 +209,27 @@ static int set_aer_event_backtrace(char *buf, struct ras_aer_event *ev){
 	return 0;
 }
 
+static int set_non_standard_event_backtrace(char *buf, struct ras_non_standard_event *ev){
+	char bt_buf[MAX_BACKTRACE_SIZE];
+
+	if(!buf || !ev)
+		return -1;
+
+	sprintf(bt_buf, "BACKTRACE="    \
+						"timestamp=%s\n"        \
+						"error_count=%d\n"       \
+						"severity=%d\n" \
+						"length=%d\n",     \
+						ev->timestamp,  \
+						ev->error_count, \
+						ev->severity,   \
+						ev->length);
+
+	strcat(buf, bt_buf);
+
+	return 0;
+}
+
 static int commit_report_backtrace(int sockfd, int type, void *ev){
 	char buf[MAX_BACKTRACE_SIZE];
 	char *pbuf = buf;
@@ -218,6 +252,9 @@ static int commit_report_backtrace(int sockfd, int type, void *ev){
 	case MCE_EVENT:
 		rc = set_mce_event_backtrace(buf, (struct mce_event *)ev);
 		break;
+	case NON_STANDARD_EVENT:
+		rc = set_non_standard_event_backtrace(buf, (struct ras_non_standard_event *)ev);
+		break;
 	default:
 		return -1;
 	}
@@ -345,6 +382,51 @@ aer_fail:
 	}
 }
 
+int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev){
+	char buf[MAX_MESSAGE_SIZE];
+	int sockfd = 0;
+	int rc = -1;
+
+	memset(buf, 0, sizeof(buf));
+
+	sockfd = setup_report_socket();
+	if(sockfd < 0){
+		return rc;
+	}
+
+	rc = commit_report_basic(sockfd);
+	if(rc < 0){
+		goto non_standard_fail;
+	}
+
+	rc = commit_report_backtrace(sockfd, NON_STANDARD_EVENT, ev);
+	if(rc < 0){
+		goto non_standard_fail;
+	}
+
+	sprintf(buf, "ANALYZER=%s", "rasdaemon-non-standard");
+	rc = write(sockfd, buf, strlen(buf) + 1);
+	if(rc < strlen(buf) + 1){
+		goto non_standard_fail;
+	}
+
+	sprintf(buf, "REASON=%s", "Unknown CPER section problem");
+	rc = write(sockfd, buf, strlen(buf) + 1);
+	if(rc < strlen(buf) + 1){
+		goto non_standard_fail;
+	}
+
+	rc = 0;
+
+non_standard_fail:
+
+	if(sockfd > 0){
+		close(sockfd);
+	}
+
+	return rc;
+}
+
 int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev){
 	char buf[MAX_MESSAGE_SIZE];
 	int sockfd = 0;
diff --git a/ras-report.h b/ras-report.h
index 7920cdf..c2fcf42 100644
--- a/ras-report.h
+++ b/ras-report.h
@@ -1,3 +1,16 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
 #ifndef __RAS_REPORT_H
 #define __RAS_REPORT_H
 
@@ -19,7 +32,8 @@
 enum {
 	MC_EVENT,
 	MCE_EVENT,
-	AER_EVENT
+	AER_EVENT,
+	NON_STANDARD_EVENT
 };
 
 #ifdef HAVE_ABRT_REPORT
@@ -27,12 +41,14 @@ enum {
 int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
 int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
 int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev);
+int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev);
 
 #else
 
 static inline int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev) { return 0; };
 static inline int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
 static inline int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev) { return 0; };
+static inline int ras_report_non_standard_event(struct ras_events *ras, struct ras_non_standard_event *ev) { return 0; };
 
 #endif
 

             reply	other threads:[~2017-06-02 21:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-02 21:40 Tyler Baicar [this message]
  -- strict thread matches above, loose matches on Subject: below --
2017-06-08  9:16 [V2,1/2] rasdaemon: add support for non standard CPER section events Mauro Carvalho Chehab
2017-06-08 17:28 Tyler Baicar

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=1496439633-23155-2-git-send-email-tbaicar@codeaurora.org \
    --to=tbaicar@codeaurora.org \
    --cc=astone@redhat.com \
    --cc=fu.wei@linaro.org \
    --cc=linux-edac@vger.kernel.org \
    --cc=mchehab@osg.samsung.com \
    --cc=shiju.jose@huawei.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.