drm/i915: fixup in-line clflushing on bit17 swizzled bos
The issue is that with inline clflushing the clflushing isn't properly swizzled. Fix this by - always clflushing entire 128 byte chunks and - unconditionally flush before writes when swizzling a given page. We could be clever and check whether we pwrite a partial 128 byte chunk instead of a partial cacheline, but I've figured that's not worth it. Now the usual approach is to fold this into the original patch series, but I've opted against this because - this fixes a corner case only very old userspace relies on and - I'd like to not invalidate all the testing the pwrite rewrite has gotten. This fixes the regression notice by tests/gem_tiled_partial_prite_pread from i-g-t. Unfortunately it doesn't fix the issues with partial pwrites to tiled buffers on bit17 swizzling machines. But that is also broken without the pwrite patches, so likely a different issue (or a problem with the testcase). v2: Simplify the patch by dropping the overly clever partial write logic for swizzled pages. Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
f56f821feb
commit
23c18c71da
|
@ -313,6 +313,28 @@ shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shmem_clflush_swizzled_range(char *addr, unsigned long length,
|
||||||
|
bool swizzled)
|
||||||
|
{
|
||||||
|
if (swizzled) {
|
||||||
|
unsigned long start = (unsigned long) addr;
|
||||||
|
unsigned long end = (unsigned long) addr + length;
|
||||||
|
|
||||||
|
/* For swizzling simply ensure that we always flush both
|
||||||
|
* channels. Lame, but simple and it works. Swizzled
|
||||||
|
* pwrite/pread is far from a hotpath - current userspace
|
||||||
|
* doesn't use it at all. */
|
||||||
|
start = round_down(start, 128);
|
||||||
|
end = round_up(end, 128);
|
||||||
|
|
||||||
|
drm_clflush_virt_range((void *)start, end - start);
|
||||||
|
} else {
|
||||||
|
drm_clflush_virt_range(addr, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Only difference to the fast-path function is that this can handle bit17
|
/* Only difference to the fast-path function is that this can handle bit17
|
||||||
* and uses non-atomic copy and kmap functions. */
|
* and uses non-atomic copy and kmap functions. */
|
||||||
static int
|
static int
|
||||||
|
@ -325,8 +347,9 @@ shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
|
||||||
|
|
||||||
vaddr = kmap(page);
|
vaddr = kmap(page);
|
||||||
if (needs_clflush)
|
if (needs_clflush)
|
||||||
drm_clflush_virt_range(vaddr + shmem_page_offset,
|
shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
|
||||||
page_length);
|
page_length,
|
||||||
|
page_do_bit17_swizzling);
|
||||||
|
|
||||||
if (page_do_bit17_swizzling)
|
if (page_do_bit17_swizzling)
|
||||||
ret = __copy_to_user_swizzled(user_data,
|
ret = __copy_to_user_swizzled(user_data,
|
||||||
|
@ -637,9 +660,10 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
vaddr = kmap(page);
|
vaddr = kmap(page);
|
||||||
if (needs_clflush_before)
|
if (needs_clflush_before || page_do_bit17_swizzling)
|
||||||
drm_clflush_virt_range(vaddr + shmem_page_offset,
|
shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
|
||||||
page_length);
|
page_length,
|
||||||
|
page_do_bit17_swizzling);
|
||||||
if (page_do_bit17_swizzling)
|
if (page_do_bit17_swizzling)
|
||||||
ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
|
ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
|
||||||
user_data,
|
user_data,
|
||||||
|
@ -649,8 +673,9 @@ shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
|
||||||
user_data,
|
user_data,
|
||||||
page_length);
|
page_length);
|
||||||
if (needs_clflush_after)
|
if (needs_clflush_after)
|
||||||
drm_clflush_virt_range(vaddr + shmem_page_offset,
|
shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
|
||||||
page_length);
|
page_length,
|
||||||
|
page_do_bit17_swizzling);
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue