* [RFC PATCH 0/4] drm: Cleanup probe function for component based masters.
@ 2015-10-15 16:11 Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 1/4] drm: Introduce generic " Liviu Dudau
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Liviu Dudau @ 2015-10-15 16:11 UTC (permalink / raw)
To: David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King
Cc: dri-devel, linux-rockchip, LAKML, LKML
A few drivers in drivers/gpu/drm are component-enabled and use quite similar
code sequences to probe for their encoder slaves at the remote end of the ports.
Move the code into a "generic" function and remove it from the drivers.
The end results is that drivers get a reference count fix (imx), more thorough
error checking (imx again), setting the DMA coherent mask (armada) plus a decrease
in the overall count of LoC.
I'm looking for comments and testing of the patchset (only compile tested from my
end as I don't have access to all the devices touched by the changes). My main
interest is in finding out if -EINVAL is the correct code to return if
dev->of_node == NULL (handy now, as it is different from the other possible error
codes and used in armada to trigger old platform_data support. Also looking for
thoughts on the correctness of the patch and if it possible to co-opt more drivers
into using the function.
Best regards,
Liviu
Liviu Dudau (4):
drm: Introduce generic probe function for component based masters.
drm/imx: Convert the probe function to the generic drm_of_component_probe()
drm/rockchip: Convert the probe function to the generic drm_of_component_probe()
drm/armada: Convert the probe function to the generic drm_of_component_probe()
drivers/gpu/drm/armada/armada_drv.c | 83 +++++++++-----------------
drivers/gpu/drm/drm_of.c | 92 +++++++++++++++++++++++++++++
drivers/gpu/drm/imx/imx-drm-core.c | 54 +----------------
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 84 ++------------------------
include/drm/drm_of.h | 12 ++++
5 files changed, 138 insertions(+), 187 deletions(-)
--
2.6.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 1/4] drm: Introduce generic probe function for component based masters.
2015-10-15 16:11 [RFC PATCH 0/4] drm: Cleanup probe function for component based masters Liviu Dudau
@ 2015-10-15 16:11 ` Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 2/4] drm/imx: Convert the probe function to the generic drm_of_component_probe() Liviu Dudau
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Liviu Dudau @ 2015-10-15 16:11 UTC (permalink / raw)
To: David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King
Cc: dri-devel, linux-rockchip, LAKML, LKML
A lot of component based DRM drivers use a variant of the same code
as the probe function. They bind the crtc ports in the first iteration
and then scan through the child nodes and bind the encoders attached
to the remote endpoints. Factor the common code into a separate
function called drm_of_component_probe() in order to increase code
reuse.
Cc: David Airlie <airlied@linux.ie>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
drivers/gpu/drm/drm_of.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_of.h | 12 +++++++
2 files changed, 104 insertions(+)
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index be38840..cf16240 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -1,3 +1,4 @@
+#include <linux/component.h>
#include <linux/export.h>
#include <linux/list.h>
#include <linux/of_graph.h>
@@ -61,3 +62,94 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
return possible_crtcs;
}
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
+
+/**
+ * drm_of_component_probe - Generic probe function for a component based master
+ * @dev: master device containing the OF node
+ * @compare_of: compare function used for matching components
+ * @master_ops: component master ops to be used
+ *
+ * Parse the platform device OF node and bind all the components associated
+ * with the master. Interface ports are added before the encoders in order to
+ * satisfy their .bind requirements
+ * See Documentation/devicetree/bindings/graph.txt for the bindings.
+ *
+ * Returns zero if successful, or one of the standard error codes if it fails.
+ */
+int drm_of_component_probe(struct device *dev,
+ int (*compare_of)(struct device *, void *),
+ const struct component_master_ops *master_ops)
+{
+ struct device_node *ep, *port, *remote;
+ struct component_match *match = NULL;
+ int i, ret;
+
+ if (!dev->of_node)
+ return -EINVAL;
+
+ /*
+ * Bind the crtc's ports first, so that drm_of_find_possible_crtcs()
+ * called from encoder's .bind callbacks works as expected
+ */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ component_match_add(dev, &match, compare_of, port);
+ of_node_put(port);
+ }
+
+ if (i == 0) {
+ dev_err(dev, "missing 'ports' property\n");
+ return -ENODEV;
+ }
+
+ if (!match) {
+ dev_err(dev, "no available port\n");
+ return -ENODEV;
+ }
+
+ /*
+ * For bound crtcs, bind the encoders attached to their remote endpoint
+ */
+ for (i = 0; ; i++) {
+ port = of_parse_phandle(dev->of_node, "ports", i);
+ if (!port)
+ break;
+
+ if (!of_device_is_available(port->parent)) {
+ of_node_put(port);
+ continue;
+ }
+
+ for_each_child_of_node(port, ep) {
+ remote = of_graph_get_remote_port_parent(ep);
+ if (!remote || !of_device_is_available(remote)) {
+ of_node_put(remote);
+ continue;
+ } else if (!of_device_is_available(remote->parent)) {
+ dev_warn(dev, "parent device of %s is not available\n",
+ remote->full_name);
+ of_node_put(remote);
+ continue;
+ }
+
+ component_match_add(dev, &match, compare_of, remote);
+ of_node_put(remote);
+ }
+ of_node_put(port);
+ }
+
+ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ return component_master_add_with_match(dev, master_ops, match);
+}
+EXPORT_SYMBOL(drm_of_component_probe);
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index 2441f71..7c0c05b 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -1,18 +1,30 @@
#ifndef __DRM_OF_H__
#define __DRM_OF_H__
+struct component_master_ops;
+struct device;
struct drm_device;
struct device_node;
#ifdef CONFIG_OF
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port);
+extern int drm_of_component_probe(struct device *dev,
+ int (*compare_of)(struct device *, void *),
+ const struct component_master_ops *master_ops);
#else
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port)
{
return 0;
}
+
+static inline int drm_of_component_probe(struct device *dev,
+ int (*compare_of)(struct device *, void *),
+ const struct component_master_ops *master_ops)
+{
+ return -EINVAL;
+}
#endif
#endif /* __DRM_OF_H__ */
--
2.6.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 2/4] drm/imx: Convert the probe function to the generic drm_of_component_probe()
2015-10-15 16:11 [RFC PATCH 0/4] drm: Cleanup probe function for component based masters Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 1/4] drm: Introduce generic " Liviu Dudau
@ 2015-10-15 16:11 ` Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 3/4] drm/rockchip: " Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 4/4] drm/armada: " Liviu Dudau
3 siblings, 0 replies; 6+ messages in thread
From: Liviu Dudau @ 2015-10-15 16:11 UTC (permalink / raw)
To: David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King
Cc: dri-devel, linux-rockchip, LAKML, LKML
The generic function is functionally equivalent to the driver's
imx_drm_platform_probe(). Use the generic function and reduce the
overall code size.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
drivers/gpu/drm/imx/imx-drm-core.c | 54 +-------------------------------------
1 file changed, 1 insertion(+), 53 deletions(-)
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 74f505b..c25e39d 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -531,59 +531,7 @@ static const struct component_master_ops imx_drm_ops = {
static int imx_drm_platform_probe(struct platform_device *pdev)
{
- struct device_node *ep, *port, *remote;
- struct component_match *match = NULL;
- int ret;
- int i;
-
- /*
- * Bind the IPU display interface ports first, so that
- * imx_drm_encoder_parse_of called from encoder .bind callbacks
- * works as expected.
- */
- for (i = 0; ; i++) {
- port = of_parse_phandle(pdev->dev.of_node, "ports", i);
- if (!port)
- break;
-
- component_match_add(&pdev->dev, &match, compare_of, port);
- }
-
- if (i == 0) {
- dev_err(&pdev->dev, "missing 'ports' property\n");
- return -ENODEV;
- }
-
- /* Then bind all encoders */
- for (i = 0; ; i++) {
- port = of_parse_phandle(pdev->dev.of_node, "ports", i);
- if (!port)
- break;
-
- for_each_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote)) {
- of_node_put(remote);
- continue;
- } else if (!of_device_is_available(remote->parent)) {
- dev_warn(&pdev->dev, "parent device of %s is not available\n",
- remote->full_name);
- of_node_put(remote);
- continue;
- }
-
- component_match_add(&pdev->dev, &match, compare_of,
- remote);
- of_node_put(remote);
- }
- of_node_put(port);
- }
-
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match);
+ return drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops);
}
static int imx_drm_platform_remove(struct platform_device *pdev)
--
2.6.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 3/4] drm/rockchip: Convert the probe function to the generic drm_of_component_probe()
2015-10-15 16:11 [RFC PATCH 0/4] drm: Cleanup probe function for component based masters Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 1/4] drm: Introduce generic " Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 2/4] drm/imx: Convert the probe function to the generic drm_of_component_probe() Liviu Dudau
@ 2015-10-15 16:11 ` Liviu Dudau
2015-10-15 20:37 ` kbuild test robot
2015-10-15 16:11 ` [RFC PATCH 4/4] drm/armada: " Liviu Dudau
3 siblings, 1 reply; 6+ messages in thread
From: Liviu Dudau @ 2015-10-15 16:11 UTC (permalink / raw)
To: David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King
Cc: dri-devel, linux-rockchip, LAKML, LKML
Use the generic drm_of_component_probe() function to probe for components.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 84 ++---------------------------
1 file changed, 5 insertions(+), 79 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 9a0c291..8cd6397 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -47,10 +47,6 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
int ret;
- ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
return arm_iommu_attach_device(dev, mapping);
@@ -416,29 +412,6 @@ static int compare_of(struct device *dev, void *data)
return dev->of_node == np;
}
-static void rockchip_add_endpoints(struct device *dev,
- struct component_match **match,
- struct device_node *port)
-{
- struct device_node *ep, *remote;
-
- for_each_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote || !of_device_is_available(remote)) {
- of_node_put(remote);
- continue;
- } else if (!of_device_is_available(remote->parent)) {
- dev_warn(dev, "parent device of %s is not available\n",
- remote->full_name);
- of_node_put(remote);
- continue;
- }
-
- component_match_add(dev, match, compare_of, remote);
- of_node_put(remote);
- }
-}
-
static int rockchip_drm_bind(struct device *dev)
{
struct drm_device *drm;
@@ -481,61 +454,14 @@ static const struct component_master_ops rockchip_drm_ops = {
static int rockchip_drm_platform_probe(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct component_match *match = NULL;
- struct device_node *np = dev->of_node;
- struct device_node *port;
- int i;
-
- if (!np)
- return -ENODEV;
- /*
- * Bind the crtc ports first, so that
- * drm_of_find_possible_crtcs called from encoder .bind callbacks
- * works as expected.
- */
- for (i = 0;; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
-
- if (!of_device_is_available(port->parent)) {
- of_node_put(port);
- continue;
- }
+ int ret = drm_of_component_probe(&pdev->dev, compare_of,
+ &rockchip_drm_ops);
- component_match_add(dev, &match, compare_of, port->parent);
- of_node_put(port);
- }
-
- if (i == 0) {
- dev_err(dev, "missing 'ports' property\n");
+ /* keep compatibility with old code that was returning -ENODEV */
+ if (ret == -EINVAL)
return -ENODEV;
- }
-
- if (!match) {
- dev_err(dev, "No available vop found for display-subsystem.\n");
- return -ENODEV;
- }
- /*
- * For each bound crtc, bind the encoders attached to its
- * remote endpoint.
- */
- for (i = 0;; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
-
- if (!of_device_is_available(port->parent)) {
- of_node_put(port);
- continue;
- }
- rockchip_add_endpoints(dev, &match, port);
- of_node_put(port);
- }
-
- return component_master_add_with_match(dev, &rockchip_drm_ops, match);
+ return ret;
}
static int rockchip_drm_platform_remove(struct platform_device *pdev)
--
2.6.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH 4/4] drm/armada: Convert the probe function to the generic drm_of_component_probe()
2015-10-15 16:11 [RFC PATCH 0/4] drm: Cleanup probe function for component based masters Liviu Dudau
` (2 preceding siblings ...)
2015-10-15 16:11 ` [RFC PATCH 3/4] drm/rockchip: " Liviu Dudau
@ 2015-10-15 16:11 ` Liviu Dudau
3 siblings, 0 replies; 6+ messages in thread
From: Liviu Dudau @ 2015-10-15 16:11 UTC (permalink / raw)
To: David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King
Cc: dri-devel, linux-rockchip, LAKML, LKML
The armada DRM driver keeps some old platform data compatibility in the
probe function that makes moving to the generic drm_of_component_probe()
a bit more complicated that it should. Refactor the probe function to do
the platform_data processing after the generic probe (and if that fails).
This way future cleanup can further remove support for it.
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
drivers/gpu/drm/armada/armada_drv.c | 83 +++++++++++++------------------------
1 file changed, 28 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 225034b..990080d 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -11,6 +11,7 @@
#include <linux/of_graph.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include "armada_crtc.h"
#include "armada_drm.h"
#include "armada_gem.h"
@@ -370,47 +371,36 @@ static void armada_add_endpoints(struct device *dev,
}
}
-static int armada_drm_find_components(struct device *dev,
- struct component_match **match)
-{
- struct device_node *port;
- int i;
-
- if (dev->of_node) {
- struct device_node *np = dev->of_node;
-
- for (i = 0; ; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
+static const struct component_master_ops armada_master_ops = {
+ .bind = armada_drm_bind,
+ .unbind = armada_drm_unbind,
+};
- component_match_add(dev, match, compare_of, port);
- of_node_put(port);
- }
+static int armada_drm_probe(struct platform_device *pdev)
+{
+ int ret;
- if (i == 0) {
- dev_err(dev, "missing 'ports' property\n");
- return -ENODEV;
- }
+ if (!is_componentized(&pdev->dev))
+ return drm_platform_init(&armada_drm_driver, pdev);
- for (i = 0; ; i++) {
- port = of_parse_phandle(np, "ports", i);
- if (!port)
- break;
+ ret = drm_of_component_probe(&pdev->dev, compare_dev_name,
+ &armada_master_ops);
+ if (ret != -EINVAL)
+ return ret;
- armada_add_endpoints(dev, match, port);
- of_node_put(port);
- }
- } else if (dev->platform_data) {
- char **devices = dev->platform_data;
+ if (pdev->dev.platform_data) {
+ struct component_match *match = NULL;
+ char **devices = pdev->dev.platform_data;
+ struct device_node *port;
struct device *d;
+ int i;
for (i = 0; devices[i]; i++)
- component_match_add(dev, match, compare_dev_name,
+ component_match_add(&pdev->dev, &match, compare_dev_name,
devices[i]);
if (i == 0) {
- dev_err(dev, "missing 'ports' property\n");
+ dev_err(&pdev->dev, "missing 'ports' property\n");
return -ENODEV;
}
@@ -419,35 +409,18 @@ static int armada_drm_find_components(struct device *dev,
devices[i]);
if (d && d->of_node) {
for_each_child_of_node(d->of_node, port)
- armada_add_endpoints(dev, match, port);
+ armada_add_endpoints(&pdev->dev,
+ &match, port);
}
put_device(d);
}
- }
-
- return 0;
-}
-
-static const struct component_master_ops armada_master_ops = {
- .bind = armada_drm_bind,
- .unbind = armada_drm_unbind,
-};
-static int armada_drm_probe(struct platform_device *pdev)
-{
- if (is_componentized(&pdev->dev)) {
- struct component_match *match = NULL;
- int ret;
-
- ret = armada_drm_find_components(&pdev->dev, &match);
- if (ret < 0)
- return ret;
-
- return component_master_add_with_match(&pdev->dev,
- &armada_master_ops, match);
- } else {
- return drm_platform_init(&armada_drm_driver, pdev);
+ ret = component_master_add_with_match(&pdev->dev,
+ &armada_master_ops,
+ match);
}
+
+ return ret;
}
static int armada_drm_remove(struct platform_device *pdev)
--
2.6.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH 3/4] drm/rockchip: Convert the probe function to the generic drm_of_component_probe()
2015-10-15 16:11 ` [RFC PATCH 3/4] drm/rockchip: " Liviu Dudau
@ 2015-10-15 20:37 ` kbuild test robot
0 siblings, 0 replies; 6+ messages in thread
From: kbuild test robot @ 2015-10-15 20:37 UTC (permalink / raw)
To: Liviu Dudau
Cc: kbuild-all, David Airlie, Daniel Vetter, Philipp Zabel, Mark Yao,
Heiko Stuebner, Russell King, dri-devel, linux-rockchip, LAKML,
LKML
[-- Attachment #1: Type: text/plain, Size: 1812 bytes --]
Hi Liviu,
[auto build test ERROR on drm/drm-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]
url: https://github.com/0day-ci/linux/commits/Liviu-Dudau/drm-Introduce-generic-probe-function-for-component-based-masters/20151016-001417
config: arm-allmodconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All error/warnings (new ones prefixed by >>):
drivers/gpu/drm/rockchip/rockchip_drm_drv.c: In function 'rockchip_drm_dma_attach_device':
>> drivers/gpu/drm/rockchip/rockchip_drm_drv.c:48:6: warning: unused variable 'ret' [-Wunused-variable]
int ret;
^
drivers/gpu/drm/rockchip/rockchip_drm_drv.c: In function 'rockchip_drm_platform_probe':
>> drivers/gpu/drm/rockchip/rockchip_drm_drv.c:457:2: error: implicit declaration of function 'drm_of_component_probe' [-Werror=implicit-function-declaration]
int ret = drm_of_component_probe(&pdev->dev, compare_of,
^
cc1: some warnings being treated as errors
vim +/drm_of_component_probe +457 drivers/gpu/drm/rockchip/rockchip_drm_drv.c
451 .bind = rockchip_drm_bind,
452 .unbind = rockchip_drm_unbind,
453 };
454
455 static int rockchip_drm_platform_probe(struct platform_device *pdev)
456 {
> 457 int ret = drm_of_component_probe(&pdev->dev, compare_of,
458 &rockchip_drm_ops);
459
460 /* keep compatibility with old code that was returning -ENODEV */
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 53719 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-10-15 20:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-15 16:11 [RFC PATCH 0/4] drm: Cleanup probe function for component based masters Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 1/4] drm: Introduce generic " Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 2/4] drm/imx: Convert the probe function to the generic drm_of_component_probe() Liviu Dudau
2015-10-15 16:11 ` [RFC PATCH 3/4] drm/rockchip: " Liviu Dudau
2015-10-15 20:37 ` kbuild test robot
2015-10-15 16:11 ` [RFC PATCH 4/4] drm/armada: " Liviu Dudau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®