/*1* Copyright (c) 2006-2008 Intel Corporation2* Copyright (c) 2007 Dave Airlie <[email protected]>3* Copyright (c) 2008 Red Hat Inc.4* Copyright (c) 2016 Intel Corporation5*6* Permission to use, copy, modify, distribute, and sell this software and its7* documentation for any purpose is hereby granted without fee, provided that8* the above copyright notice appear in all copies and that both that copyright9* notice and this permission notice appear in supporting documentation, and10* that the name of the copyright holders not be used in advertising or11* publicity pertaining to distribution of the software without specific,12* written prior permission. The copyright holders make no representations13* about the suitability of this software for any purpose. It is provided "as14* is" without express or implied warranty.15*16* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,17* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO18* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR19* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,20* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER21* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE22* OF THIS SOFTWARE.23*/2425#include <drm/drm_device.h>26#include <drm/drm_drv.h>27#include <drm/drm_gem.h>28#include <drm/drm_mode.h>2930#include "drm_crtc_internal.h"31#include "drm_internal.h"3233/**34* DOC: overview35*36* The KMS API doesn't standardize backing storage object creation and leaves it37* to driver-specific ioctls. Furthermore actually creating a buffer object even38* for GEM-based drivers is done through a driver-specific ioctl - GEM only has39* a common userspace interface for sharing and destroying objects. While not an40* issue for full-fledged graphics stacks that include device-specific userspace41* components (in libdrm for instance), this limit makes DRM-based early boot42* graphics unnecessarily complex.43*44* Dumb objects partly alleviate the problem by providing a standard API to45* create dumb buffers suitable for scanout, which can then be used to create46* KMS frame buffers.47*48* To support dumb objects drivers must implement the &drm_driver.dumb_create49* and &drm_driver.dumb_map_offset operations (the latter defaults to50* drm_gem_dumb_map_offset() if not set). Drivers that don't use GEM handles51* additionally need to implement the &drm_driver.dumb_destroy operation. See52* the callbacks for further details.53*54* Note that dumb objects may not be used for gpu acceleration, as has been55* attempted on some ARM embedded platforms. Such drivers really must have56* a hardware-specific ioctl to allocate suitable buffer objects.57*/5859int drm_mode_create_dumb(struct drm_device *dev,60struct drm_mode_create_dumb *args,61struct drm_file *file_priv)62{63u32 cpp, stride, size;6465if (!dev->driver->dumb_create)66return -ENOSYS;67if (!args->width || !args->height || !args->bpp)68return -EINVAL;6970/* overflow checks for 32bit size calculations */71if (args->bpp > U32_MAX - 8)72return -EINVAL;73cpp = DIV_ROUND_UP(args->bpp, 8);74if (cpp > U32_MAX / args->width)75return -EINVAL;76stride = cpp * args->width;77if (args->height > U32_MAX / stride)78return -EINVAL;7980/* test for wrap-around */81size = args->height * stride;82if (PAGE_ALIGN(size) == 0)83return -EINVAL;8485/*86* handle, pitch and size are output parameters. Zero them out to87* prevent drivers from accidentally using uninitialized data. Since88* not all existing userspace is clearing these fields properly we89* cannot reject IOCTL with garbage in them.90*/91args->handle = 0;92args->pitch = 0;93args->size = 0;9495return dev->driver->dumb_create(file_priv, dev, args);96}9798int drm_mode_create_dumb_ioctl(struct drm_device *dev,99void *data, struct drm_file *file_priv)100{101return drm_mode_create_dumb(dev, data, file_priv);102}103104/**105* drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer106* @dev: DRM device107* @data: ioctl data108* @file_priv: DRM file info109*110* Allocate an offset in the drm device node's address space to be able to111* memory map a dumb buffer.112*113* Called by the user via ioctl.114*115* Returns:116* Zero on success, negative errno on failure.117*/118int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,119void *data, struct drm_file *file_priv)120{121struct drm_mode_map_dumb *args = data;122123if (!dev->driver->dumb_create)124return -ENOSYS;125126if (dev->driver->dumb_map_offset)127return dev->driver->dumb_map_offset(file_priv, dev,128args->handle,129&args->offset);130else131return drm_gem_dumb_map_offset(file_priv, dev, args->handle,132&args->offset);133}134135int drm_mode_destroy_dumb(struct drm_device *dev, u32 handle,136struct drm_file *file_priv)137{138if (!dev->driver->dumb_create)139return -ENOSYS;140141return drm_gem_handle_delete(file_priv, handle);142}143144int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,145void *data, struct drm_file *file_priv)146{147struct drm_mode_destroy_dumb *args = data;148149return drm_mode_destroy_dumb(dev, args->handle, file_priv);150}151152153