Fix BULK read transfer if destination buffer is not cache line-aligned.

We can't use copyout because destination memory is userland address
in another process but we have reference to respective page so map
the page into kernel address space and copy fragments there
This commit is contained in:
Oleksandr Tymoshenko 2015-10-30 01:19:04 +00:00
parent baa7d0bf9d
commit c26ee519d1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=290176

View file

@ -109,6 +109,22 @@ vchiq_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
}
static int
copyout_page(vm_page_t p, size_t offset, void *kaddr, size_t size)
{
uint8_t *dst;
dst = pmap_mapdev(VM_PAGE_TO_PHYS(p), PAGE_SIZE);
if (!dst)
return ENOMEM;
memcpy(dst + offset, kaddr, size);
pmap_unmapdev((vm_offset_t)dst, PAGE_SIZE);
return 0;
}
int __init
vchiq_platform_init(VCHIQ_STATE_T *state)
{
@ -560,15 +576,19 @@ free_pagelist(BULKINFO_T *bi, int actual)
if (head_bytes > actual)
head_bytes = actual;
memcpy((char *)bi->buf,
copyout_page(pages[0],
pagelist->offset,
fragments->headbuf,
head_bytes);
}
if ((actual >= 0) && (head_bytes < actual) &&
(tail_bytes != 0)) {
memcpy((char *)bi->buf + actual - tail_bytes,
fragments->tailbuf, tail_bytes);
copyout_page(pages[num_pages-1],
(((vm_offset_t)bi->buf + actual) % PAGE_SIZE) - tail_bytes,
fragments->tailbuf,
tail_bytes);
}
down(&g_free_fragments_mutex);