All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH v4 3/8] drm/i915: Add a new "remapped" gtt_view
Date: Fri, 26 Oct 2018 13:48:44 +0100	[thread overview]
Message-ID: <d30ab4a7-6c71-8b88-7b46-ab027f1fb634@linux.intel.com> (raw)
In-Reply-To: <20181026124337.GT9144@intel.com>


On 26/10/2018 13:43, Ville Syrjälä wrote:
> On Fri, Oct 26, 2018 at 10:19:25AM +0100, Tvrtko Ursulin wrote:
>>
>> On 23/10/2018 17:02, Ville Syrjala wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> To overcome display engine stride limits we'll want to remap the
>>> pages in the GTT. To that end we need a new gtt_view type which
>>> is just like the "rotated" type except not rotated.
>>>
>>> v2: Use intel_remapped_plane_info base type
>>>       s/unused/unused_mbz/ (Chris)
>>>       Separate BUILD_BUG_ON()s (Chris)
>>>       Use I915_GTT_PAGE_SIZE (Chris)
>>> v3: Use i915_gem_object_get_dma_address() (Chris)
>>>       Trim the sg (Tvrtko)
>>>
>>> Cc: Chris Wilson <chris@chris-wilson.co.uk>
>>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/i915_debugfs.c       | 12 ++++
>>>    drivers/gpu/drm/i915/i915_gem_gtt.c       | 74 +++++++++++++++++++++++
>>>    drivers/gpu/drm/i915/i915_gem_gtt.h       | 25 ++++++--
>>>    drivers/gpu/drm/i915/i915_vma.c           |  6 +-
>>>    drivers/gpu/drm/i915/i915_vma.h           |  3 +
>>>    drivers/gpu/drm/i915/intel_display.c      | 11 ++++
>>>    drivers/gpu/drm/i915/intel_drv.h          |  1 +
>>>    drivers/gpu/drm/i915/selftests/i915_vma.c |  6 +-
>>>    8 files changed, 130 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
>>> index 5b37d5f8e132..ce019126304d 100644
>>> --- a/drivers/gpu/drm/i915/i915_debugfs.c
>>> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
>>> @@ -196,6 +196,18 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
>>>    					   vma->ggtt_view.rotated.plane[1].offset);
>>>    				break;
>>>    
>>> +			case I915_GGTT_VIEW_REMAPPED:
>>> +				seq_printf(m, ", remapped [(%ux%u, stride=%u, offset=%u), (%ux%u, stride=%u, offset=%u)]",
>>> +					   vma->ggtt_view.remapped.plane[0].width,
>>> +					   vma->ggtt_view.remapped.plane[0].height,
>>> +					   vma->ggtt_view.remapped.plane[0].stride,
>>> +					   vma->ggtt_view.remapped.plane[0].offset,
>>> +					   vma->ggtt_view.remapped.plane[1].width,
>>> +					   vma->ggtt_view.remapped.plane[1].height,
>>> +					   vma->ggtt_view.remapped.plane[1].stride,
>>> +					   vma->ggtt_view.remapped.plane[1].offset);
>>> +				break;
>>> +
>>>    			default:
>>>    				MISSING_CASE(vma->ggtt_view.type);
>>>    				break;
>>> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
>>> index 98d9a1eb1ed2..d0e50b584ebd 100644
>>> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
>>> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
>>> @@ -3705,6 +3705,75 @@ intel_rotate_pages(struct intel_rotation_info *rot_info,
>>>    	return ERR_PTR(ret);
>>>    }
>>>    
>>> +static struct scatterlist *
>>> +remap_pages(struct drm_i915_gem_object *obj, unsigned int offset,
>>> +	    unsigned int width, unsigned int height,
>>> +	    unsigned int stride,
>>> +	    struct sg_table *st, struct scatterlist *sg)
>>> +{
>>> +	unsigned int column, row;
>>> +
>>> +	for (row = 0; row < height; row++) {
>>> +		for (column = 0; column < width; column++) {
>>> +			st->nents++;
>>> +			/* We don't need the pages, but need to initialize
>>> +			 * the entries so the sg list can be happily traversed.
>>> +			 * The only thing we need are DMA addresses.
>>> +			 */
>>> +			sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0);
>>> +			sg_dma_address(sg) =
>>> +				i915_gem_object_get_dma_address(obj, offset + column);
>>> +			sg_dma_len(sg) = I915_GTT_PAGE_SIZE;
>>
>> Sg trim will do nothing since the nents is equal to num pages. To
>> benefit from it, you would need to look for consecutive DMA addresses
>> and "append" to the existing sg entry in those cases.
> 
> Hmm. I thought that is what sg_trim() does. I guess not.

Ah.. no, it just discards the unused sg entries, the difference from 
sg->nents to sg->orig_nents.

What you thought it does could be called i915_sg_coalesce, optimize, or 
something. Maybe it would make sense to add this kind of helper if there 
are sufficient users. It should be doable in place without too much 
trouble I think.

Regards,

Tvrtko

>> Contrary to the
>> rotated remap, this one should actually benefit a lot from it. (For this
>> reason rotated remap does not bother to try it - it would be some luck
>> to find consecutive pages after rotation.)
>>
>> Regards,
>>
>> Tvrtko
>>
>>> +			sg = sg_next(sg);
>>> +		}
>>> +		offset += stride;
>>> +	}
>>> +
>>> +	return sg;
>>> +}
>>> +
>>> +static noinline struct sg_table *
>>> +intel_remap_pages(struct intel_remapped_info *rem_info,
>>> +		  struct drm_i915_gem_object *obj)
>>> +{
>>> +	unsigned int size = intel_remapped_info_size(rem_info);
>>> +	struct sg_table *st;
>>> +	struct scatterlist *sg;
>>> +	int ret = -ENOMEM;
>>> +	int i;
>>> +
>>> +	/* Allocate target SG list. */
>>> +	st = kmalloc(sizeof(*st), GFP_KERNEL);
>>> +	if (!st)
>>> +		goto err_st_alloc;
>>> +
>>> +	ret = sg_alloc_table(st, size, GFP_KERNEL);
>>> +	if (ret)
>>> +		goto err_sg_alloc;
>>> +
>>> +	st->nents = 0;
>>> +	sg = st->sgl;
>>> +
>>> +	for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
>>> +		sg = remap_pages(obj, rem_info->plane[i].offset,
>>> +				 rem_info->plane[i].width, rem_info->plane[i].height,
>>> +				 rem_info->plane[i].stride, st, sg);
>>> +	}
>>> +
>>> +	i915_sg_trim(st);
>>> +
>>> +	return st;
>>> +
>>> +err_sg_alloc:
>>> +	kfree(st);
>>> +err_st_alloc:
>>> +
>>> +	DRM_DEBUG_DRIVER("Failed to create remapped mapping for object size %zu! (%ux%u tiles, %u pages)\n",
>>> +			 obj->base.size, rem_info->plane[0].width, rem_info->plane[0].height, size);
>>> +
>>> +	return ERR_PTR(ret);
>>> +}
>>> +
>>>    static noinline struct sg_table *
>>>    intel_partial_pages(const struct i915_ggtt_view *view,
>>>    		    struct drm_i915_gem_object *obj)
>>> @@ -3783,6 +3852,11 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma)
>>>    			intel_rotate_pages(&vma->ggtt_view.rotated, vma->obj);
>>>    		break;
>>>    
>>> +	case I915_GGTT_VIEW_REMAPPED:
>>> +		vma->pages =
>>> +			intel_remap_pages(&vma->ggtt_view.remapped, vma->obj);
>>> +		break;
>>> +
>>>    	case I915_GGTT_VIEW_PARTIAL:
>>>    		vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
>>>    		break;
>>> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
>>> index 7e2af5f4f39b..69a22f57e6ca 100644
>>> --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
>>> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
>>> @@ -160,11 +160,18 @@ typedef u64 gen8_ppgtt_pml4e_t;
>>>    
>>>    struct sg_table;
>>>    
>>> +struct intel_remapped_plane_info {
>>> +	/* in gtt pages */
>>> +	unsigned int width, height, stride, offset;
>>> +} __packed;
>>> +
>>> +struct intel_remapped_info {
>>> +	struct intel_remapped_plane_info plane[2];
>>> +	unsigned int unused_mbz;
>>> +} __packed;
>>> +
>>>    struct intel_rotation_info {
>>> -	struct intel_rotation_plane_info {
>>> -		/* tiles */
>>> -		unsigned int width, height, stride, offset;
>>> -	} plane[2];
>>> +	struct intel_remapped_plane_info plane[2];
>>>    } __packed;
>>>    
>>>    struct intel_partial_info {
>>> @@ -176,12 +183,20 @@ enum i915_ggtt_view_type {
>>>    	I915_GGTT_VIEW_NORMAL = 0,
>>>    	I915_GGTT_VIEW_ROTATED = sizeof(struct intel_rotation_info),
>>>    	I915_GGTT_VIEW_PARTIAL = sizeof(struct intel_partial_info),
>>> +	I915_GGTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info),
>>>    };
>>>    
>>>    static inline void assert_i915_gem_gtt_types(void)
>>>    {
>>>    	BUILD_BUG_ON(sizeof(struct intel_rotation_info) != 8*sizeof(unsigned int));
>>>    	BUILD_BUG_ON(sizeof(struct intel_partial_info) != sizeof(u64) + sizeof(unsigned int));
>>> +	BUILD_BUG_ON(sizeof(struct intel_remapped_info) != 9*sizeof(unsigned int));
>>> +
>>> +	/* Check that rotation/remapped shares offsets for simplicity */
>>> +	BUILD_BUG_ON(offsetof(struct intel_remapped_info, plane[0]) !=
>>> +		     offsetof(struct intel_rotation_info, plane[0]));
>>> +	BUILD_BUG_ON(offsetofend(struct intel_remapped_info, plane[1]) !=
>>> +		     offsetofend(struct intel_rotation_info, plane[1]));
>>>    
>>>    	/* As we encode the size of each branch inside the union into its type,
>>>    	 * we have to be careful that each branch has a unique size.
>>> @@ -190,6 +205,7 @@ static inline void assert_i915_gem_gtt_types(void)
>>>    	case I915_GGTT_VIEW_NORMAL:
>>>    	case I915_GGTT_VIEW_PARTIAL:
>>>    	case I915_GGTT_VIEW_ROTATED:
>>> +	case I915_GGTT_VIEW_REMAPPED:
>>>    		/* gcc complains if these are identical cases */
>>>    		break;
>>>    	}
>>> @@ -201,6 +217,7 @@ struct i915_ggtt_view {
>>>    		/* Members need to contain no holes/padding */
>>>    		struct intel_partial_info partial;
>>>    		struct intel_rotation_info rotated;
>>> +		struct intel_remapped_info remapped;
>>>    	};
>>>    };
>>>    
>>> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
>>> index 82652c3d1bed..2070e44eaa03 100644
>>> --- a/drivers/gpu/drm/i915/i915_vma.c
>>> +++ b/drivers/gpu/drm/i915/i915_vma.c
>>> @@ -164,6 +164,9 @@ vma_create(struct drm_i915_gem_object *obj,
>>>    		} else if (view->type == I915_GGTT_VIEW_ROTATED) {
>>>    			vma->size = intel_rotation_info_size(&view->rotated);
>>>    			vma->size <<= PAGE_SHIFT;
>>> +		} else if (view->type == I915_GGTT_VIEW_REMAPPED) {
>>> +			vma->size = intel_remapped_info_size(&view->remapped);
>>> +			vma->size <<= PAGE_SHIFT;
>>>    		}
>>>    	}
>>>    
>>> @@ -464,7 +467,8 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
>>>    	 * Explicitly disable for rotated VMA since the display does not
>>>    	 * need the fence and the VMA is not accessible to other users.
>>>    	 */
>>> -	if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
>>> +	if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED ||
>>> +	    vma->ggtt_view.type == I915_GGTT_VIEW_REMAPPED)
>>>    		return;
>>>    
>>>    	fenceable = (vma->node.size >= vma->fence_size &&
>>> diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
>>> index 4f7c1c7599f4..64cf029c028a 100644
>>> --- a/drivers/gpu/drm/i915/i915_vma.h
>>> +++ b/drivers/gpu/drm/i915/i915_vma.h
>>> @@ -265,8 +265,11 @@ i915_vma_compare(struct i915_vma *vma,
>>>    	 */
>>>    	BUILD_BUG_ON(I915_GGTT_VIEW_NORMAL >= I915_GGTT_VIEW_PARTIAL);
>>>    	BUILD_BUG_ON(I915_GGTT_VIEW_PARTIAL >= I915_GGTT_VIEW_ROTATED);
>>> +	BUILD_BUG_ON(I915_GGTT_VIEW_ROTATED >= I915_GGTT_VIEW_REMAPPED);
>>>    	BUILD_BUG_ON(offsetof(typeof(*view), rotated) !=
>>>    		     offsetof(typeof(*view), partial));
>>> +	BUILD_BUG_ON(offsetof(typeof(*view), rotated) !=
>>> +		     offsetof(typeof(*view), remapped));
>>>    	return memcmp(&vma->ggtt_view.partial, &view->partial, view->type);
>>>    }
>>>    
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 8a0b477a69d3..41f7e0795b14 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -1957,6 +1957,17 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
>>>    	return size;
>>>    }
>>>    
>>> +unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info)
>>> +{
>>> +	unsigned int size = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++)
>>> +		size += rem_info->plane[i].width * rem_info->plane[i].height;
>>> +
>>> +	return size;
>>> +}
>>> +
>>>    static void
>>>    intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
>>>    			const struct drm_framebuffer *fb,
>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>> index 0e9a926fca04..6993eff5dfaf 100644
>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>> @@ -1523,6 +1523,7 @@ unsigned int intel_fb_xy_to_linear(int x, int y,
>>>    void intel_add_fb_offsets(int *x, int *y,
>>>    			  const struct intel_plane_state *state, int plane);
>>>    unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
>>> +unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
>>>    bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
>>>    void intel_mark_busy(struct drm_i915_private *dev_priv);
>>>    void intel_mark_idle(struct drm_i915_private *dev_priv);
>>> diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c
>>> index ffa74290e054..4fc49c27f13c 100644
>>> --- a/drivers/gpu/drm/i915/selftests/i915_vma.c
>>> +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c
>>> @@ -395,8 +395,8 @@ assert_rotated(struct drm_i915_gem_object *obj,
>>>    	return sg;
>>>    }
>>>    
>>> -static unsigned int rotated_size(const struct intel_rotation_plane_info *a,
>>> -				 const struct intel_rotation_plane_info *b)
>>> +static unsigned int rotated_size(const struct intel_remapped_plane_info *a,
>>> +				 const struct intel_remapped_plane_info *b)
>>>    {
>>>    	return a->width * a->height + b->width * b->height;
>>>    }
>>> @@ -406,7 +406,7 @@ static int igt_vma_rotate(void *arg)
>>>    	struct drm_i915_private *i915 = arg;
>>>    	struct i915_address_space *vm = &i915->ggtt.vm;
>>>    	struct drm_i915_gem_object *obj;
>>> -	const struct intel_rotation_plane_info planes[] = {
>>> +	const struct intel_remapped_plane_info planes[] = {
>>>    		{ .width = 1, .height = 1, .stride = 1 },
>>>    		{ .width = 2, .height = 2, .stride = 2 },
>>>    		{ .width = 4, .height = 4, .stride = 4 },
>>>
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2018-10-26 12:48 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-25 19:37 [PATCH v3 0/8] drm/i915: GTT remapping for display Ville Syrjala
2018-09-25 19:37 ` [PATCH v3 1/8] drm/i915: Make sure fb gtt offsets stay within 32bits Ville Syrjala
2018-09-25 20:29   ` Chris Wilson
2018-09-26  9:27     ` Ville Syrjälä
2018-09-26 20:09       ` Chris Wilson
2018-09-27 12:24         ` Ville Syrjälä
2018-10-23 16:02   ` [PATCH v4 " Ville Syrjala
2018-10-23 18:49     ` Chris Wilson
2018-10-23 19:16       ` Ville Syrjälä
2018-09-25 19:37 ` [PATCH v3 2/8] drm/i915: Decouple SKL stride units from intel_fb_stride_alignment() Ville Syrjala
2018-10-23 18:50   ` Chris Wilson
2018-09-25 19:37 ` [PATCH v3 3/8] drm/i915: Add a new "remapped" gtt_view Ville Syrjala
2018-09-26  7:50   ` Tvrtko Ursulin
2018-10-01 15:03     ` Ville Syrjälä
2018-10-01 15:12       ` Chris Wilson
2018-10-01 15:27         ` Ville Syrjälä
2018-10-01 15:37           ` Chris Wilson
2018-10-01 15:48             ` Tvrtko Ursulin
2018-10-05 18:42               ` Ville Syrjälä
2018-10-09  8:24                 ` Tvrtko Ursulin
2018-10-09  8:41                   ` Chris Wilson
2018-10-09 11:54                   ` Ville Syrjälä
2018-10-10  7:04                     ` Tvrtko Ursulin
2018-10-01 15:38           ` Tvrtko Ursulin
2018-10-01 15:35         ` Tvrtko Ursulin
2018-10-23 16:02   ` [PATCH v4 " Ville Syrjala
2018-10-23 18:56     ` Chris Wilson
2018-10-23 19:10       ` Ville Syrjälä
2018-10-26  9:19     ` Tvrtko Ursulin
2018-10-26 12:43       ` Ville Syrjälä
2018-10-26 12:48         ` Tvrtko Ursulin [this message]
2018-09-25 19:37 ` [PATCH v3 4/8] drm/i915/selftests: Add mock selftest for remapped vmas Ville Syrjala
2018-09-25 20:22   ` Chris Wilson
2018-09-26  9:28     ` Ville Syrjälä
2018-10-23 16:03   ` [PATCH v4 " Ville Syrjala
2018-10-23 19:02     ` Chris Wilson
2018-10-23 19:14       ` Ville Syrjälä
2018-09-25 19:37 ` [PATCH v3 5/8] drm/i915/selftests: Add live vma selftest Ville Syrjala
2018-09-25 20:19   ` Chris Wilson
2018-09-25 20:40   ` Chris Wilson
2018-09-26  9:33     ` Ville Syrjälä
2018-10-23 16:03   ` [PATCH v4 " Ville Syrjala
2018-10-23 19:05     ` Chris Wilson
2018-09-25 19:37 ` [PATCH v3 6/8] drm/i915: Overcome display engine stride limits via GTT remapping Ville Syrjala
2018-10-23 19:16   ` Chris Wilson
2018-10-25 13:45     ` Ville Syrjälä
2018-09-25 19:37 ` [PATCH v3 7/8] drm/i915: Bump gen4+ fb stride limit to 256KiB Ville Syrjala
2018-09-25 20:13   ` Chris Wilson
2018-09-28 19:19     ` Ville Syrjälä
2018-09-25 19:37 ` [PATCH v3 8/8] drm/i915: Bump gen7+ fb size limits to 16kx16k Ville Syrjala
2018-09-25 19:59   ` Chris Wilson
2018-09-26  9:25     ` Ville Syrjälä
2018-09-25 20:05 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: GTT remapping for display Patchwork
2018-09-25 20:08 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-09-25 20:30 ` ✓ Fi.CI.BAT: success " Patchwork
2018-09-25 21:21 ` ✓ Fi.CI.IGT: " Patchwork
2018-10-23 16:21 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915: GTT remapping for display (rev5) Patchwork
2018-10-23 16:24 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-10-23 16:43 ` ✓ Fi.CI.BAT: success " Patchwork
2018-10-23 18:13 ` ✓ Fi.CI.IGT: " Patchwork
2019-01-09  9:45 ` [PATCH v3 0/8] drm/i915: GTT remapping for display Timo Aaltonen

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=d30ab4a7-6c71-8b88-7b46-ab027f1fb634@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=ville.syrjala@linux.intel.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.