* Re: [parisc-linux] ncr53c8xx patch for c110 @ 2004-06-21 16:11 Joel Soete 2004-06-21 16:17 ` James Bottomley 0 siblings, 1 reply; 5+ messages in thread From: Joel Soete @ 2004-06-21 16:11 UTC (permalink / raw) To: Andy Walker; +Cc: parisc-linux > -- Original Message -- > Date: Mon, 21 Jun 2004 15:40:06 +0200 (CEST) > From: "Andy Walker" <ajwalker@broadpark.no> > To: "Joel Soete" <soete.joel@tiscali.be> > Cc: parisc-linux@parisc-linux.org > Subject: Re: [parisc-linux] ncr53c8xx patch for c110 > > > >> > >> Patch works fine on the B132L too :-) As far as I know there wasn't > >> a problem here before (only Ravens seemed affected), but the patch > >> certainly didn't break anything! > > > > Umm you have right to check according > > <http://www.openpa.net/systems/b-class.html> > > model B132L (not B132L+) ,B160L are also equiped wuth NCR53C720 (as well > > as: > > * 735, 755 (ASP2) > > * B132L, B160L > > * C100, C110, C132L, C160L, C160, C180 > > * D-Class > > * J200, J210, J210XC, J280, J282 > > * K-Class > > * R380, R390 ) > > Well, I know it has 720, but it doesn't have U2/U-turn which > means ccio-dma.c isn't used (so the merge size hack wasn't > needed on B-class). ah yes I understand, it was very the couple U2/U-turn+NCR53C720 which was= broken. > Obviously its good to check that the fixed > driver works properly, Yes always ;) > but this machine didn't have the Raven > problem before your patch. > ;) > Incidentally, I spotted a report on the Gentoo forums of a 712 > with similar sounding lockups (stopped sometimes, usually when > calculating module dependencies which is the first disk > intensive thing the Gentoo boot process does assuming fsck > doesn't need to run). But 712 only has 53C710 on LASI (using > the 53C700 driver) so I guess it can't be related. It should be. The c110 also have such LASI ASIC chip ;) and on its scsi port I connected a CRW drive. This week-end I tried to uncompress-untar the src of my working kernel tree burned on a cd. but the operation faill= ed with an i/o error. At this moment, I didn't check more (too much focused on the ncr 720 patc= h) but I just check on my hpux b180 and there is any pb to read the cd. So either the drive is realy broken (but I already reach to burn and scan a full 600Mb cd-rwwith a previous kernel) or there is a pb with 53c7[01]0 driver too? James can you give us your opinion about this ? Welcome, Joel -------------------------------------------------------------------------= -- NEW: Tiscali ADSL LIGHT, 28,95 EUR/mois, c'est le moment de faire le pas!= http://reg.tiscali.be/default.asp?lg=3Dfr _______________________________________________ parisc-linux mailing list parisc-linux@lists.parisc-linux.org http://lists.parisc-linux.org/mailman/listinfo/parisc-linux ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [parisc-linux] ncr53c8xx patch for c110 2004-06-21 16:11 [parisc-linux] ncr53c8xx patch for c110 Joel Soete @ 2004-06-21 16:17 ` James Bottomley 0 siblings, 0 replies; 5+ messages in thread From: James Bottomley @ 2004-06-21 16:17 UTC (permalink / raw) To: Joel Soete; +Cc: parisc-linux On Mon, 2004-06-21 at 11:11, Joel Soete wrote: > It should be. The c110 also have such LASI ASIC chip ;) and on its scsi > port I connected a CRW drive. This week-end I tried to uncompress-untar > the src of my working kernel tree burned on a cd. but the operation failled > with an i/o error. > At this moment, I didn't check more (too much focused on the ncr 720 patch) > but I just check on my hpux b180 and there is any pb to read the cd. So > either the drive is realy broken (but I already reach to burn and scan a > full 600Mb cd-rwwith a previous kernel) or there is a pb with 53c7[01]0 > driver too? > > James can you give us your opinion about this ? I know of no outstanding problems with the 53c700 driver in the 2.6 kernel (and I use it all the time, since my other voyager has a D700 53c700-66 device for its root discs). James _______________________________________________ parisc-linux mailing list parisc-linux@lists.parisc-linux.org http://lists.parisc-linux.org/mailman/listinfo/parisc-linux ^ permalink raw reply [flat|nested] 5+ messages in thread
[parent not found: <40BD9F8700009BB8@ocpmta2.freegates.net>]
[parent not found: <1087569206.2078.13.camel@mulgrave>]
[parent not found: <40D30E3C.1010809@tiscali.be>]
* [parisc-linux] ncr53c8xx patch for c110 [not found] ` <40D30E3C.1010809@tiscali.be> @ 2004-06-18 20:01 ` Joel Soete 2004-06-20 5:55 ` Andy Walker 2004-06-21 7:48 ` Andy Walker 0 siblings, 2 replies; 5+ messages in thread From: Joel Soete @ 2004-06-18 20:01 UTC (permalink / raw) To: James Bottomley, Grant Grundler; +Cc: parisc-linux [-- Attachment #1: Type: text/plain, Size: 6159 bytes --] Hello James & Grant, Joel Soete wrote: > > otc I trust that backporting sym_scatter() into ncr_scatter() is a fix > ;) (i was not very sure) [snip] > > > James Bottomley wrote: > >> Could you try this. It doesn't fix the problems in the ncr driver, but >> it does force the block layer to respect the DISABLE_CLUSTERING flag. >> >> James >> >> ===== drivers/block/ll_rw_blk.c 1.244 vs edited ===== >> --- 1.244/drivers/block/ll_rw_blk.c 2004-05-29 11:18:19 -05:00 >> +++ edited/drivers/block/ll_rw_blk.c 2004-06-18 09:27:19 -05:00 >> @@ -850,7 +850,7 @@ >> continue; >> } >> new_segment: >> - if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && >> + if (cluster && BIOVEC_VIRT_MERGEABLE(bvprv, bv) && >> !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { >> hw_seg_size += bv->bv_len; >> } else { >> >> > I just test your patch and the following "backport" of sym_scatter in ncr53c8xx: --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h.orig 2004-06-18 20:30:09.000000000 +0200 +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h 2004-06-18 21:15:45.703972000 +0200 @@ -48,6 +48,18 @@ #include "sym53c8xx_defs.h" +/* + Build a scatter/gather entry. + see sym53c8xx_2/sym_hipd.h for more detailed sym_build_sge() + implementation ;) + */ + +#define ncr_build_sge(np, data, badd, len) \ +do { \ + (data)->addr = cpu_to_scr(badd); \ + (data)->size = cpu_to_scr(len); \ +} while (0) + /*========================================================== ** ** Structures used by the detection routine to transmit --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c.orig 2004-05-30 01:28:20.000000000 +0200 +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c 2004-06-18 21:53:34.803972000 +0200 @@ -91,7 +91,7 @@ */ /* Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3e" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -839,7 +839,7 @@ struct scr_tblmove smsg ; struct scr_tblmove cmd ; struct scr_tblmove sense ; - struct scr_tblmove data [MAX_SCATTER]; + struct scr_tblmove data[MAX_SCATTER]; }; @@ -3845,7 +3845,7 @@ direction = scsi_data_direction(cmd); if (direction != SCSI_DATA_NONE) { - segments = ncr_scatter (np, cp, cp->cmd); + segments = ncr_scatter(np, cp, cp->cmd); if (segments < 0) { ncr_free_ccb(np, cp); return(DID_ERROR); @@ -7575,44 +7575,57 @@ ** sizes to the data segment array. */ -static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) +static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) { - struct scr_tblmove *data; - int segment = 0; - int use_sg = (int) cmd->use_sg; + struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1]; + int segment; - data = cp->phys.data; - cp->data_len = 0; + cp->data_len = cmd->request_bufflen; - if (!use_sg) { - if (cmd->request_bufflen) { - u_long baddr = map_scsi_single_data(np, cmd); - - data = &data[MAX_SCATTER - 1]; - data[0].addr = cpu_to_scr(baddr); - data[0].size = cpu_to_scr(cmd->request_bufflen); - cp->data_len = cmd->request_bufflen; + if (cmd->request_bufflen) { + dma_addr_t baddr = map_scsi_single_data(np, cmd); + if (baddr) { + ncr_build_sge(np, data, baddr, cmd->request_bufflen); segment = 1; + } else { + segment = -2; } + } else { + segment = 0; } - else if (use_sg <= MAX_SCATTER) { + + return segment; +} + +static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) +{ + int segment = 0; + int use_sg = (int) cmd->use_sg; + + cp->data_len = 0; + + if (!use_sg) + segment = ncr_scatter_no_sglist(np, cp, cmd); + else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scr_tblmove *data; + + if (use_sg > MAX_SCATTER) { + unmap_scsi_data(np, cmd); + return -1; + } + + data = &cp->phys.data[MAX_SCATTER - use_sg]; - use_sg = map_scsi_sg_data(np, cmd); - data = &data[MAX_SCATTER - use_sg]; + for (segment = 0; segment < use_sg; segment++) { + dma_addr_t baddr = sg_dma_address(&scatter[segment]); + unsigned int len = sg_dma_len(&scatter[segment]); - while (segment < use_sg) { - u_long baddr = scsi_sg_dma_address(&scatter[segment]); - unsigned int len = scsi_sg_dma_len(&scatter[segment]); - - data[segment].addr = cpu_to_scr(baddr); - data[segment].size = cpu_to_scr(len); - cp->data_len += len; - ++segment; + ncr_build_sge(np, &data[segment], baddr, len); + cp->data_len += len; } - } - else { - return -1; + } else { + segment = -2; } return segment; =========><========= And all works fine now for me. Unfortunately I don't have other model (C, D, R, J or K) using the same driver to test it more :( I don't have any cvs ci access, so if there are no negative feedback can somebody ci. Thanks in advance, Joel PS: I just noticed that this cut&past didn't respect my patch tabs (became 8 space) so I attache also the original diff file (sorry for inconvenience [-- Attachment #2: ncr53c8xx.diff --] [-- Type: text/plain, Size: 3409 bytes --] --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h.orig 2004-06-18 20:30:09.000000000 +0200 +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h 2004-06-18 21:15:45.703972000 +0200 @@ -48,6 +48,18 @@ #include "sym53c8xx_defs.h" +/* + Build a scatter/gather entry. + see sym53c8xx_2/sym_hipd.h for more detailed sym_build_sge() + implementation ;) + */ + +#define ncr_build_sge(np, data, badd, len) \ +do { \ + (data)->addr = cpu_to_scr(badd); \ + (data)->size = cpu_to_scr(len); \ +} while (0) + /*========================================================== ** ** Structures used by the detection routine to transmit --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c.orig 2004-05-30 01:28:20.000000000 +0200 +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c 2004-06-18 21:53:34.803972000 +0200 @@ -91,7 +91,7 @@ */ /* Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3e" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -839,7 +839,7 @@ struct scr_tblmove smsg ; struct scr_tblmove cmd ; struct scr_tblmove sense ; - struct scr_tblmove data [MAX_SCATTER]; + struct scr_tblmove data[MAX_SCATTER]; }; @@ -3845,7 +3845,7 @@ direction = scsi_data_direction(cmd); if (direction != SCSI_DATA_NONE) { - segments = ncr_scatter (np, cp, cp->cmd); + segments = ncr_scatter(np, cp, cp->cmd); if (segments < 0) { ncr_free_ccb(np, cp); return(DID_ERROR); @@ -7575,44 +7575,57 @@ ** sizes to the data segment array. */ -static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) +static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) { - struct scr_tblmove *data; - int segment = 0; - int use_sg = (int) cmd->use_sg; + struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1]; + int segment; - data = cp->phys.data; - cp->data_len = 0; + cp->data_len = cmd->request_bufflen; - if (!use_sg) { - if (cmd->request_bufflen) { - u_long baddr = map_scsi_single_data(np, cmd); - - data = &data[MAX_SCATTER - 1]; - data[0].addr = cpu_to_scr(baddr); - data[0].size = cpu_to_scr(cmd->request_bufflen); - cp->data_len = cmd->request_bufflen; + if (cmd->request_bufflen) { + dma_addr_t baddr = map_scsi_single_data(np, cmd); + if (baddr) { + ncr_build_sge(np, data, baddr, cmd->request_bufflen); segment = 1; + } else { + segment = -2; } + } else { + segment = 0; } - else if (use_sg <= MAX_SCATTER) { + + return segment; +} + +static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd) +{ + int segment = 0; + int use_sg = (int) cmd->use_sg; + + cp->data_len = 0; + + if (!use_sg) + segment = ncr_scatter_no_sglist(np, cp, cmd); + else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { struct scatterlist *scatter = (struct scatterlist *)cmd->buffer; + struct scr_tblmove *data; + + if (use_sg > MAX_SCATTER) { + unmap_scsi_data(np, cmd); + return -1; + } + + data = &cp->phys.data[MAX_SCATTER - use_sg]; - use_sg = map_scsi_sg_data(np, cmd); - data = &data[MAX_SCATTER - use_sg]; + for (segment = 0; segment < use_sg; segment++) { + dma_addr_t baddr = sg_dma_address(&scatter[segment]); + unsigned int len = sg_dma_len(&scatter[segment]); - while (segment < use_sg) { - u_long baddr = scsi_sg_dma_address(&scatter[segment]); - unsigned int len = scsi_sg_dma_len(&scatter[segment]); ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [parisc-linux] ncr53c8xx patch for c110 2004-06-18 20:01 ` Joel Soete @ 2004-06-20 5:55 ` Andy Walker 2004-06-21 7:48 ` Andy Walker 1 sibling, 0 replies; 5+ messages in thread From: Andy Walker @ 2004-06-20 5:55 UTC (permalink / raw) To: Joel Soete; +Cc: parisc-linux > Hello James & Grant, > Joel Soete wrote: >> >> otc I trust that backporting sym_scatter() into ncr_scatter() is a fix >> ;) (i was not very sure) > [snip] >> >> >> James Bottomley wrote: >> >>> Could you try this. It doesn't fix the problems in the ncr driver, but >>> it does force the block layer to respect the DISABLE_CLUSTERING flag. >>> >>> James >>> >>> ===== drivers/block/ll_rw_blk.c 1.244 vs edited ===== >>> --- 1.244/drivers/block/ll_rw_blk.c 2004-05-29 11:18:19 -05:00 >>> +++ edited/drivers/block/ll_rw_blk.c 2004-06-18 09:27:19 -05:00 >>> @@ -850,7 +850,7 @@ >>> continue; >>> } >>> new_segment: >>> - if (BIOVEC_VIRT_MERGEABLE(bvprv, bv) && >>> + if (cluster && BIOVEC_VIRT_MERGEABLE(bvprv, bv) && >>> !BIOVEC_VIRT_OVERSIZE(hw_seg_size + bv->bv_len)) { >>> hw_seg_size += bv->bv_len; >>> } else { >>> >>> >> > I just test your patch and the following "backport" of sym_scatter in > ncr53c8xx: > --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h.orig 2004-06-18 > 20:30:09.000000000 +0200 > +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.h 2004-06-18 > 21:15:45.703972000 +0200 > @@ -48,6 +48,18 @@ > > #include "sym53c8xx_defs.h" > > +/* > + Build a scatter/gather entry. > + see sym53c8xx_2/sym_hipd.h for more detailed sym_build_sge() > + implementation ;) > + */ > + > +#define ncr_build_sge(np, data, badd, len) \ > +do { \ > + (data)->addr = cpu_to_scr(badd); \ > + (data)->size = cpu_to_scr(len); \ > +} while (0) > + > /*========================================================== > ** > ** Structures used by the detection routine to transmit > --- linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c.orig 2004-05-30 > 01:28:20.000000000 +0200 > +++ linux-2.6.7-pa1-wrk/drivers/scsi/ncr53c8xx.c 2004-06-18 > 21:53:34.803972000 +0200 > @@ -91,7 +91,7 @@ > */ > > /* Name and version of the driver */ > -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3e" > +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f" > > #define SCSI_NCR_DEBUG_FLAGS (0) > > @@ -839,7 +839,7 @@ > struct scr_tblmove smsg ; > struct scr_tblmove cmd ; > struct scr_tblmove sense ; > - struct scr_tblmove data [MAX_SCATTER]; > + struct scr_tblmove data[MAX_SCATTER]; > }; > > > @@ -3845,7 +3845,7 @@ > > direction = scsi_data_direction(cmd); > if (direction != SCSI_DATA_NONE) { > - segments = ncr_scatter (np, cp, cp->cmd); > + segments = ncr_scatter(np, cp, cp->cmd); > if (segments < 0) { > ncr_free_ccb(np, cp); > return(DID_ERROR); > @@ -7575,44 +7575,57 @@ > ** sizes to the data segment array. > */ > > -static int ncr_scatter(struct ncb *np, struct ccb *cp, struct > scsi_cmnd *cmd) > +static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct > scsi_cmnd *cmd) > { > - struct scr_tblmove *data; > - int segment = 0; > - int use_sg = (int) cmd->use_sg; > + struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1]; > + int segment; > > - data = cp->phys.data; > - cp->data_len = 0; > + cp->data_len = cmd->request_bufflen; > > - if (!use_sg) { > - if (cmd->request_bufflen) { > - u_long baddr = map_scsi_single_data(np, cmd); > - > - data = &data[MAX_SCATTER - 1]; > - data[0].addr = cpu_to_scr(baddr); > - data[0].size = cpu_to_scr(cmd->request_bufflen); > - cp->data_len = cmd->request_bufflen; > + if (cmd->request_bufflen) { > + dma_addr_t baddr = map_scsi_single_data(np, cmd); > + if (baddr) { > + ncr_build_sge(np, data, baddr, > cmd->request_bufflen); > segment = 1; > + } else { > + segment = -2; > } > + } else { > + segment = 0; > } > - else if (use_sg <= MAX_SCATTER) { > + > + return segment; > +} > + > +static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd > *cmd) > +{ > + int segment = 0; > + int use_sg = (int) cmd->use_sg; > + > + cp->data_len = 0; > + > + if (!use_sg) > + segment = ncr_scatter_no_sglist(np, cp, cmd); > + else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) { > struct scatterlist *scatter = (struct scatterlist > *)cmd->buffer; > + struct scr_tblmove *data; > + > + if (use_sg > MAX_SCATTER) { > + unmap_scsi_data(np, cmd); > + return -1; > + } > + > + data = &cp->phys.data[MAX_SCATTER - use_sg]; > > - use_sg = map_scsi_sg_data(np, cmd); > - data = &data[MAX_SCATTER - use_sg]; > + for (segment = 0; segment < use_sg; segment++) { > + dma_addr_t baddr = > sg_dma_address(&scatter[segment]); > + unsigned int len = sg_dma_len(&scatter[segment]); > > - while (segment < use_sg) { > - u_long baddr = > scsi_sg_dma_address(&scatter[segment]); > - unsigned int len = > scsi_sg_dma_len(&scatter[segment]); > - > - data[segment].addr = cpu_to_scr(baddr); > - data[segment].size = cpu_to_scr(len); > - cp->data_len += len; > - ++segment; > + ncr_build_sge(np, &data[segment], baddr, len); > + cp->data_len += len; > } > - } > - else { > - return -1; > + } else { > + segment = -2; > } > > return segment; > =========><========= > > And all works fine now for me. Unfortunately I don't have other model (C, > D, R, J or K) using the same driver to test it more :( > > I don't have any cvs ci access, so if there are no negative feedback can > somebody ci. > > Thanks in advance, > Joel Hi folks, Excellent! Just tried this patch on my C180 and can confirm it works. I'll give it a spin on the B132L too - but the box is heavily tied up compiling today. Thanks for working on this Joel. -Andy _______________________________________________ parisc-linux mailing list parisc-linux@lists.parisc-linux.org http://lists.parisc-linux.org/mailman/listinfo/parisc-linux ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [parisc-linux] ncr53c8xx patch for c110 2004-06-18 20:01 ` Joel Soete 2004-06-20 5:55 ` Andy Walker @ 2004-06-21 7:48 ` Andy Walker 1 sibling, 0 replies; 5+ messages in thread From: Andy Walker @ 2004-06-21 7:48 UTC (permalink / raw) To: Joel Soete; +Cc: parisc-linux > Hello James & Grant, > > Joel Soete wrote: >> >> otc I trust that backporting sym_scatter() into ncr_scatter() is a fix >> ;) (i was not very sure) <..snip..> Patch works fine on the B132L too :-) As far as I know there wasn't a problem here before (only Ravens seemed affected), but the patch certainly didn't break anything! The machine has been constantly compiling big packages (gnome/gtk/perl etc.) since the reboot, including downloads from portage, large copies.. so the disk has been getting a thrashing with no hiccoughs. -Andy _______________________________________________ parisc-linux mailing list parisc-linux@lists.parisc-linux.org http://lists.parisc-linux.org/mailman/listinfo/parisc-linux ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2004-06-21 16:17 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-21 16:11 [parisc-linux] ncr53c8xx patch for c110 Joel Soete
2004-06-21 16:17 ` James Bottomley
[not found] <40BD9F8700009BB8@ocpmta2.freegates.net>
[not found] ` <1087569206.2078.13.camel@mulgrave>
[not found] ` <40D30E3C.1010809@tiscali.be>
2004-06-18 20:01 ` Joel Soete
2004-06-20 5:55 ` Andy Walker
2004-06-21 7:48 ` Andy Walker
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.