Date: Sat, 02 Mar 2013 16:02:45 -0800 From: Thomas Skibo <ThomasSkibo@sbcglobal.net> To: freebsd-arm@freebsd.org Subject: A bug in busdma_machdep-v6.c? Message-ID: <51329325.7070301@sbcglobal.net>
next in thread | raw e-mail | index | archive | help
Hello. I've been trying to solve a tcp checksum bug and I think I see a problem in _bus_dmamap_load_buffer(): In the following code bit, a segment is tacked onto the previous segment's slist[] entry if it is adjacent to the previous segment in virtual memory. That's okay if all cache operations use virtual addresses but if the level 2 cache operations need physical addresses (ARM_L2_PIPT), the physical address of the second segment is lost. I don't think bus_dmamap_sync() is properly wb/invalidating the second segment from the level 2 cache. 1008 sl = &map->slist[map->sync_count - 1]; 1009 if (map->sync_count == 0 || 1010 vaddr != sl->vaddr + sl->datacount) { 1011 if (++map->sync_count > dmat->nsegments) 1012 goto cleanup; 1013 sl++; 1014 sl->vaddr = vaddr; 1015 sl->datacount = sgsize; 1016 sl->busaddr = curaddr; 1017 } else 1018 sl->datacount += sgsize; 1019 } I was seeing bad checksums on large packets. While examining the dma descriptors of the offending packets, I noticed that the second of three segments always ended on a page boundary so I just guessed the second and third were one buffer straddling a page boundary. So far, this patch is fixing the problem for me: *************** *** 1007,1012 **** --- 1007,1015 ---- } else { sl = &map->slist[map->sync_count - 1]; if (map->sync_count == 0 || + #ifdef ARM_L2_PIPT + curaddr != sl->busaddr + sl->datacount || + #endif vaddr != sl->vaddr + sl->datacount) { if (++map->sync_count > dmat->nsegments) goto cleanup; -- -------- Thomas Skibo ThomasSkibo@sbcglobal.net
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51329325.7070301>