drm_gem.c revision 2e6e901d9406e1a048063c872149376a6bf7cb63
/*
* Copyright (c) 2009, Intel Corporation.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <vm/seg_kmem.h>
#include <gfx_private.h>
#include "drmP.h"
#include "drm.h"
/*
* @file drm_gem.c
*
* This file provides some of the base ioctls and library routines for
* the graphics memory manager implemented by each device driver.
*
* Because various devices have different requirements in terms of
* synchronization and migration strategies, implementing that is left up to
* the driver, and all that the general API provides should be generic --
* the CPU mean we'll likely hook those out to driver-specific calls. However,
*
* The goal was to have swap-backed object allocation managed through
* struct file. However, file descriptors as handles to a struct file have
* two major failings:
* - Process limits prevent more than 1024 or so being used at a time by
* default.
* - Inability to allocate high fds will aggravate the X Server's select()
* handling, and likely that of many GL client applications as well.
*
* This led to a plan of using our own integer IDs(called handles, following
* DRM terminology) to mimic fds, and implement the fd syscalls we need as
* ioctls. The objects themselves will still include the struct file so
* that we can transition to fds if the required kernel infrastructure shows
* up at a later date, and as our interface with shmfs for memory allocation.
*/
void
{
/* HASH for accelerate */
for (int i = 0; i < DRM_GEM_OBJIDR_HASHNODE; i++) {
INIT_LIST_HEAD(&entry[i]);
}
}
int
struct drm_gem_object *obj,
int *handlep)
{
int key;
return (0);
}
struct drm_gem_object *
{
int key;
}
return (NULL);
}
int
{
int key;
return (0);
}
}
return (-1);
}
void
{
}
}
DRM_GEM_OBJIDR_HASHNODE * sizeof (struct idr_list));
}
int
{
int empty;
if (!empty)
return (empty);
}
return (1);
}
static uint32_t shfile_name = 0;
#define SHFILE_NAME_MAX 0xffffffff
/*
* will be set to 1 for 32 bit x86 systems only, in startup.c
*/
extern int segkp_fromheap;
extern ulong_t *segkp_bitmap;
void
{
}
void
{
return;
}
void
{
}
void
{
return;
/*
* Must bump handle count first as this may be the last
* ref, in which case the object would disappear before we
* checked for a name
*/
if (obj->handlecount == 0)
}
/*
* Initialize the GEM device fields
*/
int
{
return (0);
}
/*
* Allocate a GEM object of the specified size with shmfs backing store
*/
struct drm_gem_object *
{
static ddi_dma_attr_t dma_attr = {
0U, /* dma_attr_addr_lo */
0xffffffffU, /* dma_attr_addr_hi */
0xffffffffU, /* dma_attr_count_max */
4096, /* dma_attr_align */
0x1fffU, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0xffffffffU, /* dma_attr_maxxfer */
0xffffffffU, /* dma_attr_seg */
1, /* dma_attr_sgllen, variable */
4, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static ddi_device_acc_attr_t acc_attr = {
};
struct drm_gem_object *obj;
int i, n;
return (NULL);
if (shfile_name == SHFILE_NAME_MAX) {
DRM_ERROR("No name space for object");
goto err1;
} else {
}
DRM_ERROR("drm_gem_object_alloc: "
"ddi_dma_alloc_handle failed");
goto err1;
}
DRM_ERROR("drm_gem_object_alloc: "
"ddi_dma_mem_alloc failed");
goto err2;
}
!= DDI_DMA_MAPPED) {
DRM_ERROR("drm_gem_object_alloc: "
"ddi_dma_addr_bind_handle failed");
goto err3;
}
goto err4;
}
for (n = 0, i = 1; ; i++) {
paddr < cookie_end;
if (n >= real_pgcnt)
goto addmap;
}
if (i >= cookie_cnt)
break;
}
goto err5;
}
goto err6;
}
goto err7;
}
return (obj);
err7:
err6:
err5:
err4:
err3:
err2:
err1:
return (NULL);
}
/*
* Removes the mapping from handle to filp for this object.
*/
static int
{
struct drm_device *dev;
struct drm_gem_object *obj;
int err;
/*
* This is gross. The idr system doesn't let us try a delete and
* return an error code. It just spews if you fail at deleting.
* So, we have to grab a lock around finding the object and then
* doing the delete on it and dropping the refcount, or the user
* could race us to double-decrement the refcount and cause a
* use-after-free later. Given the frequency of our handle lookups,
* we may want to use ida for number allocation and a hash table
* for the pointers, anyway.
*/
/* Check if we currently have a reference on the object */
return (EINVAL);
}
/* Release reference and decrement refcount. */
if (err == -1)
return (0);
}
/*
* Create a handle for this object. This adds a handle reference
* to the object, which includes a regular reference count. Callers
* will likely want to dereference the object afterwards.
*/
int
struct drm_gem_object *obj,
int *handlep)
{
int ret;
/*
* Get the user-visible handle using idr.
*/
/* ensure there is space available to allocate a handle */
/* do the allocation under our spinlock */
goto again;
if (ret != 0) {
DRM_ERROR("Failed to create handle");
return (ret);
}
return (0);
}
/* Returns a reference to the object named by the handle. */
struct drm_gem_object *
int handle)
{
struct drm_gem_object *obj;
/* Check if we currently have a reference on the object */
return (NULL);
}
return (obj);
}
/*
* Releases the handle to an mm object.
*/
/*ARGSUSED*/
int
{
struct drm_gem_close args;
int ret;
return (ENODEV);
return (ret);
}
/*
* Create a global name for an object, returning the name.
*
* Note that the name does not hold a reference; when the object
* is freed, the name goes away.
*/
/*ARGSUSED*/
int
{
struct drm_gem_flink args;
struct drm_gem_object *obj;
return (ENODEV);
return (EINVAL);
/* only creat a node in object_name_idr, no update anything */
/* Allocate a reference for the name table. */
}
/*
* Leave the reference from the lookup around as the
* name table now holds one
*/
if (ret != 0)
return (ret);
}
/*
* Open an object using the global name, returning a handle and the size.
*
* This handle (of course) holds a reference to the object, so the object
* will not go away until the handle is deleted.
*/
/*ARGSUSED*/
int
{
struct drm_gem_open args;
struct drm_gem_object *obj;
int ret;
int handle;
DRM_ERROR("Not support GEM");
return (ENODEV);
}
if (obj)
if (!obj) {
return (ENOENT);
}
if (ret != 0)
return (ret);
}
/*
* Called at device open time, sets up the structure for handling refcounting
* of mm objects.
*/
void
{
}
/*
* Called at device close to release the file's
* handle references on objects.
*/
static void
{
}
/*
* Called at close time when the filp is going away.
*
* Releases any remaining references on objects by this filp.
*/
void
{
}
/*
* Called after the last reference to the object has been lost.
*
* Frees the object
*/
void
{
}
/*
* Called after the last handle to the object has been closed
*
* Removes any name for the object. Note that this must be
* called before drm_gem_object_free or we'll be touching
* freed memory
*/
void
{
int err;
/* Remove any name for this object */
if (err == -1)
/*
* The object name held a reference to this object, drop
* that now.
*/
} else
}