qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: aik@ozlabs.ru, agraf@suse.de, ncmike@ncultra.org,
	qemu-ppc@nongnu.org, tyreld@linux.vnet.ibm.com,
	nfont@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH 10/12] spapr_events: re-use EPOW event infrastructure for hotplug events
Date: Mon, 18 Aug 2014 19:21:56 -0500	[thread overview]
Message-ID: <1408407718-10835-11-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1408407718-10835-1-git-send-email-mdroth@linux.vnet.ibm.com>

From: Nathan Fontenot <nfont@linux.vnet.ibm.com>

This extends the data structures currently used to report EPOW events to
gets via the check-exception RTAS interfaces to also include event types
for hotplug/unplug events.

This is currently undocumented and being finalized for inclusion in PAPR
specification, but we implement this here as an extension for guest
userspace tools to implement (existing guest kernels simply log these
events via a sysfs interface that's read by rtas_errd).

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c         |   2 +-
 hw/ppc/spapr_events.c  | 215 ++++++++++++++++++++++++++++++++++++++++---------
 include/hw/ppc/spapr.h |   4 +-
 3 files changed, 180 insertions(+), 41 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 39cb0bb..825fd31 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1706,7 +1706,7 @@ static void ppc_spapr_init(MachineState *machine)
     spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size,
                                             kernel_size, kernel_le,
                                             boot_device, kernel_cmdline,
-                                            spapr->epow_irq);
+                                            spapr->check_exception_irq);
     assert(spapr->fdt_skel != NULL);
 }
 
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 1b6157d..c0be0e5 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -32,6 +32,8 @@
 
 #include "hw/ppc/spapr.h"
 #include "hw/ppc/spapr_vio.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/spapr.h"
 
 #include <libfdt.h>
 
@@ -77,6 +79,7 @@ struct rtas_error_log {
 #define   RTAS_LOG_TYPE_ECC_UNCORR              0x00000009
 #define   RTAS_LOG_TYPE_ECC_CORR                0x0000000a
 #define   RTAS_LOG_TYPE_EPOW                    0x00000040
+#define   RTAS_LOG_TYPE_HOTPLUG                 0x000000e5
     uint32_t extended_length;
 } QEMU_PACKED;
 
@@ -166,6 +169,38 @@ struct epow_log_full {
     struct rtas_event_log_v6_epow epow;
 } QEMU_PACKED;
 
+struct rtas_event_log_v6_hp {
+#define RTAS_LOG_V6_SECTION_ID_HOTPLUG              0x4850 /* HP */
+    struct rtas_event_log_v6_section_header hdr;
+    uint8_t hotplug_type;
+#define RTAS_LOG_V6_HP_TYPE_CPU                          1
+#define RTAS_LOG_V6_HP_TYPE_MEMORY                       2
+#define RTAS_LOG_V6_HP_TYPE_SLOT                         3
+#define RTAS_LOG_V6_HP_TYPE_PHB                          4
+#define RTAS_LOG_V6_HP_TYPE_PCI                          5
+    uint8_t hotplug_action;
+#define RTAS_LOG_V6_HP_ACTION_ADD                        1
+#define RTAS_LOG_V6_HP_ACTION_REMOVE                     2
+    uint8_t hotplug_identifier;
+#define RTAS_LOG_V6_HP_ID_DRC_NAME                       1
+#define RTAS_LOG_V6_HP_ID_DRC_INDEX                      2
+#define RTAS_LOG_V6_HP_ID_DRC_COUNT                      3
+    uint8_t reserved;
+    union {
+        uint32_t index;
+        uint32_t count;
+        char name[1];
+    } drc;
+} QEMU_PACKED;
+
+struct hp_log_full {
+    struct rtas_error_log hdr;
+    struct rtas_event_log_v6 v6hdr;
+    struct rtas_event_log_v6_maina maina;
+    struct rtas_event_log_v6_mainb mainb;
+    struct rtas_event_log_v6_hp hp;
+} QEMU_PACKED;
+
 #define EVENT_MASK_INTERNAL_ERRORS           0x80000000
 #define EVENT_MASK_EPOW                      0x40000000
 #define EVENT_MASK_HOTPLUG                   0x10000000
@@ -181,29 +216,61 @@ struct epow_log_full {
         }                                                          \
     } while (0)
 
-void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq)
+void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
 {
-    uint32_t epow_irq_ranges[] = {cpu_to_be32(epow_irq), cpu_to_be32(1)};
-    uint32_t epow_interrupts[] = {cpu_to_be32(epow_irq), 0};
+    uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
+    uint32_t interrupts[] = {cpu_to_be32(check_exception_irq), 0};
 
     _FDT((fdt_begin_node(fdt, "event-sources")));
 
     _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
     _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
     _FDT((fdt_property(fdt, "interrupt-ranges",
-                       epow_irq_ranges, sizeof(epow_irq_ranges))));
+                       irq_ranges, sizeof(irq_ranges))));
 
     _FDT((fdt_begin_node(fdt, "epow-events")));
-    _FDT((fdt_property(fdt, "interrupts",
-                       epow_interrupts, sizeof(epow_interrupts))));
+    _FDT((fdt_property(fdt, "interrupts", interrupts, sizeof(interrupts))));
     _FDT((fdt_end_node(fdt)));
 
     _FDT((fdt_end_node(fdt)));
 }
 
 static struct epow_log_full *pending_epow;
+static struct hp_log_full *pending_hp;
 static uint32_t next_plid;
 
+static void spapr_init_v6hdr(struct rtas_event_log_v6 *v6hdr)
+{
+    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
+        | RTAS_LOG_V6_B0_BIGENDIAN;
+    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
+        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
+    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
+}
+
+static void spapr_init_maina(struct rtas_event_log_v6_maina *maina,
+                             int section_count)
+{
+    struct tm tm;
+    int year;
+
+    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
+    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
+    /* FIXME: section version, subtype and creator id? */
+    qemu_get_timedate(&tm, spapr->rtc_offset);
+    year = tm.tm_year + 1900;
+    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
+                                       | (to_bcd(year % 100) << 16)
+                                       | (to_bcd(tm.tm_mon + 1) << 8)
+                                       | to_bcd(tm.tm_mday));
+    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
+                                       | (to_bcd(tm.tm_min) << 16)
+                                       | (to_bcd(tm.tm_sec) << 8));
+    maina->creator_id = 'H'; /* Hypervisor */
+    maina->section_count = section_count;
+    maina->plid = next_plid++;
+}
+
 static void spapr_powerdown_req(Notifier *n, void *opaque)
 {
     sPAPREnvironment *spapr = container_of(n, sPAPREnvironment, epow_notifier);
@@ -212,8 +279,6 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     struct rtas_event_log_v6_maina *maina;
     struct rtas_event_log_v6_mainb *mainb;
     struct rtas_event_log_v6_epow *epow;
-    struct tm tm;
-    int year;
 
     if (pending_epow) {
         /* For now, we just throw away earlier events if two come
@@ -237,27 +302,8 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     hdr->extended_length = cpu_to_be32(sizeof(*pending_epow)
                                        - sizeof(pending_epow->hdr));
 
-    v6hdr->b0 = RTAS_LOG_V6_B0_VALID | RTAS_LOG_V6_B0_NEW_LOG
-        | RTAS_LOG_V6_B0_BIGENDIAN;
-    v6hdr->b2 = RTAS_LOG_V6_B2_POWERPC_FORMAT
-        | RTAS_LOG_V6_B2_LOG_FORMAT_PLATFORM_EVENT;
-    v6hdr->company = cpu_to_be32(RTAS_LOG_V6_COMPANY_IBM);
-
-    maina->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINA);
-    maina->hdr.section_length = cpu_to_be16(sizeof(*maina));
-    /* FIXME: section version, subtype and creator id? */
-    qemu_get_timedate(&tm, spapr->rtc_offset);
-    year = tm.tm_year + 1900;
-    maina->creation_date = cpu_to_be32((to_bcd(year / 100) << 24)
-                                       | (to_bcd(year % 100) << 16)
-                                       | (to_bcd(tm.tm_mon + 1) << 8)
-                                       | to_bcd(tm.tm_mday));
-    maina->creation_time = cpu_to_be32((to_bcd(tm.tm_hour) << 24)
-                                       | (to_bcd(tm.tm_min) << 16)
-                                       | (to_bcd(tm.tm_sec) << 8));
-    maina->creator_id = 'H'; /* Hypervisor */
-    maina->section_count = 3; /* Main-A, Main-B and EPOW */
-    maina->plid = next_plid++;
+    spapr_init_v6hdr(v6hdr);
+    spapr_init_maina(maina, 3 /* Main-A, Main-B and EPOW */);
 
     mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
     mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
@@ -274,7 +320,87 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
     epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
 
-    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->epow_irq));
+    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
+}
+
+static void spapr_hotplug_req_event(uint8_t hp_type, uint8_t hp_action,
+                                    sPAPRPHBState *phb, int slot)
+{
+    struct rtas_error_log *hdr;
+    struct rtas_event_log_v6 *v6hdr;
+    struct rtas_event_log_v6_maina *maina;
+    struct rtas_event_log_v6_mainb *mainb;
+    struct rtas_event_log_v6_hp *hp;
+    sPAPRDrcEntry *drc_entry;
+
+    if (pending_hp) {
+        /* Just toss any pending hotplug events for now, this will
+         * need to be fixed later on.
+         */
+        g_free(pending_hp);
+    }
+
+    pending_hp = g_malloc0(sizeof(*pending_hp));
+    hdr = &pending_hp->hdr;
+    v6hdr = &pending_hp->v6hdr;
+    maina = &pending_hp->maina;
+    mainb = &pending_hp->mainb;
+    hp = &pending_hp->hp;
+
+    hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
+                               | RTAS_LOG_SEVERITY_EVENT
+                               | RTAS_LOG_DISPOSITION_NOT_RECOVERED
+                               | RTAS_LOG_OPTIONAL_PART_PRESENT
+                               | RTAS_LOG_INITIATOR_HOTPLUG
+                               | RTAS_LOG_TYPE_HOTPLUG);
+    hdr->extended_length = cpu_to_be32(sizeof(*pending_hp)
+                                       - sizeof(pending_hp->hdr));
+
+    spapr_init_v6hdr(v6hdr);
+    spapr_init_maina(maina, 3 /* Main-A, Main-B, HP */);
+
+    mainb->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_MAINB);
+    mainb->hdr.section_length = cpu_to_be16(sizeof(*mainb));
+    mainb->subsystem_id = 0x80; /* External environment */
+    mainb->event_severity = 0x00; /* Informational / non-error */
+    mainb->event_subtype = 0x00; /* Normal shutdown */
+
+    hp->hdr.section_id = cpu_to_be16(RTAS_LOG_V6_SECTION_ID_HOTPLUG);
+    hp->hdr.section_length = cpu_to_be16(sizeof(*hp));
+    hp->hdr.section_version = 1; /* includes extended modifier */
+    hp->hotplug_action = hp_action;
+
+    hp->hotplug_type = hp_type;
+
+    drc_entry = spapr_phb_to_drc_entry(phb->buid);
+    if (!drc_entry) {
+        drc_entry = spapr_add_phb_to_drc_table(phb->buid, 2 /* Unusable */);
+    }
+
+    switch (hp_type) {
+    case RTAS_LOG_V6_HP_TYPE_PCI:
+        hp->drc.index = drc_entry->child_entries[slot].drc_index;
+        hp->hotplug_identifier = RTAS_LOG_V6_HP_ID_DRC_INDEX;
+        break;
+    }
+
+    qemu_irq_pulse(xics_get_qirq(spapr->icp, spapr->check_exception_irq));
+}
+
+void spapr_pci_hotplug_add_event(DeviceState *qdev, int slot)
+{
+    sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(qdev);
+
+    return spapr_hotplug_req_event(RTAS_LOG_V6_HP_TYPE_PCI,
+                                   RTAS_LOG_V6_HP_ACTION_ADD, phb, slot);
+}
+
+void spapr_pci_hotplug_remove_event(DeviceState *qdev, int slot)
+{
+    sPAPRPHBState *phb = SPAPR_PCI_HOST_BRIDGE(qdev);
+
+    return spapr_hotplug_req_event(RTAS_LOG_V6_HP_TYPE_PCI,
+                                   RTAS_LOG_V6_HP_ACTION_REMOVE, phb, slot);
 }
 
 static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@@ -298,15 +424,26 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
         xinfo |= (uint64_t)rtas_ld(args, 6) << 32;
     }
 
-    if ((mask & EVENT_MASK_EPOW) && pending_epow) {
-        if (sizeof(*pending_epow) < len) {
-            len = sizeof(*pending_epow);
-        }
+    if (mask & EVENT_MASK_EPOW) {
+        if (pending_epow) {
+            if (sizeof(*pending_epow) < len) {
+                len = sizeof(*pending_epow);
+            }
 
-        cpu_physical_memory_write(buf, pending_epow, len);
-        g_free(pending_epow);
-        pending_epow = NULL;
-        rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+            cpu_physical_memory_write(buf, pending_epow, len);
+            g_free(pending_epow);
+            pending_epow = NULL;
+            rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+        } else if (pending_hp) {
+            if (sizeof(*pending_hp) < len) {
+                len = sizeof(*pending_hp);
+            }
+
+            cpu_physical_memory_write(buf, pending_hp, len);
+            g_free(pending_hp);
+            pending_hp = NULL;
+            rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+        }
     } else {
         rtas_st(rets, 0, RTAS_OUT_NO_ERRORS_FOUND);
     }
@@ -314,7 +451,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 
 void spapr_events_init(sPAPREnvironment *spapr)
 {
-    spapr->epow_irq = xics_alloc(spapr->icp, 0, 0, false);
+    spapr->check_exception_irq = xics_alloc(spapr->icp, 0, 0, false);
     spapr->epow_notifier.notify = spapr_powerdown_req;
     qemu_register_powerdown_notifier(&spapr->epow_notifier);
     spapr_rtas_register(RTAS_CHECK_EXCEPTION, "check-exception",
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e08dd2f..5382bf1 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -63,7 +63,7 @@ typedef struct sPAPREnvironment {
     struct PPCTimebase tb;
     bool has_graphics;
 
-    uint32_t epow_irq;
+    uint32_t check_exception_irq;
     Notifier epow_notifier;
 
     /* Migration state */
@@ -521,5 +521,7 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
 sPAPRDrcEntry *spapr_add_phb_to_drc_table(uint64_t buid, uint32_t state);
 sPAPRDrcEntry *spapr_phb_to_drc_entry(uint64_t buid);
 sPAPRDrcEntry *spapr_find_drc_entry(int drc_index);
+void spapr_pci_hotplug_add_event(DeviceState *qdev, int slot);
+void spapr_pci_hotplug_remove_event(DeviceState *qdev, int slot);
 
 #endif /* !defined (__HW_SPAPR_H__) */
-- 
1.9.1

  parent reply	other threads:[~2014-08-19  0:23 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-19  0:21 [Qemu-devel] [PATCH v3 00/12] spapr: add support for pci hotplug Michael Roth
2014-08-19  0:21 ` [Qemu-devel] [PATCH 01/12] spapr: populate DRC entries for root dt node Michael Roth
2014-08-26  7:55   ` Alexey Kardashevskiy
2014-08-26  8:24     ` Alexey Kardashevskiy
2014-08-26 15:25       ` Michael Roth
2014-08-26 15:41         ` Michael Roth
2014-08-29 18:27         ` Tyrel Datwyler
2014-08-29 23:15           ` Alexander Graf
2014-08-26 14:56     ` Michael Roth
2014-09-05  0:31     ` [Qemu-devel] [Qemu-ppc] " Tyrel Datwyler
2014-08-26 11:11   ` [Qemu-devel] " Alexander Graf
2014-08-26 16:47     ` Michael Roth
2014-08-26 17:16       ` Alexander Graf
2014-09-03  5:55   ` Bharata B Rao
2014-09-05 22:00   ` Tyrel Datwyler
2014-08-19  0:21 ` [Qemu-devel] [PATCH 02/12] spapr_pci: populate DRC dt entries for PHBs Michael Roth
2014-08-26  8:32   ` Alexey Kardashevskiy
2014-08-26 17:16     ` Michael Roth
2014-08-26  9:09   ` Alexey Kardashevskiy
2014-08-26 17:52     ` Michael Roth
2014-08-26 11:29   ` Alexander Graf
2014-08-26 18:30     ` Michael Roth
2014-08-19  0:21 ` [Qemu-devel] [PATCH 03/12] spapr: add helper to retrieve a PHB/device DrcEntry Michael Roth
2014-08-19  0:21 ` [Qemu-devel] [PATCH 04/12] spapr_pci: add set-indicator RTAS interface Michael Roth
2014-08-26 11:36   ` Alexander Graf
2014-09-05  2:55     ` Nathan Fontenot
2014-09-30 22:08     ` Michael Roth
2014-10-01 14:30       ` Alexander Graf
2014-11-26  4:51         ` Bharata B Rao
2014-11-26  4:54         ` Bharata B Rao
2014-11-26  6:27           ` Michael Roth
2014-12-01  4:57             ` Bharata B Rao
2014-12-23 15:12               ` Michael Roth
2015-01-01  6:35                 ` Bharata B Rao
2014-08-19  0:21 ` [Qemu-devel] [PATCH 05/12] spapr_pci: add get/set-power-level RTAS interfaces Michael Roth
2014-08-19  0:21 ` [Qemu-devel] [PATCH 06/12] spapr_pci: add get-sensor-state RTAS interface Michael Roth
2014-09-05  0:34   ` Tyrel Datwyler
2014-08-19  0:21 ` [Qemu-devel] [PATCH 07/12] spapr_pci: add ibm, configure-connector " Michael Roth
2014-08-26  9:12   ` Alexey Kardashevskiy
2014-09-05  3:03     ` Nathan Fontenot
2014-08-26 11:39   ` Alexander Graf
2014-08-19  0:21 ` [Qemu-devel] [PATCH 08/12] pci: allow 0 address for PCI IO regions Michael Roth
2014-08-26  9:14   ` Alexey Kardashevskiy
2014-08-26 11:55     ` Peter Maydell
2014-08-26 18:34     ` Michael Roth
2014-08-26 11:41   ` Alexander Graf
2014-08-27 13:47   ` Michael S. Tsirkin
2014-08-28 21:21     ` Michael Roth
2014-08-28 21:33       ` Peter Maydell
2014-08-28 21:46         ` Michael S. Tsirkin
2014-08-19  0:21 ` [Qemu-devel] [PATCH 09/12] spapr_pci: enable basic hotplug operations Michael Roth
2014-08-26  9:40   ` Alexey Kardashevskiy
2014-08-26 12:30   ` Alexander Graf
2014-09-03 10:33   ` Bharata B Rao
2014-09-03 23:03     ` Michael Roth
2014-09-04 15:08       ` Bharata B Rao
2014-09-04 16:12         ` Michael Roth
2014-09-04 16:34           ` Michael Roth
2014-09-05  3:10             ` Nathan Fontenot
2014-09-05 17:17               ` [Qemu-devel] [Qemu-ppc] " Tyrel Datwyler
2014-08-19  0:21 ` Michael Roth [this message]
2014-08-26  9:28   ` [Qemu-devel] [PATCH 10/12] spapr_events: re-use EPOW event infrastructure for hotplug events Alexey Kardashevskiy
2014-08-19  0:21 ` [Qemu-devel] [PATCH 11/12] spapr_events: event-scan RTAS interface Michael Roth
2014-08-26  9:30   ` Alexey Kardashevskiy
2014-08-29 18:43     ` Tyrel Datwyler
2014-08-19  0:21 ` [Qemu-devel] [PATCH 12/12] spapr_pci: emit hotplug add/remove events during hotplug Michael Roth
2014-08-26  9:35   ` Alexey Kardashevskiy
2014-08-26 12:36   ` Alexander Graf
2014-08-26  9:24 ` [Qemu-devel] [PATCH v3 00/12] spapr: add support for pci hotplug Alexey Kardashevskiy

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=1408407718-10835-11-git-send-email-mdroth@linux.vnet.ibm.com \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=agraf@suse.de \
    --cc=aik@ozlabs.ru \
    --cc=ncmike@ncultra.org \
    --cc=nfont@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=tyreld@linux.vnet.ibm.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).