140d5c108SFrançois Tigeot /**************************************************************************
240d5c108SFrançois Tigeot *
340d5c108SFrançois Tigeot * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
440d5c108SFrançois Tigeot * All Rights Reserved.
540d5c108SFrançois Tigeot *
640d5c108SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
740d5c108SFrançois Tigeot * copy of this software and associated documentation files (the
840d5c108SFrançois Tigeot * "Software"), to deal in the Software without restriction, including
940d5c108SFrançois Tigeot * without limitation the rights to use, copy, modify, merge, publish,
1040d5c108SFrançois Tigeot * distribute, sub license, and/or sell copies of the Software, and to
1140d5c108SFrançois Tigeot * permit persons to whom the Software is furnished to do so, subject to
1240d5c108SFrançois Tigeot * the following conditions:
1340d5c108SFrançois Tigeot *
1440d5c108SFrançois Tigeot * The above copyright notice and this permission notice (including the
1540d5c108SFrançois Tigeot * next paragraph) shall be included in all copies or substantial portions
1640d5c108SFrançois Tigeot * of the Software.
1740d5c108SFrançois Tigeot *
1840d5c108SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1940d5c108SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2040d5c108SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
2140d5c108SFrançois Tigeot * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
2240d5c108SFrançois Tigeot * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2340d5c108SFrançois Tigeot * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2440d5c108SFrançois Tigeot * USE OR OTHER DEALINGS IN THE SOFTWARE.
2540d5c108SFrançois Tigeot *
2640d5c108SFrançois Tigeot **************************************************************************/
2740d5c108SFrançois Tigeot /*
2840d5c108SFrançois Tigeot * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
2940d5c108SFrançois Tigeot */
3040d5c108SFrançois Tigeot
3140d5c108SFrançois Tigeot #include <linux/export.h>
32*a85cb24fSFrançois Tigeot #include <linux/highmem.h>
33*a85cb24fSFrançois Tigeot
34*a85cb24fSFrançois Tigeot #include <drm/drm_cache.h>
35*a85cb24fSFrançois Tigeot
36*a85cb24fSFrançois Tigeot #if defined(CONFIG_X86)
37*a85cb24fSFrançois Tigeot #include <asm/smp.h>
3840d5c108SFrançois Tigeot
3985d09e23SFrançois Tigeot /*
4085d09e23SFrançois Tigeot * clflushopt is an unordered instruction which needs fencing with mfence or
4185d09e23SFrançois Tigeot * sfence to avoid ordering issues. For drm_clflush_page this fencing happens
4285d09e23SFrançois Tigeot * in the caller.
4385d09e23SFrançois Tigeot */
4485d09e23SFrançois Tigeot static void
drm_clflush_page(struct page * page)45f0bba3d1SFrançois Tigeot drm_clflush_page(struct page *page)
4685d09e23SFrançois Tigeot {
4785d09e23SFrançois Tigeot uint8_t *page_virtual;
4885d09e23SFrançois Tigeot unsigned int i;
49862a9d7eSFrançois Tigeot const int size = boot_cpu_data.x86_clflush_size;
5085d09e23SFrançois Tigeot
5185d09e23SFrançois Tigeot if (unlikely(page == NULL))
5285d09e23SFrançois Tigeot return;
5385d09e23SFrançois Tigeot
5485d09e23SFrançois Tigeot page_virtual = kmap_atomic(page);
5585d09e23SFrançois Tigeot for (i = 0; i < PAGE_SIZE; i += size)
56fc8df113SFrançois Tigeot clflushopt(page_virtual + i);
5785d09e23SFrançois Tigeot kunmap_atomic(page_virtual);
5885d09e23SFrançois Tigeot }
5985d09e23SFrançois Tigeot
drm_cache_flush_clflush(struct page * pages[],unsigned long num_pages)60f0bba3d1SFrançois Tigeot static void drm_cache_flush_clflush(struct page *pages[],
618621f407SFrançois Tigeot unsigned long num_pages)
628621f407SFrançois Tigeot {
638621f407SFrançois Tigeot unsigned long i;
648621f407SFrançois Tigeot
658621f407SFrançois Tigeot mb();
668621f407SFrançois Tigeot for (i = 0; i < num_pages; i++)
678621f407SFrançois Tigeot drm_clflush_page(*pages++);
688621f407SFrançois Tigeot mb();
698621f407SFrançois Tigeot }
70*a85cb24fSFrançois Tigeot #endif
718621f407SFrançois Tigeot
7240d5c108SFrançois Tigeot void
drm_clflush_pages(struct page * pages[],unsigned long num_pages)73f0bba3d1SFrançois Tigeot drm_clflush_pages(struct page *pages[], unsigned long num_pages)
746431cd91SFrançois Tigeot {
758621f407SFrançois Tigeot
76*a85cb24fSFrançois Tigeot #if defined(CONFIG_X86)
778621f407SFrançois Tigeot if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
788621f407SFrançois Tigeot drm_cache_flush_clflush(pages, num_pages);
798621f407SFrançois Tigeot return;
806431cd91SFrançois Tigeot }
816431cd91SFrançois Tigeot
828621f407SFrançois Tigeot cpu_wbinvd_on_all_cpus();
83*a85cb24fSFrançois Tigeot
84*a85cb24fSFrançois Tigeot #elif defined(__powerpc__)
85*a85cb24fSFrançois Tigeot unsigned long i;
86*a85cb24fSFrançois Tigeot for (i = 0; i < num_pages; i++) {
87*a85cb24fSFrançois Tigeot struct page *page = pages[i];
88*a85cb24fSFrançois Tigeot void *page_virtual;
89*a85cb24fSFrançois Tigeot
90*a85cb24fSFrançois Tigeot if (unlikely(page == NULL))
91*a85cb24fSFrançois Tigeot continue;
92*a85cb24fSFrançois Tigeot
93*a85cb24fSFrançois Tigeot page_virtual = kmap_atomic(page);
94*a85cb24fSFrançois Tigeot flush_dcache_range((unsigned long)page_virtual,
95*a85cb24fSFrançois Tigeot (unsigned long)page_virtual + PAGE_SIZE);
96*a85cb24fSFrançois Tigeot kunmap_atomic(page_virtual);
97*a85cb24fSFrançois Tigeot }
98*a85cb24fSFrançois Tigeot #else
99*a85cb24fSFrançois Tigeot pr_err("Architecture has no drm_cache.c support\n");
100*a85cb24fSFrançois Tigeot WARN_ON_ONCE(1);
101*a85cb24fSFrançois Tigeot #endif
1028621f407SFrançois Tigeot }
1038621f407SFrançois Tigeot EXPORT_SYMBOL(drm_clflush_pages);
1048621f407SFrançois Tigeot
1056431cd91SFrançois Tigeot void
drm_clflush_sg(struct sg_table * st)10685d09e23SFrançois Tigeot drm_clflush_sg(struct sg_table *st)
10785d09e23SFrançois Tigeot {
108*a85cb24fSFrançois Tigeot #if defined(CONFIG_X86)
1098621f407SFrançois Tigeot if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
11085d09e23SFrançois Tigeot struct sg_page_iter sg_iter;
11185d09e23SFrançois Tigeot
11285d09e23SFrançois Tigeot mb();
11385d09e23SFrançois Tigeot for_each_sg_page(st->sgl, &sg_iter, st->nents, 0)
11485d09e23SFrançois Tigeot drm_clflush_page(sg_page_iter_page(&sg_iter));
11585d09e23SFrançois Tigeot mb();
11685d09e23SFrançois Tigeot
11785d09e23SFrançois Tigeot return;
11885d09e23SFrançois Tigeot }
11985d09e23SFrançois Tigeot
12085d09e23SFrançois Tigeot cpu_wbinvd_on_all_cpus();
121*a85cb24fSFrançois Tigeot #else
122*a85cb24fSFrançois Tigeot printk(KERN_ERR "Architecture has no drm_cache.c support\n");
123*a85cb24fSFrançois Tigeot WARN_ON_ONCE(1);
124*a85cb24fSFrançois Tigeot #endif
12585d09e23SFrançois Tigeot }
12685d09e23SFrançois Tigeot EXPORT_SYMBOL(drm_clflush_sg);
12785d09e23SFrançois Tigeot
12885d09e23SFrançois Tigeot void
drm_clflush_virt_range(void * addr,unsigned long length)129*a85cb24fSFrançois Tigeot drm_clflush_virt_range(void *addr, unsigned long length)
13040d5c108SFrançois Tigeot {
131*a85cb24fSFrançois Tigeot #if defined(CONFIG_X86)
1328621f407SFrançois Tigeot if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
133*a85cb24fSFrançois Tigeot const int size = boot_cpu_data.x86_clflush_size;
134*a85cb24fSFrançois Tigeot void *end = addr + length;
13519c468b4SFrançois Tigeot addr = (void *)(((unsigned long)addr) & -size);
13619c468b4SFrançois Tigeot mb();
13719c468b4SFrançois Tigeot for (; addr < end; addr += size)
138fc8df113SFrançois Tigeot clflushopt(addr);
1398621f407SFrançois Tigeot clflushopt(end - 1); /* force serialisation */
14019c468b4SFrançois Tigeot mb();
14140d5c108SFrançois Tigeot return;
14240d5c108SFrançois Tigeot }
14340d5c108SFrançois Tigeot
14440d5c108SFrançois Tigeot cpu_wbinvd_on_all_cpus();
145*a85cb24fSFrançois Tigeot #else
146*a85cb24fSFrançois Tigeot printk(KERN_ERR "Architecture has no drm_cache.c support\n");
147*a85cb24fSFrançois Tigeot WARN_ON_ONCE(1);
148*a85cb24fSFrançois Tigeot #endif
14940d5c108SFrançois Tigeot }
15040d5c108SFrançois Tigeot EXPORT_SYMBOL(drm_clflush_virt_range);
151