netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] miscellaneous dm9000 driver fixes
@ 2014-06-04 22:28 Andrew Ruder
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
  2014-06-05 22:14 ` [PATCH 0/6] miscellaneous dm9000 driver fixes David Miller
  0 siblings, 2 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

This is a collection of changes discovered while bringing a PXA270 based board
(Arcom ZEUS) with a Davicom DM9000A/B up to a more recent kernel (from 2.6.xx).
This addresses all of my earlier issues (August 2013) listed here:

http://marc.info/?l=linux-netdev&m=137598605603324&w=2

Andrew Ruder (6):
  dm9000: acquire irq flags from device tree
  dm9000: clean up reset code
  dm9000: clean up edge-triggered irq compatibility
  dm9000: remove redundant ISR status clear
  dm9000: handle initial link status
  dm9000: avoid sleeping in dm9000_timeout callback

 drivers/net/ethernet/davicom/dm9000.c | 68 +++++++++++++++++++++--------------
 1 file changed, 42 insertions(+), 26 deletions(-)

-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 1/6] dm9000: acquire irq flags from device tree
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
@ 2014-06-04 22:28   ` Andrew Ruder
  2014-06-04 22:28   ` [PATCH 2/6] dm9000: clean up reset code Andrew Ruder
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

The DM9000 supports both active high interrupts and active low interrupts.
This is configured via the attached EEPROM.  In the device-tree case, make sure
that the DM9000 driver passes the correct flags to request_irq.

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index a1a2b40..9d44c3f 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1292,6 +1292,9 @@ dm9000_open(struct net_device *dev)
 	 * may work, and tell the user that this is a problem */
 
 	if (irqflags == IRQF_TRIGGER_NONE)
+		irqflags = irq_get_trigger_type(dev->irq);
+
+	if (irqflags == IRQF_TRIGGER_NONE)
 		dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
 
 	irqflags |= IRQF_SHARED;
-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 2/6] dm9000: clean up reset code
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
  2014-06-04 22:28   ` [PATCH 1/6] dm9000: acquire irq flags from device tree Andrew Ruder
@ 2014-06-04 22:28   ` Andrew Ruder
  2014-06-04 22:28   ` [PATCH 3/6] dm9000: clean up edge-triggered irq compatibility Andrew Ruder
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

* Change a hard-coded 0x3 to NCR_RST | NCR_MAC_LBK in dm9000_reset

* Every single place where dm9000_init_dm9000 was ran, a dm9000_reset
  was called immediately before-hand.  Bring dm9000_reset into
  dm9000_init_dm9000.

* The following commit updated the dm9000_probe reset routine to use NCR_RST
  | NCR_MAC_LBK:

    6741f40 DM9000B: driver initialization upgrade

  and a later commit added a bug-fix to always reset the chip twice:

    09ee9f8 dm9000: Implement full reset of DM9000 network device

  Unfortunately, since the changes in 6741f40 were made by replacing the
  dm9000_probe dm9000_reset with the adjusted iow(), the changes in
  09ee9f8 were not incorporated into the dm9000_probe reset.
  Furthermore, it bypassed the requisite reset-delay causing some boards
  to get at least one "read wrong id ..." dev_err message during
  dm9000_probe.

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 9d44c3f..e6b1bc3 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -187,13 +187,13 @@ dm9000_reset(board_info_t *db)
 	 * The essential point is that we have to do a double reset, and the
 	 * instruction is to set LBK into MAC internal loopback mode.
 	 */
-	iow(db, DM9000_NCR, 0x03);
+	iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);
 	udelay(100); /* Application note says at least 20 us */
 	if (ior(db, DM9000_NCR) & 1)
 		dev_err(db->dev, "dm9000 did not respond to first reset\n");
 
 	iow(db, DM9000_NCR, 0);
-	iow(db, DM9000_NCR, 0x03);
+	iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK);
 	udelay(100);
 	if (ior(db, DM9000_NCR) & 1)
 		dev_err(db->dev, "dm9000 did not respond to second reset\n");
@@ -894,6 +894,8 @@ dm9000_init_dm9000(struct net_device *dev)
 
 	dm9000_dbg(db, 1, "entering %s\n", __func__);
 
+	dm9000_reset(db);
+
 	/* I/O mode */
 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
 
@@ -962,7 +964,6 @@ static void dm9000_timeout(struct net_device *dev)
 	reg_save = readb(db->io_addr);
 
 	netif_stop_queue(dev);
-	dm9000_reset(db);
 	dm9000_init_dm9000(dev);
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1304,7 +1305,6 @@ dm9000_open(struct net_device *dev)
 	mdelay(1); /* delay needs by DM9000B */
 
 	/* Initialize DM9000 board */
-	dm9000_reset(db);
 	dm9000_init_dm9000(dev);
 
 	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
@@ -1550,12 +1550,7 @@ dm9000_probe(struct platform_device *pdev)
 	db->flags |= DM9000_PLATF_SIMPLE_PHY;
 #endif
 
-	/* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
-	 * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
-	 * while probe stage.
-	 */
-
-	iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
+	dm9000_reset(db);
 
 	/* try multiple times, DM9000 sometimes gets the read wrong */
 	for (i = 0; i < 8; i++) {
@@ -1698,7 +1693,6 @@ dm9000_drv_resume(struct device *dev)
 			/* reset if we were not in wake mode to ensure if
 			 * the device was powered off it is in a known state */
 			if (!db->wake_state) {
-				dm9000_reset(db);
 				dm9000_init_dm9000(ndev);
 			}
 
-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 3/6] dm9000: clean up edge-triggered irq compatibility
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
  2014-06-04 22:28   ` [PATCH 1/6] dm9000: acquire irq flags from device tree Andrew Ruder
  2014-06-04 22:28   ` [PATCH 2/6] dm9000: clean up reset code Andrew Ruder
@ 2014-06-04 22:28   ` Andrew Ruder
  2014-06-04 22:28   ` [PATCH 4/6] dm9000: remove redundant ISR status clear Andrew Ruder
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

DM9000 uses level-triggered interrupts.  Some systems (PXA270) only
support edge-triggered interrupts on GPIOs.  Some changes are necessary
to ensure that interrupts are not triggered while the GPIO interrupt is
masked or we will miss the interrupt forever.

* Make some helper functions called dm9000_mask_interrupts() and
  dm9000_unmask_interrupts() for readability.

* dm9000_init_dm9000(): ensure that this function always leaves interrupts
  masked regardless of the state when it entered the function.  This is
  primarily to support the situation in dm9000_open where the logic used
  to go:

    dm9000_open()
        dm9000_init_dm9000()
            unmask interrupts
        request_irq()

  If an interrupt occurred between unmasking the interrupt and
  requesting the irq, it would be missed forever as the edge event would
  never be seen by the GPIO hardware in the PXA270.  This allows us to
  change the logic to:

    dm9000_open()
        dm9000_init_dm9000()
            dm9000_mask_interrupts()
        request_irq()
        dm9000_unmask_interrupts()

* dm9000_timeout(), dm9000_drv_resume(): Add the missing
  dm9000_unmask_interrupts() now required by the change above.

* dm9000_shutdown(): Use mask helper function

* dm9000_interrupt(): Use mask/unmask helper functions

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index e6b1bc3..c508a33 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -882,6 +882,18 @@ dm9000_hash_table(struct net_device *dev)
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
+static void
+dm9000_mask_interrupts(board_info_t *db)
+{
+	iow(db, DM9000_IMR, IMR_PAR);
+}
+
+static void
+dm9000_unmask_interrupts(board_info_t *db)
+{
+	iow(db, DM9000_IMR, db->imr_all);
+}
+
 /*
  * Initialize dm9000 board
  */
@@ -895,6 +907,7 @@ dm9000_init_dm9000(struct net_device *dev)
 	dm9000_dbg(db, 1, "entering %s\n", __func__);
 
 	dm9000_reset(db);
+	dm9000_mask_interrupts(db);
 
 	/* I/O mode */
 	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
@@ -943,9 +956,6 @@ dm9000_init_dm9000(struct net_device *dev)
 
 	db->imr_all = imr;
 
-	/* Enable TX/RX interrupt mask */
-	iow(db, DM9000_IMR, imr);
-
 	/* Init Driver variable */
 	db->tx_pkt_cnt = 0;
 	db->queue_pkt_len = 0;
@@ -965,6 +975,7 @@ static void dm9000_timeout(struct net_device *dev)
 
 	netif_stop_queue(dev);
 	dm9000_init_dm9000(dev);
+	dm9000_unmask_interrupts(db);
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies; /* prevent tx timeout */
 	netif_wake_queue(dev);
@@ -1194,9 +1205,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
 	/* Save previous register address */
 	reg_save = readb(db->io_addr);
 
-	/* Disable all interrupts */
-	iow(db, DM9000_IMR, IMR_PAR);
-
+	dm9000_mask_interrupts(db);
 	/* Got DM9000 interrupt status */
 	int_status = ior(db, DM9000_ISR);	/* Got ISR */
 	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */
@@ -1219,9 +1228,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
 		}
 	}
 
-	/* Re-enable interrupt mask */
-	iow(db, DM9000_IMR, db->imr_all);
-
+	dm9000_unmask_interrupts(db);
 	/* Restore previous register address */
 	writeb(reg_save, db->io_addr);
 
@@ -1309,6 +1316,10 @@ dm9000_open(struct net_device *dev)
 
 	if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
 		return -EAGAIN;
+	/* Now that we have an interrupt handler hooked up we can unmask
+	 * our interrupts
+	 */
+	dm9000_unmask_interrupts(db);
 
 	/* Init driver variable */
 	db->dbug_cnt = 0;
@@ -1329,7 +1340,7 @@ dm9000_shutdown(struct net_device *dev)
 	/* RESET device */
 	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */
 	iow(db, DM9000_GPR, 0x01);	/* Power-Down PHY */
-	iow(db, DM9000_IMR, IMR_PAR);	/* Disable all interrupt */
+	dm9000_mask_interrupts(db);
 	iow(db, DM9000_RCR, 0x00);	/* Disable RX */
 }
 
@@ -1694,6 +1705,7 @@ dm9000_drv_resume(struct device *dev)
 			 * the device was powered off it is in a known state */
 			if (!db->wake_state) {
 				dm9000_init_dm9000(ndev);
+				dm9000_unmask_interrupts(db);
 			}
 
 			netif_device_attach(ndev);
-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 4/6] dm9000: remove redundant ISR status clear
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
                     ` (2 preceding siblings ...)
  2014-06-04 22:28   ` [PATCH 3/6] dm9000: clean up edge-triggered irq compatibility Andrew Ruder
@ 2014-06-04 22:28   ` Andrew Ruder
  2014-06-04 22:28   ` [PATCH 5/6] dm9000: handle initial link status Andrew Ruder
  2014-06-04 22:28   ` [PATCH 6/6] dm9000: avoid sleeping in dm9000_timeout callback Andrew Ruder
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

Since dm9000_interrupt() is already reading/clearing every set bit in
DM9000_ISR, this additional clear in dm9000_rx() (which is only called
by dm9000_interrupt()) is unnecessary and can be removed.

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index c508a33..d1a5b2f 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1105,7 +1105,6 @@ dm9000_rx(struct net_device *dev)
 		if (rxbyte & DM9000_PKT_ERR) {
 			dev_warn(db->dev, "status check fail: %d\n", rxbyte);
 			iow(db, DM9000_RCR, 0x00);	/* Stop Device */
-			iow(db, DM9000_ISR, IMR_PAR);	/* Stop INT request */
 			return;
 		}
 
-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 5/6] dm9000: handle initial link status
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
                     ` (3 preceding siblings ...)
  2014-06-04 22:28   ` [PATCH 4/6] dm9000: remove redundant ISR status clear Andrew Ruder
@ 2014-06-04 22:28   ` Andrew Ruder
  2014-06-04 22:28   ` [PATCH 6/6] dm9000: avoid sleeping in dm9000_timeout callback Andrew Ruder
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

On the DM9000A/DM9000B force the initial check of the link status.  The
DM9000A/B has a link status changed event and this interrupt bit isn't
always set out of reset when a cable is plugged in.  This results in the
driver not seeing the cable attached link status until the cable is
removed and plugged in again.

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index d1a5b2f..eb9b704 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -1326,7 +1326,8 @@ dm9000_open(struct net_device *dev)
 	mii_check_media(&db->mii, netif_msg_link(db), 1);
 	netif_start_queue(dev);
 
-	dm9000_schedule_poll(db);
+	/* Poll initial link status */
+	schedule_delayed_work(&db->phy_poll, 1);
 
 	return 0;
 }
-- 
1.9.0.rc3.12.gbc97e2d

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

* [PATCH 6/6] dm9000: avoid sleeping in dm9000_timeout callback
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
                     ` (4 preceding siblings ...)
  2014-06-04 22:28   ` [PATCH 5/6] dm9000: handle initial link status Andrew Ruder
@ 2014-06-04 22:28   ` Andrew Ruder
  5 siblings, 0 replies; 8+ messages in thread
From: Andrew Ruder @ 2014-06-04 22:28 UTC (permalink / raw)
  To: netdev; +Cc: Andrew Ruder, Joseph CHANG

On the DM9000B, dm9000_msleep() is called during the dm9000_timeout()
routine.  Since dm9000_timeout() holds the main spinlock through the
entire routine, mdelay() needs to be used rather than msleep().
Furthermore, the mutex_lock()/mutex_unlock() should be avoided so as to
not sleep with spinlocks held.

Signed-off-by: Andrew Ruder <andrew.ruder@elecsyscorp.com>
---
 drivers/net/ethernet/davicom/dm9000.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index eb9b704..785afa5 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -109,6 +109,7 @@ typedef struct board_info {
 	u8		imr_all;
 
 	unsigned int	flags;
+	unsigned int	in_timeout:1;
 	unsigned int	in_suspend:1;
 	unsigned int	wake_supported:1;
 
@@ -273,7 +274,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
  */
 static void dm9000_msleep(board_info_t *db, unsigned int ms)
 {
-	if (db->in_suspend)
+	if (db->in_suspend || db->in_timeout)
 		mdelay(ms);
 	else
 		msleep(ms);
@@ -334,7 +335,8 @@ dm9000_phy_write(struct net_device *dev,
 	unsigned long reg_save;
 
 	dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-	mutex_lock(&db->addr_lock);
+	if (!db->in_timeout)
+		mutex_lock(&db->addr_lock);
 
 	spin_lock_irqsave(&db->lock, flags);
 
@@ -365,7 +367,8 @@ dm9000_phy_write(struct net_device *dev,
 	writeb(reg_save, db->io_addr);
 
 	spin_unlock_irqrestore(&db->lock, flags);
-	mutex_unlock(&db->addr_lock);
+	if (!db->in_timeout)
+		mutex_unlock(&db->addr_lock);
 }
 
 /* dm9000_set_io
@@ -971,6 +974,7 @@ static void dm9000_timeout(struct net_device *dev)
 
 	/* Save previous register address */
 	spin_lock_irqsave(&db->lock, flags);
+	db->in_timeout = 1;
 	reg_save = readb(db->io_addr);
 
 	netif_stop_queue(dev);
@@ -982,6 +986,7 @@ static void dm9000_timeout(struct net_device *dev)
 
 	/* Restore previous register address */
 	writeb(reg_save, db->io_addr);
+	db->in_timeout = 0;
 	spin_unlock_irqrestore(&db->lock, flags);
 }
 
-- 
1.9.0.rc3.12.gbc97e2d

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

* Re: [PATCH 0/6] miscellaneous dm9000 driver fixes
  2014-06-04 22:28 [PATCH 0/6] miscellaneous dm9000 driver fixes Andrew Ruder
       [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
@ 2014-06-05 22:14 ` David Miller
  1 sibling, 0 replies; 8+ messages in thread
From: David Miller @ 2014-06-05 22:14 UTC (permalink / raw)
  To: andrew.ruder; +Cc: netdev, josright123

From: Andrew Ruder <andrew.ruder@elecsyscorp.com>
Date: Wed,  4 Jun 2014 17:28:43 -0500

> This is a collection of changes discovered while bringing a PXA270 based board
> (Arcom ZEUS) with a Davicom DM9000A/B up to a more recent kernel (from 2.6.xx).
> This addresses all of my earlier issues (August 2013) listed here:
> 
> http://marc.info/?l=linux-netdev&m=137598605603324&w=2

Series applied to net-next, thanks.

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

end of thread, other threads:[~2014-06-05 22:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-04 22:28 [PATCH 0/6] miscellaneous dm9000 driver fixes Andrew Ruder
     [not found] ` <cover.1401920694.git.andrew.ruder@elecsyscorp.com>
2014-06-04 22:28   ` [PATCH 1/6] dm9000: acquire irq flags from device tree Andrew Ruder
2014-06-04 22:28   ` [PATCH 2/6] dm9000: clean up reset code Andrew Ruder
2014-06-04 22:28   ` [PATCH 3/6] dm9000: clean up edge-triggered irq compatibility Andrew Ruder
2014-06-04 22:28   ` [PATCH 4/6] dm9000: remove redundant ISR status clear Andrew Ruder
2014-06-04 22:28   ` [PATCH 5/6] dm9000: handle initial link status Andrew Ruder
2014-06-04 22:28   ` [PATCH 6/6] dm9000: avoid sleeping in dm9000_timeout callback Andrew Ruder
2014-06-05 22:14 ` [PATCH 0/6] miscellaneous dm9000 driver fixes David Miller

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).