From: Greg Ungerer <gerg@snapgear.com>
To: jaredeh@gmail.com
Cc: "David Woodhouse" <dwmw2@infradead.org>,
"Jörn Engel" <joern@logfs.org>,
"Alexander Larsson" <alex@cendio.se>,
linux-mtd <linux-mtd@lists.infradead.org>,
"Mark Ferrell" <mferrell@mvista.com>,
"Nicolas Pitre" <nico@cam.org>,
"Jochen Schaeuble" <psionic@psionic.de>
Subject: Re: [MTD][NOR] adding physical address to point()
Date: Wed, 12 Mar 2008 09:56:31 +1000 [thread overview]
Message-ID: <47D71C2F.4090102@snapgear.com> (raw)
In-Reply-To: <47D6F132.2050002@gmail.com>
Hi Jared,
Jared Hulbert wrote:
> [MTD][NOR] adding physical address to point()
>
> Adding the ability to get a physical address from point() in addition
> to virtual address. This physical address is required for XIP of
> userspace code from flash.
>
> Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
> Reviewed-by: Joern Engel <joern@logfs.org>
> Acked-by: Nicolas Pitre <nico@cam.org>
I have no problem with the change to uclinux.c.
Heres an acked-by for that change if you want:
Acked-by: Greg Ungerer <gerg@uclinux.org>
Regards
Greg
> CC'ing dwmw2 and owners of diff'ed files. Adding Nicolas as Acked-by.
>
> I need this to do ANY legitimate XIP of
> userspace code from Flash. I've written AXFS to do XIP of userspace
> code. Working with the linux-mm guys we come up with a way to make
> mm/filemap_xip.c to what we need it to. To XIP Flash pages we need to
> do a vm_insert_pfn(). To get a pfn we need a physical address.
> virt_to_page() doesn't work for ioremap'ed kaddr's (like mtd->virt
> mtd->cached) and Linus told us "no sneaky page table walks and don't
> screw with virt_to_page()." So we're stuck needing to get this
> physical address from the mtd driver. This was the way we came up
> with to do that a while back.
>
>
> drivers/mtd/devices/mtdram.c | 11 +++++++----
> drivers/mtd/devices/phram.c | 13 +++++++------
> drivers/mtd/devices/pmc551.c | 27 +++++++++++++++++----------
> drivers/mtd/devices/slram.c | 15 ++++++++++-----
> drivers/mtd/maps/uclinux.c | 6 ++++--
> drivers/mtd/mtdpart.c | 8 ++++----
> fs/jffs2/erase.c | 7 ++++---
> fs/jffs2/readinode.c | 9 +++++----
> fs/jffs2/scan.c | 7 ++++---
> include/linux/mtd/mtd.h | 6 ++++--
> include/linux/mtd/pmc551.h | 5 +++--
> drivers/mtd/chips/cfi_cmdset_0001.c | 14 ++++++++------
> 12 files changed, 77 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
> index 47794d2..d2105aa 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0001.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0001.c
> @@ -82,9 +82,8 @@ static struct mtd_info *cfi_intelext_setup (struct mtd_info *);
> static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **);
>
> static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **mtdbuf);
> -static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from,
> - size_t len);
> + size_t *retlen, void **virt, resource_size_t *phys);
> +static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
>
> static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
> static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode);
> @@ -1237,7 +1236,8 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
> return ret;
> }
>
> -static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf)
> +static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> struct map_info *map = mtd->priv;
> struct cfi_private *cfi = map->fldrv_priv;
> @@ -1254,8 +1254,10 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
> chipnum = (from >> cfi->chipshift);
> ofs = from - (chipnum << cfi->chipshift);
>
> - *mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
> + *virt = map->virt + cfi->chips[chipnum].start + ofs;
> *retlen = 0;
> + if (phys)
> + *phys = map->phys + cfi->chips[chipnum].start + ofs;
>
> while (len) {
> unsigned long thislen;
> @@ -1288,7 +1290,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
> return 0;
> }
>
> -static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
> +static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> struct map_info *map = mtd->priv;
> struct cfi_private *cfi = map->fldrv_priv;
> diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
> index e427c82..fe39a9d 100644
> --- a/drivers/mtd/devices/mtdram.c
> +++ b/drivers/mtd/devices/mtdram.c
> @@ -47,18 +47,21 @@ static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
> }
>
> static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **mtdbuf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> if (from + len > mtd->size)
> return -EINVAL;
>
> - *mtdbuf = mtd->priv + from;
> + /* can we return a physical address with this driver? */
> + if (phys)
> + return -EINVAL;
> +
> + *virt = mtd->priv + from;
> *retlen = len;
> return 0;
> }
>
> -static void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
> - size_t len)
> +static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> }
>
> diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
> index 180298b..2b4d739 100644
> --- a/drivers/mtd/devices/phram.c
> +++ b/drivers/mtd/devices/phram.c
> @@ -57,20 +57,21 @@ static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
> }
>
> static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **mtdbuf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> - u_char *start = mtd->priv;
> -
> if (from + len > mtd->size)
> return -EINVAL;
>
> - *mtdbuf = start + from;
> + /* can we return a physical address with this driver? */
> + if (phys)
> + return -EINVAL;
> +
> + *virt = mtd->priv + from;
> *retlen = len;
> return 0;
> }
>
> -static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from,
> - size_t len)
> +static void phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> }
>
> diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
> index 7060a08..bc99817 100644
> --- a/drivers/mtd/devices/pmc551.c
> +++ b/drivers/mtd/devices/pmc551.c
> @@ -134,7 +134,8 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
> eoff_lo = end & (priv->asize - 1);
> soff_lo = instr->addr & (priv->asize - 1);
>
> - pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr);
> + pmc551_point(mtd, instr->addr, instr->len, &retlen,
> + (void **)&ptr, NULL);
>
> if (soff_hi == eoff_hi || mtd->size == priv->asize) {
> /* The whole thing fits within one access, so just one shot
> @@ -154,7 +155,8 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
> }
> soff_hi += priv->asize;
> pmc551_point(mtd, (priv->base_map0 | soff_hi),
> - priv->asize, &retlen, &ptr);
> + priv->asize, &retlen,
> + (void **)&ptr, NULL);
> }
> memset(ptr, 0xff, eoff_lo);
> }
> @@ -170,7 +172,7 @@ static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr)
> }
>
> static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
> - size_t * retlen, u_char ** mtdbuf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> struct mypriv *priv = mtd->priv;
> u32 soff_hi;
> @@ -188,6 +190,10 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
> return -EINVAL;
> }
>
> + /* can we return a physical address with this driver? */
> + if (phys)
> + return -EINVAL;
> +
> soff_hi = from & ~(priv->asize - 1);
> soff_lo = from & (priv->asize - 1);
>
> @@ -198,13 +204,12 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
> priv->curr_map0 = soff_hi;
> }
>
> - *mtdbuf = priv->start + soff_lo;
> + *virt = priv->start + soff_lo;
> *retlen = len;
> return 0;
> }
>
> -static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from,
> - size_t len)
> +static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> #ifdef CONFIG_MTD_PMC551_DEBUG
> printk(KERN_DEBUG "pmc551_unpoint()\n");
> @@ -242,7 +247,7 @@ static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
> soff_lo = from & (priv->asize - 1);
> eoff_lo = end & (priv->asize - 1);
>
> - pmc551_point(mtd, from, len, retlen, &ptr);
> + pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL);
>
> if (soff_hi == eoff_hi) {
> /* The whole thing fits within one access, so just one shot
> @@ -263,7 +268,8 @@ static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len,
> goto out;
> }
> soff_hi += priv->asize;
> - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
> + pmc551_point(mtd, soff_hi, priv->asize, retlen,
> + (void **)&ptr, NULL);
> }
> memcpy(copyto, ptr, eoff_lo);
> copyto += eoff_lo;
> @@ -308,7 +314,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
> soff_lo = to & (priv->asize - 1);
> eoff_lo = end & (priv->asize - 1);
>
> - pmc551_point(mtd, to, len, retlen, &ptr);
> + pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL);
>
> if (soff_hi == eoff_hi) {
> /* The whole thing fits within one access, so just one shot
> @@ -329,7 +335,8 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
> goto out;
> }
> soff_hi += priv->asize;
> - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr);
> + pmc551_point(mtd, soff_hi, priv->asize, retlen,
> + (void **)&ptr, NULL);
> }
> memcpy(ptr, copyfrom, eoff_lo);
> copyfrom += eoff_lo;
> diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
> index d293add..cb86db7 100644
> --- a/drivers/mtd/devices/slram.c
> +++ b/drivers/mtd/devices/slram.c
> @@ -76,8 +76,9 @@ static char *map;
> static slram_mtd_list_t *slram_mtdlist = NULL;
>
> static int slram_erase(struct mtd_info *, struct erase_info *);
> -static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **);
> -static void slram_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
> +static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **,
> + resource_size_t *);
> +static void slram_unpoint(struct mtd_info *, loff_t, size_t);
> static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
> static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
>
> @@ -104,19 +105,23 @@ static int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
> }
>
> static int slram_point(struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **mtdbuf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> slram_priv_t *priv = mtd->priv;
>
> + /* can we return a physical address with this driver? */
> + if (phys)
> + return -EINVAL;
> +
> if (from + len > mtd->size)
> return -EINVAL;
>
> - *mtdbuf = priv->start + from;
> + *virt = priv->start + from;
> *retlen = len;
> return(0);
> }
>
> -static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
> +static void slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> }
>
> diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
> index 14ffb1a..c42f4b8 100644
> --- a/drivers/mtd/maps/uclinux.c
> +++ b/drivers/mtd/maps/uclinux.c
> @@ -40,10 +40,12 @@ struct mtd_partition uclinux_romfs[] = {
> /****************************************************************************/
>
> int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **mtdbuf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> struct map_info *map = mtd->priv;
> - *mtdbuf = (u_char *) (map->virt + ((int) from));
> + *virt = map->virt + from;
> + if (phys)
> + *phys = map->phys + from;
> *retlen = len;
> return(0);
> }
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index c66902d..07c7011 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -68,7 +68,7 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
> }
>
> static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
> - size_t *retlen, u_char **buf)
> + size_t *retlen, void **virt, resource_size_t *phys)
> {
> struct mtd_part *part = PART(mtd);
> if (from >= mtd->size)
> @@ -76,14 +76,14 @@ static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
> else if (from + len > mtd->size)
> len = mtd->size - from;
> return part->master->point (part->master, from + part->offset,
> - len, retlen, buf);
> + len, retlen, virt, phys);
> }
>
> -static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
> +static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
> {
> struct mtd_part *part = PART(mtd);
>
> - part->master->unpoint (part->master, addr, from + part->offset, len);
> + part->master->unpoint(part->master, from + part->offset, len);
> }
>
> static int part_read_oob(struct mtd_info *mtd, loff_t from,
> diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
> index a1db918..6c2a046 100644
> --- a/fs/jffs2/erase.c
> +++ b/fs/jffs2/erase.c
> @@ -332,7 +332,8 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
> if (c->mtd->point) {
> unsigned long *wordebuf;
>
> - ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
> + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size,
> + &retlen, &ebuf, NULL);
> if (ret) {
> D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
> goto do_flash_read;
> @@ -340,7 +341,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
> if (retlen < c->sector_size) {
> /* Don't muck about if it won't let us point to the whole erase sector */
> D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
> - c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen);
> + c->mtd->unpoint(c->mtd, jeb->offset, retlen);
> goto do_flash_read;
> }
> wordebuf = ebuf-sizeof(*wordebuf);
> @@ -349,7 +350,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
> if (*++wordebuf != ~0)
> break;
> } while(--retlen);
> - c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
> + c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size);
> if (retlen)
> printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
> *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
> diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
> index e512a93..22acc12 100644
> --- a/fs/jffs2/readinode.c
> +++ b/fs/jffs2/readinode.c
> @@ -63,10 +63,11 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
> /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
> * adding and jffs2_flash_read_end() interface. */
> if (c->mtd->point) {
> - err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
> + err = c->mtd->point(c->mtd, ofs, len, &retlen,
> + (void **)&buffer, NULL);
> if (!err && retlen < len) {
> JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
> - c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
> + c->mtd->unpoint(c->mtd, ofs, retlen);
> } else if (err)
> JFFS2_WARNING("MTD point failed: error code %d.\n", err);
> else
> @@ -100,7 +101,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
> kfree(buffer);
> #ifndef __ECOS
> else
> - c->mtd->unpoint(c->mtd, buffer, ofs, len);
> + c->mtd->unpoint(c->mtd, ofs, len);
> #endif
>
> if (crc != tn->data_crc) {
> @@ -136,7 +137,7 @@ free_out:
> kfree(buffer);
> #ifndef __ECOS
> else
> - c->mtd->unpoint(c->mtd, buffer, ofs, len);
> + c->mtd->unpoint(c->mtd, ofs, len);
> #endif
> return err;
> }
> diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
> index 272872d..b1b3884 100644
> --- a/fs/jffs2/scan.c
> +++ b/fs/jffs2/scan.c
> @@ -97,11 +97,12 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
> size_t pointlen;
>
> if (c->mtd->point) {
> - ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf);
> + ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen,
> + (void **)&flashbuf, NULL);
> if (!ret && pointlen < c->mtd->size) {
> /* Don't muck about if it won't let us point to the whole flash */
> D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen));
> - c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen);
> + c->mtd->unpoint(c->mtd, 0, pointlen);
> flashbuf = NULL;
> }
> if (ret)
> @@ -267,7 +268,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
> kfree(flashbuf);
> #ifndef __ECOS
> else
> - c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
> + c->mtd->unpoint(c->mtd, 0, c->mtd->size);
> #endif
> if (s)
> kfree(s);
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 0a13bb3..245f909 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -143,10 +143,12 @@ struct mtd_info {
> int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
>
> /* This stuff for eXecute-In-Place */
> - int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
> + /* phys is optional and may be set to NULL */
> + int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
> + size_t *retlen, void **virt, resource_size_t *phys);
>
> /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
> - void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
> + void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
>
>
> int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
> diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h
> index a7f6d20..5cc070c 100644
> --- a/include/linux/mtd/pmc551.h
> +++ b/include/linux/mtd/pmc551.h
> @@ -36,8 +36,9 @@ struct mypriv {
> * Function Prototypes
> */
> static int pmc551_erase(struct mtd_info *, struct erase_info *);
> -static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t);
> -static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
> +static void pmc551_unpoint(struct mtd_info *, loff_t, size_t);
> +static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len,
> + size_t *retlen, void **virt, resource_size_t *phys);
> static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
> static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
>
>
>
--
------------------------------------------------------------------------
Greg Ungerer -- Chief Software Dude EMAIL: gerg@snapgear.com
Secure Computing Corporation PHONE: +61 7 3435 2888
825 Stanley St, FAX: +61 7 3891 3630
Woolloongabba, QLD, 4102, Australia WEB: http://www.SnapGear.com
prev parent reply other threads:[~2008-03-11 23:57 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-05 10:13 [MTD][NOR] adding physical address to point() Jared Hulbert
2008-03-05 12:00 ` Jörn Engel
2008-03-05 14:45 ` Nicolas Pitre
2008-03-11 20:53 ` Jared Hulbert
2008-03-11 23:56 ` Greg Ungerer [this message]
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=47D71C2F.4090102@snapgear.com \
--to=gerg@snapgear.com \
--cc=alex@cendio.se \
--cc=dwmw2@infradead.org \
--cc=jaredeh@gmail.com \
--cc=joern@logfs.org \
--cc=linux-mtd@lists.infradead.org \
--cc=mferrell@mvista.com \
--cc=nico@cam.org \
--cc=psionic@psionic.de \
/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.