Subversion Repositories Kolibri OS

Rev

Rev 3031 | Rev 3764 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3031 Rev 3480
Line 40... Line 40...
40
 * goal is try to reuse that object for our own fbcon which must always
40
 * goal is try to reuse that object for our own fbcon which must always
41
 * be available for panics. Anything else we can reuse the stolen memory
41
 * be available for panics. Anything else we can reuse the stolen memory
42
 * for is a boon.
42
 * for is a boon.
43
 */
43
 */
Line 44... Line -...
44
 
-
 
45
#define PTE_ADDRESS_MASK		0xfffff000
-
 
46
#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */
-
 
47
#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1)
-
 
48
#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */
-
 
49
#define PTE_MAPPING_TYPE_CACHED		(3 << 1)
-
 
50
#define PTE_MAPPING_TYPE_MASK		(3 << 1)
-
 
51
#define PTE_VALID			(1 << 0)
-
 
52
 
-
 
53
/**
-
 
54
 * i915_stolen_to_phys - take an offset into stolen memory and turn it into
-
 
55
 *                       a physical one
-
 
56
 * @dev: drm device
-
 
57
 * @offset: address to translate
-
 
58
 *
-
 
59
 * Some chip functions require allocations from stolen space and need the
-
 
60
 * physical address of the memory in question.
-
 
61
 */
44
 
62
static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
45
static unsigned long i915_stolen_to_physical(struct drm_device *dev)
63
{
46
{
64
	struct drm_i915_private *dev_priv = dev->dev_private;
47
	struct drm_i915_private *dev_priv = dev->dev_private;
65
	struct pci_dev *pdev = dev_priv->bridge_dev;
48
	struct pci_dev *pdev = dev_priv->bridge_dev;
Line 66... Line -...
66
	u32 base;
-
 
67
 
49
	u32 base;
68
#if 0
50
 
69
	/* On the machines I have tested the Graphics Base of Stolen Memory
51
	/* On the machines I have tested the Graphics Base of Stolen Memory
70
	 * is unreliable, so compute the base by subtracting the stolen memory
52
	 * is unreliable, so on those compute the base by subtracting the
-
 
53
	 * stolen memory from the Top of Low Usable DRAM which is where the
-
 
54
	 * BIOS places the graphics stolen memory.
-
 
55
	 *
-
 
56
	 * On gen2, the layout is slightly different with the Graphics Segment
-
 
57
	 * immediately following Top of Memory (or Top of Usable DRAM). Note
-
 
58
	 * it appears that TOUD is only reported by 865g, so we just use the
-
 
59
	 * top of memory as determined by the e820 probe.
-
 
60
	 *
-
 
61
	 * XXX gen2 requires an unavailable symbol and 945gm fails with
-
 
62
	 * its value of TOLUD.
-
 
63
	 */
-
 
64
	base = 0;
-
 
65
	if (INTEL_INFO(dev)->gen >= 6) {
-
 
66
		/* Read Base Data of Stolen Memory Register (BDSM) directly.
71
	 * from the Top of Low Usable DRAM which is where the BIOS places
67
		 * Note that there is also a MCHBAR miror at 0x1080c0 or
-
 
68
		 * we could use device 2:0x5c instead.
-
 
69
	 */
72
	 * the graphics stolen memory.
70
		pci_read_config_dword(pdev, 0xB0, &base);
73
	 */
71
		base &= ~4095; /* lower bits used for locking register */
74
	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
72
	} else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
75
		/* top 32bits are reserved = 0 */
-
 
76
		pci_read_config_dword(pdev, 0xA4, &base);
-
 
77
	} else {
-
 
78
		/* XXX presume 8xx is the same as i915 */
-
 
79
		pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
73
		/* Read Graphics Base of Stolen Memory directly */
80
	}
74
		pci_read_config_dword(pdev, 0xA4, &base);
81
#else
-
 
82
	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
-
 
83
		u16 val;
-
 
84
		pci_read_config_word(pdev, 0xb0, &val);
-
 
85
		base = val >> 4 << 20;
75
#if 0
-
 
76
	} else if (IS_GEN3(dev)) {
86
	} else {
77
		u8 val;
87
		u8 val;
78
		/* Stolen is immediately below Top of Low Usable DRAM */
88
		pci_read_config_byte(pdev, 0x9c, &val);
-
 
89
		base = val >> 3 << 27;
79
		pci_read_config_byte(pdev, 0x9c, &val);
-
 
80
		base = val >> 3 << 27;
-
 
81
	base -= dev_priv->mm.gtt->stolen_size;
-
 
82
	} else {
90
	}
83
		/* Stolen is immediately above Top of Memory */
91
	base -= dev_priv->mm.gtt->stolen_size;
-
 
92
#endif
-
 
93
 
84
		base = max_low_pfn_mapped << PAGE_SHIFT;
Line 94... Line 85...
94
	return base + offset;
85
#endif
95
}
-
 
96
 
-
 
97
static void i915_warn_stolen(struct drm_device *dev)
-
 
98
{
86
	}
Line 99... Line 87...
99
	DRM_INFO("not enough stolen space for compressed buffer, disabling\n");
87
 
100
	DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
88
	return base;
101
}
89
}
102
 
90
 
103
static void i915_setup_compression(struct drm_device *dev, int size)
-
 
104
{
-
 
105
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
106
	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
-
 
107
	unsigned long cfb_base;
-
 
Line -... Line 91...
-
 
91
static int i915_setup_compression(struct drm_device *dev, int size)
108
	unsigned long ll_base = 0;
92
{
-
 
93
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
94
	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
-
 
95
 
-
 
96
	/* Try to over-allocate to reduce reallocations and fragmentation */
109
 
97
	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
110
	/* Just in case the BIOS is doing something questionable. */
98
					   size <<= 1, 4096, 0);
111
	intel_disable_fbc(dev);
99
	if (!compressed_fb)
112
 
100
		compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen,
Line -... Line 101...
-
 
101
						   size >>= 1, 4096, 0);
113
	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
102
	if (compressed_fb)
114
	if (compressed_fb)
103
		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
-
 
104
	if (!compressed_fb)
115
		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
105
		goto err;
116
	if (!compressed_fb)
-
 
117
		goto err;
-
 
118
 
106
 
119
	cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
107
	if (HAS_PCH_SPLIT(dev))
120
	if (!cfb_base)
108
		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
121
		goto err_fb;
109
	else if (IS_GM45(dev)) {
122
 
110
		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
123
	if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
111
	} else {
124
		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
112
		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
Line -... Line 113...
-
 
113
						    4096, 4096, 0);
-
 
114
		if (compressed_llb)
-
 
115
			compressed_llb = drm_mm_get_block(compressed_llb,
125
						    4096, 4096, 0);
116
							  4096, 4096);
126
		if (compressed_llb)
117
		if (!compressed_llb)
127
			compressed_llb = drm_mm_get_block(compressed_llb,
118
			goto err_fb;
128
							  4096, 4096);
119
 
Line -... Line 120...
-
 
120
		dev_priv->compressed_llb = compressed_llb;
129
		if (!compressed_llb)
121
 
Line 130... Line 122...
130
			goto err_fb;
122
		I915_WRITE(FBC_CFB_BASE,
131
 
-
 
132
		ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
-
 
133
		if (!ll_base)
-
 
134
			goto err_llb;
-
 
135
	}
123
			   dev_priv->mm.stolen_base + compressed_fb->start);
136
 
-
 
137
	dev_priv->cfb_size = size;
-
 
138
 
-
 
139
	dev_priv->compressed_fb = compressed_fb;
-
 
Line 140... Line -...
140
	if (HAS_PCH_SPLIT(dev))
-
 
141
		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
-
 
142
	else if (IS_GM45(dev)) {
124
		I915_WRITE(FBC_LL_BASE,
Line 143... Line -...
143
		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
-
 
144
	} else {
-
 
145
		I915_WRITE(FBC_CFB_BASE, cfb_base);
125
			   dev_priv->mm.stolen_base + compressed_llb->start);
146
		I915_WRITE(FBC_LL_BASE, ll_base);
126
	}
147
		dev_priv->compressed_llb = compressed_llb;
127
 
-
 
128
	dev_priv->compressed_fb = compressed_fb;
-
 
129
	dev_priv->cfb_size = size;
-
 
130
 
-
 
131
	DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n",
-
 
132
		      size);
-
 
133
 
-
 
134
	return 0;
148
	}
135
 
-
 
136
err_fb:
-
 
137
	drm_mm_put_block(compressed_fb);
-
 
138
err:
-
 
139
	return -ENOSPC;
-
 
140
}
-
 
141
 
149
 
142
int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
-
 
143
{
-
 
144
	struct drm_i915_private *dev_priv = dev->dev_private;
150
	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
145
 
Line 151... Line 146...
151
		      cfb_base, ll_base, size >> 20);
146
	if (dev_priv->mm.stolen_base == 0)
152
	return;
147
		return -ENODEV;
153
 
148
 
Line -... Line 149...
-
 
149
	if (size < dev_priv->cfb_size)
-
 
150
		return 0;
-
 
151
 
-
 
152
	/* Release any current block */
154
err_llb:
153
	i915_gem_stolen_cleanup_compression(dev);
-
 
154
 
155
	drm_mm_put_block(compressed_llb);
155
	return i915_setup_compression(dev, size);
156
err_fb:
156
}
-
 
157
 
-
 
158
void i915_gem_stolen_cleanup_compression(struct drm_device *dev)
157
	drm_mm_put_block(compressed_fb);
159
{
Line 158... Line 160...
158
err:
160
	struct drm_i915_private *dev_priv = dev->dev_private;
159
	dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
161
 
160
	i915_warn_stolen(dev);
162
	if (dev_priv->cfb_size == 0)
-
 
163
		return;
161
}
164
 
-
 
165
	if (dev_priv->compressed_fb)
162
 
166
	drm_mm_put_block(dev_priv->compressed_fb);
Line 163... Line 167...
163
static void i915_cleanup_compression(struct drm_device *dev)
167
 
164
{
168
	if (dev_priv->compressed_llb)
165
	struct drm_i915_private *dev_priv = dev->dev_private;
169
		drm_mm_put_block(dev_priv->compressed_llb);
-
 
170
 
-
 
171
	dev_priv->cfb_size = 0;
-
 
172
}
-
 
173
 
-
 
174
void i915_gem_cleanup_stolen(struct drm_device *dev)
-
 
175
{
166
 
176
	struct drm_i915_private *dev_priv = dev->dev_private;
Line 167... Line 177...
167
	drm_mm_put_block(dev_priv->compressed_fb);
177
 
168
	if (dev_priv->compressed_llb)
178
	i915_gem_stolen_cleanup_compression(dev);
Line 169... Line -...
169
		drm_mm_put_block(dev_priv->compressed_llb);
-
 
170
}
-
 
171
 
179
	drm_mm_takedown(&dev_priv->mm.stolen);
172
void i915_gem_cleanup_stolen(struct drm_device *dev)
-
 
173
{
-
 
174
	if (I915_HAS_FBC(dev) && i915_powersave)
-
 
175
		i915_cleanup_compression(dev);
-
 
176
}
-
 
177
 
-
 
178
int i915_gem_init_stolen(struct drm_device *dev)
-
 
179
{
-
 
180
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
181
	unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size;
180
}
Line -... Line 181...
-
 
181
 
-
 
182
int i915_gem_init_stolen(struct drm_device *dev)
-
 
183
{
-
 
184
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
185
 
-
 
186
	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
-
 
187
	if (dev_priv->mm.stolen_base == 0)
-
 
188
		return 0;
-
 
189
 
-
 
190
	DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
-
 
191
		      dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
-
 
192
 
-
 
193
	/* Basic memrange allocator for stolen space */
-
 
194
	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size);
-
 
195
 
-
 
196
	return 0;
-
 
197
}
-
 
198
 
-
 
199
static struct sg_table *
-
 
200
i915_pages_create_for_stolen(struct drm_device *dev,
-
 
201
			     u32 offset, u32 size)
-
 
202
{
-
 
203
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
204
	struct sg_table *st;
-
 
205
	struct scatterlist *sg;
-
 
206
 
-
 
207
	DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
-
 
208
	BUG_ON(offset > dev_priv->gtt.stolen_size - size);
-
 
209
 
-
 
210
	/* We hide that we have no struct page backing our stolen object
-
 
211
	 * by wrapping the contiguous physical allocation with a fake
-
 
212
	 * dma mapping in a single scatterlist.
182
 
213
	 */
-
 
214
 
-
 
215
	st = kmalloc(sizeof(*st), GFP_KERNEL);
-
 
216
	if (st == NULL)
-
 
217
		return NULL;
-
 
218
 
-
 
219
	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
-
 
220
		kfree(st);
-
 
221
		return NULL;
-
 
222
	}
-
 
223
 
-
 
224
	sg = st->sgl;
-
 
225
	sg->offset = offset;
-
 
226
	sg->length = size;
-
 
227
 
-
 
228
	sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset;
-
 
229
	sg_dma_len(sg) = size;
-
 
230
 
-
 
231
	return st;
-
 
232
}
-
 
233
 
-
 
234
static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
-
 
235
{
-
 
236
	BUG();
-
 
237
	return -EINVAL;
-
 
238
}
-
 
239
 
-
 
240
static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj)
-
 
241
{
-
 
242
	/* Should only be called during free */
-
 
243
	sg_free_table(obj->pages);
-
 
244
	kfree(obj->pages);
-
 
245
}
-
 
246
 
-
 
247
static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
-
 
248
	.get_pages = i915_gem_object_get_pages_stolen,
-
 
249
	.put_pages = i915_gem_object_put_pages_stolen,
-
 
250
};
-
 
251
 
-
 
252
static struct drm_i915_gem_object *
-
 
253
_i915_gem_object_create_stolen(struct drm_device *dev,
-
 
254
			       struct drm_mm_node *stolen)
-
 
255
{
-
 
256
	struct drm_i915_gem_object *obj;
-
 
257
 
-
 
258
	obj = i915_gem_object_alloc(dev);
-
 
259
	if (obj == NULL)
-
 
260
		return NULL;
-
 
261
 
-
 
262
	if (drm_gem_private_object_init(dev, &obj->base, stolen->size))
-
 
263
		goto cleanup;
-
 
264
 
-
 
265
	i915_gem_object_init(obj, &i915_gem_object_stolen_ops);
-
 
266
 
-
 
267
	obj->pages = i915_pages_create_for_stolen(dev,
-
 
268
						  stolen->start, stolen->size);
-
 
269
	if (obj->pages == NULL)
-
 
270
		goto cleanup;
-
 
271
 
-
 
272
	obj->has_dma_mapping = true;
-
 
273
	obj->pages_pin_count = 1;
-
 
274
	obj->stolen = stolen;
-
 
275
 
-
 
276
	obj->base.write_domain = I915_GEM_DOMAIN_GTT;
-
 
277
	obj->base.read_domains = I915_GEM_DOMAIN_GTT;
-
 
278
	obj->cache_level = I915_CACHE_NONE;
-
 
279
 
-
 
280
	return obj;
-
 
281
 
-
 
282
cleanup:
-
 
283
	i915_gem_object_free(obj);
-
 
284
	return NULL;
-
 
285
}
-
 
286
 
-
 
287
struct drm_i915_gem_object *
-
 
288
i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
-
 
289
{
-
 
290
	struct drm_i915_private *dev_priv = dev->dev_private;
-
 
291
	struct drm_i915_gem_object *obj;
-
 
292
	struct drm_mm_node *stolen;
-
 
293
 
-
 
294
	if (dev_priv->mm.stolen_base == 0)
-
 
295
		return NULL;
-
 
296
 
-
 
297
	DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
-
 
298
	if (size == 0)
-
 
299
		return NULL;
-
 
300
 
-
 
301
	stolen = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
-
 
302
	if (stolen)
-
 
303
		stolen = drm_mm_get_block(stolen, size, 4096);
183
	/* Basic memrange allocator for stolen space */
304
	if (stolen == NULL)