From: Ian Campbell <ian.campbell@citrix.com>
To: Julien Grall <julien.grall@linaro.org>
Cc: Zoltan Kiss <zoltan.kiss@huawei.com>,
Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
tim@xen.org, Frediano Ziglio <frediano.ziglio@huawei.com>,
stefano.stabellini@citrix.com, xen-devel@lists.xenproject.org
Subject: Re: [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts
Date: Tue, 31 Mar 2015 12:44:40 +0100 [thread overview]
Message-ID: <1427802280.2115.98.camel@citrix.com> (raw)
In-Reply-To: <1426793399-6283-2-git-send-email-julien.grall@linaro.org>
Frediano, Zoltan,
On Thu, 2015-03-19 at 19:29 +0000, Julien Grall wrote:
> Note that the HIP04 GIC driver has not been modified because I don't
> have a platform where I can test my changes. Although, the code is
> still building.
>
> I let the Hisilicon guys (Frediano and Zoltan) providing a suitable
> patch for there platform.
Are you going to provide an update for the hip04 driver for this change?
> Meanwhile, I think it can go upstream as it has been acked by both
> Ian and Stefano.
>
> Changes in v4:
> - Rebase on the latest staging (no functional changes)
> - Add Ian and Stefano's ack
> - Typo in the commit message
>
> Changes in v3:
> - Patch was previously sent in a separate series [1]
> - Reorder the function to avoid forward declaration
> - Make gic-v3 driver compliant to the new interface
> - Remove spurious field addition in gicv2 structure
>
> Changelog based on the separate series:
>
> Changes in v3:
> - Patch added.
>
> [1] https://patches.linaro.org/33313/
> ---
> xen/arch/arm/gic-v2.c | 70 ++++++++++++++++++++++---------------------
> xen/arch/arm/gic-v3.c | 75 ++++++++++++++++++++++++-----------------------
> xen/arch/arm/gic.c | 16 ++++++++--
> xen/arch/arm/setup.c | 3 +-
> xen/include/asm-arm/gic.h | 8 +++++
> 5 files changed, 100 insertions(+), 72 deletions(-)
>
> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> index 20cdbc9..3be4ad6 100644
> --- a/xen/arch/arm/gic-v2.c
> +++ b/xen/arch/arm/gic-v2.c
> @@ -674,37 +674,10 @@ static hw_irq_controller gicv2_guest_irq_type = {
> .set_affinity = gicv2_irq_set_affinity,
> };
>
> -const static struct gic_hw_operations gicv2_ops = {
> - .info = &gicv2_info,
> - .secondary_init = gicv2_secondary_cpu_init,
> - .save_state = gicv2_save_state,
> - .restore_state = gicv2_restore_state,
> - .dump_state = gicv2_dump_state,
> - .gicv_setup = gicv2v_setup,
> - .gic_host_irq_type = &gicv2_host_irq_type,
> - .gic_guest_irq_type = &gicv2_guest_irq_type,
> - .eoi_irq = gicv2_eoi_irq,
> - .deactivate_irq = gicv2_dir_irq,
> - .read_irq = gicv2_read_irq,
> - .set_irq_properties = gicv2_set_irq_properties,
> - .send_SGI = gicv2_send_SGI,
> - .disable_interface = gicv2_disable_interface,
> - .update_lr = gicv2_update_lr,
> - .update_hcr_status = gicv2_hcr_status,
> - .clear_lr = gicv2_clear_lr,
> - .read_lr = gicv2_read_lr,
> - .write_lr = gicv2_write_lr,
> - .read_vmcr_priority = gicv2_read_vmcr_priority,
> - .read_apr = gicv2_read_apr,
> - .make_dt_node = gicv2_make_dt_node,
> -};
> -
> -/* Set up the GIC */
> -static int __init gicv2_init(struct dt_device_node *node, const void *data)
> +static int __init gicv2_init(void)
> {
> int res;
> -
> - dt_device_set_used_by(node, DOMID_XEN);
> + const struct dt_device_node *node = gicv2_info.node;
>
> res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
> if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
> @@ -727,9 +700,6 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
> panic("GICv2: Cannot find the maintenance IRQ");
> gicv2_info.maintenance_irq = res;
>
> - /* Set the GIC as the primary interrupt controller */
> - dt_interrupt_controller = node;
> -
> /* TODO: Add check on distributor, cpu size */
>
> printk("GICv2 initialization:\n"
> @@ -774,8 +744,42 @@ static int __init gicv2_init(struct dt_device_node *node, const void *data)
>
> spin_unlock(&gicv2.lock);
>
> + return 0;
> +}
> +
> +const static struct gic_hw_operations gicv2_ops = {
> + .info = &gicv2_info,
> + .init = gicv2_init,
> + .secondary_init = gicv2_secondary_cpu_init,
> + .save_state = gicv2_save_state,
> + .restore_state = gicv2_restore_state,
> + .dump_state = gicv2_dump_state,
> + .gicv_setup = gicv2v_setup,
> + .gic_host_irq_type = &gicv2_host_irq_type,
> + .gic_guest_irq_type = &gicv2_guest_irq_type,
> + .eoi_irq = gicv2_eoi_irq,
> + .deactivate_irq = gicv2_dir_irq,
> + .read_irq = gicv2_read_irq,
> + .set_irq_properties = gicv2_set_irq_properties,
> + .send_SGI = gicv2_send_SGI,
> + .disable_interface = gicv2_disable_interface,
> + .update_lr = gicv2_update_lr,
> + .update_hcr_status = gicv2_hcr_status,
> + .clear_lr = gicv2_clear_lr,
> + .read_lr = gicv2_read_lr,
> + .write_lr = gicv2_write_lr,
> + .read_vmcr_priority = gicv2_read_vmcr_priority,
> + .read_apr = gicv2_read_apr,
> + .make_dt_node = gicv2_make_dt_node,
> +};
> +
> +/* Set up the GIC */
> +static int __init gicv2_preinit(struct dt_device_node *node, const void *data)
> +{
> gicv2_info.hw_version = GIC_V2;
> + gicv2_info.node = node;
> register_gic_ops(&gicv2_ops);
> + dt_irq_xlate = gic_irq_xlate;
>
> return 0;
> }
> @@ -788,7 +792,7 @@ static const struct dt_device_match gicv2_dt_match[] __initconst =
>
> DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
> .dt_match = gicv2_dt_match,
> - .init = gicv2_init,
> + .init = gicv2_preinit,
> DT_DEVICE_END
>
> /*
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index ab80670..48772f1 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -1173,31 +1173,6 @@ static const hw_irq_controller gicv3_guest_irq_type = {
> .set_affinity = gicv3_irq_set_affinity,
> };
>
> -static const struct gic_hw_operations gicv3_ops = {
> - .info = &gicv3_info,
> - .save_state = gicv3_save_state,
> - .restore_state = gicv3_restore_state,
> - .dump_state = gicv3_dump_state,
> - .gicv_setup = gicv_v3_init,
> - .gic_host_irq_type = &gicv3_host_irq_type,
> - .gic_guest_irq_type = &gicv3_guest_irq_type,
> - .eoi_irq = gicv3_eoi_irq,
> - .deactivate_irq = gicv3_dir_irq,
> - .read_irq = gicv3_read_irq,
> - .set_irq_properties = gicv3_set_irq_properties,
> - .send_SGI = gicv3_send_sgi,
> - .disable_interface = gicv3_disable_interface,
> - .update_lr = gicv3_update_lr,
> - .update_hcr_status = gicv3_hcr_status,
> - .clear_lr = gicv3_clear_lr,
> - .read_lr = gicv3_read_lr,
> - .write_lr = gicv3_write_lr,
> - .read_vmcr_priority = gicv3_read_vmcr_priority,
> - .read_apr = gicv3_read_apr,
> - .secondary_init = gicv3_secondary_cpu_init,
> - .make_dt_node = gicv3_make_dt_node,
> -};
> -
> static int __init cmp_rdist(const void *a, const void *b)
> {
> const struct rdist_region *l = a, *r = a;
> @@ -1207,11 +1182,12 @@ static int __init cmp_rdist(const void *a, const void *b)
> }
>
> /* Set up the GIC */
> -static int __init gicv3_init(struct dt_device_node *node, const void *data)
> +static int __init gicv3_init(void)
> {
> struct rdist_region *rdist_regs;
> int res, i;
> uint32_t reg;
> + const struct dt_device_node *node = gicv3_info.node;
>
> if ( !cpu_has_gicv3 )
> {
> @@ -1219,8 +1195,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
> return -ENODEV;
> }
>
> - dt_device_set_used_by(node, DOMID_XEN);
> -
> res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size);
> if ( res || !gicv3.dbase )
> panic("GICv3: Cannot find a valid distributor address");
> @@ -1274,9 +1248,6 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
> panic("GICv3: Cannot find the maintenance IRQ");
> gicv3_info.maintenance_irq = res;
>
> - /* Set the GIC as the primary interrupt controller */
> - dt_interrupt_controller = node;
> -
> for ( i = 0; i < gicv3.rdist_count; i++ )
> {
> /* map dbase & rdist regions */
> @@ -1311,15 +1282,47 @@ static int __init gicv3_init(struct dt_device_node *node, const void *data)
> res = gicv3_cpu_init();
> gicv3_hyp_init();
>
> - gicv3_info.hw_version = GIC_V3;
> - /* Register hw ops*/
> - register_gic_ops(&gicv3_ops);
> -
> spin_unlock(&gicv3.lock);
>
> return res;
> }
>
> +static const struct gic_hw_operations gicv3_ops = {
> + .info = &gicv3_info,
> + .init = gicv3_init,
> + .save_state = gicv3_save_state,
> + .restore_state = gicv3_restore_state,
> + .dump_state = gicv3_dump_state,
> + .gicv_setup = gicv_v3_init,
> + .gic_host_irq_type = &gicv3_host_irq_type,
> + .gic_guest_irq_type = &gicv3_guest_irq_type,
> + .eoi_irq = gicv3_eoi_irq,
> + .deactivate_irq = gicv3_dir_irq,
> + .read_irq = gicv3_read_irq,
> + .set_irq_properties = gicv3_set_irq_properties,
> + .send_SGI = gicv3_send_sgi,
> + .disable_interface = gicv3_disable_interface,
> + .update_lr = gicv3_update_lr,
> + .update_hcr_status = gicv3_hcr_status,
> + .clear_lr = gicv3_clear_lr,
> + .read_lr = gicv3_read_lr,
> + .write_lr = gicv3_write_lr,
> + .read_vmcr_priority = gicv3_read_vmcr_priority,
> + .read_apr = gicv3_read_apr,
> + .secondary_init = gicv3_secondary_cpu_init,
> + .make_dt_node = gicv3_make_dt_node,
> +};
> +
> +static int __init gicv3_preinit(struct dt_device_node *node, const void *data)
> +{
> + gicv3_info.hw_version = GIC_V3;
> + gicv3_info.node = node;
> + register_gic_ops(&gicv3_ops);
> + dt_irq_xlate = gic_irq_xlate;
> +
> + return 0;
> +}
> +
> static const struct dt_device_match gicv3_dt_match[] __initconst =
> {
> DT_MATCH_GIC_V3,
> @@ -1328,7 +1331,7 @@ static const struct dt_device_match gicv3_dt_match[] __initconst =
>
> DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC)
> .dt_match = gicv3_dt_match,
> - .init = gicv3_init,
> + .init = gicv3_preinit,
> DT_DEVICE_END
>
> /*
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 940fb8e..8e7f24b 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int intsize,
> return 0;
> }
>
> -/* Set up the GIC */
> -void __init gic_init(void)
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +void __init gic_preinit(void)
> {
> int rc;
> struct dt_device_node *node;
> @@ -189,6 +191,16 @@ void __init gic_init(void)
> if ( !num_gics )
> panic("Unable to find compatible GIC in the device tree");
>
> + /* Set the GIC as the primary interrupt controller */
> + dt_interrupt_controller = node;
> + dt_device_set_used_by(node, DOMID_XEN);
> +}
> +
> +/* Set up the GIC */
> +void __init gic_init(void)
> +{
> + if ( gic_hw_ops->init() )
> + panic("Failed to initialize the GIC drivers");
> /* Clear LR mask for cpu0 */
> clear_cpu_lr_mask();
> }
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index b905c9f..4f05f57 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -752,7 +752,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>
> vm_init();
> dt_unflatten_host_device_tree();
> - dt_irq_xlate = gic_irq_xlate;
>
> init_IRQ();
>
> @@ -760,6 +759,8 @@ void __init start_xen(unsigned long boot_phys_offset,
>
> preinit_xen_time();
>
> + gic_preinit();
> +
> dt_uart_init();
> console_init_preirq();
> console_init_ring();
> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index 89a9b6f..b16f98e 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -232,6 +232,10 @@ extern void gic_remove_from_queues(struct vcpu *v, unsigned int virtual_irq);
>
> /* Accept an interrupt from the GIC and dispatch its handler */
> extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +extern void gic_preinit(void);
> /* Bring up the interrupt controller, and report # cpus attached */
> extern void gic_init(void);
> /* Bring up a secondary CPU's per-CPU GIC interface */
> @@ -284,11 +288,15 @@ struct gic_info {
> uint8_t nr_lrs;
> /* Maintenance irq number */
> unsigned int maintenance_irq;
> + /* Pointer to the device tree node representing the interrupt controller */
> + const struct dt_device_node *node;
> };
>
> struct gic_hw_operations {
> /* Hold GIC HW information */
> const struct gic_info *info;
> + /* Initialize the GIC and the boot CPU */
> + int (*init)(void);
> /* Save GIC registers */
> void (*save_state)(struct vcpu *);
> /* Restore GIC registers */
next prev parent reply other threads:[~2015-03-31 11:44 UTC|newest]
Thread overview: 103+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-19 19:29 [PATCH v4 00/33] xen/arm: Add support for non-PCI passthrough Julien Grall
2015-03-19 19:29 ` [PATCH v4 01/33] xen/arm: Divide GIC initialization in 2 parts Julien Grall
2015-03-31 11:44 ` Ian Campbell [this message]
2015-03-19 19:29 ` [PATCH v4 02/33] xen/dts: Allow only IRQ translation that are mapped to main GIC Julien Grall
2015-03-19 19:29 ` [PATCH v4 03/33] xen/dts: Use unsigned int for MMIO and IRQ index Julien Grall
2015-03-19 19:29 ` [PATCH v4 04/33] xen/arm: vgic: Introduce a function to initialize pending_irq Julien Grall
2015-03-19 19:29 ` [PATCH v4 05/33] xen/arm: Map disabled device in DOM0 Julien Grall
2015-03-19 19:29 ` [PATCH v4 06/33] xen/arm: Introduce xen, passthrough property Julien Grall
2015-03-31 10:25 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 07/33] xen: guestcopy: Provide an helper to safely copy string from guest Julien Grall
2015-03-31 13:24 ` Andrew Cooper
2015-03-31 13:30 ` Julien Grall
2015-03-31 13:49 ` Andrew Cooper
2015-03-31 14:00 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 08/33] MAINTAINERS: move drivers/passthrough/device_tree.c in "DEVICE TREE" Julien Grall
2015-03-31 10:26 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 09/33] xen: Extend DOMCTL createdomain to support arch configuration Julien Grall
2015-03-31 10:39 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 10/33] xen/arm: Allow virq != irq Julien Grall
2015-03-31 10:41 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 11/33] xen/arm: route_irq_to_guest: Check validity of the IRQ Julien Grall
2015-03-20 11:36 ` Stefano Stabellini
2015-03-31 10:43 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 12/33] xen/arm: gic: Add sanity checks gic_route_irq_to_guest Julien Grall
2015-03-31 10:44 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 13/33] xen/arm: gic_route_irq_to_guest: Honor the priority given in parameter Julien Grall
2015-03-20 11:51 ` Stefano Stabellini
2015-03-31 10:45 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 14/33] xen/arm: vgic: Correctly calculate GICD_TYPER.ITLinesNumber Julien Grall
2015-03-31 10:46 ` Ian Campbell
2015-03-31 11:28 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 15/33] xen/arm: gic: GICv2 & GICv3 only supports 1020 physical interrupts Julien Grall
2015-03-31 10:47 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 16/33] xen/arm: Let the toolstack configure the number of SPIs Julien Grall
2015-03-31 10:54 ` Ian Campbell
2015-03-31 11:44 ` Julien Grall
2015-03-31 11:59 ` Ian Campbell
2015-03-31 12:07 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 17/33] xen/arm: vgic: Add spi_to_pending Julien Grall
2015-03-31 10:55 ` Ian Campbell
2015-03-31 11:58 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 18/33] xen/arm: Release IRQ routed to a domain when it's destroying Julien Grall
2015-03-31 10:58 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 19/33] xen/arm: Implement hypercall DOMCTL_{, un}bind_pt_pirq Julien Grall
2015-03-31 11:11 ` Ian Campbell
2015-03-31 12:23 ` Julien Grall
2015-03-31 12:31 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 20/33] xen/dts: Provide an helper to get a DT node from a path provided by a guest Julien Grall
2015-03-31 11:12 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 21/33] xen/passthrough: Introduce iommu_construct Julien Grall
2015-03-20 10:53 ` Jan Beulich
2015-03-31 11:13 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 22/33] xen/passthrough: arm: release the DT devices assigned to a guest earlier Julien Grall
2015-03-31 11:16 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 23/33] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Julien Grall
2015-03-31 11:16 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 24/33] xen/iommu: arm: Wire iommu DOMCTL for ARM Julien Grall
2015-03-19 19:29 ` [PATCH v4 25/33] xen/xsm: Add helpers to check permission for device tree passthrough Julien Grall
2015-03-31 11:17 ` Ian Campbell
2015-03-31 17:12 ` Daniel De Graaf
2015-03-31 17:14 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 26/33] xen/passthrough: Extend XEN_DOMCTL_*assign_device to support DT device Julien Grall
2015-03-20 11:01 ` Jan Beulich
2015-03-31 11:24 ` Ian Campbell
2015-03-31 12:30 ` Julien Grall
2015-03-31 13:16 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 27/33] tools/libxl: Create a per-arch function to map IRQ to a domain Julien Grall
2015-03-31 11:26 ` Ian Campbell
2015-03-31 12:33 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 28/33] tools/libxl: Check if fdt_{first, next}_subnode are present in libfdt Julien Grall
2015-03-19 19:42 ` Julien Grall
2015-03-31 11:35 ` Ian Campbell
2015-03-31 12:46 ` Julien Grall
2015-03-31 13:18 ` Ian Campbell
2015-04-07 17:15 ` Julien Grall
2015-04-09 12:16 ` Ian Jackson
2015-04-09 13:59 ` Julien Grall
2015-04-14 11:40 ` Ian Campbell
2015-04-14 13:34 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 29/33] tools/(lib)xl: Add partial device tree support for ARM Julien Grall
2015-03-31 11:41 ` Ian Campbell
2015-03-31 12:55 ` Julien Grall
2015-03-31 13:19 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 30/33] tools/libxl: arm: Use an higher value for the GIC phandle Julien Grall
2015-03-31 11:43 ` Ian Campbell
2015-04-09 12:36 ` Julien Grall
2015-03-19 19:29 ` [PATCH v4 31/33] libxl: Add support for non-PCI passthrough Julien Grall
2015-03-31 11:49 ` Ian Campbell
2015-03-31 13:00 ` Julien Grall
2015-03-31 13:20 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 32/33] xl: Add new option dtdev Julien Grall
2015-03-31 11:50 ` Ian Campbell
2015-03-19 19:29 ` [PATCH v4 33/33] docs/misc: arm: Add documentation about non-PCI passthrough Julien Grall
2015-03-31 11:55 ` Ian Campbell
2015-03-31 13:03 ` Julien Grall
2015-03-31 13:21 ` Ian Campbell
2015-04-09 13:36 ` Julien Grall
2015-03-20 1:22 ` [PATCH v4 00/33] xen/arm: Add support for " Edgar E. Iglesias
2015-03-20 17:34 ` Julien Grall
2015-03-31 11:57 ` Ian Campbell
2015-03-31 13:07 ` Julien Grall
2015-03-31 13:22 ` Ian Campbell
2015-04-01 14:21 ` Julien Grall
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=1427802280.2115.98.camel@citrix.com \
--to=ian.campbell@citrix.com \
--cc=frediano.ziglio@huawei.com \
--cc=julien.grall@linaro.org \
--cc=stefano.stabellini@citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=tim@xen.org \
--cc=xen-devel@lists.xenproject.org \
--cc=zoltan.kiss@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.