drm_cache.c revision 1.1
1/*	$OpenBSD: drm_cache.c,v 1.1 2013/08/12 04:11:52 jsg Exp $	*/
2/**************************************************************************
3 *
4 * Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28/*
29 * Authors: Thomas Hellstr��m <thomas-at-tungstengraphics-dot-com>
30 */
31
32#include <linux/export.h>
33#include <drm/drmP.h>
34
35#if defined(CONFIG_X86)
36static void
37drm_clflush_page(struct page *page)
38{
39	uint8_t *page_virtual;
40	unsigned int i;
41	const int size = boot_cpu_data.x86_clflush_size;
42
43	if (unlikely(page == NULL))
44		return;
45
46	page_virtual = kmap_atomic(page);
47	for (i = 0; i < PAGE_SIZE; i += size)
48		clflush(page_virtual + i);
49	kunmap_atomic(page_virtual);
50}
51
52static void drm_cache_flush_clflush(struct page *pages[],
53				    unsigned long num_pages)
54{
55	unsigned long i;
56
57	mb();
58	for (i = 0; i < num_pages; i++)
59		drm_clflush_page(*pages++);
60	mb();
61}
62
63static void
64drm_clflush_ipi_handler(void *null)
65{
66	wbinvd();
67}
68#endif
69
70void
71drm_clflush_pages(struct page *pages[], unsigned long num_pages)
72{
73
74#if defined(CONFIG_X86)
75	if (cpu_has_clflush) {
76		drm_cache_flush_clflush(pages, num_pages);
77		return;
78	}
79
80	if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
81		printk(KERN_ERR "Timed out waiting for cache flush.\n");
82
83#elif defined(__powerpc__)
84	unsigned long i;
85	for (i = 0; i < num_pages; i++) {
86		struct page *page = pages[i];
87		void *page_virtual;
88
89		if (unlikely(page == NULL))
90			continue;
91
92		page_virtual = kmap_atomic(page);
93		flush_dcache_range((unsigned long)page_virtual,
94				   (unsigned long)page_virtual + PAGE_SIZE);
95		kunmap_atomic(page_virtual);
96	}
97#else
98	printk(KERN_ERR "Architecture has no drm_cache.c support\n");
99	WARN_ON_ONCE(1);
100#endif
101}
102EXPORT_SYMBOL(drm_clflush_pages);
103
104void
105drm_clflush_sg(struct sg_table *st)
106{
107#if defined(CONFIG_X86)
108	if (cpu_has_clflush) {
109		struct scatterlist *sg;
110		int i;
111
112		mb();
113		for_each_sg(st->sgl, sg, st->nents, i)
114			drm_clflush_page(sg_page(sg));
115		mb();
116
117		return;
118	}
119
120	if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
121		printk(KERN_ERR "Timed out waiting for cache flush.\n");
122#else
123	printk(KERN_ERR "Architecture has no drm_cache.c support\n");
124	WARN_ON_ONCE(1);
125#endif
126}
127EXPORT_SYMBOL(drm_clflush_sg);
128
129void
130drm_clflush_virt_range(char *addr, unsigned long length)
131{
132#if defined(CONFIG_X86)
133	if (cpu_has_clflush) {
134		char *end = addr + length;
135		mb();
136		for (; addr < end; addr += boot_cpu_data.x86_clflush_size)
137			clflush(addr);
138		clflush(end - 1);
139		mb();
140		return;
141	}
142
143	if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
144		printk(KERN_ERR "Timed out waiting for cache flush.\n");
145#else
146	printk(KERN_ERR "Architecture has no drm_cache.c support\n");
147	WARN_ON_ONCE(1);
148#endif
149}
150EXPORT_SYMBOL(drm_clflush_virt_range);
151