xref: /dragonfly/sys/dev/drm/drm_bufs.c (revision ae24b5e0)
1 /*
2  * Legacy: Generic DRM Buffer Management
3  *
4  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
5  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
6  * All Rights Reserved.
7  *
8  * Author: Rickard E. (Rik) Faith <faith@valinux.com>
9  * Author: Gareth Hughes <gareth@valinux.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice (including the next
19  * paragraph) shall be included in all copies or substantial portions of the
20  * Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
25  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  */
30 
31 #include <sys/conf.h>
32 #include <bus/pci/pcireg.h>
33 #include <linux/types.h>
34 #include <linux/export.h>
35 #include <drm/drmP.h>
36 #include "drm_legacy.h"
37 
38 int drm_legacy_addmap(struct drm_device * dev, resource_size_t offset,
39 		      unsigned int size, enum drm_map_type type,
40 		      enum drm_map_flags flags, struct drm_local_map **map_ptr)
41 {
42 	struct drm_local_map *map;
43 	struct drm_map_list *entry = NULL;
44 	drm_dma_handle_t *dmah;
45 
46 	/* Allocate a new map structure, fill it in, and do any type-specific
47 	 * initialization necessary.
48 	 */
49 	map = kmalloc(sizeof(*map), M_DRM, M_ZERO | M_WAITOK | M_NULLOK);
50 	if (!map) {
51 		return -ENOMEM;
52 	}
53 
54 	map->offset = offset;
55 	map->size = size;
56 	map->type = type;
57 	map->flags = flags;
58 
59 	/* Only allow shared memory to be removable since we only keep enough
60 	 * book keeping information about shared memory to allow for removal
61 	 * when processes fork.
62 	 */
63 	if ((flags & _DRM_REMOVABLE) && type != _DRM_SHM) {
64 		DRM_ERROR("Requested removable map for non-DRM_SHM\n");
65 		kfree(map);
66 		return -EINVAL;
67 	}
68 	if ((offset & PAGE_MASK) || (size & PAGE_MASK)) {
69 		DRM_ERROR("offset/size not page aligned: 0x%jx/0x%04x\n",
70 		    (uintmax_t)offset, size);
71 		kfree(map);
72 		return -EINVAL;
73 	}
74 	if (offset + size < offset) {
75 		DRM_ERROR("offset and size wrap around: 0x%jx/0x%04x\n",
76 		    (uintmax_t)offset, size);
77 		kfree(map);
78 		return -EINVAL;
79 	}
80 
81 	DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
82 		  (unsigned long long)map->offset, map->size, map->type);
83 
84 	/* Check if this is just another version of a kernel-allocated map, and
85 	 * just hand that back if so.
86 	 */
87 	if (type == _DRM_REGISTERS || type == _DRM_FRAME_BUFFER ||
88 	    type == _DRM_SHM) {
89 		list_for_each_entry(entry, &dev->maplist, head) {
90 			if (entry->map->type == type && (entry->map->offset == offset ||
91 			    (entry->map->type == _DRM_SHM &&
92 			    entry->map->flags == _DRM_CONTAINS_LOCK))) {
93 				entry->map->size = size;
94 				DRM_DEBUG("Found kernel map %d\n", type);
95 				goto done;
96 			}
97 		}
98 	}
99 
100 	switch (map->type) {
101 	case _DRM_REGISTERS:
102 	case _DRM_FRAME_BUFFER:
103 
104 		if (map->type == _DRM_FRAME_BUFFER ||
105 		    (map->flags & _DRM_WRITE_COMBINING)) {
106 			map->mtrr =
107 				arch_phys_wc_add(map->offset, map->size);
108 		}
109 		if (map->type == _DRM_REGISTERS) {
110 			if (map->flags & _DRM_WRITE_COMBINING)
111 				map->handle = ioremap_wc(map->offset,
112 							 map->size);
113 			else
114 				map->handle = ioremap(map->offset, map->size);
115 			if (!map->handle) {
116 				kfree(map);
117 				return -ENOMEM;
118 			}
119 		}
120 
121 		break;
122 	case _DRM_SHM:
123 		map->handle = kmalloc(map->size, M_DRM, M_WAITOK | M_NULLOK);
124 		DRM_DEBUG("%lu %d %p\n",
125 			  map->size, order_base_2(map->size), map->handle);
126 		if (!map->handle) {
127 			kfree(map);
128 			return -ENOMEM;
129 		}
130 		map->offset = (unsigned long)map->handle;
131 		if (map->flags & _DRM_CONTAINS_LOCK) {
132 			/* Prevent a 2nd X Server from creating a 2nd lock */
133 			DRM_LOCK(dev);
134 			if (dev->lock.hw_lock != NULL) {
135 				DRM_UNLOCK(dev);
136 				kfree(map->handle);
137 				kfree(map);
138 				return -EBUSY;
139 			}
140 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
141 			DRM_UNLOCK(dev);
142 		}
143 		break;
144 	case _DRM_AGP:
145 
146 		if (!dev->agp) {
147 			kfree(map);
148 			return -EINVAL;
149 		}
150 		/*valid = 0;*/
151 		/* In some cases (i810 driver), user space may have already
152 		 * added the AGP base itself, because dev->agp->base previously
153 		 * only got set during AGP enable.  So, only add the base
154 		 * address if the map's offset isn't already within the
155 		 * aperture.
156 		 */
157 		if (map->offset < dev->agp->base ||
158 		    map->offset > dev->agp->base +
159 		    dev->agp->agp_info.ai_aperture_size - 1) {
160 			map->offset += dev->agp->base;
161 		}
162 		map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
163 		/*for (entry = dev->agp->memory; entry; entry = entry->next) {
164 			if ((map->offset >= entry->bound) &&
165 			    (map->offset + map->size <=
166 			    entry->bound + entry->pages * PAGE_SIZE)) {
167 				valid = 1;
168 				break;
169 			}
170 		}
171 		if (!valid) {
172 			kfree(map);
173 			return -EACCES;
174 		}*/
175 		break;
176 	case _DRM_SCATTER_GATHER:
177 		if (!dev->sg) {
178 			kfree(map);
179 			return -EINVAL;
180 		}
181 		map->handle = (void *)(uintptr_t)(dev->sg->vaddr + offset);
182 		map->offset = dev->sg->vaddr + offset;
183 		break;
184 	case _DRM_CONSISTENT:
185 		/* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
186 		 * As we're limiting the address to 2^32-1 (or less),
187 		 * casting it down to 32 bits is no problem, but we
188 		 * need to point to a 64bit variable first. */
189 		dmah = drm_pci_alloc(dev, map->size, map->size);
190 		if (!dmah) {
191 			kfree(map);
192 			return -ENOMEM;
193 		}
194 		map->handle = dmah->vaddr;
195 		map->offset = dmah->busaddr;
196 		break;
197 	default:
198 		DRM_ERROR("Bad map type %d\n", map->type);
199 		kfree(map);
200 		return -EINVAL;
201 	}
202 
203 	list_add(&entry->head, &dev->maplist);
204 
205 done:
206 	/* Jumped to, with lock held, when a kernel map is found. */
207 
208 	DRM_DEBUG("Added map %d 0x%lx/0x%lx\n", map->type, map->offset,
209 	    map->size);
210 
211 	*map_ptr = map;
212 
213 	return 0;
214 }
215 
216 /**
217  * Ioctl to specify a range of memory that is available for mapping by a
218  * non-root process.
219  *
220  * \param inode device inode.
221  * \param file_priv DRM file private.
222  * \param cmd command.
223  * \param arg pointer to a drm_map structure.
224  * \return zero on success or a negative value on error.
225  *
226  */
227 int drm_legacy_addmap_ioctl(struct drm_device *dev, void *data,
228 			    struct drm_file *file_priv)
229 {
230 	struct drm_map *request = data;
231 	drm_local_map_t *map;
232 	int err;
233 
234 	if (!(dev->flags & (FREAD|FWRITE)))
235 		return -EACCES; /* Require read/write */
236 
237 	if (!capable(CAP_SYS_ADMIN) && request->type != _DRM_AGP)
238 		return -EACCES;
239 
240 	DRM_LOCK(dev);
241 	err = drm_legacy_addmap(dev, request->offset, request->size, request->type,
242 	    request->flags, &map);
243 	DRM_UNLOCK(dev);
244 	if (err != 0)
245 		return err;
246 
247 	request->offset = map->offset;
248 	request->size = map->size;
249 	request->type = map->type;
250 	request->flags = map->flags;
251 	request->mtrr   = map->mtrr;
252 	request->handle = (void *)map->handle;
253 
254 	return 0;
255 }
256 
257 /**
258  * Remove a map private from list and deallocate resources if the mapping
259  * isn't in use.
260  *
261  * Searches the map on drm_device::maplist, removes it from the list, see if
262  * its being used, and free any associate resource (such as MTRR's) if it's not
263  * being on use.
264  *
265  * \sa drm_legacy_addmap
266  */
267 int drm_legacy_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
268 {
269 	struct drm_map_list *r_list = NULL, *list_t;
270 	drm_dma_handle_t dmah;
271 	int found = 0;
272 
273 	/* Find the list entry for the map and remove it */
274 	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
275 		if (r_list->map == map) {
276 			list_del(&r_list->head);
277 			kfree(r_list);
278 			found = 1;
279 			break;
280 		}
281 	}
282 
283 	if (!found)
284 		return -EINVAL;
285 
286 	switch (map->type) {
287 	case _DRM_REGISTERS:
288 		drm_legacy_ioremapfree(map, dev);
289 		/* FALLTHROUGH */
290 	case _DRM_FRAME_BUFFER:
291 		arch_phys_wc_del(map->mtrr);
292 		break;
293 	case _DRM_SHM:
294 		kfree(map->handle);
295 		break;
296 	case _DRM_AGP:
297 	case _DRM_SCATTER_GATHER:
298 		break;
299 	case _DRM_CONSISTENT:
300 		dmah.vaddr = map->handle;
301 		dmah.busaddr = map->offset;
302 		dmah.size = map->size;
303 		__drm_legacy_pci_free(dev, &dmah);
304 		break;
305 	}
306 	kfree(map);
307 
308 	return 0;
309 }
310 
311 int drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map)
312 {
313 	int ret;
314 
315 	mutex_lock(&dev->struct_mutex);
316 	ret = drm_legacy_rmmap_locked(dev, map);
317 	mutex_unlock(&dev->struct_mutex);
318 
319 	return ret;
320 }
321 EXPORT_SYMBOL(drm_legacy_rmmap);
322 
323 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
324  * the last close of the device, and this is necessary for cleanup when things
325  * exit uncleanly.  Therefore, having userland manually remove mappings seems
326  * like a pointless exercise since they're going away anyway.
327  *
328  * One use case might be after addmap is allowed for normal users for SHM and
329  * gets used by drivers that the server doesn't need to care about.  This seems
330  * unlikely.
331  *
332  * \param inode device inode.
333  * \param file_priv DRM file private.
334  * \param cmd command.
335  * \param arg pointer to a struct drm_map structure.
336  * \return zero on success or a negative value on error.
337  */
338 int drm_legacy_rmmap_ioctl(struct drm_device *dev, void *data,
339 			   struct drm_file *file_priv)
340 {
341 	struct drm_map *request = data;
342 	struct drm_local_map *map = NULL;
343 	struct drm_map_list *r_list;
344 
345 	DRM_LOCK(dev);
346 	list_for_each_entry(r_list, &dev->maplist, head) {
347 		if (r_list->map &&
348 		    r_list->user_token == (unsigned long)request->handle &&
349 		    r_list->map->flags & _DRM_REMOVABLE) {
350 			map = r_list->map;
351 			break;
352 		}
353 	}
354 
355 	/* List has wrapped around to the head pointer, or its empty we didn't
356 	 * find anything.
357 	 */
358 	if (list_empty(&dev->maplist) || !map) {
359 		DRM_UNLOCK(dev);
360 		return -EINVAL;
361 	}
362 
363 	/* Register and framebuffer maps are permanent */
364 	if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
365 		DRM_UNLOCK(dev);
366 		return 0;
367 	}
368 
369 	drm_legacy_rmmap(dev, map);
370 
371 	DRM_UNLOCK(dev);
372 
373 	return 0;
374 }
375 
376 /**
377  * Cleanup after an error on one of the addbufs() functions.
378  *
379  * \param dev DRM device.
380  * \param entry buffer entry where the error occurred.
381  *
382  * Frees any pages and buffers associated with the given entry.
383  */
384 static void drm_cleanup_buf_error(struct drm_device * dev,
385 				  struct drm_buf_entry * entry)
386 {
387 	int i;
388 
389 	if (entry->seg_count) {
390 		for (i = 0; i < entry->seg_count; i++) {
391 			drm_pci_free(dev, entry->seglist[i]);
392 		}
393 		kfree(entry->seglist);
394 
395 		entry->seg_count = 0;
396 	}
397 
398 	if (entry->buf_count) {
399 		for (i = 0; i < entry->buf_count; i++) {
400 			kfree(entry->buflist[i].dev_private);
401 		}
402 		kfree(entry->buflist);
403 
404 		entry->buf_count = 0;
405 	}
406 }
407 
408 static int drm_do_addbufs_agp(struct drm_device *dev, struct drm_buf_desc *request)
409 {
410 	struct drm_device_dma *dma = dev->dma;
411 	struct drm_buf_entry *entry;
412 	/* struct drm_agp_mem *agp_entry; */
413 	/* int valid */
414 	struct drm_buf *buf;
415 	unsigned long offset;
416 	unsigned long agp_offset;
417 	int count;
418 	int order;
419 	int size;
420 	int alignment;
421 	int page_order;
422 	int total;
423 	int byte_count;
424 	int i;
425 	struct drm_buf **temp_buflist;
426 
427 	count = request->count;
428 	order = order_base_2(request->size);
429 	size = 1 << order;
430 
431 	alignment  = (request->flags & _DRM_PAGE_ALIGN)
432 	    ? round_page(size) : size;
433 	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
434 	total = PAGE_SIZE << page_order;
435 
436 	byte_count = 0;
437 	agp_offset = dev->agp->base + request->agp_start;
438 
439 	DRM_DEBUG("count:      %d\n",  count);
440 	DRM_DEBUG("order:      %d\n",  order);
441 	DRM_DEBUG("size:       %d\n",  size);
442 	DRM_DEBUG("agp_offset: 0x%lx\n", agp_offset);
443 	DRM_DEBUG("alignment:  %d\n",  alignment);
444 	DRM_DEBUG("page_order: %d\n",  page_order);
445 	DRM_DEBUG("total:      %d\n",  total);
446 
447 	/* Make sure buffers are located in AGP memory that we own */
448 	/* Breaks MGA due to drm_alloc_agp not setting up entries for the
449 	 * memory.  Safe to ignore for now because these ioctls are still
450 	 * root-only.
451 	 */
452 	/*valid = 0;
453 	for (agp_entry = dev->agp->memory; agp_entry;
454 	    agp_entry = agp_entry->next) {
455 		if ((agp_offset >= agp_entry->bound) &&
456 		    (agp_offset + total * count <=
457 		    agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
458 			valid = 1;
459 			break;
460 		}
461 	}
462 	if (!valid) {
463 		DRM_DEBUG("zone invalid\n");
464 		return -EINVAL;
465 	}*/
466 
467 	entry = &dma->bufs[order];
468 
469 	entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
470 				 M_WAITOK | M_NULLOK | M_ZERO);
471 	if (!entry->buflist) {
472 		return -ENOMEM;
473 	}
474 
475 	entry->buf_size = size;
476 	entry->page_order = page_order;
477 
478 	offset = 0;
479 
480 	while (entry->buf_count < count) {
481 		buf          = &entry->buflist[entry->buf_count];
482 		buf->idx     = dma->buf_count + entry->buf_count;
483 		buf->total   = alignment;
484 		buf->order   = order;
485 		buf->used    = 0;
486 
487 		buf->offset  = (dma->byte_count + offset);
488 		buf->bus_address = agp_offset + offset;
489 		buf->address = (void *)(agp_offset + offset);
490 		buf->next    = NULL;
491 		buf->pending = 0;
492 		buf->file_priv = NULL;
493 
494 		buf->dev_priv_size = dev->driver->dev_priv_size;
495 		buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
496 					   M_WAITOK | M_NULLOK | M_ZERO);
497 		if (buf->dev_private == NULL) {
498 			/* Set count correctly so we free the proper amount. */
499 			entry->buf_count = count;
500 			drm_cleanup_buf_error(dev, entry);
501 			return -ENOMEM;
502 		}
503 
504 		offset += alignment;
505 		entry->buf_count++;
506 		byte_count += PAGE_SIZE << page_order;
507 	}
508 
509 	DRM_DEBUG("byte_count: %d\n", byte_count);
510 
511 	temp_buflist = krealloc(dma->buflist,
512 	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
513 	    M_DRM, M_WAITOK | M_NULLOK);
514 	if (temp_buflist == NULL) {
515 		/* Free the entry because it isn't valid */
516 		drm_cleanup_buf_error(dev, entry);
517 		return -ENOMEM;
518 	}
519 	dma->buflist = temp_buflist;
520 
521 	for (i = 0; i < entry->buf_count; i++) {
522 		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
523 	}
524 
525 	dma->buf_count += entry->buf_count;
526 	dma->byte_count += byte_count;
527 
528 	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
529 	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
530 
531 	request->count = entry->buf_count;
532 	request->size = size;
533 
534 	dma->flags = _DRM_DMA_USE_AGP;
535 
536 	return 0;
537 }
538 
539 static int drm_do_addbufs_pci(struct drm_device *dev, struct drm_buf_desc *request)
540 {
541 	struct drm_device_dma *dma = dev->dma;
542 	int count;
543 	int order;
544 	int size;
545 	int total;
546 	int page_order;
547 	struct drm_buf_entry *entry;
548 	drm_dma_handle_t *dmah;
549 	struct drm_buf *buf;
550 	int alignment;
551 	unsigned long offset;
552 	int i;
553 	int byte_count;
554 	int page_count;
555 	unsigned long *temp_pagelist;
556 	struct drm_buf **temp_buflist;
557 
558 	count = request->count;
559 	order = order_base_2(request->size);
560 	size = 1 << order;
561 
562 	DRM_DEBUG("count=%d, size=%d (%d), order=%d\n",
563 	    request->count, request->size, size, order);
564 
565 	alignment = (request->flags & _DRM_PAGE_ALIGN)
566 	    ? round_page(size) : size;
567 	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
568 	total = PAGE_SIZE << page_order;
569 
570 	entry = &dma->bufs[order];
571 
572 	entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
573 				 M_WAITOK | M_NULLOK | M_ZERO);
574 	entry->seglist = kmalloc(count * sizeof(*entry->seglist), M_DRM,
575 				 M_WAITOK | M_NULLOK | M_ZERO);
576 
577 	/* Keep the original pagelist until we know all the allocations
578 	 * have succeeded
579 	 */
580 	temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
581 				sizeof(*dma->pagelist),
582 				M_DRM, M_WAITOK | M_NULLOK);
583 
584 	if (entry->buflist == NULL || entry->seglist == NULL ||
585 	    temp_pagelist == NULL) {
586 		kfree(temp_pagelist);
587 		kfree(entry->seglist);
588 		kfree(entry->buflist);
589 		return -ENOMEM;
590 	}
591 
592 	memcpy(temp_pagelist, dma->pagelist, dma->page_count *
593 	    sizeof(*dma->pagelist));
594 
595 	DRM_DEBUG("pagelist: %d entries\n",
596 	    dma->page_count + (count << page_order));
597 
598 	entry->buf_size	= size;
599 	entry->page_order = page_order;
600 	byte_count = 0;
601 	page_count = 0;
602 
603 	while (entry->buf_count < count) {
604 		spin_unlock(&dev->dma_lock);
605 		dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000);
606 		spin_lock(&dev->dma_lock);
607 
608 		if (!dmah) {
609 			/* Set count correctly so we free the proper amount. */
610 			entry->buf_count = count;
611 			entry->seg_count = count;
612 			drm_cleanup_buf_error(dev, entry);
613 			kfree(temp_pagelist);
614 			return -ENOMEM;
615 		}
616 		entry->seglist[entry->seg_count++] = dmah;
617 		for (i = 0; i < (1 << page_order); i++) {
618 			DRM_DEBUG("page %d @ 0x%08lx\n",
619 				  dma->page_count + page_count,
620 				  (unsigned long)dmah->vaddr + PAGE_SIZE * i);
621 			temp_pagelist[dma->page_count + page_count++]
622 				= (unsigned long)dmah->vaddr + PAGE_SIZE * i;
623 		}
624 		for (offset = 0;
625 		    offset + size <= total && entry->buf_count < count;
626 		    offset += alignment, ++entry->buf_count) {
627 			buf	     = &entry->buflist[entry->buf_count];
628 			buf->idx     = dma->buf_count + entry->buf_count;
629 			buf->total   = alignment;
630 			buf->order   = order;
631 			buf->used    = 0;
632 			buf->offset  = (dma->byte_count + byte_count + offset);
633 			buf->address = ((char *)dmah->vaddr + offset);
634 			buf->bus_address = dmah->busaddr + offset;
635 			buf->next    = NULL;
636 			buf->pending = 0;
637 			buf->file_priv = NULL;
638 
639 			buf->dev_priv_size = dev->driver->dev_priv_size;
640 			buf->dev_private = kmalloc(buf->dev_priv_size,
641 						   M_DRM,
642 						   M_WAITOK | M_NULLOK |
643 						    M_ZERO);
644 			if (buf->dev_private == NULL) {
645 				/* Set count correctly so we free the proper amount. */
646 				entry->buf_count = count;
647 				entry->seg_count = count;
648 				drm_cleanup_buf_error(dev, entry);
649 				kfree(temp_pagelist);
650 				return -ENOMEM;
651 			}
652 
653 			DRM_DEBUG("buffer %d @ %p\n",
654 			    entry->buf_count, buf->address);
655 		}
656 		byte_count += PAGE_SIZE << page_order;
657 	}
658 
659 	temp_buflist = krealloc(dma->buflist,
660 	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
661 	    M_DRM, M_WAITOK | M_NULLOK);
662 	if (temp_buflist == NULL) {
663 		/* Free the entry because it isn't valid */
664 		drm_cleanup_buf_error(dev, entry);
665 		kfree(temp_pagelist);
666 		return -ENOMEM;
667 	}
668 	dma->buflist = temp_buflist;
669 
670 	for (i = 0; i < entry->buf_count; i++) {
671 		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
672 	}
673 
674 	/* No allocations failed, so now we can replace the original pagelist
675 	 * with the new one.
676 	 */
677 	kfree(dma->pagelist);
678 	dma->pagelist = temp_pagelist;
679 
680 	dma->buf_count += entry->buf_count;
681 	dma->seg_count += entry->seg_count;
682 	dma->page_count += entry->seg_count << page_order;
683 	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
684 
685 	request->count = entry->buf_count;
686 	request->size = size;
687 
688 	return 0;
689 
690 }
691 
692 static int drm_do_addbufs_sg(struct drm_device *dev, struct drm_buf_desc *request)
693 {
694 	struct drm_device_dma *dma = dev->dma;
695 	struct drm_buf_entry *entry;
696 	struct drm_buf *buf;
697 	unsigned long offset;
698 	unsigned long agp_offset;
699 	int count;
700 	int order;
701 	int size;
702 	int alignment;
703 	int page_order;
704 	int total;
705 	int byte_count;
706 	int i;
707 	struct drm_buf **temp_buflist;
708 
709 	count = request->count;
710 	order = order_base_2(request->size);
711 	size = 1 << order;
712 
713 	alignment  = (request->flags & _DRM_PAGE_ALIGN)
714 	    ? round_page(size) : size;
715 	page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
716 	total = PAGE_SIZE << page_order;
717 
718 	byte_count = 0;
719 	agp_offset = request->agp_start;
720 
721 	DRM_DEBUG("count:      %d\n",  count);
722 	DRM_DEBUG("order:      %d\n",  order);
723 	DRM_DEBUG("size:       %d\n",  size);
724 	DRM_DEBUG("agp_offset: %ld\n", agp_offset);
725 	DRM_DEBUG("alignment:  %d\n",  alignment);
726 	DRM_DEBUG("page_order: %d\n",  page_order);
727 	DRM_DEBUG("total:      %d\n",  total);
728 
729 	entry = &dma->bufs[order];
730 
731 	entry->buflist = kmalloc(count * sizeof(*entry->buflist), M_DRM,
732 				 M_WAITOK | M_NULLOK | M_ZERO);
733 	if (entry->buflist == NULL)
734 		return -ENOMEM;
735 
736 	entry->buf_size = size;
737 	entry->page_order = page_order;
738 
739 	offset = 0;
740 
741 	while (entry->buf_count < count) {
742 		buf          = &entry->buflist[entry->buf_count];
743 		buf->idx     = dma->buf_count + entry->buf_count;
744 		buf->total   = alignment;
745 		buf->order   = order;
746 		buf->used    = 0;
747 
748 		buf->offset  = (dma->byte_count + offset);
749 		buf->bus_address = agp_offset + offset;
750 		buf->address = (void *)(agp_offset + offset + dev->sg->vaddr);
751 		buf->next    = NULL;
752 		buf->pending = 0;
753 		buf->file_priv = NULL;
754 
755 		buf->dev_priv_size = dev->driver->dev_priv_size;
756 		buf->dev_private = kmalloc(buf->dev_priv_size, M_DRM,
757 					   M_WAITOK | M_NULLOK | M_ZERO);
758 		if (buf->dev_private == NULL) {
759 			/* Set count correctly so we free the proper amount. */
760 			entry->buf_count = count;
761 			drm_cleanup_buf_error(dev, entry);
762 			return -ENOMEM;
763 		}
764 
765 		DRM_DEBUG("buffer %d @ %p\n",
766 		    entry->buf_count, buf->address);
767 
768 		offset += alignment;
769 		entry->buf_count++;
770 		byte_count += PAGE_SIZE << page_order;
771 	}
772 
773 	DRM_DEBUG("byte_count: %d\n", byte_count);
774 
775 	temp_buflist = krealloc(dma->buflist,
776 	    (dma->buf_count + entry->buf_count) * sizeof(*dma->buflist),
777 	    M_DRM, M_WAITOK | M_NULLOK);
778 	if (temp_buflist == NULL) {
779 		/* Free the entry because it isn't valid */
780 		drm_cleanup_buf_error(dev, entry);
781 		return -ENOMEM;
782 	}
783 	dma->buflist = temp_buflist;
784 
785 	for (i = 0; i < entry->buf_count; i++) {
786 		dma->buflist[i + dma->buf_count] = &entry->buflist[i];
787 	}
788 
789 	dma->buf_count += entry->buf_count;
790 	dma->byte_count += byte_count;
791 
792 	DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
793 	DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
794 
795 	request->count = entry->buf_count;
796 	request->size = size;
797 
798 	dma->flags = _DRM_DMA_USE_SG;
799 
800 	return 0;
801 }
802 
803 /**
804  * Add AGP buffers for DMA transfers.
805  *
806  * \param dev struct drm_device to which the buffers are to be added.
807  * \param request pointer to a struct drm_buf_desc describing the request.
808  * \return zero on success or a negative number on failure.
809  *
810  * After some sanity checks creates a drm_buf structure for each buffer and
811  * reallocates the buffer list of the same size order to accommodate the new
812  * buffers.
813  */
814 int drm_legacy_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
815 {
816 	int order, ret;
817 
818 	if (request->count < 0 || request->count > 4096)
819 		return -EINVAL;
820 
821 	order = order_base_2(request->size);
822 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
823 		return -EINVAL;
824 
825 	spin_lock(&dev->dma_lock);
826 
827 	/* No more allocations after first buffer-using ioctl. */
828 	if (dev->buf_use != 0) {
829 		spin_unlock(&dev->dma_lock);
830 		return -EBUSY;
831 	}
832 	/* No more than one allocation per order */
833 	if (dev->dma->bufs[order].buf_count != 0) {
834 		spin_unlock(&dev->dma_lock);
835 		return -ENOMEM;
836 	}
837 
838 	ret = drm_do_addbufs_agp(dev, request);
839 
840 	spin_unlock(&dev->dma_lock);
841 
842 	return ret;
843 }
844 
845 static int drm_legacy_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
846 {
847 	int order, ret;
848 
849 	if (!capable(CAP_SYS_ADMIN))
850 		return -EACCES;
851 
852 	if (request->count < 0 || request->count > 4096)
853 		return -EINVAL;
854 
855 	order = order_base_2(request->size);
856 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
857 		return -EINVAL;
858 
859 	spin_lock(&dev->dma_lock);
860 
861 	/* No more allocations after first buffer-using ioctl. */
862 	if (dev->buf_use != 0) {
863 		spin_unlock(&dev->dma_lock);
864 		return -EBUSY;
865 	}
866 	/* No more than one allocation per order */
867 	if (dev->dma->bufs[order].buf_count != 0) {
868 		spin_unlock(&dev->dma_lock);
869 		return -ENOMEM;
870 	}
871 
872 	ret = drm_do_addbufs_sg(dev, request);
873 
874 	spin_unlock(&dev->dma_lock);
875 
876 	return ret;
877 }
878 
879 int drm_legacy_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
880 {
881 	int order, ret;
882 
883 	if (!capable(CAP_SYS_ADMIN))
884 		return -EACCES;
885 
886 	if (request->count < 0 || request->count > 4096)
887 		return -EINVAL;
888 
889 	order = order_base_2(request->size);
890 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
891 		return -EINVAL;
892 
893 	spin_lock(&dev->dma_lock);
894 
895 	/* No more allocations after first buffer-using ioctl. */
896 	if (dev->buf_use != 0) {
897 		spin_unlock(&dev->dma_lock);
898 		return -EBUSY;
899 	}
900 	/* No more than one allocation per order */
901 	if (dev->dma->bufs[order].buf_count != 0) {
902 		spin_unlock(&dev->dma_lock);
903 		return -ENOMEM;
904 	}
905 
906 	ret = drm_do_addbufs_pci(dev, request);
907 
908 	spin_unlock(&dev->dma_lock);
909 
910 	return ret;
911 }
912 
913 /**
914  * Add buffers for DMA transfers (ioctl).
915  *
916  * \param inode device inode.
917  * \param file_priv DRM file private.
918  * \param cmd command.
919  * \param arg pointer to a struct drm_buf_desc request.
920  * \return zero on success or a negative number on failure.
921  *
922  * According with the memory type specified in drm_buf_desc::flags and the
923  * build options, it dispatches the call either to addbufs_agp(),
924  * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
925  * PCI memory respectively.
926  */
927 int drm_legacy_addbufs(struct drm_device *dev, void *data,
928 		       struct drm_file *file_priv)
929 {
930 	struct drm_buf_desc *request = data;
931 	int err;
932 
933 	if (request->flags & _DRM_AGP_BUFFER)
934 		err = drm_legacy_addbufs_agp(dev, request);
935 	else if (request->flags & _DRM_SG_BUFFER)
936 		err = drm_legacy_addbufs_sg(dev, request);
937 	else
938 		err = drm_legacy_addbufs_pci(dev, request);
939 
940 	return err;
941 }
942 
943 /**
944  * Get information about the buffer mappings.
945  *
946  * This was originally mean for debugging purposes, or by a sophisticated
947  * client library to determine how best to use the available buffers (e.g.,
948  * large buffers can be used for image transfer).
949  *
950  * \param inode device inode.
951  * \param file_priv DRM file private.
952  * \param cmd command.
953  * \param arg pointer to a drm_buf_info structure.
954  * \return zero on success or a negative number on failure.
955  *
956  * Increments drm_device::buf_use while holding the drm_device::buf_lock
957  * lock, preventing of allocating more buffers after this call. Information
958  * about each requested buffer is then copied into user space.
959  */
960 int drm_legacy_infobufs(struct drm_device *dev, void *data,
961 			struct drm_file *file_priv)
962 {
963 	struct drm_device_dma *dma = dev->dma;
964 	struct drm_buf_info *request = data;
965 	int i;
966 	int count;
967 
968 	if (drm_core_check_feature(dev, DRIVER_MODESET))
969 		return -EINVAL;
970 
971 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
972 		return -EINVAL;
973 
974 	if (!dma)
975 		return -EINVAL;
976 
977 	spin_lock(&dev->buf_lock);
978 	if (atomic_read(&dev->buf_alloc)) {
979 		spin_unlock(&dev->buf_lock);
980 		return -EBUSY;
981 	}
982 	++dev->buf_use;		/* Can't allocate more after this call */
983 	spin_unlock(&dev->buf_lock);
984 
985 	for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
986 		if (dma->bufs[i].buf_count)
987 			++count;
988 	}
989 
990 	DRM_DEBUG("count = %d\n", count);
991 
992 	if (request->count >= count) {
993 		for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
994 			if (dma->bufs[i].buf_count) {
995 				struct drm_buf_desc __user *to =
996 				    &request->list[count];
997 				struct drm_buf_entry *from = &dma->bufs[i];
998 				if (copy_to_user(&to->count,
999 						 &from->buf_count,
1000 						 sizeof(from->buf_count)) ||
1001 				    copy_to_user(&to->size,
1002 						 &from->buf_size,
1003 						 sizeof(from->buf_size)) ||
1004 				    copy_to_user(&to->low_mark,
1005 						 &from->low_mark,
1006 						 sizeof(from->low_mark)) ||
1007 				    copy_to_user(&to->high_mark,
1008 						 &from->high_mark,
1009 						 sizeof(from->high_mark)))
1010 					return -EFAULT;
1011 
1012 				DRM_DEBUG("%d %d %d %d %d\n",
1013 					  i,
1014 					  dma->bufs[i].buf_count,
1015 					  dma->bufs[i].buf_size,
1016 					  dma->bufs[i].low_mark,
1017 					  dma->bufs[i].high_mark);
1018 				++count;
1019 			}
1020 		}
1021 	}
1022 	request->count = count;
1023 
1024 	return 0;
1025 }
1026 
1027 /**
1028  * Specifies a low and high water mark for buffer allocation
1029  *
1030  * \param inode device inode.
1031  * \param file_priv DRM file private.
1032  * \param cmd command.
1033  * \param arg a pointer to a drm_buf_desc structure.
1034  * \return zero on success or a negative number on failure.
1035  *
1036  * Verifies that the size order is bounded between the admissible orders and
1037  * updates the respective drm_device_dma::bufs entry low and high water mark.
1038  *
1039  * \note This ioctl is deprecated and mostly never used.
1040  */
1041 int drm_legacy_markbufs(struct drm_device *dev, void *data,
1042 			struct drm_file *file_priv)
1043 {
1044 	struct drm_device_dma *dma = dev->dma;
1045 	struct drm_buf_desc *request = data;
1046 	int order;
1047 	struct drm_buf_entry *entry;
1048 
1049 	if (drm_core_check_feature(dev, DRIVER_MODESET))
1050 		return -EINVAL;
1051 
1052 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
1053 		return -EINVAL;
1054 
1055 	if (!dma)
1056 		return -EINVAL;
1057 
1058 	DRM_DEBUG("%d, %d, %d\n",
1059 		  request->size, request->low_mark, request->high_mark);
1060 	order = order_base_2(request->size);
1061 	if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
1062 		return -EINVAL;
1063 	entry = &dma->bufs[order];
1064 
1065 	if (request->low_mark < 0 || request->low_mark > entry->buf_count)
1066 		return -EINVAL;
1067 	if (request->high_mark < 0 || request->high_mark > entry->buf_count)
1068 		return -EINVAL;
1069 
1070 	entry->low_mark = request->low_mark;
1071 	entry->high_mark = request->high_mark;
1072 
1073 	return 0;
1074 }
1075 
1076 /**
1077  * Unreserve the buffers in list, previously reserved using drmDMA.
1078  *
1079  * \param inode device inode.
1080  * \param file_priv DRM file private.
1081  * \param cmd command.
1082  * \param arg pointer to a drm_buf_free structure.
1083  * \return zero on success or a negative number on failure.
1084  *
1085  * Calls free_buffer() for each used buffer.
1086  * This function is primarily used for debugging.
1087  */
1088 int drm_legacy_freebufs(struct drm_device *dev, void *data,
1089 			struct drm_file *file_priv)
1090 {
1091 	struct drm_device_dma *dma = dev->dma;
1092 	struct drm_buf_free *request = data;
1093 	int i;
1094 	int idx;
1095 	struct drm_buf *buf;
1096 	int retcode = 0;
1097 
1098 	DRM_DEBUG("%d\n", request->count);
1099 
1100 	spin_lock(&dev->dma_lock);
1101 	for (i = 0; i < request->count; i++) {
1102 		if (copy_from_user(&idx, &request->list[i], sizeof(idx))) {
1103 			retcode = -EFAULT;
1104 			break;
1105 		}
1106 		if (idx < 0 || idx >= dma->buf_count) {
1107 			DRM_ERROR("Index %d (of %d max)\n",
1108 			    idx, dma->buf_count - 1);
1109 			retcode = -EINVAL;
1110 			break;
1111 		}
1112 		buf = dma->buflist[idx];
1113 		if (buf->file_priv != file_priv) {
1114 			DRM_ERROR("Process %d freeing buffer not owned\n",
1115 			    DRM_CURRENTPID);
1116 			retcode = -EINVAL;
1117 			break;
1118 		}
1119 		drm_legacy_free_buffer(dev, buf);
1120 	}
1121 	spin_unlock(&dev->dma_lock);
1122 
1123 	return retcode;
1124 }
1125 
1126 /**
1127  * Maps all of the DMA buffers into client-virtual space (ioctl).
1128  *
1129  * \param inode device inode.
1130  * \param file_priv DRM file private.
1131  * \param cmd command.
1132  * \param arg pointer to a drm_buf_map structure.
1133  * \return zero on success or a negative number on failure.
1134  *
1135  * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
1136  * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
1137  * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
1138  * drm_mmap_dma().
1139  */
1140 int drm_legacy_mapbufs(struct drm_device *dev, void *data,
1141 		       struct drm_file *file_priv)
1142 {
1143 	struct drm_device_dma *dma = dev->dma;
1144 	int retcode = 0;
1145 	const int zero = 0;
1146 	vm_offset_t address;
1147 	struct vmspace *vms;
1148 	vm_ooffset_t foff;
1149 	vm_size_t size;
1150 	vm_offset_t vaddr;
1151 	struct drm_buf_map *request = data;
1152 	int i;
1153 
1154 	vms = DRM_CURPROC->td_proc->p_vmspace;
1155 
1156 	spin_lock(&dev->dma_lock);
1157 	dev->buf_use++;		/* Can't allocate more after this call */
1158 	spin_unlock(&dev->dma_lock);
1159 
1160 	if (request->count < dma->buf_count)
1161 		goto done;
1162 
1163 	if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) ||
1164 	    (drm_core_check_feature(dev, DRIVER_SG) &&
1165 	    (dma->flags & _DRM_DMA_USE_SG))) {
1166 		drm_local_map_t *map = dev->agp_buffer_map;
1167 
1168 		if (map == NULL) {
1169 			retcode = -EINVAL;
1170 			goto done;
1171 		}
1172 		size = round_page(map->size);
1173 		foff = (unsigned long)map->handle;
1174 	} else {
1175 		size = round_page(dma->byte_count),
1176 		foff = 0;
1177 	}
1178 
1179 	vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ);
1180 	retcode = -vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE,
1181 	    VM_PROT_ALL, MAP_SHARED | MAP_NOSYNC,
1182 	    SLIST_FIRST(&dev->devnode->si_hlist), foff);
1183 	if (retcode)
1184 		goto done;
1185 
1186 	request->virtual = (void *)vaddr;
1187 
1188 	for (i = 0; i < dma->buf_count; i++) {
1189 		if (copy_to_user(&request->list[i].idx,
1190 		    &dma->buflist[i]->idx, sizeof(request->list[0].idx))) {
1191 			retcode = -EFAULT;
1192 			goto done;
1193 		}
1194 		if (copy_to_user(&request->list[i].total,
1195 		    &dma->buflist[i]->total, sizeof(request->list[0].total))) {
1196 			retcode = -EFAULT;
1197 			goto done;
1198 		}
1199 		if (copy_to_user(&request->list[i].used, &zero,
1200 		    sizeof(zero))) {
1201 			retcode = -EFAULT;
1202 			goto done;
1203 		}
1204 		address = vaddr + dma->buflist[i]->offset; /* *** */
1205 		if (copy_to_user(&request->list[i].address, &address,
1206 		    sizeof(address))) {
1207 			retcode = -EFAULT;
1208 			goto done;
1209 		}
1210 	}
1211       done:
1212 	request->count = dma->buf_count;
1213 	DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
1214 
1215 	return retcode;
1216 }
1217 
1218 int drm_legacy_dma_ioctl(struct drm_device *dev, void *data,
1219 		  struct drm_file *file_priv)
1220 {
1221 	if (drm_core_check_feature(dev, DRIVER_MODESET))
1222 		return -EINVAL;
1223 
1224 	if (dev->driver->dma_ioctl)
1225 		return dev->driver->dma_ioctl(dev, data, file_priv);
1226 	else
1227 		return -EINVAL;
1228 }
1229 
1230 struct drm_local_map *drm_legacy_getsarea(struct drm_device *dev)
1231 {
1232 	struct drm_map_list *entry;
1233 
1234 	list_for_each_entry(entry, &dev->maplist, head) {
1235 		if (entry->map && entry->map->type == _DRM_SHM &&
1236 		    (entry->map->flags & _DRM_CONTAINS_LOCK)) {
1237 			return entry->map;
1238 		}
1239 	}
1240 	return NULL;
1241 }
1242 EXPORT_SYMBOL(drm_legacy_getsarea);
1243