Linux SPI subsystem development
 help / color / mirror / Atom feed
* [PATCH 0/2] spi: fsl-qspi: Fix kernel panic when unbinding the SPI host
@ 2025-03-21 12:40 Kevin Hao
  2025-03-21 12:40 ` [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct Kevin Hao
  2025-03-21 12:40 ` [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove() Kevin Hao
  0 siblings, 2 replies; 6+ messages in thread
From: Kevin Hao @ 2025-03-21 12:40 UTC (permalink / raw)
  To: linux-spi
  Cc: Han Xu, Mark Brown, Volker Haspel, John Ogness, imx, Kevin Hao,
	stable

Hi,

I observed a kernel panic on my imx8mq-evk board. It can be easily
reproduced with the following steps:
  while true; do cat /dev/mtd0 >/dev/null; done &
  echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind

The following is the kernel log:
  Unable to handle kernel paging request at virtual address ffffffc082a6015c
  Mem abort info:
    ESR = 0x0000000096000007
    EC = 0x25: DABT (current EL), IL = 32 bits
    SET = 0, FnV = 0
    EA = 0, S1PTW = 0
    FSC = 0x07: level 3 translation fault
  Data abort info:
    ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000
    CM = 0, WnR = 0, TnD = 0, TagAccess = 0
    GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
  swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000041dc3000
  [ffffffc082a6015c] pgd=1000000042779003, p4d=1000000042779003, pud=1000000042779003, pmd=1000000044631403, pte=0000000000000000
  Internal error: Oops: 0000000096000007 [#1]  SMP
  Modules linked in: 8021q ath10k_pci ath10k_core etnaviv snd_soc_fsl_asoc_card ath snd_soc_imx_audmux gpu_sched snd_soc_fsl_sai snd_soc_fsl_spdif imx_sdma imx_pcm_dma snd_soc_fsl_utils snd_soc_wm8524 sch_fq_codel openvswitch nsh nf_conncount nf_nat fuse configfs nfnetlink
  Hardware name: NXP i.MX8MQ EVK (DT)
  pc : fsl_qspi_exec_op+0xa8/0x7c0
  lr : fsl_qspi_exec_op+0x88/0x7c0
  sp : ffffffc08433b650
  x8 : ffffffc08433b748 x7 : 0000000000000000 x6 : 0000000000000004
  x5 : 0000000000000001 x4 : 0000000000000000 x3 : 0000000000004174
  x2 : 0032724c809254be x1 : 000000000000c2a2 x0 : 000000173a720be8
  Call trace:
   fsl_qspi_exec_op+0xa8/0x7c0 (P)
   spi_mem_exec_op+0x410/0x4a0
   spi_mem_no_dirmap_read+0xb0/0xd0
   spi_mem_dirmap_read+0xdc/0x150
   spi_nor_read_data+0x128/0x1a0
   spi_nor_read+0xf4/0x2c8
   mtd_read_oob_std+0x80/0x98
   mtd_read_oob+0x9c/0x168
   mtd_read+0x70/0xe0
   mtdchar_read+0x224/0x2a8
   vfs_read+0xcc/0x310
   ksys_read+0x78/0x118
   __arm64_sys_read+0x24/0x38
   invoke_syscall+0x5c/0x130
   el0_svc_common.constprop.0+0x48/0xf0
   do_el0_svc+0x24/0x38
   el0_svc+0x30/0xd0
   el0t_64_sync_handler+0x10c/0x138
   el0t_64_sync+0x198/0x1a0

CPU: 1 UID: 0 PID: 527 Comm: cat Not tainted 6.14.0-rc7-next-20250321-yocto-standard+ #11 PREEMPT
pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
x29: ffffffc08433b670 x28: 0000007f8019f000 x27: 000000000000000e
x26: ffffff8004781140 x25: 000000173a814e28 x24: 0000000000000006
x23: ffffffc082a6015c x22: ffffff80046a3d80 x21: ffffff80046a3d98
x20: ffffffc082a60000 x19: ffffffc08433b9b8 x18: 0000000000000000
x17: 0000000000000000 x16: 003135312e373631 x15: 2e3432322e383231
x14: 0000000000000000 x13: ffffff80bf74d940 x12: 0000000000000000
x11: 0000000000000160 x10: 00000000000009b0 x9 : ffffffc08010ea78
Code: d2800141 d2800060 941ecb48 d503203f (b94002e1)
---
Kevin Hao (2):
      spi: fsl-qsi: Optimize fsl_qspi struct
      spi: fsl-qspi: Explicitly unregister SPI host in remove()

 drivers/spi/spi-fsl-qspi.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)
---
base-commit: 9388ec571cb1adba59d1cded2300eeb11827679c
change-id: 20250321-spi-8d7999765767

Best regards,
-- 
Kevin Hao <haokexin@gmail.com>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct
  2025-03-21 12:40 [PATCH 0/2] spi: fsl-qspi: Fix kernel panic when unbinding the SPI host Kevin Hao
@ 2025-03-21 12:40 ` Kevin Hao
  2025-03-21 15:26   ` Han Xu
  2025-03-21 12:40 ` [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove() Kevin Hao
  1 sibling, 1 reply; 6+ messages in thread
From: Kevin Hao @ 2025-03-21 12:40 UTC (permalink / raw)
  To: linux-spi; +Cc: Han Xu, Mark Brown, Volker Haspel, John Ogness, imx, Kevin Hao

Reorgize the members of the fsl_qspi struct to:
  - Reduce a hole in the struct.
  - Group members required by each op (e.g., iobase, ahb_addr,
    devtype_data and lock) into the same cacheline.

Before:
struct fsl_qspi {
	[...]

	/* size: 176, cachelines: 3, members: 11 */
	/* sum members: 168, holes: 1, sum holes: 4 */
	/* padding: 4 */
	/* member types with holes: 1, total: 1 */
	/* last cacheline: 48 bytes */
};

after:
struct fsl_qspi {
	void *                     iobase;               /*     0     8 */
	void *                     ahb_addr;             /*     8     8 */
	const struct fsl_qspi_devtype_data  * devtype_data; /*    16     8 */
	struct mutex               lock;                 /*    24    32 */
	struct completion          c;                    /*    56    32 */

	/* XXX last struct has 1 hole */

	/* --- cacheline 1 boundary (64 bytes) was 24 bytes ago --- */
	struct clk *               clk;                  /*    88     8 */
	struct clk *               clk_en;               /*    96     8 */
	struct pm_qos_request      pm_qos_req;           /*   104    48 */
	/* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
	struct device *            dev;                  /*   152     8 */
	int                        selected;             /*   160     4 */
	u32                        memmap_phy;           /*   164     4 */

	/* size: 168, cachelines: 3, members: 11 */
	/* member types with holes: 1, total: 1 */
	/* last cacheline: 40 bytes */
};

Signed-off-by: Kevin Hao <haokexin@gmail.com>
---
 drivers/spi/spi-fsl-qspi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
index 355e6a39fb41896f460e2474a90b8f0b42068ff3..efd87f44c63a5b12b76538aa459ca8eb203b9dcd 100644
--- a/drivers/spi/spi-fsl-qspi.c
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -264,14 +264,14 @@ static const struct fsl_qspi_devtype_data ls2080a_data = {
 struct fsl_qspi {
 	void __iomem *iobase;
 	void __iomem *ahb_addr;
-	u32 memmap_phy;
-	struct clk *clk, *clk_en;
-	struct device *dev;
-	struct completion c;
 	const struct fsl_qspi_devtype_data *devtype_data;
 	struct mutex lock;
+	struct completion c;
+	struct clk *clk, *clk_en;
 	struct pm_qos_request pm_qos_req;
+	struct device *dev;
 	int selected;
+	u32 memmap_phy;
 };
 
 static inline int needs_swap_endian(struct fsl_qspi *q)

-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove()
  2025-03-21 12:40 [PATCH 0/2] spi: fsl-qspi: Fix kernel panic when unbinding the SPI host Kevin Hao
  2025-03-21 12:40 ` [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct Kevin Hao
@ 2025-03-21 12:40 ` Kevin Hao
  2025-03-21 15:23   ` Han Xu
  1 sibling, 1 reply; 6+ messages in thread
From: Kevin Hao @ 2025-03-21 12:40 UTC (permalink / raw)
  To: linux-spi
  Cc: Han Xu, Mark Brown, Volker Haspel, John Ogness, imx, stable,
	Kevin Hao

Currently, the SPI host is registered using a managed API, which
automatically unregisters it when the device is detached from its driver.
However, this unregistration occurs after the driver's remove() callback.

Since the host is already disabled inside the remove(), any pending IO
from child devices can easily corrupt the kernel.

For example, the following steps on an imx8mq-evk board can trigger a
kernel panic:
  while true; do cat /dev/mtd0 >/dev/null; done &
  echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind

To fix this, explicitly call spi_unregister_controller() in the
remove() callback. This ensures that all child devices are properly
removed before the host is disabled.

Cc: stable@vger.kernel.org
Fixes: 8fcb830a00f0 ("spi: spi-fsl-qspi: use devm_spi_register_controller")
Signed-off-by: Kevin Hao <haokexin@gmail.com>
---
 drivers/spi/spi-fsl-qspi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
index efd87f44c63a5b12b76538aa459ca8eb203b9dcd..4767d2085510c2f231476ba75e46f83271c4c645 100644
--- a/drivers/spi/spi-fsl-qspi.c
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -272,6 +272,7 @@ struct fsl_qspi {
 	struct device *dev;
 	int selected;
 	u32 memmap_phy;
+	struct spi_controller *host;
 };
 
 static inline int needs_swap_endian(struct fsl_qspi *q)
@@ -862,6 +863,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 
 	q = spi_controller_get_devdata(ctlr);
 	q->dev = dev;
+	q->host = ctlr;
 	q->devtype_data = of_device_get_match_data(dev);
 	if (!q->devtype_data) {
 		ret = -ENODEV;
@@ -934,7 +936,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 
 	ctlr->dev.of_node = np;
 
-	ret = devm_spi_register_controller(dev, ctlr);
+	ret = spi_register_controller(ctlr);
 	if (ret)
 		goto err_destroy_mutex;
 
@@ -957,6 +959,8 @@ static void fsl_qspi_remove(struct platform_device *pdev)
 {
 	struct fsl_qspi *q = platform_get_drvdata(pdev);
 
+	spi_unregister_controller(q->host);
+
 	/* disable the hardware */
 	qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
 	qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);

-- 
2.48.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove()
  2025-03-21 12:40 ` [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove() Kevin Hao
@ 2025-03-21 15:23   ` Han Xu
  2025-03-21 15:55     ` Mark Brown
  0 siblings, 1 reply; 6+ messages in thread
From: Han Xu @ 2025-03-21 15:23 UTC (permalink / raw)
  To: Kevin Hao; +Cc: linux-spi, Mark Brown, Volker Haspel, John Ogness, imx, stable

On 25/03/21 08:40PM, Kevin Hao wrote:
> 
> Currently, the SPI host is registered using a managed API, which
> automatically unregisters it when the device is detached from its driver.
> However, this unregistration occurs after the driver's remove() callback.
> 
> Since the host is already disabled inside the remove(), any pending IO
> from child devices can easily corrupt the kernel.
> 
> For example, the following steps on an imx8mq-evk board can trigger a
> kernel panic:
>   while true; do cat /dev/mtd0 >/dev/null; done &
>   echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind
> 
> To fix this, explicitly call spi_unregister_controller() in the
> remove() callback. This ensures that all child devices are properly
> removed before the host is disabled.

If you explicitly remove the child devices, such as 
cd /sys/bus/spi/drivers/spi-nor
echo spi0.0 > unbind
then unbind the fsl-quadspi driver, the kernel panic does not occur.

Not sure if it should be the responsibility of the fsl-quadspi driver to handle
this, IMO it is a common issue with all SPI drivers.

> 
> Cc: stable@vger.kernel.org
> Fixes: 8fcb830a00f0 ("spi: spi-fsl-qspi: use devm_spi_register_controller")
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> ---
>  drivers/spi/spi-fsl-qspi.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
> index efd87f44c63a5b12b76538aa459ca8eb203b9dcd..4767d2085510c2f231476ba75e46f83271c4c645 100644
> --- a/drivers/spi/spi-fsl-qspi.c
> +++ b/drivers/spi/spi-fsl-qspi.c
> @@ -272,6 +272,7 @@ struct fsl_qspi {
>         struct device *dev;
>         int selected;
>         u32 memmap_phy;
> +       struct spi_controller *host;
>  };
> 
>  static inline int needs_swap_endian(struct fsl_qspi *q)
> @@ -862,6 +863,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> 
>         q = spi_controller_get_devdata(ctlr);
>         q->dev = dev;
> +       q->host = ctlr;
>         q->devtype_data = of_device_get_match_data(dev);
>         if (!q->devtype_data) {
>                 ret = -ENODEV;
> @@ -934,7 +936,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> 
>         ctlr->dev.of_node = np;
> 
> -       ret = devm_spi_register_controller(dev, ctlr);
> +       ret = spi_register_controller(ctlr);
>         if (ret)
>                 goto err_destroy_mutex;
> 
> @@ -957,6 +959,8 @@ static void fsl_qspi_remove(struct platform_device *pdev)
>  {
>         struct fsl_qspi *q = platform_get_drvdata(pdev);
> 
> +       spi_unregister_controller(q->host);
> +
>         /* disable the hardware */
>         qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
>         qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
> 
> --
> 2.48.1
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct
  2025-03-21 12:40 ` [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct Kevin Hao
@ 2025-03-21 15:26   ` Han Xu
  0 siblings, 0 replies; 6+ messages in thread
From: Han Xu @ 2025-03-21 15:26 UTC (permalink / raw)
  To: Kevin Hao; +Cc: linux-spi, Mark Brown, Volker Haspel, John Ogness, imx

On 25/03/21 08:40PM, Kevin Hao wrote:
> 
> Reorgize the members of the fsl_qspi struct to:
>   - Reduce a hole in the struct.
>   - Group members required by each op (e.g., iobase, ahb_addr,
>     devtype_data and lock) into the same cacheline.
> 
> Before:
> struct fsl_qspi {
>         [...]
> 
>         /* size: 176, cachelines: 3, members: 11 */
>         /* sum members: 168, holes: 1, sum holes: 4 */
>         /* padding: 4 */
>         /* member types with holes: 1, total: 1 */
>         /* last cacheline: 48 bytes */
> };
> 
> after:
> struct fsl_qspi {
>         void *                     iobase;               /*     0     8 */
>         void *                     ahb_addr;             /*     8     8 */
>         const struct fsl_qspi_devtype_data  * devtype_data; /*    16     8 */
>         struct mutex               lock;                 /*    24    32 */
>         struct completion          c;                    /*    56    32 */
> 
>         /* XXX last struct has 1 hole */
> 
>         /* --- cacheline 1 boundary (64 bytes) was 24 bytes ago --- */
>         struct clk *               clk;                  /*    88     8 */
>         struct clk *               clk_en;               /*    96     8 */
>         struct pm_qos_request      pm_qos_req;           /*   104    48 */
>         /* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
>         struct device *            dev;                  /*   152     8 */
>         int                        selected;             /*   160     4 */
>         u32                        memmap_phy;           /*   164     4 */
> 
>         /* size: 168, cachelines: 3, members: 11 */
>         /* member types with holes: 1, total: 1 */
>         /* last cacheline: 40 bytes */
> };
> 
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> ---
>  drivers/spi/spi-fsl-qspi.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
> index 355e6a39fb41896f460e2474a90b8f0b42068ff3..efd87f44c63a5b12b76538aa459ca8eb203b9dcd 100644
> --- a/drivers/spi/spi-fsl-qspi.c
> +++ b/drivers/spi/spi-fsl-qspi.c
> @@ -264,14 +264,14 @@ static const struct fsl_qspi_devtype_data ls2080a_data = {
>  struct fsl_qspi {
>         void __iomem *iobase;
>         void __iomem *ahb_addr;
> -       u32 memmap_phy;
> -       struct clk *clk, *clk_en;
> -       struct device *dev;
> -       struct completion c;
>         const struct fsl_qspi_devtype_data *devtype_data;
>         struct mutex lock;
> +       struct completion c;
> +       struct clk *clk, *clk_en;
>         struct pm_qos_request pm_qos_req;
> +       struct device *dev;
>         int selected;
> +       u32 memmap_phy;
>  };

Reviewed-by: Han Xu <han.xu@nxp.com>

> 
>  static inline int needs_swap_endian(struct fsl_qspi *q)
> 
> --
> 2.48.1
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove()
  2025-03-21 15:23   ` Han Xu
@ 2025-03-21 15:55     ` Mark Brown
  0 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2025-03-21 15:55 UTC (permalink / raw)
  To: Han Xu; +Cc: Kevin Hao, linux-spi, Volker Haspel, John Ogness, imx, stable

[-- Attachment #1: Type: text/plain, Size: 2839 bytes --]

On Fri, Mar 21, 2025 at 10:23:07AM -0500, Han Xu wrote:
> On 25/03/21 08:40PM, Kevin Hao wrote:

> > Since the host is already disabled inside the remove(), any pending IO
> > from child devices can easily corrupt the kernel.

...

> > To fix this, explicitly call spi_unregister_controller() in the
> > remove() callback. This ensures that all child devices are properly
> > removed before the host is disabled.

> If you explicitly remove the child devices, such as 
> cd /sys/bus/spi/drivers/spi-nor
> echo spi0.0 > unbind
> then unbind the fsl-quadspi driver, the kernel panic does not occur.

> Not sure if it should be the responsibility of the fsl-quadspi driver to handle
> this, IMO it is a common issue with all SPI drivers.

This is a bug in the driver, it needs to be able to continue supporting
child devices until it is unregistered.  This means that either the
unregistration needs to be manual or any disabling also needs to be done
via devm.

> 
> > 
> > Cc: stable@vger.kernel.org
> > Fixes: 8fcb830a00f0 ("spi: spi-fsl-qspi: use devm_spi_register_controller")
> > Signed-off-by: Kevin Hao <haokexin@gmail.com>
> > ---
> >  drivers/spi/spi-fsl-qspi.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c
> > index efd87f44c63a5b12b76538aa459ca8eb203b9dcd..4767d2085510c2f231476ba75e46f83271c4c645 100644
> > --- a/drivers/spi/spi-fsl-qspi.c
> > +++ b/drivers/spi/spi-fsl-qspi.c
> > @@ -272,6 +272,7 @@ struct fsl_qspi {
> >         struct device *dev;
> >         int selected;
> >         u32 memmap_phy;
> > +       struct spi_controller *host;
> >  };
> > 
> >  static inline int needs_swap_endian(struct fsl_qspi *q)
> > @@ -862,6 +863,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> > 
> >         q = spi_controller_get_devdata(ctlr);
> >         q->dev = dev;
> > +       q->host = ctlr;
> >         q->devtype_data = of_device_get_match_data(dev);
> >         if (!q->devtype_data) {
> >                 ret = -ENODEV;
> > @@ -934,7 +936,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)
> > 
> >         ctlr->dev.of_node = np;
> > 
> > -       ret = devm_spi_register_controller(dev, ctlr);
> > +       ret = spi_register_controller(ctlr);
> >         if (ret)
> >                 goto err_destroy_mutex;
> > 
> > @@ -957,6 +959,8 @@ static void fsl_qspi_remove(struct platform_device *pdev)
> >  {
> >         struct fsl_qspi *q = platform_get_drvdata(pdev);
> > 
> > +       spi_unregister_controller(q->host);
> > +
> >         /* disable the hardware */
> >         qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
> >         qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
> > 
> > --
> > 2.48.1
> > 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-03-21 15:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-21 12:40 [PATCH 0/2] spi: fsl-qspi: Fix kernel panic when unbinding the SPI host Kevin Hao
2025-03-21 12:40 ` [PATCH 1/2] spi: fsl-qsi: Optimize fsl_qspi struct Kevin Hao
2025-03-21 15:26   ` Han Xu
2025-03-21 12:40 ` [PATCH 2/2] spi: fsl-qspi: Explicitly unregister SPI host in remove() Kevin Hao
2025-03-21 15:23   ` Han Xu
2025-03-21 15:55     ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox