From 841021713a4d700059774e0d3c77ec6c538daae2 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 16 Nov 2016 17:20:32 +0200 Subject: drm/i915: Add bannable context parameter Now when driver has per context scoring of 'hanging badness' and also subsequent hangs during short windows are allowed, if there is progress made in between, it does not make sense to expose a ban timing window as a context parameter anymore. Let the scoring be the sole indicator for ban policy and substitute ban period context parameter as a boolean to get/set context bannable property. v2: allow non root to opt into being banned (Chris) Cc: Chris Wilson Suggested-by: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala --- include/uapi/drm/i915_drm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 1c12a350eca3..12003f0d8c7f 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1224,6 +1224,7 @@ struct drm_i915_gem_context_param { #define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2 #define I915_CONTEXT_PARAM_GTT_SIZE 0x3 #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE 0x4 +#define I915_CONTEXT_PARAM_BANNABLE 0x5 __u64 value; }; -- cgit v1.2.3 From eec688e1420da584afb36ffa5f0cad75f53cf286 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 7 Nov 2016 19:49:47 +0000 Subject: drm/i915: Add i915 perf infrastructure Adds base i915 perf infrastructure for Gen performance metrics. This adds a DRM_IOCTL_I915_PERF_OPEN ioctl that takes an array of uint64 properties to configure a stream of metrics and returns a new fd usable with standard VFS system calls including read() to read typed and sized records; ioctl() to enable or disable capture and poll() to wait for data. A stream is opened something like: uint64_t properties[] = { /* Single context sampling */ DRM_I915_PERF_PROP_CTX_HANDLE, ctx_handle, /* Include OA reports in samples */ DRM_I915_PERF_PROP_SAMPLE_OA, true, /* OA unit configuration */ DRM_I915_PERF_PROP_OA_METRICS_SET, metrics_set_id, DRM_I915_PERF_PROP_OA_FORMAT, report_format, DRM_I915_PERF_PROP_OA_EXPONENT, period_exponent, }; struct drm_i915_perf_open_param parm = { .flags = I915_PERF_FLAG_FD_CLOEXEC | I915_PERF_FLAG_FD_NONBLOCK | I915_PERF_FLAG_DISABLED, .properties_ptr = (uint64_t)properties, .num_properties = sizeof(properties) / 16, }; int fd = drmIoctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m); Records read all start with a common { type, size } header with DRM_I915_PERF_RECORD_SAMPLE being of most interest. Sample records contain an extensible number of fields and it's the DRM_I915_PERF_PROP_SAMPLE_xyz properties given when opening that determine what's included in every sample. No specific streams are supported yet so any attempt to open a stream will return an error. v2: use i915_gem_context_get() - Chris Wilson v3: update read() interface to avoid passing state struct - Chris Wilson fix some rebase fallout, with i915-perf init/deinit v4: s/DRM_IORW/DRM_IOW/ - Emil Velikov Signed-off-by: Robert Bragg Reviewed-by: Matthew Auld Reviewed-by: Sourab Gupta Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161107194957.3385-2-robert@sixbynine.org --- drivers/gpu/drm/i915/Makefile | 3 + drivers/gpu/drm/i915/i915_drv.c | 4 + drivers/gpu/drm/i915/i915_drv.h | 91 ++++++++ drivers/gpu/drm/i915/i915_perf.c | 449 +++++++++++++++++++++++++++++++++++++++ include/uapi/drm/i915_drm.h | 67 ++++++ 5 files changed, 614 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_perf.c (limited to 'include') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 3dea46af9fe6..3e40d8f51f90 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -117,6 +117,9 @@ i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o # virtual gpu code i915-y += i915_vgpu.o +# perf code +i915-y += i915_perf.o + ifeq ($(CONFIG_DRM_I915_GVT),y) i915-y += intel_gvt.o include $(src)/gvt/Makefile diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 445fec9c2841..94a9fb0f7b39 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -848,6 +848,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, intel_detect_preproduction_hw(dev_priv); + i915_perf_init(dev_priv); + return 0; err_gvt: @@ -863,6 +865,7 @@ err_workqueues: */ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) { + i915_perf_fini(dev_priv); i915_gem_load_cleanup(&dev_priv->drm); i915_workqueues_cleanup(dev_priv); } @@ -2565,6 +2568,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_USERPTR, i915_gem_userptr_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW), }; static struct drm_driver driver = { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c7d5f7a30fe8..b69f8445af7e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1797,6 +1797,84 @@ struct intel_wm_config { bool sprites_scaled; }; +struct i915_perf_stream; + +struct i915_perf_stream_ops { + /* Enables the collection of HW samples, either in response to + * I915_PERF_IOCTL_ENABLE or implicitly called when stream is + * opened without I915_PERF_FLAG_DISABLED. + */ + void (*enable)(struct i915_perf_stream *stream); + + /* Disables the collection of HW samples, either in response to + * I915_PERF_IOCTL_DISABLE or implicitly called before + * destroying the stream. + */ + void (*disable)(struct i915_perf_stream *stream); + + /* Return: true if any i915 perf records are ready to read() + * for this stream. + */ + bool (*can_read)(struct i915_perf_stream *stream); + + /* Call poll_wait, passing a wait queue that will be woken + * once there is something ready to read() for the stream + */ + void (*poll_wait)(struct i915_perf_stream *stream, + struct file *file, + poll_table *wait); + + /* For handling a blocking read, wait until there is something + * to ready to read() for the stream. E.g. wait on the same + * wait queue that would be passed to poll_wait() until + * ->can_read() returns true (if its safe to call ->can_read() + * without the i915 perf lock held). + */ + int (*wait_unlocked)(struct i915_perf_stream *stream); + + /* read - Copy buffered metrics as records to userspace + * @buf: the userspace, destination buffer + * @count: the number of bytes to copy, requested by userspace + * @offset: zero at the start of the read, updated as the read + * proceeds, it represents how many bytes have been + * copied so far and the buffer offset for copying the + * next record. + * + * Copy as many buffered i915 perf samples and records for + * this stream to userspace as will fit in the given buffer. + * + * Only write complete records; returning -ENOSPC if there + * isn't room for a complete record. + * + * Return any error condition that results in a short read + * such as -ENOSPC or -EFAULT, even though these may be + * squashed before returning to userspace. + */ + int (*read)(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset); + + /* Cleanup any stream specific resources. + * + * The stream will always be disabled before this is called. + */ + void (*destroy)(struct i915_perf_stream *stream); +}; + +struct i915_perf_stream { + struct drm_i915_private *dev_priv; + + struct list_head link; + + u32 sample_flags; + + struct i915_gem_context *ctx; + bool enabled; + + struct i915_perf_stream_ops *ops; +}; + struct drm_i915_private { struct drm_device drm; @@ -2092,6 +2170,12 @@ struct drm_i915_private { struct i915_runtime_pm pm; + struct { + bool initialized; + struct mutex lock; + struct list_head streams; + } perf; + /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ struct { void (*resume)(struct drm_i915_private *); @@ -3253,6 +3337,9 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +int i915_perf_open_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); + /* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct i915_address_space *vm, u64 min_size, u64 alignment, @@ -3383,6 +3470,10 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, u32 batch_len, bool is_master); +/* i915_perf.c */ +extern void i915_perf_init(struct drm_i915_private *dev_priv); +extern void i915_perf_fini(struct drm_i915_private *dev_priv); + /* i915_suspend.c */ extern int i915_save_state(struct drm_device *dev); extern int i915_restore_state(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c new file mode 100644 index 000000000000..777ce65f910d --- /dev/null +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -0,0 +1,449 @@ +/* + * Copyright © 2015-2016 Intel Corporation + * + * 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, + * and/or sell copies of the Software, and to permit persons to whom the + * 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: + * Robert Bragg + */ + +#include + +#include "i915_drv.h" + +struct perf_open_properties { + u32 sample_flags; + + u64 single_context:1; + u64 ctx_handle; +}; + +static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream, + struct file *file, + char __user *buf, + size_t count, + loff_t *ppos) +{ + /* Note we keep the offset (aka bytes read) separate from any + * error status so that the final check for whether we return + * the bytes read with a higher precedence than any error (see + * comment below) doesn't need to be handled/duplicated in + * stream->ops->read() implementations. + */ + size_t offset = 0; + int ret = stream->ops->read(stream, buf, count, &offset); + + /* If we've successfully copied any data then reporting that + * takes precedence over any internal error status, so the + * data isn't lost. + * + * For example ret will be -ENOSPC whenever there is more + * buffered data than can be copied to userspace, but that's + * only interesting if we weren't able to copy some data + * because it implies the userspace buffer is too small to + * receive a single record (and we never split records). + * + * Another case with ret == -EFAULT is more of a grey area + * since it would seem like bad form for userspace to ask us + * to overrun its buffer, but the user knows best: + * + * http://yarchive.net/comp/linux/partial_reads_writes.html + */ + return offset ?: (ret ?: -EAGAIN); +} + +static ssize_t i915_perf_read(struct file *file, + char __user *buf, + size_t count, + loff_t *ppos) +{ + struct i915_perf_stream *stream = file->private_data; + struct drm_i915_private *dev_priv = stream->dev_priv; + ssize_t ret; + + if (!(file->f_flags & O_NONBLOCK)) { + /* Allow false positives from stream->ops->wait_unlocked. + */ + do { + ret = stream->ops->wait_unlocked(stream); + if (ret) + return ret; + + mutex_lock(&dev_priv->perf.lock); + ret = i915_perf_read_locked(stream, file, + buf, count, ppos); + mutex_unlock(&dev_priv->perf.lock); + } while (ret == -EAGAIN); + } else { + mutex_lock(&dev_priv->perf.lock); + ret = i915_perf_read_locked(stream, file, buf, count, ppos); + mutex_unlock(&dev_priv->perf.lock); + } + + return ret; +} + +static unsigned int i915_perf_poll_locked(struct i915_perf_stream *stream, + struct file *file, + poll_table *wait) +{ + unsigned int streams = 0; + + stream->ops->poll_wait(stream, file, wait); + + if (stream->ops->can_read(stream)) + streams |= POLLIN; + + return streams; +} + +static unsigned int i915_perf_poll(struct file *file, poll_table *wait) +{ + struct i915_perf_stream *stream = file->private_data; + struct drm_i915_private *dev_priv = stream->dev_priv; + int ret; + + mutex_lock(&dev_priv->perf.lock); + ret = i915_perf_poll_locked(stream, file, wait); + mutex_unlock(&dev_priv->perf.lock); + + return ret; +} + +static void i915_perf_enable_locked(struct i915_perf_stream *stream) +{ + if (stream->enabled) + return; + + /* Allow stream->ops->enable() to refer to this */ + stream->enabled = true; + + if (stream->ops->enable) + stream->ops->enable(stream); +} + +static void i915_perf_disable_locked(struct i915_perf_stream *stream) +{ + if (!stream->enabled) + return; + + /* Allow stream->ops->disable() to refer to this */ + stream->enabled = false; + + if (stream->ops->disable) + stream->ops->disable(stream); +} + +static long i915_perf_ioctl_locked(struct i915_perf_stream *stream, + unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case I915_PERF_IOCTL_ENABLE: + i915_perf_enable_locked(stream); + return 0; + case I915_PERF_IOCTL_DISABLE: + i915_perf_disable_locked(stream); + return 0; + } + + return -EINVAL; +} + +static long i915_perf_ioctl(struct file *file, + unsigned int cmd, + unsigned long arg) +{ + struct i915_perf_stream *stream = file->private_data; + struct drm_i915_private *dev_priv = stream->dev_priv; + long ret; + + mutex_lock(&dev_priv->perf.lock); + ret = i915_perf_ioctl_locked(stream, cmd, arg); + mutex_unlock(&dev_priv->perf.lock); + + return ret; +} + +static void i915_perf_destroy_locked(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + if (stream->enabled) + i915_perf_disable_locked(stream); + + if (stream->ops->destroy) + stream->ops->destroy(stream); + + list_del(&stream->link); + + if (stream->ctx) { + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_context_put(stream->ctx); + mutex_unlock(&dev_priv->drm.struct_mutex); + } + + kfree(stream); +} + +static int i915_perf_release(struct inode *inode, struct file *file) +{ + struct i915_perf_stream *stream = file->private_data; + struct drm_i915_private *dev_priv = stream->dev_priv; + + mutex_lock(&dev_priv->perf.lock); + i915_perf_destroy_locked(stream); + mutex_unlock(&dev_priv->perf.lock); + + return 0; +} + + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .release = i915_perf_release, + .poll = i915_perf_poll, + .read = i915_perf_read, + .unlocked_ioctl = i915_perf_ioctl, +}; + + +static struct i915_gem_context * +lookup_context(struct drm_i915_private *dev_priv, + struct drm_i915_file_private *file_priv, + u32 ctx_user_handle) +{ + struct i915_gem_context *ctx; + int ret; + + ret = i915_mutex_lock_interruptible(&dev_priv->drm); + if (ret) + return ERR_PTR(ret); + + ctx = i915_gem_context_lookup(file_priv, ctx_user_handle); + if (!IS_ERR(ctx)) + i915_gem_context_get(ctx); + + mutex_unlock(&dev_priv->drm.struct_mutex); + + return ctx; +} + +static int +i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv, + struct drm_i915_perf_open_param *param, + struct perf_open_properties *props, + struct drm_file *file) +{ + struct i915_gem_context *specific_ctx = NULL; + struct i915_perf_stream *stream = NULL; + unsigned long f_flags = 0; + int stream_fd; + int ret; + + if (props->single_context) { + u32 ctx_handle = props->ctx_handle; + struct drm_i915_file_private *file_priv = file->driver_priv; + + specific_ctx = lookup_context(dev_priv, file_priv, ctx_handle); + if (IS_ERR(specific_ctx)) { + ret = PTR_ERR(specific_ctx); + if (ret != -EINTR) + DRM_ERROR("Failed to look up context with ID %u for opening perf stream\n", + ctx_handle); + goto err; + } + } + + if (!specific_ctx && !capable(CAP_SYS_ADMIN)) { + DRM_ERROR("Insufficient privileges to open system-wide i915 perf stream\n"); + ret = -EACCES; + goto err_ctx; + } + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) { + ret = -ENOMEM; + goto err_ctx; + } + + stream->sample_flags = props->sample_flags; + stream->dev_priv = dev_priv; + stream->ctx = specific_ctx; + + /* + * TODO: support sampling something + * + * For now this is as far as we can go. + */ + DRM_ERROR("Unsupported i915 perf stream configuration\n"); + ret = -EINVAL; + goto err_alloc; + + list_add(&stream->link, &dev_priv->perf.streams); + + if (param->flags & I915_PERF_FLAG_FD_CLOEXEC) + f_flags |= O_CLOEXEC; + if (param->flags & I915_PERF_FLAG_FD_NONBLOCK) + f_flags |= O_NONBLOCK; + + stream_fd = anon_inode_getfd("[i915_perf]", &fops, stream, f_flags); + if (stream_fd < 0) { + ret = stream_fd; + goto err_open; + } + + if (!(param->flags & I915_PERF_FLAG_DISABLED)) + i915_perf_enable_locked(stream); + + return stream_fd; + +err_open: + list_del(&stream->link); + if (stream->ops->destroy) + stream->ops->destroy(stream); +err_alloc: + kfree(stream); +err_ctx: + if (specific_ctx) { + mutex_lock(&dev_priv->drm.struct_mutex); + i915_gem_context_put(specific_ctx); + mutex_unlock(&dev_priv->drm.struct_mutex); + } +err: + return ret; +} + +/* Note we copy the properties from userspace outside of the i915 perf + * mutex to avoid an awkward lockdep with mmap_sem. + * + * Note this function only validates properties in isolation it doesn't + * validate that the combination of properties makes sense or that all + * properties necessary for a particular kind of stream have been set. + */ +static int read_properties_unlocked(struct drm_i915_private *dev_priv, + u64 __user *uprops, + u32 n_props, + struct perf_open_properties *props) +{ + u64 __user *uprop = uprops; + int i; + + memset(props, 0, sizeof(struct perf_open_properties)); + + if (!n_props) { + DRM_ERROR("No i915 perf properties given"); + return -EINVAL; + } + + /* Considering that ID = 0 is reserved and assuming that we don't + * (currently) expect any configurations to ever specify duplicate + * values for a particular property ID then the last _PROP_MAX value is + * one greater than the maximum number of properties we expect to get + * from userspace. + */ + if (n_props >= DRM_I915_PERF_PROP_MAX) { + DRM_ERROR("More i915 perf properties specified than exist"); + return -EINVAL; + } + + for (i = 0; i < n_props; i++) { + u64 id, value; + int ret; + + ret = get_user(id, uprop); + if (ret) + return ret; + + ret = get_user(value, uprop + 1); + if (ret) + return ret; + + switch ((enum drm_i915_perf_property_id)id) { + case DRM_I915_PERF_PROP_CTX_HANDLE: + props->single_context = 1; + props->ctx_handle = value; + break; + default: + MISSING_CASE(id); + DRM_ERROR("Unknown i915 perf property ID"); + return -EINVAL; + } + + uprop += 2; + } + + return 0; +} + +int i915_perf_open_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_perf_open_param *param = data; + struct perf_open_properties props; + u32 known_open_flags; + int ret; + + if (!dev_priv->perf.initialized) { + DRM_ERROR("i915 perf interface not available for this system"); + return -ENOTSUPP; + } + + known_open_flags = I915_PERF_FLAG_FD_CLOEXEC | + I915_PERF_FLAG_FD_NONBLOCK | + I915_PERF_FLAG_DISABLED; + if (param->flags & ~known_open_flags) { + DRM_ERROR("Unknown drm_i915_perf_open_param flag\n"); + return -EINVAL; + } + + ret = read_properties_unlocked(dev_priv, + u64_to_user_ptr(param->properties_ptr), + param->num_properties, + &props); + if (ret) + return ret; + + mutex_lock(&dev_priv->perf.lock); + ret = i915_perf_open_ioctl_locked(dev_priv, param, &props, file); + mutex_unlock(&dev_priv->perf.lock); + + return ret; +} + +void i915_perf_init(struct drm_i915_private *dev_priv) +{ + INIT_LIST_HEAD(&dev_priv->perf.streams); + mutex_init(&dev_priv->perf.lock); + + dev_priv->perf.initialized = true; +} + +void i915_perf_fini(struct drm_i915_private *dev_priv) +{ + if (!dev_priv->perf.initialized) + return; + + /* Currently nothing to clean up */ + + dev_priv->perf.initialized = false; +} diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 12003f0d8c7f..192dc1f8256b 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -258,6 +258,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_GEM_USERPTR 0x33 #define DRM_I915_GEM_CONTEXT_GETPARAM 0x34 #define DRM_I915_GEM_CONTEXT_SETPARAM 0x35 +#define DRM_I915_PERF_OPEN 0x36 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -311,6 +312,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_USERPTR, struct drm_i915_gem_userptr) #define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param) #define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param) +#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1228,6 +1230,71 @@ struct drm_i915_gem_context_param { __u64 value; }; +enum drm_i915_perf_property_id { + /** + * Open the stream for a specific context handle (as used with + * execbuffer2). A stream opened for a specific context this way + * won't typically require root privileges. + */ + DRM_I915_PERF_PROP_CTX_HANDLE = 1, + + DRM_I915_PERF_PROP_MAX /* non-ABI */ +}; + +struct drm_i915_perf_open_param { + __u32 flags; +#define I915_PERF_FLAG_FD_CLOEXEC (1<<0) +#define I915_PERF_FLAG_FD_NONBLOCK (1<<1) +#define I915_PERF_FLAG_DISABLED (1<<2) + + /** The number of u64 (id, value) pairs */ + __u32 num_properties; + + /** + * Pointer to array of u64 (id, value) pairs configuring the stream + * to open. + */ + __u64 __user properties_ptr; +}; + +#define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) +#define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) + +/** + * Common to all i915 perf records + */ +struct drm_i915_perf_record_header { + __u32 type; + __u16 pad; + __u16 size; +}; + +enum drm_i915_perf_record_type { + + /** + * Samples are the work horse record type whose contents are extensible + * and defined when opening an i915 perf stream based on the given + * properties. + * + * Boolean properties following the naming convention + * DRM_I915_PERF_SAMPLE_xyz_PROP request the inclusion of 'xyz' data in + * every sample. + * + * The order of these sample properties given by userspace has no + * affect on the ordering of data within a sample. The order will be + * documented here. + * + * struct { + * struct drm_i915_perf_record_header header; + * + * TODO: itemize extensible sample data here + * }; + */ + DRM_I915_PERF_RECORD_SAMPLE = 1, + + DRM_I915_PERF_RECORD_MAX /* non-ABI */ +}; + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From d79651522e89c4ffa8992b48dfe449f0c583f809 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 7 Nov 2016 19:49:52 +0000 Subject: drm/i915: Enable i915 perf stream for Haswell OA unit Gen graphics hardware can be set up to periodically write snapshots of performance counters into a circular buffer via its Observation Architecture and this patch exposes that capability to userspace via the i915 perf interface. v2: Make sure to initialize ->specific_ctx_id when opening, without relying on _pin_notify hook, in case ctx already pinned. v3: Revert back to pinning ctx upfront when opening stream, removing need to hook in to pinning and to update OACONTROL on the fly. Signed-off-by: Robert Bragg Signed-off-by: Zhenyu Wang Cc: Chris Wilson Reviewed-by: Matthew Auld Reviewed-by: Sourab Gupta Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161107194957.3385-7-robert@sixbynine.org --- drivers/gpu/drm/i915/i915_drv.h | 66 ++- drivers/gpu/drm/i915/i915_perf.c | 1036 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_reg.h | 338 +++++++++++++ include/uapi/drm/i915_drm.h | 71 ++- 4 files changed, 1482 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b11506f65936..3a69e219c7a2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1797,6 +1797,11 @@ struct intel_wm_config { bool sprites_scaled; }; +struct i915_oa_format { + u32 format; + int size; +}; + struct i915_oa_reg { i915_reg_t addr; u32 value; @@ -1817,11 +1822,6 @@ struct i915_perf_stream_ops { */ void (*disable)(struct i915_perf_stream *stream); - /* Return: true if any i915 perf records are ready to read() - * for this stream. - */ - bool (*can_read)(struct i915_perf_stream *stream); - /* Call poll_wait, passing a wait queue that will be woken * once there is something ready to read() for the stream */ @@ -1831,9 +1831,7 @@ struct i915_perf_stream_ops { /* For handling a blocking read, wait until there is something * to ready to read() for the stream. E.g. wait on the same - * wait queue that would be passed to poll_wait() until - * ->can_read() returns true (if its safe to call ->can_read() - * without the i915 perf lock held). + * wait queue that would be passed to poll_wait(). */ int (*wait_unlocked)(struct i915_perf_stream *stream); @@ -1873,11 +1871,28 @@ struct i915_perf_stream { struct list_head link; u32 sample_flags; + int sample_size; struct i915_gem_context *ctx; bool enabled; - struct i915_perf_stream_ops *ops; + const struct i915_perf_stream_ops *ops; +}; + +struct i915_oa_ops { + void (*init_oa_buffer)(struct drm_i915_private *dev_priv); + int (*enable_metric_set)(struct drm_i915_private *dev_priv); + void (*disable_metric_set)(struct drm_i915_private *dev_priv); + void (*oa_enable)(struct drm_i915_private *dev_priv); + void (*oa_disable)(struct drm_i915_private *dev_priv); + void (*update_oacontrol)(struct drm_i915_private *dev_priv); + void (*update_hw_ctx_id_locked)(struct drm_i915_private *dev_priv, + u32 ctx_id); + int (*read)(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset); + bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv); }; struct drm_i915_private { @@ -2177,16 +2192,47 @@ struct drm_i915_private { struct { bool initialized; + struct mutex lock; struct list_head streams; + spinlock_t hook_lock; + struct { - u32 metrics_set; + struct i915_perf_stream *exclusive_stream; + + u32 specific_ctx_id; + struct i915_vma *pinned_rcs_vma; + + struct hrtimer poll_check_timer; + wait_queue_head_t poll_wq; + bool pollin; + + bool periodic; + int period_exponent; + int timestamp_frequency; + + int tail_margin; + + int metrics_set; const struct i915_oa_reg *mux_regs; int mux_regs_len; const struct i915_oa_reg *b_counter_regs; int b_counter_regs_len; + + struct { + struct i915_vma *vma; + u8 *vaddr; + int format; + int format_size; + } oa_buffer; + + u32 gen7_latched_oastatus1; + + struct i915_oa_ops ops; + const struct i915_oa_format *oa_formats; + int n_builtin_sets; } oa; } perf; diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 777ce65f910d..54653bcf0d79 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -25,16 +25,899 @@ */ #include +#include #include "i915_drv.h" +#include "i915_oa_hsw.h" + +/* HW requires this to be a power of two, between 128k and 16M, though driver + * is currently generally designed assuming the largest 16M size is used such + * that the overflow cases are unlikely in normal operation. + */ +#define OA_BUFFER_SIZE SZ_16M + +#define OA_TAKEN(tail, head) ((tail - head) & (OA_BUFFER_SIZE - 1)) + +/* There's a HW race condition between OA unit tail pointer register updates and + * writes to memory whereby the tail pointer can sometimes get ahead of what's + * been written out to the OA buffer so far. + * + * Although this can be observed explicitly by checking for a zeroed report-id + * field in tail reports, it seems preferable to account for this earlier e.g. + * as part of the _oa_buffer_is_empty checks to minimize -EAGAIN polling cycles + * in this situation. + * + * To give time for the most recent reports to land before they may be copied to + * userspace, the driver operates as if the tail pointer effectively lags behind + * the HW tail pointer by 'tail_margin' bytes. The margin in bytes is calculated + * based on this constant in nanoseconds, the current OA sampling exponent + * and current report size. + * + * There is also a fallback check while reading to simply skip over reports with + * a zeroed report-id. + */ +#define OA_TAIL_MARGIN_NSEC 100000ULL + +/* frequency for checking whether the OA unit has written new reports to the + * circular OA buffer... + */ +#define POLL_FREQUENCY 200 +#define POLL_PERIOD (NSEC_PER_SEC / POLL_FREQUENCY) + +/* The maximum exponent the hardware accepts is 63 (essentially it selects one + * of the 64bit timestamp bits to trigger reports from) but there's currently + * no known use case for sampling as infrequently as once per 47 thousand years. + * + * Since the timestamps included in OA reports are only 32bits it seems + * reasonable to limit the OA exponent where it's still possible to account for + * overflow in OA report timestamps. + */ +#define OA_EXPONENT_MAX 31 + +#define INVALID_CTX_ID 0xffffffff + + +/* XXX: beware if future OA HW adds new report formats that the current + * code assumes all reports have a power-of-two size and ~(size - 1) can + * be used as a mask to align the OA tail pointer. + */ +static struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = { + [I915_OA_FORMAT_A13] = { 0, 64 }, + [I915_OA_FORMAT_A29] = { 1, 128 }, + [I915_OA_FORMAT_A13_B8_C8] = { 2, 128 }, + /* A29_B8_C8 Disallowed as 192 bytes doesn't factor into buffer size */ + [I915_OA_FORMAT_B4_C8] = { 4, 64 }, + [I915_OA_FORMAT_A45_B8_C8] = { 5, 256 }, + [I915_OA_FORMAT_B4_C8_A16] = { 6, 128 }, + [I915_OA_FORMAT_C4_B8] = { 7, 64 }, +}; + +#define SAMPLE_OA_REPORT (1<<0) struct perf_open_properties { u32 sample_flags; u64 single_context:1; u64 ctx_handle; + + /* OA sampling state */ + int metrics_set; + int oa_format; + bool oa_periodic; + int oa_period_exponent; +}; + +/* NB: This is either called via fops or the poll check hrtimer (atomic ctx) + * + * It's safe to read OA config state here unlocked, assuming that this is only + * called while the stream is enabled, while the global OA configuration can't + * be modified. + * + * Note: we don't lock around the head/tail reads even though there's the slim + * possibility of read() fop errors forcing a re-init of the OA buffer + * pointers. A race here could result in a false positive !empty status which + * is acceptable. + */ +static bool gen7_oa_buffer_is_empty_fop_unlocked(struct drm_i915_private *dev_priv) +{ + int report_size = dev_priv->perf.oa.oa_buffer.format_size; + u32 oastatus2 = I915_READ(GEN7_OASTATUS2); + u32 oastatus1 = I915_READ(GEN7_OASTATUS1); + u32 head = oastatus2 & GEN7_OASTATUS2_HEAD_MASK; + u32 tail = oastatus1 & GEN7_OASTATUS1_TAIL_MASK; + + return OA_TAKEN(tail, head) < + dev_priv->perf.oa.tail_margin + report_size; +} + +/** + * Appends a status record to a userspace read() buffer. + */ +static int append_oa_status(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset, + enum drm_i915_perf_record_type type) +{ + struct drm_i915_perf_record_header header = { type, 0, sizeof(header) }; + + if ((count - *offset) < header.size) + return -ENOSPC; + + if (copy_to_user(buf + *offset, &header, sizeof(header))) + return -EFAULT; + + (*offset) += header.size; + + return 0; +} + +/** + * Copies single OA report into userspace read() buffer. + */ +static int append_oa_sample(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset, + const u8 *report) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + int report_size = dev_priv->perf.oa.oa_buffer.format_size; + struct drm_i915_perf_record_header header; + u32 sample_flags = stream->sample_flags; + + header.type = DRM_I915_PERF_RECORD_SAMPLE; + header.pad = 0; + header.size = stream->sample_size; + + if ((count - *offset) < header.size) + return -ENOSPC; + + buf += *offset; + if (copy_to_user(buf, &header, sizeof(header))) + return -EFAULT; + buf += sizeof(header); + + if (sample_flags & SAMPLE_OA_REPORT) { + if (copy_to_user(buf, report, report_size)) + return -EFAULT; + } + + (*offset) += header.size; + + return 0; +} + +/** + * Copies all buffered OA reports into userspace read() buffer. + * @stream: An i915-perf stream opened for OA metrics + * @buf: destination buffer given by userspace + * @count: the number of bytes userspace wants to read + * @offset: (inout): the current position for writing into @buf + * @head_ptr: (inout): the current oa buffer cpu read position + * @tail: the current oa buffer gpu write position + * + * Returns 0 on success, negative error code on failure. + * + * Notably any error condition resulting in a short read (-ENOSPC or + * -EFAULT) will be returned even though one or more records may + * have been successfully copied. In this case it's up to the caller + * to decide if the error should be squashed before returning to + * userspace. + * + * Note: reports are consumed from the head, and appended to the + * tail, so the head chases the tail?... If you think that's mad + * and back-to-front you're not alone, but this follows the + * Gen PRM naming convention. + */ +static int gen7_append_oa_reports(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset, + u32 *head_ptr, + u32 tail) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + int report_size = dev_priv->perf.oa.oa_buffer.format_size; + u8 *oa_buf_base = dev_priv->perf.oa.oa_buffer.vaddr; + int tail_margin = dev_priv->perf.oa.tail_margin; + u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma); + u32 mask = (OA_BUFFER_SIZE - 1); + u32 head; + u32 taken; + int ret = 0; + + if (WARN_ON(!stream->enabled)) + return -EIO; + + head = *head_ptr - gtt_offset; + tail -= gtt_offset; + + /* The OA unit is expected to wrap the tail pointer according to the OA + * buffer size and since we should never write a misaligned head + * pointer we don't expect to read one back either... + */ + if (tail > OA_BUFFER_SIZE || head > OA_BUFFER_SIZE || + head % report_size) { + DRM_ERROR("Inconsistent OA buffer pointer (head = %u, tail = %u): force restart\n", + head, tail); + dev_priv->perf.oa.ops.oa_disable(dev_priv); + dev_priv->perf.oa.ops.oa_enable(dev_priv); + *head_ptr = I915_READ(GEN7_OASTATUS2) & + GEN7_OASTATUS2_HEAD_MASK; + return -EIO; + } + + + /* The tail pointer increases in 64 byte increments, not in report_size + * steps... + */ + tail &= ~(report_size - 1); + + /* Move the tail pointer back by the current tail_margin to account for + * the possibility that the latest reports may not have really landed + * in memory yet... + */ + + if (OA_TAKEN(tail, head) < report_size + tail_margin) + return -EAGAIN; + + tail -= tail_margin; + tail &= mask; + + for (/* none */; + (taken = OA_TAKEN(tail, head)); + head = (head + report_size) & mask) { + u8 *report = oa_buf_base + head; + u32 *report32 = (void *)report; + + /* All the report sizes factor neatly into the buffer + * size so we never expect to see a report split + * between the beginning and end of the buffer. + * + * Given the initial alignment check a misalignment + * here would imply a driver bug that would result + * in an overrun. + */ + if (WARN_ON((OA_BUFFER_SIZE - head) < report_size)) { + DRM_ERROR("Spurious OA head ptr: non-integral report offset\n"); + break; + } + + /* The report-ID field for periodic samples includes + * some undocumented flags related to what triggered + * the report and is never expected to be zero so we + * can check that the report isn't invalid before + * copying it to userspace... + */ + if (report32[0] == 0) { + DRM_ERROR("Skipping spurious, invalid OA report\n"); + continue; + } + + ret = append_oa_sample(stream, buf, count, offset, report); + if (ret) + break; + + /* The above report-id field sanity check is based on + * the assumption that the OA buffer is initially + * zeroed and we reset the field after copying so the + * check is still meaningful once old reports start + * being overwritten. + */ + report32[0] = 0; + } + + *head_ptr = gtt_offset + head; + + return ret; +} + +static int gen7_oa_read(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + int report_size = dev_priv->perf.oa.oa_buffer.format_size; + u32 oastatus2; + u32 oastatus1; + u32 head; + u32 tail; + int ret; + + if (WARN_ON(!dev_priv->perf.oa.oa_buffer.vaddr)) + return -EIO; + + oastatus2 = I915_READ(GEN7_OASTATUS2); + oastatus1 = I915_READ(GEN7_OASTATUS1); + + head = oastatus2 & GEN7_OASTATUS2_HEAD_MASK; + tail = oastatus1 & GEN7_OASTATUS1_TAIL_MASK; + + /* XXX: On Haswell we don't have a safe way to clear oastatus1 + * bits while the OA unit is enabled (while the tail pointer + * may be updated asynchronously) so we ignore status bits + * that have already been reported to userspace. + */ + oastatus1 &= ~dev_priv->perf.oa.gen7_latched_oastatus1; + + /* We treat OABUFFER_OVERFLOW as a significant error: + * + * - The status can be interpreted to mean that the buffer is + * currently full (with a higher precedence than OA_TAKEN() + * which will start to report a near-empty buffer after an + * overflow) but it's awkward that we can't clear the status + * on Haswell, so without a reset we won't be able to catch + * the state again. + * + * - Since it also implies the HW has started overwriting old + * reports it may also affect our sanity checks for invalid + * reports when copying to userspace that assume new reports + * are being written to cleared memory. + * + * - In the future we may want to introduce a flight recorder + * mode where the driver will automatically maintain a safe + * guard band between head/tail, avoiding this overflow + * condition, but we avoid the added driver complexity for + * now. + */ + if (unlikely(oastatus1 & GEN7_OASTATUS1_OABUFFER_OVERFLOW)) { + ret = append_oa_status(stream, buf, count, offset, + DRM_I915_PERF_RECORD_OA_BUFFER_LOST); + if (ret) + return ret; + + DRM_ERROR("OA buffer overflow: force restart\n"); + + dev_priv->perf.oa.ops.oa_disable(dev_priv); + dev_priv->perf.oa.ops.oa_enable(dev_priv); + + oastatus2 = I915_READ(GEN7_OASTATUS2); + oastatus1 = I915_READ(GEN7_OASTATUS1); + + head = oastatus2 & GEN7_OASTATUS2_HEAD_MASK; + tail = oastatus1 & GEN7_OASTATUS1_TAIL_MASK; + } + + if (unlikely(oastatus1 & GEN7_OASTATUS1_REPORT_LOST)) { + ret = append_oa_status(stream, buf, count, offset, + DRM_I915_PERF_RECORD_OA_REPORT_LOST); + if (ret) + return ret; + dev_priv->perf.oa.gen7_latched_oastatus1 |= + GEN7_OASTATUS1_REPORT_LOST; + } + + ret = gen7_append_oa_reports(stream, buf, count, offset, + &head, tail); + + /* All the report sizes are a power of two and the + * head should always be incremented by some multiple + * of the report size. + * + * A warning here, but notably if we later read back a + * misaligned pointer we will treat that as a bug since + * it could lead to a buffer overrun. + */ + WARN_ONCE(head & (report_size - 1), + "i915: Writing misaligned OA head pointer"); + + /* Note: we update the head pointer here even if an error + * was returned since the error may represent a short read + * where some some reports were successfully copied. + */ + I915_WRITE(GEN7_OASTATUS2, + ((head & GEN7_OASTATUS2_HEAD_MASK) | + OA_MEM_SELECT_GGTT)); + + return ret; +} + +static int i915_oa_wait_unlocked(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + /* We would wait indefinitely if periodic sampling is not enabled */ + if (!dev_priv->perf.oa.periodic) + return -EIO; + + /* Note: the oa_buffer_is_empty() condition is ok to run unlocked as it + * just performs mmio reads of the OA buffer head + tail pointers and + * it's assumed we're handling some operation that implies the stream + * can't be destroyed until completion (such as a read()) that ensures + * the device + OA buffer can't disappear + */ + return wait_event_interruptible(dev_priv->perf.oa.poll_wq, + !dev_priv->perf.oa.ops.oa_buffer_is_empty(dev_priv)); +} + +static void i915_oa_poll_wait(struct i915_perf_stream *stream, + struct file *file, + poll_table *wait) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + poll_wait(file, &dev_priv->perf.oa.poll_wq, wait); +} + +static int i915_oa_read(struct i915_perf_stream *stream, + char __user *buf, + size_t count, + size_t *offset) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + return dev_priv->perf.oa.ops.read(stream, buf, count, offset); +} + +/* Determine the render context hw id, and ensure it remains fixed for the + * lifetime of the stream. This ensures that we don't have to worry about + * updating the context ID in OACONTROL on the fly. + */ +static int oa_get_render_ctx_id(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + struct i915_vma *vma; + int ret; + + ret = i915_mutex_lock_interruptible(&dev_priv->drm); + if (ret) + return ret; + + /* As the ID is the gtt offset of the context's vma we pin + * the vma to ensure the ID remains fixed. + * + * NB: implied RCS engine... + */ + vma = i915_gem_context_pin_legacy(stream->ctx, 0); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto unlock; + } + + dev_priv->perf.oa.pinned_rcs_vma = vma; + + /* Explicitly track the ID (instead of calling i915_ggtt_offset() + * on the fly) considering the difference with gen8+ and + * execlists + */ + dev_priv->perf.oa.specific_ctx_id = i915_ggtt_offset(vma); + +unlock: + mutex_unlock(&dev_priv->drm.struct_mutex); + + return ret; +} + +static void oa_put_render_ctx_id(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + mutex_lock(&dev_priv->drm.struct_mutex); + + i915_vma_unpin(dev_priv->perf.oa.pinned_rcs_vma); + dev_priv->perf.oa.pinned_rcs_vma = NULL; + + dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; + + mutex_unlock(&dev_priv->drm.struct_mutex); +} + +static void +free_oa_buffer(struct drm_i915_private *i915) +{ + mutex_lock(&i915->drm.struct_mutex); + + i915_gem_object_unpin_map(i915->perf.oa.oa_buffer.vma->obj); + i915_vma_unpin(i915->perf.oa.oa_buffer.vma); + i915_gem_object_put(i915->perf.oa.oa_buffer.vma->obj); + + i915->perf.oa.oa_buffer.vma = NULL; + i915->perf.oa.oa_buffer.vaddr = NULL; + + mutex_unlock(&i915->drm.struct_mutex); +} + +static void i915_oa_stream_destroy(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + BUG_ON(stream != dev_priv->perf.oa.exclusive_stream); + + dev_priv->perf.oa.ops.disable_metric_set(dev_priv); + + free_oa_buffer(dev_priv); + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_put(dev_priv); + + if (stream->ctx) + oa_put_render_ctx_id(stream); + + dev_priv->perf.oa.exclusive_stream = NULL; +} + +static void gen7_init_oa_buffer(struct drm_i915_private *dev_priv) +{ + u32 gtt_offset = i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma); + + /* Pre-DevBDW: OABUFFER must be set with counters off, + * before OASTATUS1, but after OASTATUS2 + */ + I915_WRITE(GEN7_OASTATUS2, gtt_offset | OA_MEM_SELECT_GGTT); /* head */ + I915_WRITE(GEN7_OABUFFER, gtt_offset); + I915_WRITE(GEN7_OASTATUS1, gtt_offset | OABUFFER_SIZE_16M); /* tail */ + + /* On Haswell we have to track which OASTATUS1 flags we've + * already seen since they can't be cleared while periodic + * sampling is enabled. + */ + dev_priv->perf.oa.gen7_latched_oastatus1 = 0; + + /* NB: although the OA buffer will initially be allocated + * zeroed via shmfs (and so this memset is redundant when + * first allocating), we may re-init the OA buffer, either + * when re-enabling a stream or in error/reset paths. + * + * The reason we clear the buffer for each re-init is for the + * sanity check in gen7_append_oa_reports() that looks at the + * report-id field to make sure it's non-zero which relies on + * the assumption that new reports are being written to zeroed + * memory... + */ + memset(dev_priv->perf.oa.oa_buffer.vaddr, 0, OA_BUFFER_SIZE); + + /* Maybe make ->pollin per-stream state if we support multiple + * concurrent streams in the future. + */ + dev_priv->perf.oa.pollin = false; +} + +static int alloc_oa_buffer(struct drm_i915_private *dev_priv) +{ + struct drm_i915_gem_object *bo; + struct i915_vma *vma; + int ret; + + if (WARN_ON(dev_priv->perf.oa.oa_buffer.vma)) + return -ENODEV; + + ret = i915_mutex_lock_interruptible(&dev_priv->drm); + if (ret) + return ret; + + BUILD_BUG_ON_NOT_POWER_OF_2(OA_BUFFER_SIZE); + BUILD_BUG_ON(OA_BUFFER_SIZE < SZ_128K || OA_BUFFER_SIZE > SZ_16M); + + bo = i915_gem_object_create(&dev_priv->drm, OA_BUFFER_SIZE); + if (IS_ERR(bo)) { + DRM_ERROR("Failed to allocate OA buffer\n"); + ret = PTR_ERR(bo); + goto unlock; + } + + ret = i915_gem_object_set_cache_level(bo, I915_CACHE_LLC); + if (ret) + goto err_unref; + + /* PreHSW required 512K alignment, HSW requires 16M */ + vma = i915_gem_object_ggtt_pin(bo, NULL, 0, SZ_16M, 0); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err_unref; + } + dev_priv->perf.oa.oa_buffer.vma = vma; + + dev_priv->perf.oa.oa_buffer.vaddr = + i915_gem_object_pin_map(bo, I915_MAP_WB); + if (IS_ERR(dev_priv->perf.oa.oa_buffer.vaddr)) { + ret = PTR_ERR(dev_priv->perf.oa.oa_buffer.vaddr); + goto err_unpin; + } + + dev_priv->perf.oa.ops.init_oa_buffer(dev_priv); + + DRM_DEBUG_DRIVER("OA Buffer initialized, gtt offset = 0x%x, vaddr = %p\n", + i915_ggtt_offset(dev_priv->perf.oa.oa_buffer.vma), + dev_priv->perf.oa.oa_buffer.vaddr); + + goto unlock; + +err_unpin: + __i915_vma_unpin(vma); + +err_unref: + i915_gem_object_put(bo); + + dev_priv->perf.oa.oa_buffer.vaddr = NULL; + dev_priv->perf.oa.oa_buffer.vma = NULL; + +unlock: + mutex_unlock(&dev_priv->drm.struct_mutex); + return ret; +} + +static void config_oa_regs(struct drm_i915_private *dev_priv, + const struct i915_oa_reg *regs, + int n_regs) +{ + int i; + + for (i = 0; i < n_regs; i++) { + const struct i915_oa_reg *reg = regs + i; + + I915_WRITE(reg->addr, reg->value); + } +} + +static int hsw_enable_metric_set(struct drm_i915_private *dev_priv) +{ + int ret = i915_oa_select_metric_set_hsw(dev_priv); + + if (ret) + return ret; + + I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) | + GT_NOA_ENABLE)); + + /* PRM: + * + * OA unit is using “crclk” for its functionality. When trunk + * level clock gating takes place, OA clock would be gated, + * unable to count the events from non-render clock domain. + * Render clock gating must be disabled when OA is enabled to + * count the events from non-render domain. Unit level clock + * gating for RCS should also be disabled. + */ + I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & + ~GEN7_DOP_CLOCK_GATE_ENABLE)); + I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) | + GEN6_CSUNIT_CLOCK_GATE_DISABLE)); + + config_oa_regs(dev_priv, dev_priv->perf.oa.mux_regs, + dev_priv->perf.oa.mux_regs_len); + + /* It apparently takes a fairly long time for a new MUX + * configuration to be be applied after these register writes. + * This delay duration was derived empirically based on the + * render_basic config but hopefully it covers the maximum + * configuration latency. + * + * As a fallback, the checks in _append_oa_reports() to skip + * invalid OA reports do also seem to work to discard reports + * generated before this config has completed - albeit not + * silently. + * + * Unfortunately this is essentially a magic number, since we + * don't currently know of a reliable mechanism for predicting + * how long the MUX config will take to apply and besides + * seeing invalid reports we don't know of a reliable way to + * explicitly check that the MUX config has landed. + * + * It's even possible we've miss characterized the underlying + * problem - it just seems like the simplest explanation why + * a delay at this location would mitigate any invalid reports. + */ + usleep_range(15000, 20000); + + config_oa_regs(dev_priv, dev_priv->perf.oa.b_counter_regs, + dev_priv->perf.oa.b_counter_regs_len); + + return 0; +} + +static void hsw_disable_metric_set(struct drm_i915_private *dev_priv) +{ + I915_WRITE(GEN6_UCGCTL1, (I915_READ(GEN6_UCGCTL1) & + ~GEN6_CSUNIT_CLOCK_GATE_DISABLE)); + I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) | + GEN7_DOP_CLOCK_GATE_ENABLE)); + + I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & + ~GT_NOA_ENABLE)); +} + +static void gen7_update_oacontrol_locked(struct drm_i915_private *dev_priv) +{ + assert_spin_locked(&dev_priv->perf.hook_lock); + + if (dev_priv->perf.oa.exclusive_stream->enabled) { + struct i915_gem_context *ctx = + dev_priv->perf.oa.exclusive_stream->ctx; + u32 ctx_id = dev_priv->perf.oa.specific_ctx_id; + + bool periodic = dev_priv->perf.oa.periodic; + u32 period_exponent = dev_priv->perf.oa.period_exponent; + u32 report_format = dev_priv->perf.oa.oa_buffer.format; + + I915_WRITE(GEN7_OACONTROL, + (ctx_id & GEN7_OACONTROL_CTX_MASK) | + (period_exponent << + GEN7_OACONTROL_TIMER_PERIOD_SHIFT) | + (periodic ? GEN7_OACONTROL_TIMER_ENABLE : 0) | + (report_format << GEN7_OACONTROL_FORMAT_SHIFT) | + (ctx ? GEN7_OACONTROL_PER_CTX_ENABLE : 0) | + GEN7_OACONTROL_ENABLE); + } else + I915_WRITE(GEN7_OACONTROL, 0); +} + +static void gen7_oa_enable(struct drm_i915_private *dev_priv) +{ + unsigned long flags; + + /* Reset buf pointers so we don't forward reports from before now. + * + * Think carefully if considering trying to avoid this, since it + * also ensures status flags and the buffer itself are cleared + * in error paths, and we have checks for invalid reports based + * on the assumption that certain fields are written to zeroed + * memory which this helps maintains. + */ + gen7_init_oa_buffer(dev_priv); + + spin_lock_irqsave(&dev_priv->perf.hook_lock, flags); + gen7_update_oacontrol_locked(dev_priv); + spin_unlock_irqrestore(&dev_priv->perf.hook_lock, flags); +} + +static void i915_oa_stream_enable(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + dev_priv->perf.oa.ops.oa_enable(dev_priv); + + if (dev_priv->perf.oa.periodic) + hrtimer_start(&dev_priv->perf.oa.poll_check_timer, + ns_to_ktime(POLL_PERIOD), + HRTIMER_MODE_REL_PINNED); +} + +static void gen7_oa_disable(struct drm_i915_private *dev_priv) +{ + I915_WRITE(GEN7_OACONTROL, 0); +} + +static void i915_oa_stream_disable(struct i915_perf_stream *stream) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + + dev_priv->perf.oa.ops.oa_disable(dev_priv); + + if (dev_priv->perf.oa.periodic) + hrtimer_cancel(&dev_priv->perf.oa.poll_check_timer); +} + +static u64 oa_exponent_to_ns(struct drm_i915_private *dev_priv, int exponent) +{ + return 1000000000ULL * (2ULL << exponent) / + dev_priv->perf.oa.timestamp_frequency; +} + +static const struct i915_perf_stream_ops i915_oa_stream_ops = { + .destroy = i915_oa_stream_destroy, + .enable = i915_oa_stream_enable, + .disable = i915_oa_stream_disable, + .wait_unlocked = i915_oa_wait_unlocked, + .poll_wait = i915_oa_poll_wait, + .read = i915_oa_read, }; +static int i915_oa_stream_init(struct i915_perf_stream *stream, + struct drm_i915_perf_open_param *param, + struct perf_open_properties *props) +{ + struct drm_i915_private *dev_priv = stream->dev_priv; + int format_size; + int ret; + + if (!(props->sample_flags & SAMPLE_OA_REPORT)) { + DRM_ERROR("Only OA report sampling supported\n"); + return -EINVAL; + } + + if (!dev_priv->perf.oa.ops.init_oa_buffer) { + DRM_ERROR("OA unit not supported\n"); + return -ENODEV; + } + + /* To avoid the complexity of having to accurately filter + * counter reports and marshal to the appropriate client + * we currently only allow exclusive access + */ + if (dev_priv->perf.oa.exclusive_stream) { + DRM_ERROR("OA unit already in use\n"); + return -EBUSY; + } + + if (!props->metrics_set) { + DRM_ERROR("OA metric set not specified\n"); + return -EINVAL; + } + + if (!props->oa_format) { + DRM_ERROR("OA report format not specified\n"); + return -EINVAL; + } + + stream->sample_size = sizeof(struct drm_i915_perf_record_header); + + format_size = dev_priv->perf.oa.oa_formats[props->oa_format].size; + + stream->sample_flags |= SAMPLE_OA_REPORT; + stream->sample_size += format_size; + + dev_priv->perf.oa.oa_buffer.format_size = format_size; + if (WARN_ON(dev_priv->perf.oa.oa_buffer.format_size == 0)) + return -EINVAL; + + dev_priv->perf.oa.oa_buffer.format = + dev_priv->perf.oa.oa_formats[props->oa_format].format; + + dev_priv->perf.oa.metrics_set = props->metrics_set; + + dev_priv->perf.oa.periodic = props->oa_periodic; + if (dev_priv->perf.oa.periodic) { + u64 period_ns = oa_exponent_to_ns(dev_priv, + props->oa_period_exponent); + + dev_priv->perf.oa.period_exponent = props->oa_period_exponent; + + /* See comment for OA_TAIL_MARGIN_NSEC for details + * about this tail_margin... + */ + dev_priv->perf.oa.tail_margin = + ((OA_TAIL_MARGIN_NSEC / period_ns) + 1) * format_size; + } + + if (stream->ctx) { + ret = oa_get_render_ctx_id(stream); + if (ret) + return ret; + } + + ret = alloc_oa_buffer(dev_priv); + if (ret) + goto err_oa_buf_alloc; + + /* PRM - observability performance counters: + * + * OACONTROL, performance counter enable, note: + * + * "When this bit is set, in order to have coherent counts, + * RC6 power state and trunk clock gating must be disabled. + * This can be achieved by programming MMIO registers as + * 0xA094=0 and 0xA090[31]=1" + * + * In our case we are expecting that taking pm + FORCEWAKE + * references will effectively disable RC6. + */ + intel_runtime_pm_get(dev_priv); + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv); + if (ret) + goto err_enable; + + stream->ops = &i915_oa_stream_ops; + + dev_priv->perf.oa.exclusive_stream = stream; + + return 0; + +err_enable: + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_put(dev_priv); + free_oa_buffer(dev_priv); + +err_oa_buf_alloc: + if (stream->ctx) + oa_put_render_ctx_id(stream); + + return ret; +} + static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream, struct file *file, char __user *buf, @@ -78,8 +961,20 @@ static ssize_t i915_perf_read(struct file *file, struct drm_i915_private *dev_priv = stream->dev_priv; ssize_t ret; + /* To ensure it's handled consistently we simply treat all reads of a + * disabled stream as an error. In particular it might otherwise lead + * to a deadlock for blocking file descriptors... + */ + if (!stream->enabled) + return -EIO; + if (!(file->f_flags & O_NONBLOCK)) { - /* Allow false positives from stream->ops->wait_unlocked. + /* There's the small chance of false positives from + * stream->ops->wait_unlocked. + * + * E.g. with single context filtering since we only wait until + * oabuffer has >= 1 report we don't immediately know whether + * any reports really belong to the current context */ do { ret = stream->ops->wait_unlocked(stream); @@ -97,21 +992,51 @@ static ssize_t i915_perf_read(struct file *file, mutex_unlock(&dev_priv->perf.lock); } + if (ret >= 0) { + /* Maybe make ->pollin per-stream state if we support multiple + * concurrent streams in the future. + */ + dev_priv->perf.oa.pollin = false; + } + return ret; } -static unsigned int i915_perf_poll_locked(struct i915_perf_stream *stream, +static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer) +{ + struct drm_i915_private *dev_priv = + container_of(hrtimer, typeof(*dev_priv), + perf.oa.poll_check_timer); + + if (!dev_priv->perf.oa.ops.oa_buffer_is_empty(dev_priv)) { + dev_priv->perf.oa.pollin = true; + wake_up(&dev_priv->perf.oa.poll_wq); + } + + hrtimer_forward_now(hrtimer, ns_to_ktime(POLL_PERIOD)); + + return HRTIMER_RESTART; +} + +static unsigned int i915_perf_poll_locked(struct drm_i915_private *dev_priv, + struct i915_perf_stream *stream, struct file *file, poll_table *wait) { - unsigned int streams = 0; + unsigned int events = 0; stream->ops->poll_wait(stream, file, wait); - if (stream->ops->can_read(stream)) - streams |= POLLIN; + /* Note: we don't explicitly check whether there's something to read + * here since this path may be very hot depending on what else + * userspace is polling, or on the timeout in use. We rely solely on + * the hrtimer/oa_poll_check_timer_cb to notify us when there are + * samples to read. + */ + if (dev_priv->perf.oa.pollin) + events |= POLLIN; - return streams; + return events; } static unsigned int i915_perf_poll(struct file *file, poll_table *wait) @@ -121,7 +1046,7 @@ static unsigned int i915_perf_poll(struct file *file, poll_table *wait) int ret; mutex_lock(&dev_priv->perf.lock); - ret = i915_perf_poll_locked(stream, file, wait); + ret = i915_perf_poll_locked(dev_priv, stream, file, wait); mutex_unlock(&dev_priv->perf.lock); return ret; @@ -285,18 +1210,21 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv, goto err_ctx; } - stream->sample_flags = props->sample_flags; stream->dev_priv = dev_priv; stream->ctx = specific_ctx; - /* - * TODO: support sampling something - * - * For now this is as far as we can go. + ret = i915_oa_stream_init(stream, param, props); + if (ret) + goto err_alloc; + + /* we avoid simply assigning stream->sample_flags = props->sample_flags + * to have _stream_init check the combination of sample flags more + * thoroughly, but still this is the expected result at this point. */ - DRM_ERROR("Unsupported i915 perf stream configuration\n"); - ret = -EINVAL; - goto err_alloc; + if (WARN_ON(stream->sample_flags != props->sample_flags)) { + ret = -ENODEV; + goto err_alloc; + } list_add(&stream->link, &dev_priv->perf.streams); @@ -382,6 +1310,56 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv, props->single_context = 1; props->ctx_handle = value; break; + case DRM_I915_PERF_PROP_SAMPLE_OA: + props->sample_flags |= SAMPLE_OA_REPORT; + break; + case DRM_I915_PERF_PROP_OA_METRICS_SET: + if (value == 0 || + value > dev_priv->perf.oa.n_builtin_sets) { + DRM_ERROR("Unknown OA metric set ID"); + return -EINVAL; + } + props->metrics_set = value; + break; + case DRM_I915_PERF_PROP_OA_FORMAT: + if (value == 0 || value >= I915_OA_FORMAT_MAX) { + DRM_ERROR("Invalid OA report format\n"); + return -EINVAL; + } + if (!dev_priv->perf.oa.oa_formats[value].size) { + DRM_ERROR("Invalid OA report format\n"); + return -EINVAL; + } + props->oa_format = value; + break; + case DRM_I915_PERF_PROP_OA_EXPONENT: + if (value > OA_EXPONENT_MAX) { + DRM_ERROR("OA timer exponent too high (> %u)\n", + OA_EXPONENT_MAX); + return -EINVAL; + } + + /* NB: The exponent represents a period as follows: + * + * 80ns * 2^(period_exponent + 1) + * + * Theoretically we can program the OA unit to sample + * every 160ns but don't allow that by default unless + * root. + * + * Referring to perf's + * kernel.perf_event_max_sample_rate for a precedent + * (100000 by default); with an OA exponent of 6 we get + * a period of 10.240 microseconds -just under 100000Hz + */ + if (value < 6 && !capable(CAP_SYS_ADMIN)) { + DRM_ERROR("Minimum OA sampling exponent is 6 without root privileges\n"); + return -EACCES; + } + + props->oa_periodic = true; + props->oa_period_exponent = value; + break; default: MISSING_CASE(id); DRM_ERROR("Unknown i915 perf property ID"); @@ -432,8 +1410,33 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, void i915_perf_init(struct drm_i915_private *dev_priv) { + if (!IS_HASWELL(dev_priv)) + return; + + hrtimer_init(&dev_priv->perf.oa.poll_check_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + dev_priv->perf.oa.poll_check_timer.function = oa_poll_check_timer_cb; + init_waitqueue_head(&dev_priv->perf.oa.poll_wq); + INIT_LIST_HEAD(&dev_priv->perf.streams); mutex_init(&dev_priv->perf.lock); + spin_lock_init(&dev_priv->perf.hook_lock); + + dev_priv->perf.oa.ops.init_oa_buffer = gen7_init_oa_buffer; + dev_priv->perf.oa.ops.enable_metric_set = hsw_enable_metric_set; + dev_priv->perf.oa.ops.disable_metric_set = hsw_disable_metric_set; + dev_priv->perf.oa.ops.oa_enable = gen7_oa_enable; + dev_priv->perf.oa.ops.oa_disable = gen7_oa_disable; + dev_priv->perf.oa.ops.read = gen7_oa_read; + dev_priv->perf.oa.ops.oa_buffer_is_empty = + gen7_oa_buffer_is_empty_fop_unlocked; + + dev_priv->perf.oa.timestamp_frequency = 12500000; + + dev_priv->perf.oa.oa_formats = hsw_oa_formats; + + dev_priv->perf.oa.n_builtin_sets = + i915_oa_n_builtin_metric_sets_hsw; dev_priv->perf.initialized = true; } @@ -443,7 +1446,6 @@ void i915_perf_fini(struct drm_i915_private *dev_priv) if (!dev_priv->perf.initialized) return; - /* Currently nothing to clean up */ - + memset(&dev_priv->perf.oa.ops, 0, sizeof(dev_priv->perf.oa.ops)); dev_priv->perf.initialized = false; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ee8707343ae4..fcad8fa41274 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -616,6 +616,343 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define HSW_CS_GPR_UDW(n) _MMIO(0x2600 + (n) * 8 + 4) #define GEN7_OACONTROL _MMIO(0x2360) +#define GEN7_OACONTROL_CTX_MASK 0xFFFFF000 +#define GEN7_OACONTROL_TIMER_PERIOD_MASK 0x3F +#define GEN7_OACONTROL_TIMER_PERIOD_SHIFT 6 +#define GEN7_OACONTROL_TIMER_ENABLE (1<<5) +#define GEN7_OACONTROL_FORMAT_A13 (0<<2) +#define GEN7_OACONTROL_FORMAT_A29 (1<<2) +#define GEN7_OACONTROL_FORMAT_A13_B8_C8 (2<<2) +#define GEN7_OACONTROL_FORMAT_A29_B8_C8 (3<<2) +#define GEN7_OACONTROL_FORMAT_B4_C8 (4<<2) +#define GEN7_OACONTROL_FORMAT_A45_B8_C8 (5<<2) +#define GEN7_OACONTROL_FORMAT_B4_C8_A16 (6<<2) +#define GEN7_OACONTROL_FORMAT_C4_B8 (7<<2) +#define GEN7_OACONTROL_FORMAT_SHIFT 2 +#define GEN7_OACONTROL_PER_CTX_ENABLE (1<<1) +#define GEN7_OACONTROL_ENABLE (1<<0) + +#define GEN8_OACTXID _MMIO(0x2364) + +#define GEN8_OACONTROL _MMIO(0x2B00) +#define GEN8_OA_REPORT_FORMAT_A12 (0<<2) +#define GEN8_OA_REPORT_FORMAT_A12_B8_C8 (2<<2) +#define GEN8_OA_REPORT_FORMAT_A36_B8_C8 (5<<2) +#define GEN8_OA_REPORT_FORMAT_C4_B8 (7<<2) +#define GEN8_OA_REPORT_FORMAT_SHIFT 2 +#define GEN8_OA_SPECIFIC_CONTEXT_ENABLE (1<<1) +#define GEN8_OA_COUNTER_ENABLE (1<<0) + +#define GEN8_OACTXCONTROL _MMIO(0x2360) +#define GEN8_OA_TIMER_PERIOD_MASK 0x3F +#define GEN8_OA_TIMER_PERIOD_SHIFT 2 +#define GEN8_OA_TIMER_ENABLE (1<<1) +#define GEN8_OA_COUNTER_RESUME (1<<0) + +#define GEN7_OABUFFER _MMIO(0x23B0) /* R/W */ +#define GEN7_OABUFFER_OVERRUN_DISABLE (1<<3) +#define GEN7_OABUFFER_EDGE_TRIGGER (1<<2) +#define GEN7_OABUFFER_STOP_RESUME_ENABLE (1<<1) +#define GEN7_OABUFFER_RESUME (1<<0) + +#define GEN8_OABUFFER _MMIO(0x2b14) + +#define GEN7_OASTATUS1 _MMIO(0x2364) +#define GEN7_OASTATUS1_TAIL_MASK 0xffffffc0 +#define GEN7_OASTATUS1_COUNTER_OVERFLOW (1<<2) +#define GEN7_OASTATUS1_OABUFFER_OVERFLOW (1<<1) +#define GEN7_OASTATUS1_REPORT_LOST (1<<0) + +#define GEN7_OASTATUS2 _MMIO(0x2368) +#define GEN7_OASTATUS2_HEAD_MASK 0xffffffc0 + +#define GEN8_OASTATUS _MMIO(0x2b08) +#define GEN8_OASTATUS_OVERRUN_STATUS (1<<3) +#define GEN8_OASTATUS_COUNTER_OVERFLOW (1<<2) +#define GEN8_OASTATUS_OABUFFER_OVERFLOW (1<<1) +#define GEN8_OASTATUS_REPORT_LOST (1<<0) + +#define GEN8_OAHEADPTR _MMIO(0x2B0C) +#define GEN8_OATAILPTR _MMIO(0x2B10) + +#define OABUFFER_SIZE_128K (0<<3) +#define OABUFFER_SIZE_256K (1<<3) +#define OABUFFER_SIZE_512K (2<<3) +#define OABUFFER_SIZE_1M (3<<3) +#define OABUFFER_SIZE_2M (4<<3) +#define OABUFFER_SIZE_4M (5<<3) +#define OABUFFER_SIZE_8M (6<<3) +#define OABUFFER_SIZE_16M (7<<3) + +#define OA_MEM_SELECT_GGTT (1<<0) + +#define EU_PERF_CNTL0 _MMIO(0xe458) + +#define GDT_CHICKEN_BITS _MMIO(0x9840) +#define GT_NOA_ENABLE 0x00000080 + +/* + * OA Boolean state + */ + +#define OAREPORTTRIG1 _MMIO(0x2740) +#define OAREPORTTRIG1_THRESHOLD_MASK 0xffff +#define OAREPORTTRIG1_EDGE_LEVEL_TRIGER_SELECT_MASK 0xffff0000 /* 0=level */ + +#define OAREPORTTRIG2 _MMIO(0x2744) +#define OAREPORTTRIG2_INVERT_A_0 (1<<0) +#define OAREPORTTRIG2_INVERT_A_1 (1<<1) +#define OAREPORTTRIG2_INVERT_A_2 (1<<2) +#define OAREPORTTRIG2_INVERT_A_3 (1<<3) +#define OAREPORTTRIG2_INVERT_A_4 (1<<4) +#define OAREPORTTRIG2_INVERT_A_5 (1<<5) +#define OAREPORTTRIG2_INVERT_A_6 (1<<6) +#define OAREPORTTRIG2_INVERT_A_7 (1<<7) +#define OAREPORTTRIG2_INVERT_A_8 (1<<8) +#define OAREPORTTRIG2_INVERT_A_9 (1<<9) +#define OAREPORTTRIG2_INVERT_A_10 (1<<10) +#define OAREPORTTRIG2_INVERT_A_11 (1<<11) +#define OAREPORTTRIG2_INVERT_A_12 (1<<12) +#define OAREPORTTRIG2_INVERT_A_13 (1<<13) +#define OAREPORTTRIG2_INVERT_A_14 (1<<14) +#define OAREPORTTRIG2_INVERT_A_15 (1<<15) +#define OAREPORTTRIG2_INVERT_B_0 (1<<16) +#define OAREPORTTRIG2_INVERT_B_1 (1<<17) +#define OAREPORTTRIG2_INVERT_B_2 (1<<18) +#define OAREPORTTRIG2_INVERT_B_3 (1<<19) +#define OAREPORTTRIG2_INVERT_C_0 (1<<20) +#define OAREPORTTRIG2_INVERT_C_1 (1<<21) +#define OAREPORTTRIG2_INVERT_D_0 (1<<22) +#define OAREPORTTRIG2_THRESHOLD_ENABLE (1<<23) +#define OAREPORTTRIG2_REPORT_TRIGGER_ENABLE (1<<31) + +#define OAREPORTTRIG3 _MMIO(0x2748) +#define OAREPORTTRIG3_NOA_SELECT_MASK 0xf +#define OAREPORTTRIG3_NOA_SELECT_8_SHIFT 0 +#define OAREPORTTRIG3_NOA_SELECT_9_SHIFT 4 +#define OAREPORTTRIG3_NOA_SELECT_10_SHIFT 8 +#define OAREPORTTRIG3_NOA_SELECT_11_SHIFT 12 +#define OAREPORTTRIG3_NOA_SELECT_12_SHIFT 16 +#define OAREPORTTRIG3_NOA_SELECT_13_SHIFT 20 +#define OAREPORTTRIG3_NOA_SELECT_14_SHIFT 24 +#define OAREPORTTRIG3_NOA_SELECT_15_SHIFT 28 + +#define OAREPORTTRIG4 _MMIO(0x274c) +#define OAREPORTTRIG4_NOA_SELECT_MASK 0xf +#define OAREPORTTRIG4_NOA_SELECT_0_SHIFT 0 +#define OAREPORTTRIG4_NOA_SELECT_1_SHIFT 4 +#define OAREPORTTRIG4_NOA_SELECT_2_SHIFT 8 +#define OAREPORTTRIG4_NOA_SELECT_3_SHIFT 12 +#define OAREPORTTRIG4_NOA_SELECT_4_SHIFT 16 +#define OAREPORTTRIG4_NOA_SELECT_5_SHIFT 20 +#define OAREPORTTRIG4_NOA_SELECT_6_SHIFT 24 +#define OAREPORTTRIG4_NOA_SELECT_7_SHIFT 28 + +#define OAREPORTTRIG5 _MMIO(0x2750) +#define OAREPORTTRIG5_THRESHOLD_MASK 0xffff +#define OAREPORTTRIG5_EDGE_LEVEL_TRIGER_SELECT_MASK 0xffff0000 /* 0=level */ + +#define OAREPORTTRIG6 _MMIO(0x2754) +#define OAREPORTTRIG6_INVERT_A_0 (1<<0) +#define OAREPORTTRIG6_INVERT_A_1 (1<<1) +#define OAREPORTTRIG6_INVERT_A_2 (1<<2) +#define OAREPORTTRIG6_INVERT_A_3 (1<<3) +#define OAREPORTTRIG6_INVERT_A_4 (1<<4) +#define OAREPORTTRIG6_INVERT_A_5 (1<<5) +#define OAREPORTTRIG6_INVERT_A_6 (1<<6) +#define OAREPORTTRIG6_INVERT_A_7 (1<<7) +#define OAREPORTTRIG6_INVERT_A_8 (1<<8) +#define OAREPORTTRIG6_INVERT_A_9 (1<<9) +#define OAREPORTTRIG6_INVERT_A_10 (1<<10) +#define OAREPORTTRIG6_INVERT_A_11 (1<<11) +#define OAREPORTTRIG6_INVERT_A_12 (1<<12) +#define OAREPORTTRIG6_INVERT_A_13 (1<<13) +#define OAREPORTTRIG6_INVERT_A_14 (1<<14) +#define OAREPORTTRIG6_INVERT_A_15 (1<<15) +#define OAREPORTTRIG6_INVERT_B_0 (1<<16) +#define OAREPORTTRIG6_INVERT_B_1 (1<<17) +#define OAREPORTTRIG6_INVERT_B_2 (1<<18) +#define OAREPORTTRIG6_INVERT_B_3 (1<<19) +#define OAREPORTTRIG6_INVERT_C_0 (1<<20) +#define OAREPORTTRIG6_INVERT_C_1 (1<<21) +#define OAREPORTTRIG6_INVERT_D_0 (1<<22) +#define OAREPORTTRIG6_THRESHOLD_ENABLE (1<<23) +#define OAREPORTTRIG6_REPORT_TRIGGER_ENABLE (1<<31) + +#define OAREPORTTRIG7 _MMIO(0x2758) +#define OAREPORTTRIG7_NOA_SELECT_MASK 0xf +#define OAREPORTTRIG7_NOA_SELECT_8_SHIFT 0 +#define OAREPORTTRIG7_NOA_SELECT_9_SHIFT 4 +#define OAREPORTTRIG7_NOA_SELECT_10_SHIFT 8 +#define OAREPORTTRIG7_NOA_SELECT_11_SHIFT 12 +#define OAREPORTTRIG7_NOA_SELECT_12_SHIFT 16 +#define OAREPORTTRIG7_NOA_SELECT_13_SHIFT 20 +#define OAREPORTTRIG7_NOA_SELECT_14_SHIFT 24 +#define OAREPORTTRIG7_NOA_SELECT_15_SHIFT 28 + +#define OAREPORTTRIG8 _MMIO(0x275c) +#define OAREPORTTRIG8_NOA_SELECT_MASK 0xf +#define OAREPORTTRIG8_NOA_SELECT_0_SHIFT 0 +#define OAREPORTTRIG8_NOA_SELECT_1_SHIFT 4 +#define OAREPORTTRIG8_NOA_SELECT_2_SHIFT 8 +#define OAREPORTTRIG8_NOA_SELECT_3_SHIFT 12 +#define OAREPORTTRIG8_NOA_SELECT_4_SHIFT 16 +#define OAREPORTTRIG8_NOA_SELECT_5_SHIFT 20 +#define OAREPORTTRIG8_NOA_SELECT_6_SHIFT 24 +#define OAREPORTTRIG8_NOA_SELECT_7_SHIFT 28 + +#define OASTARTTRIG1 _MMIO(0x2710) +#define OASTARTTRIG1_THRESHOLD_COUNT_MASK_MBZ 0xffff0000 +#define OASTARTTRIG1_THRESHOLD_MASK 0xffff + +#define OASTARTTRIG2 _MMIO(0x2714) +#define OASTARTTRIG2_INVERT_A_0 (1<<0) +#define OASTARTTRIG2_INVERT_A_1 (1<<1) +#define OASTARTTRIG2_INVERT_A_2 (1<<2) +#define OASTARTTRIG2_INVERT_A_3 (1<<3) +#define OASTARTTRIG2_INVERT_A_4 (1<<4) +#define OASTARTTRIG2_INVERT_A_5 (1<<5) +#define OASTARTTRIG2_INVERT_A_6 (1<<6) +#define OASTARTTRIG2_INVERT_A_7 (1<<7) +#define OASTARTTRIG2_INVERT_A_8 (1<<8) +#define OASTARTTRIG2_INVERT_A_9 (1<<9) +#define OASTARTTRIG2_INVERT_A_10 (1<<10) +#define OASTARTTRIG2_INVERT_A_11 (1<<11) +#define OASTARTTRIG2_INVERT_A_12 (1<<12) +#define OASTARTTRIG2_INVERT_A_13 (1<<13) +#define OASTARTTRIG2_INVERT_A_14 (1<<14) +#define OASTARTTRIG2_INVERT_A_15 (1<<15) +#define OASTARTTRIG2_INVERT_B_0 (1<<16) +#define OASTARTTRIG2_INVERT_B_1 (1<<17) +#define OASTARTTRIG2_INVERT_B_2 (1<<18) +#define OASTARTTRIG2_INVERT_B_3 (1<<19) +#define OASTARTTRIG2_INVERT_C_0 (1<<20) +#define OASTARTTRIG2_INVERT_C_1 (1<<21) +#define OASTARTTRIG2_INVERT_D_0 (1<<22) +#define OASTARTTRIG2_THRESHOLD_ENABLE (1<<23) +#define OASTARTTRIG2_START_TRIG_FLAG_MBZ (1<<24) +#define OASTARTTRIG2_EVENT_SELECT_0 (1<<28) +#define OASTARTTRIG2_EVENT_SELECT_1 (1<<29) +#define OASTARTTRIG2_EVENT_SELECT_2 (1<<30) +#define OASTARTTRIG2_EVENT_SELECT_3 (1<<31) + +#define OASTARTTRIG3 _MMIO(0x2718) +#define OASTARTTRIG3_NOA_SELECT_MASK 0xf +#define OASTARTTRIG3_NOA_SELECT_8_SHIFT 0 +#define OASTARTTRIG3_NOA_SELECT_9_SHIFT 4 +#define OASTARTTRIG3_NOA_SELECT_10_SHIFT 8 +#define OASTARTTRIG3_NOA_SELECT_11_SHIFT 12 +#define OASTARTTRIG3_NOA_SELECT_12_SHIFT 16 +#define OASTARTTRIG3_NOA_SELECT_13_SHIFT 20 +#define OASTARTTRIG3_NOA_SELECT_14_SHIFT 24 +#define OASTARTTRIG3_NOA_SELECT_15_SHIFT 28 + +#define OASTARTTRIG4 _MMIO(0x271c) +#define OASTARTTRIG4_NOA_SELECT_MASK 0xf +#define OASTARTTRIG4_NOA_SELECT_0_SHIFT 0 +#define OASTARTTRIG4_NOA_SELECT_1_SHIFT 4 +#define OASTARTTRIG4_NOA_SELECT_2_SHIFT 8 +#define OASTARTTRIG4_NOA_SELECT_3_SHIFT 12 +#define OASTARTTRIG4_NOA_SELECT_4_SHIFT 16 +#define OASTARTTRIG4_NOA_SELECT_5_SHIFT 20 +#define OASTARTTRIG4_NOA_SELECT_6_SHIFT 24 +#define OASTARTTRIG4_NOA_SELECT_7_SHIFT 28 + +#define OASTARTTRIG5 _MMIO(0x2720) +#define OASTARTTRIG5_THRESHOLD_COUNT_MASK_MBZ 0xffff0000 +#define OASTARTTRIG5_THRESHOLD_MASK 0xffff + +#define OASTARTTRIG6 _MMIO(0x2724) +#define OASTARTTRIG6_INVERT_A_0 (1<<0) +#define OASTARTTRIG6_INVERT_A_1 (1<<1) +#define OASTARTTRIG6_INVERT_A_2 (1<<2) +#define OASTARTTRIG6_INVERT_A_3 (1<<3) +#define OASTARTTRIG6_INVERT_A_4 (1<<4) +#define OASTARTTRIG6_INVERT_A_5 (1<<5) +#define OASTARTTRIG6_INVERT_A_6 (1<<6) +#define OASTARTTRIG6_INVERT_A_7 (1<<7) +#define OASTARTTRIG6_INVERT_A_8 (1<<8) +#define OASTARTTRIG6_INVERT_A_9 (1<<9) +#define OASTARTTRIG6_INVERT_A_10 (1<<10) +#define OASTARTTRIG6_INVERT_A_11 (1<<11) +#define OASTARTTRIG6_INVERT_A_12 (1<<12) +#define OASTARTTRIG6_INVERT_A_13 (1<<13) +#define OASTARTTRIG6_INVERT_A_14 (1<<14) +#define OASTARTTRIG6_INVERT_A_15 (1<<15) +#define OASTARTTRIG6_INVERT_B_0 (1<<16) +#define OASTARTTRIG6_INVERT_B_1 (1<<17) +#define OASTARTTRIG6_INVERT_B_2 (1<<18) +#define OASTARTTRIG6_INVERT_B_3 (1<<19) +#define OASTARTTRIG6_INVERT_C_0 (1<<20) +#define OASTARTTRIG6_INVERT_C_1 (1<<21) +#define OASTARTTRIG6_INVERT_D_0 (1<<22) +#define OASTARTTRIG6_THRESHOLD_ENABLE (1<<23) +#define OASTARTTRIG6_START_TRIG_FLAG_MBZ (1<<24) +#define OASTARTTRIG6_EVENT_SELECT_4 (1<<28) +#define OASTARTTRIG6_EVENT_SELECT_5 (1<<29) +#define OASTARTTRIG6_EVENT_SELECT_6 (1<<30) +#define OASTARTTRIG6_EVENT_SELECT_7 (1<<31) + +#define OASTARTTRIG7 _MMIO(0x2728) +#define OASTARTTRIG7_NOA_SELECT_MASK 0xf +#define OASTARTTRIG7_NOA_SELECT_8_SHIFT 0 +#define OASTARTTRIG7_NOA_SELECT_9_SHIFT 4 +#define OASTARTTRIG7_NOA_SELECT_10_SHIFT 8 +#define OASTARTTRIG7_NOA_SELECT_11_SHIFT 12 +#define OASTARTTRIG7_NOA_SELECT_12_SHIFT 16 +#define OASTARTTRIG7_NOA_SELECT_13_SHIFT 20 +#define OASTARTTRIG7_NOA_SELECT_14_SHIFT 24 +#define OASTARTTRIG7_NOA_SELECT_15_SHIFT 28 + +#define OASTARTTRIG8 _MMIO(0x272c) +#define OASTARTTRIG8_NOA_SELECT_MASK 0xf +#define OASTARTTRIG8_NOA_SELECT_0_SHIFT 0 +#define OASTARTTRIG8_NOA_SELECT_1_SHIFT 4 +#define OASTARTTRIG8_NOA_SELECT_2_SHIFT 8 +#define OASTARTTRIG8_NOA_SELECT_3_SHIFT 12 +#define OASTARTTRIG8_NOA_SELECT_4_SHIFT 16 +#define OASTARTTRIG8_NOA_SELECT_5_SHIFT 20 +#define OASTARTTRIG8_NOA_SELECT_6_SHIFT 24 +#define OASTARTTRIG8_NOA_SELECT_7_SHIFT 28 + +/* CECX_0 */ +#define OACEC_COMPARE_LESS_OR_EQUAL 6 +#define OACEC_COMPARE_NOT_EQUAL 5 +#define OACEC_COMPARE_LESS_THAN 4 +#define OACEC_COMPARE_GREATER_OR_EQUAL 3 +#define OACEC_COMPARE_EQUAL 2 +#define OACEC_COMPARE_GREATER_THAN 1 +#define OACEC_COMPARE_ANY_EQUAL 0 + +#define OACEC_COMPARE_VALUE_MASK 0xffff +#define OACEC_COMPARE_VALUE_SHIFT 3 + +#define OACEC_SELECT_NOA (0<<19) +#define OACEC_SELECT_PREV (1<<19) +#define OACEC_SELECT_BOOLEAN (2<<19) + +/* CECX_1 */ +#define OACEC_MASK_MASK 0xffff +#define OACEC_CONSIDERATIONS_MASK 0xffff +#define OACEC_CONSIDERATIONS_SHIFT 16 + +#define OACEC0_0 _MMIO(0x2770) +#define OACEC0_1 _MMIO(0x2774) +#define OACEC1_0 _MMIO(0x2778) +#define OACEC1_1 _MMIO(0x277c) +#define OACEC2_0 _MMIO(0x2780) +#define OACEC2_1 _MMIO(0x2784) +#define OACEC3_0 _MMIO(0x2788) +#define OACEC3_1 _MMIO(0x278c) +#define OACEC4_0 _MMIO(0x2790) +#define OACEC4_1 _MMIO(0x2794) +#define OACEC5_0 _MMIO(0x2798) +#define OACEC5_1 _MMIO(0x279c) +#define OACEC6_0 _MMIO(0x27a0) +#define OACEC6_1 _MMIO(0x27a4) +#define OACEC7_0 _MMIO(0x27a8) +#define OACEC7_1 _MMIO(0x27ac) + #define _GEN7_PIPEA_DE_LOAD_SL 0x70068 #define _GEN7_PIPEB_DE_LOAD_SL 0x71068 @@ -6914,6 +7251,7 @@ enum { # define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11) #define GEN6_UCGCTL3 _MMIO(0x9408) +# define GEN6_OACSUNIT_CLOCK_GATE_DISABLE (1 << 20) #define GEN7_UCGCTL4 _MMIO(0x940c) #define GEN7_L3BANK2X_CLOCK_GATE_DISABLE (1<<25) diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 192dc1f8256b..bdfc68876990 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1230,6 +1230,18 @@ struct drm_i915_gem_context_param { __u64 value; }; +enum drm_i915_oa_format { + I915_OA_FORMAT_A13 = 1, + I915_OA_FORMAT_A29, + I915_OA_FORMAT_A13_B8_C8, + I915_OA_FORMAT_B4_C8, + I915_OA_FORMAT_A45_B8_C8, + I915_OA_FORMAT_B4_C8_A16, + I915_OA_FORMAT_C4_B8, + + I915_OA_FORMAT_MAX /* non-ABI */ +}; + enum drm_i915_perf_property_id { /** * Open the stream for a specific context handle (as used with @@ -1238,6 +1250,32 @@ enum drm_i915_perf_property_id { */ DRM_I915_PERF_PROP_CTX_HANDLE = 1, + /** + * A value of 1 requests the inclusion of raw OA unit reports as + * part of stream samples. + */ + DRM_I915_PERF_PROP_SAMPLE_OA, + + /** + * The value specifies which set of OA unit metrics should be + * be configured, defining the contents of any OA unit reports. + */ + DRM_I915_PERF_PROP_OA_METRICS_SET, + + /** + * The value specifies the size and layout of OA unit reports. + */ + DRM_I915_PERF_PROP_OA_FORMAT, + + /** + * Specifying this property implicitly requests periodic OA unit + * sampling and (at least on Haswell) the sampling frequency is derived + * from this exponent as follows: + * + * 80ns * 2^(period_exponent + 1) + */ + DRM_I915_PERF_PROP_OA_EXPONENT, + DRM_I915_PERF_PROP_MAX /* non-ABI */ }; @@ -1257,7 +1295,23 @@ struct drm_i915_perf_open_param { __u64 __user properties_ptr; }; +/** + * Enable data capture for a stream that was either opened in a disabled state + * via I915_PERF_FLAG_DISABLED or was later disabled via + * I915_PERF_IOCTL_DISABLE. + * + * It is intended to be cheaper to disable and enable a stream than it may be + * to close and re-open a stream with the same configuration. + * + * It's undefined whether any pending data for the stream will be lost. + */ #define I915_PERF_IOCTL_ENABLE _IO('i', 0x0) + +/** + * Disable data capture for a stream. + * + * It is an error to try and read a stream that is disabled. + */ #define I915_PERF_IOCTL_DISABLE _IO('i', 0x1) /** @@ -1281,17 +1335,30 @@ enum drm_i915_perf_record_type { * every sample. * * The order of these sample properties given by userspace has no - * affect on the ordering of data within a sample. The order will be + * affect on the ordering of data within a sample. The order is * documented here. * * struct { * struct drm_i915_perf_record_header header; * - * TODO: itemize extensible sample data here + * { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA * }; */ DRM_I915_PERF_RECORD_SAMPLE = 1, + /* + * Indicates that one or more OA reports were not written by the + * hardware. This can happen for example if an MI_REPORT_PERF_COUNT + * command collides with periodic sampling - which would be more likely + * at higher sampling frequencies. + */ + DRM_I915_PERF_RECORD_OA_REPORT_LOST = 2, + + /** + * An error occurred that resulted in all pending OA reports being lost. + */ + DRM_I915_PERF_RECORD_OA_BUFFER_LOST = 3, + DRM_I915_PERF_RECORD_MAX /* non-ABI */ }; -- cgit v1.2.3 From cd8bddc4ab535009a3cdf700a14f10d75eda899c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 30 Nov 2016 16:46:49 +0000 Subject: drm/i915/perf: Treat u64 in uabi as a normal integer Forgo marking up the u64 integer representing a user pointer as this just annoys sparse. The conversion from u64 to a user pointer is managed by u64_to_user_ptr(). Fixes: eec688e1420d ("drm/i915: Add i915 perf infrastructure") Signed-off-by: Chris Wilson Cc: Robert Bragg Cc: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/20161130164649.26809-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld --- include/uapi/drm/i915_drm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index bdfc68876990..da32c2f6c3f9 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1292,7 +1292,7 @@ struct drm_i915_perf_open_param { * Pointer to array of u64 (id, value) pairs configuring the stream * to open. */ - __u64 __user properties_ptr; + __u64 properties_ptr; }; /** -- cgit v1.2.3 From 8363e3c3947d0e22955f94a6a87e4f17ce5087b4 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 10 Nov 2016 17:23:08 +0200 Subject: drm/i915/glk: Add Geminilake PCI IDs v2: Add new 0x3185 ID. (Joonas) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1478791400-21756-4-git-send-email-ander.conselvan.de.oliveira@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 1 + include/drm/i915_pciids.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index a3cc0e7d0ac8..ab4fe712126b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -437,6 +437,7 @@ static const struct pci_device_id pciidlist[] = { INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), INTEL_SKL_GT4_IDS(&intel_skylake_gt3_info), INTEL_BXT_IDS(&intel_broxton_info), + INTEL_GLK_IDS(&intel_geminilake_info), INTEL_KBL_GT1_IDS(&intel_kabylake_info), INTEL_KBL_GT2_IDS(&intel_kabylake_info), INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info), diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 0d5f4268d75f..540be9ff0346 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -292,6 +292,10 @@ INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */ \ INTEL_VGA_DEVICE(0x5A85, info) /* APL HD Graphics 500 */ +#define INTEL_GLK_IDS(info) \ + INTEL_VGA_DEVICE(0x3184, info), \ + INTEL_VGA_DEVICE(0x3185, info) + #define INTEL_KBL_GT1_IDS(info) \ INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */ \ INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */ \ -- cgit v1.2.3 From 122020af856181c24fe45903e43e3cc987c175f7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 15 Nov 2016 15:46:42 +0000 Subject: dma-buf: Provide wrappers for reservation's lock Joonas complained that writing ww_mutex_lock(&resv->lock, ctx) was too intrusive compared to reservation_object_lock(resv, ctx); Signed-off-by: Chris Wilson Cc: Sumit Semwal Cc: Joonas Lahtinen Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161115154642.31850-1-chris@chris-wilson.co.uk --- include/linux/reservation.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'include') diff --git a/include/linux/reservation.h b/include/linux/reservation.h index d9706a6f5ae2..2b5a4679daea 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h @@ -144,6 +144,40 @@ reservation_object_get_list(struct reservation_object *obj) reservation_object_held(obj)); } +/** + * reservation_object_lock - lock the reservation object + * @obj: the reservation object + * @ctx: the locking context + * + * Locks the reservation object for exclusive access and modification. Note, + * that the lock is only against other writers, readers will run concurrently + * with a writer under RCU. The seqlock is used to notify readers if they + * overlap with a writer. + * + * As the reservation object may be locked by multiple parties in an + * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle + * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation + * object may be locked by itself by passing NULL as @ctx. + */ +static inline int +reservation_object_lock(struct reservation_object *obj, + struct ww_acquire_ctx *ctx) +{ + return ww_mutex_lock(&obj->lock, ctx); +} + +/** + * reservation_object_unlock - unlock the reservation object + * @obj: the reservation object + * + * Unlocks the reservation object following exclusive access. + */ +static inline void +reservation_object_unlock(struct reservation_object *obj) +{ + ww_mutex_unlock(&obj->lock); +} + /** * reservation_object_get_excl - get the reservation object's * exclusive fence, with update-side lock held -- cgit v1.2.3 From b9fb2a21ac8058965a6b3fcae736cfa7f411d6eb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 9 Nov 2016 13:36:36 +0100 Subject: drm_fourcc: Document linear modifier Not setting the fb modifiers flag is something different from setting the fb modifiers to 0 (which means explicitly linear). We kinda failed to document that properly. Spotted by Kristian. Cc: hoegsberg@google.com Reviewed-by: Kristian H. Kristensen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1478694996-4200-1-git-send-email-daniel.vetter@ffwll.ch --- include/uapi/drm/drm_fourcc.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index a5890bf44c0a..0ccef30e56b6 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -172,6 +172,16 @@ extern "C" { * authoritative source for all of these. */ +/* + * Linear Layout + * + * Just plain linear layout. Note that this is different from no specifying any + * modifier (e.g. not setting DRM_MODE_FB_MODIFIERS in the DRM_ADDFB2 ioctl), + * which tells the driver to also take driver-internal information into account + * and so might actually result in a tiled framebuffer. + */ +#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0) + /* Intel framebuffer modifiers */ /* -- cgit v1.2.3 From 5acc614ac47465fee6375a9af4740f618830762d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 10 Dec 2016 22:52:52 +0100 Subject: drm: Protect master->unique with dev->master_mutex No one looks at the major/minor versions except the unique/busid stuff. If we protect that with the master_mutex (since it also affects the unique of each master, oh well) we can mark these two IOCTL with DRM_UNLOCKED. While doing this I realized that the comment for the magic_map is outdated, I've forgotten to update it in: commit d2b34ee62b409a03c6fe43c07b779983be51d017 Author: Daniel Vetter Date: Fri Jun 17 09:33:21 2016 +0200 drm: Protect authmagic with master_mutex Cc: Chris Wilson Cc: Emil Velikov Reviewed-by: Chris Wilson Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161210215255.7765-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_ioctl.c | 12 +++++++++--- include/drm/drm_auth.h | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index fed22c2b98b6..daacef9bf902 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -115,11 +115,15 @@ static int drm_getunique(struct drm_device *dev, void *data, struct drm_unique *u = data; struct drm_master *master = file_priv->master; + mutex_lock(&master->dev->master_mutex); if (u->unique_len >= master->unique_len) { - if (copy_to_user(u->unique, master->unique, master->unique_len)) + if (copy_to_user(u->unique, master->unique, master->unique_len)) { + mutex_unlock(&master->dev->master_mutex); return -EFAULT; + } } u->unique_len = master->unique_len; + mutex_unlock(&master->dev->master_mutex); return 0; } @@ -340,6 +344,7 @@ static int drm_setversion(struct drm_device *dev, void *data, struct drm_file *f struct drm_set_version *sv = data; int if_version, retcode = 0; + mutex_lock(&dev->master_mutex); if (sv->drm_di_major != -1) { if (sv->drm_di_major != DRM_IF_MAJOR || sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { @@ -374,6 +379,7 @@ done: sv->drm_di_minor = DRM_IF_MINOR; sv->drm_dd_major = dev->driver->major; sv->drm_dd_minor = dev->driver->minor; + mutex_unlock(&dev->master_mutex); return retcode; } @@ -528,7 +534,7 @@ EXPORT_SYMBOL(drm_ioctl_permit); static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, DRM_UNLOCKED), @@ -536,7 +542,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), - DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_UNLOCKED | DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h index 610223b0481b..155588eb8ccf 100644 --- a/include/drm/drm_auth.h +++ b/include/drm/drm_auth.h @@ -33,10 +33,7 @@ * * @refcount: Refcount for this master object. * @dev: Link back to the DRM device - * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex. - * @unique_len: Length of unique field. Protected by drm_global_mutex. - * @magic_map: Map of used authentication tokens. Protected by struct_mutex. - * @lock: DRI lock information. + * @lock: DRI1 lock information. * @driver_priv: Pointer to driver-private information. * * Note that master structures are only relevant for the legacy/primary device @@ -45,8 +42,20 @@ struct drm_master { struct kref refcount; struct drm_device *dev; + /** + * @unique: Unique identifier: e.g. busid. Protected by struct + * &drm_device master_mutex. + */ char *unique; + /** + * @unique_len: Length of unique field. Protected by struct &drm_device + * master_mutex. + */ int unique_len; + /** + * @magic_map: Map of used authentication tokens. Protected by struct + * &drm_device master_mutex. + */ struct idr magic_map; struct drm_lock_data lock; void *driver_priv; -- cgit v1.2.3 From 2904a8c1311f02896635fd35744262413a0b2726 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 9 Dec 2016 19:53:07 +0100 Subject: dma-buf: Reorganize device dma access docs - Put the initial overview for dma-buf into dma-buf.rst. - Put all the comments about detailed semantics into the right kernel-doc comment for functions or ops structure member. - To allow that detail, switch the reworked kerneldoc to inline style for dma_buf_ops. - Tie everything together into a much more streamlined overview comment, relying on the hyperlinks for all the details. - Also sprinkle some links into the kerneldoc for dma_buf and dma_buf_attachment to tie it all together. Cc: linux-doc@vger.kernel.org Cc: Jonathan Corbet Cc: Sumit Semwal Signed-off-by: Daniel Vetter Signed-off-by: Sumit Semwal Link: http://patchwork.freedesktop.org/patch/msgid/20161209185309.1682-4-daniel.vetter@ffwll.ch --- Documentation/dma-buf-sharing.txt | 222 ----------------------------------- Documentation/driver-api/dma-buf.rst | 38 ++++++ drivers/dma-buf/dma-buf.c | 64 +++++++++- drivers/dma-buf/sync_file.c | 1 - include/linux/dma-buf.h | 133 +++++++++++++++++---- 5 files changed, 207 insertions(+), 251 deletions(-) (limited to 'include') diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index ca44c5820585..dca2fb7ac3b4 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt @@ -5,228 +5,6 @@ -This document serves as a guide to device-driver writers on what is the dma-buf -buffer sharing API, how to use it for exporting and using shared buffers. - -Any device driver which wishes to be a part of DMA buffer sharing, can do so as -either the 'exporter' of buffers, or the 'user' of buffers. - -Say a driver A wants to use buffers created by driver B, then we call B as the -exporter, and A as buffer-user. - -The exporter -- implements and manages operations[1] for the buffer -- allows other users to share the buffer by using dma_buf sharing APIs, -- manages the details of buffer allocation, -- decides about the actual backing storage where this allocation happens, -- takes care of any migration of scatterlist - for all (shared) users of this - buffer, - -The buffer-user -- is one of (many) sharing users of the buffer. -- doesn't need to worry about how the buffer is allocated, or where. -- needs a mechanism to get access to the scatterlist that makes up this buffer - in memory, mapped into its own address space, so it can access the same area - of memory. - -dma-buf operations for device dma only --------------------------------------- - -The dma_buf buffer sharing API usage contains the following steps: - -1. Exporter announces that it wishes to export a buffer -2. Userspace gets the file descriptor associated with the exported buffer, and - passes it around to potential buffer-users based on use case -3. Each buffer-user 'connects' itself to the buffer -4. When needed, buffer-user requests access to the buffer from exporter -5. When finished with its use, the buffer-user notifies end-of-DMA to exporter -6. when buffer-user is done using this buffer completely, it 'disconnects' - itself from the buffer. - - -1. Exporter's announcement of buffer export - - The buffer exporter announces its wish to export a buffer. In this, it - connects its own private buffer data, provides implementation for operations - that can be performed on the exported dma_buf, and flags for the file - associated with this buffer. All these fields are filled in struct - dma_buf_export_info, defined via the DEFINE_DMA_BUF_EXPORT_INFO macro. - - Interface: - DEFINE_DMA_BUF_EXPORT_INFO(exp_info) - struct dma_buf *dma_buf_export(struct dma_buf_export_info *exp_info) - - If this succeeds, dma_buf_export allocates a dma_buf structure, and - returns a pointer to the same. It also associates an anonymous file with this - buffer, so it can be exported. On failure to allocate the dma_buf object, - it returns NULL. - - 'exp_name' in struct dma_buf_export_info is the name of exporter - to - facilitate information while debugging. It is set to KBUILD_MODNAME by - default, so exporters don't have to provide a specific name, if they don't - wish to. - - DEFINE_DMA_BUF_EXPORT_INFO macro defines the struct dma_buf_export_info, - zeroes it out and pre-populates exp_name in it. - - -2. Userspace gets a handle to pass around to potential buffer-users - - Userspace entity requests for a file-descriptor (fd) which is a handle to the - anonymous file associated with the buffer. It can then share the fd with other - drivers and/or processes. - - Interface: - int dma_buf_fd(struct dma_buf *dmabuf, int flags) - - This API installs an fd for the anonymous file associated with this buffer; - returns either 'fd', or error. - -3. Each buffer-user 'connects' itself to the buffer - - Each buffer-user now gets a reference to the buffer, using the fd passed to - it. - - Interface: - struct dma_buf *dma_buf_get(int fd) - - This API will return a reference to the dma_buf, and increment refcount for - it. - - After this, the buffer-user needs to attach its device with the buffer, which - helps the exporter to know of device buffer constraints. - - Interface: - struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, - struct device *dev) - - This API returns reference to an attachment structure, which is then used - for scatterlist operations. It will optionally call the 'attach' dma_buf - operation, if provided by the exporter. - - The dma-buf sharing framework does the bookkeeping bits related to managing - the list of all attachments to a buffer. - -Until this stage, the buffer-exporter has the option to choose not to actually -allocate the backing storage for this buffer, but wait for the first buffer-user -to request use of buffer for allocation. - - -4. When needed, buffer-user requests access to the buffer - - Whenever a buffer-user wants to use the buffer for any DMA, it asks for - access to the buffer using dma_buf_map_attachment API. At least one attach to - the buffer must have happened before map_dma_buf can be called. - - Interface: - struct sg_table * dma_buf_map_attachment(struct dma_buf_attachment *, - enum dma_data_direction); - - This is a wrapper to dma_buf->ops->map_dma_buf operation, which hides the - "dma_buf->ops->" indirection from the users of this interface. - - In struct dma_buf_ops, map_dma_buf is defined as - struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *, - enum dma_data_direction); - - It is one of the buffer operations that must be implemented by the exporter. - It should return the sg_table containing scatterlist for this buffer, mapped - into caller's address space. - - If this is being called for the first time, the exporter can now choose to - scan through the list of attachments for this buffer, collate the requirements - of the attached devices, and choose an appropriate backing storage for the - buffer. - - Based on enum dma_data_direction, it might be possible to have multiple users - accessing at the same time (for reading, maybe), or any other kind of sharing - that the exporter might wish to make available to buffer-users. - - map_dma_buf() operation can return -EINTR if it is interrupted by a signal. - - -5. When finished, the buffer-user notifies end-of-DMA to exporter - - Once the DMA for the current buffer-user is over, it signals 'end-of-DMA' to - the exporter using the dma_buf_unmap_attachment API. - - Interface: - void dma_buf_unmap_attachment(struct dma_buf_attachment *, - struct sg_table *); - - This is a wrapper to dma_buf->ops->unmap_dma_buf() operation, which hides the - "dma_buf->ops->" indirection from the users of this interface. - - In struct dma_buf_ops, unmap_dma_buf is defined as - void (*unmap_dma_buf)(struct dma_buf_attachment *, - struct sg_table *, - enum dma_data_direction); - - unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like - map_dma_buf, this API also must be implemented by the exporter. - - -6. when buffer-user is done using this buffer, it 'disconnects' itself from the - buffer. - - After the buffer-user has no more interest in using this buffer, it should - disconnect itself from the buffer: - - - it first detaches itself from the buffer. - - Interface: - void dma_buf_detach(struct dma_buf *dmabuf, - struct dma_buf_attachment *dmabuf_attach); - - This API removes the attachment from the list in dmabuf, and optionally calls - dma_buf->ops->detach(), if provided by exporter, for any housekeeping bits. - - - Then, the buffer-user returns the buffer reference to exporter. - - Interface: - void dma_buf_put(struct dma_buf *dmabuf); - - This API then reduces the refcount for this buffer. - - If, as a result of this call, the refcount becomes 0, the 'release' file - operation related to this fd is called. It calls the dmabuf->ops->release() - operation in turn, and frees the memory allocated for dmabuf when exported. - -NOTES: -- Importance of attach-detach and {map,unmap}_dma_buf operation pairs - The attach-detach calls allow the exporter to figure out backing-storage - constraints for the currently-interested devices. This allows preferential - allocation, and/or migration of pages across different types of storage - available, if possible. - - Bracketing of DMA access with {map,unmap}_dma_buf operations is essential - to allow just-in-time backing of storage, and migration mid-way through a - use-case. - -- Migration of backing storage if needed - If after - - at least one map_dma_buf has happened, - - and the backing storage has been allocated for this buffer, - another new buffer-user intends to attach itself to this buffer, it might - be allowed, if possible for the exporter. - - In case it is allowed by the exporter: - if the new buffer-user has stricter 'backing-storage constraints', and the - exporter can handle these constraints, the exporter can just stall on the - map_dma_buf until all outstanding access is completed (as signalled by - unmap_dma_buf). - Once all users have finished accessing and have unmapped this buffer, the - exporter could potentially move the buffer to the stricter backing-storage, - and then allow further {map,unmap}_dma_buf operations from any buffer-user - from the migrated backing-storage. - - If the exporter cannot fulfill the backing-storage constraints of the new - buffer-user device as requested, dma_buf_attach() would return an error to - denote non-compatibility of the new buffer-sharing request with the current - buffer. - - If the exporter chooses not to allow an attach() operation once a - map_dma_buf() API has been called, it simply returns an error. Kernel cpu access to a dma-buf buffer object -------------------------------------------- diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst index a9b457a4b949..906d1532efad 100644 --- a/Documentation/driver-api/dma-buf.rst +++ b/Documentation/driver-api/dma-buf.rst @@ -17,6 +17,44 @@ shared or exclusive fence(s) associated with the buffer. Shared DMA Buffers ------------------ +This document serves as a guide to device-driver writers on what is the dma-buf +buffer sharing API, how to use it for exporting and using shared buffers. + +Any device driver which wishes to be a part of DMA buffer sharing, can do so as +either the 'exporter' of buffers, or the 'user' or 'importer' of buffers. + +Say a driver A wants to use buffers created by driver B, then we call B as the +exporter, and A as buffer-user/importer. + +The exporter + + - implements and manages operations in :c:type:`struct dma_buf_ops + ` for the buffer, + - allows other users to share the buffer by using dma_buf sharing APIs, + - manages the details of buffer allocation, wrapped int a :c:type:`struct + dma_buf `, + - decides about the actual backing storage where this allocation happens, + - and takes care of any migration of scatterlist - for all (shared) users of + this buffer. + +The buffer-user + + - is one of (many) sharing users of the buffer. + - doesn't need to worry about how the buffer is allocated, or where. + - and needs a mechanism to get access to the scatterlist that makes up this + buffer in memory, mapped into its own address space, so it can access the + same area of memory. This interface is provided by :c:type:`struct + dma_buf_attachment `. + +Basic Operation and Device DMA Access +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/dma-buf/dma-buf.c + :doc: dma buf device access + +Kernel Functions and Structures Reference +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + .. kernel-doc:: drivers/dma-buf/dma-buf.c :export: diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index e72e64484131..09f948fd62ad 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -313,6 +313,37 @@ static inline int is_dma_buf_file(struct file *file) return file->f_op == &dma_buf_fops; } +/** + * DOC: dma buf device access + * + * For device DMA access to a shared DMA buffer the usual sequence of operations + * is fairly simple: + * + * 1. The exporter defines his exporter instance using + * DEFINE_DMA_BUF_EXPORT_INFO() and calls dma_buf_export() to wrap a private + * buffer object into a &dma_buf. It then exports that &dma_buf to userspace + * as a file descriptor by calling dma_buf_fd(). + * + * 2. Userspace passes this file-descriptors to all drivers it wants this buffer + * to share with: First the filedescriptor is converted to a &dma_buf using + * dma_buf_get(). The the buffer is attached to the device using + * dma_buf_attach(). + * + * Up to this stage the exporter is still free to migrate or reallocate the + * backing storage. + * + * 3. Once the buffer is attached to all devices userspace can inniate DMA + * access to the shared buffer. In the kernel this is done by calling + * dma_buf_map_attachment() and dma_buf_unmap_attachment(). + * + * 4. Once a driver is done with a shared buffer it needs to call + * dma_buf_detach() (after cleaning up any mappings) and then release the + * reference acquired with dma_buf_get by calling dma_buf_put(). + * + * For the detailed semantics exporters are expected to implement see + * &dma_buf_ops. + */ + /** * dma_buf_export - Creates a new dma_buf, and associates an anon file * with this buffer, so it can be exported. @@ -320,13 +351,15 @@ static inline int is_dma_buf_file(struct file *file) * Additionally, provide a name string for exporter; useful in debugging. * * @exp_info: [in] holds all the export related information provided - * by the exporter. see struct dma_buf_export_info + * by the exporter. see struct &dma_buf_export_info * for further details. * * Returns, on success, a newly created dma_buf object, which wraps the * supplied private data and operations for dma_buf_ops. On either missing * ops, or error in allocating struct dma_buf, will return negative error. * + * For most cases the easiest way to create @exp_info is through the + * %DEFINE_DMA_BUF_EXPORT_INFO macro. */ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) { @@ -458,7 +491,12 @@ EXPORT_SYMBOL_GPL(dma_buf_get); * dma_buf_put - decreases refcount of the buffer * @dmabuf: [in] buffer to reduce refcount of * - * Uses file's refcounting done implicitly by fput() + * Uses file's refcounting done implicitly by fput(). + * + * If, as a result of this call, the refcount becomes 0, the 'release' file + * operation related to this fd is called. It calls the release operation of + * struct &dma_buf_ops in turn, and frees the memory allocated for dmabuf when + * exported. */ void dma_buf_put(struct dma_buf *dmabuf) { @@ -475,8 +513,17 @@ EXPORT_SYMBOL_GPL(dma_buf_put); * @dmabuf: [in] buffer to attach device to. * @dev: [in] device to be attached. * - * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on - * error. + * Returns struct dma_buf_attachment pointer for this attachment. Attachments + * must be cleaned up by calling dma_buf_detach(). + * + * Returns: + * + * A pointer to newly created &dma_buf_attachment on success, or a negative + * error code wrapped into a pointer on failure. + * + * Note that this can fail if the backing storage of @dmabuf is in a place not + * accessible to @dev, and cannot be moved to a more suitable place. This is + * indicated with the error code -EBUSY. */ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, struct device *dev) @@ -519,6 +566,7 @@ EXPORT_SYMBOL_GPL(dma_buf_attach); * @dmabuf: [in] buffer to detach from. * @attach: [in] attachment to be detached; is free'd after this call. * + * Clean up a device attachment obtained by calling dma_buf_attach(). */ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) { @@ -543,7 +591,12 @@ EXPORT_SYMBOL_GPL(dma_buf_detach); * @direction: [in] direction of DMA transfer * * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR - * on error. + * on error. May return -EINTR if it is interrupted by a signal. + * + * A mapping must be unmapped again using dma_buf_map_attachment(). Note that + * the underlying backing storage is pinned for as long as a mapping exists, + * therefore users/importers should not hold onto a mapping for undue amounts of + * time. */ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, enum dma_data_direction direction) @@ -571,6 +624,7 @@ EXPORT_SYMBOL_GPL(dma_buf_map_attachment); * @sg_table: [in] scatterlist info of the buffer to unmap * @direction: [in] direction of DMA transfer * + * This unmaps a DMA mapping for @attached obtained by dma_buf_map_attachment(). */ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, struct sg_table *sg_table, diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index d5179d7e8575..07cb9b908f30 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -462,4 +462,3 @@ static const struct file_operations sync_file_fops = { .unlocked_ioctl = sync_file_ioctl, .compat_ioctl = sync_file_ioctl, }; - diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 8daeb3ce0016..6df170fb243f 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -39,19 +39,6 @@ struct dma_buf_attachment; /** * struct dma_buf_ops - operations possible on struct dma_buf - * @attach: [optional] allows different devices to 'attach' themselves to the - * given buffer. It might return -EBUSY to signal that backing storage - * is already allocated and incompatible with the requirements - * of requesting device. - * @detach: [optional] detach a given device from this buffer. - * @map_dma_buf: returns list of scatter pages allocated, increases usecount - * of the buffer. Requires atleast one attach to be called - * before. Returned sg list should already be mapped into - * _device_ address space. This call may sleep. May also return - * -EINTR. Should return -EINVAL if attach hasn't been called yet. - * @unmap_dma_buf: decreases usecount of buffer, might deallocate scatter - * pages. - * @release: release this buffer; to be called after the last dma_buf_put. * @begin_cpu_access: [optional] called before cpu access to invalidate cpu * caches and allocate backing storage (if not yet done) * respectively pin the object into memory. @@ -72,25 +59,109 @@ struct dma_buf_attachment; * @vunmap: [optional] unmaps a vmap from the buffer */ struct dma_buf_ops { + /** + * @attach: + * + * This is called from dma_buf_attach() to make sure that a given + * &device can access the provided &dma_buf. Exporters which support + * buffer objects in special locations like VRAM or device-specific + * carveout areas should check whether the buffer could be move to + * system memory (or directly accessed by the provided device), and + * otherwise need to fail the attach operation. + * + * The exporter should also in general check whether the current + * allocation fullfills the DMA constraints of the new device. If this + * is not the case, and the allocation cannot be moved, it should also + * fail the attach operation. + * + * Any exporter-private housekeeping data can be stored in the priv + * pointer of &dma_buf_attachment structure. + * + * This callback is optional. + * + * Returns: + * + * 0 on success, negative error code on failure. It might return -EBUSY + * to signal that backing storage is already allocated and incompatible + * with the requirements of requesting device. + */ int (*attach)(struct dma_buf *, struct device *, - struct dma_buf_attachment *); + struct dma_buf_attachment *); + /** + * @detach: + * + * This is called by dma_buf_detach() to release a &dma_buf_attachment. + * Provided so that exporters can clean up any housekeeping for an + * &dma_buf_attachment. + * + * This callback is optional. + */ void (*detach)(struct dma_buf *, struct dma_buf_attachment *); - /* For {map,unmap}_dma_buf below, any specific buffer attributes - * required should get added to device_dma_parameters accessible - * via dev->dma_params. + /** + * @map_dma_buf: + * + * This is called by dma_buf_map_attachment() and is used to map a + * shared &dma_buf into device address space, and it is mandatory. It + * can only be called if @attach has been called successfully. This + * essentially pins the DMA buffer into place, and it cannot be moved + * any more + * + * This call may sleep, e.g. when the backing storage first needs to be + * allocated, or moved to a location suitable for all currently attached + * devices. + * + * Note that any specific buffer attributes required for this function + * should get added to device_dma_parameters accessible via + * device->dma_params from the &dma_buf_attachment. The @attach callback + * should also check these constraints. + * + * If this is being called for the first time, the exporter can now + * choose to scan through the list of attachments for this buffer, + * collate the requirements of the attached devices, and choose an + * appropriate backing storage for the buffer. + * + * Based on enum dma_data_direction, it might be possible to have + * multiple users accessing at the same time (for reading, maybe), or + * any other kind of sharing that the exporter might wish to make + * available to buffer-users. + * + * Returns: + * + * A &sg_table scatter list of or the backing storage of the DMA buffer, + * already mapped into the device address space of the &device attached + * with the provided &dma_buf_attachment. + * + * On failure, returns a negative error value wrapped into a pointer. + * May also return -EINTR when a signal was received while being + * blocked. */ struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *, - enum dma_data_direction); + enum dma_data_direction); + /** + * @unmap_dma_buf: + * + * This is called by dma_buf_unmap_attachment() and should unmap and + * release the &sg_table allocated in @map_dma_buf, and it is mandatory. + * It should also unpin the backing storage if this is the last mapping + * of the DMA buffer, it the exporter supports backing storage + * migration. + */ void (*unmap_dma_buf)(struct dma_buf_attachment *, - struct sg_table *, - enum dma_data_direction); + struct sg_table *, + enum dma_data_direction); + /* TODO: Add try_map_dma_buf version, to return immed with -EBUSY * if the call would block. */ - /* after final dma_buf_put() */ + /** + * @release: + * + * Called after the last dma_buf_put to release the &dma_buf, and + * mandatory. + */ void (*release)(struct dma_buf *); int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction); @@ -124,6 +195,15 @@ struct dma_buf_ops { * @poll: for userspace poll support * @cb_excl: for userspace poll support * @cb_shared: for userspace poll support + * + * This represents a shared buffer, created by calling dma_buf_export(). The + * userspace representation is a normal file descriptor, which can be created by + * calling dma_buf_fd(). + * + * Shared dma buffers are reference counted using dma_buf_put() and + * get_dma_buf(). + * + * Device DMA access is handled by the separate struct &dma_buf_attachment. */ struct dma_buf { size_t size; @@ -160,6 +240,11 @@ struct dma_buf { * This structure holds the attachment information between the dma_buf buffer * and its user device(s). The list contains one attachment struct per device * attached to the buffer. + * + * An attachment is created by calling dma_buf_attach(), and released again by + * calling dma_buf_detach(). The DMA mapping itself needed to initiate a + * transfer is created by dma_buf_map_attachment() and freed again by calling + * dma_buf_unmap_attachment(). */ struct dma_buf_attachment { struct dma_buf *dmabuf; @@ -192,9 +277,11 @@ struct dma_buf_export_info { }; /** - * helper macro for exporters; zeros and fills in most common values - * + * DEFINE_DMA_BUF_EXPORT_INFO - helper macro for exporters * @name: export-info name + * + * DEFINE_DMA_BUF_EXPORT_INFO macro defines the struct &dma_buf_export_info, + * zeroes it out and pre-populates exp_name in it. */ #define DEFINE_DMA_BUF_EXPORT_INFO(name) \ struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \ -- cgit v1.2.3 From 0959a1683d78270bab6381d498707fb8655ae11c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 9 Dec 2016 19:53:08 +0100 Subject: dma-buf: Update cpu access documentation - Again move the information relevant for driver writers next to the callbacks. - Put the overview and userspace interface documentation into a DOC: section within the code. - Remove the text that mmap needs to be coherent - since the DMA_BUF_IOCTL_SYNC landed that's no longer the case. But keep the text that for pte zapping exporters need to adjust the address space. - Add a FIXME that kmap and the new begin/end stuff used by the SYNC ioctl don't really mix correctly. That's something I just realized while doing this doc rework. - Augment function and structure docs like usual. Cc: linux-doc@vger.kernel.org Cc: Jonathan Corbet Cc: Sumit Semwal Signed-off-by: Daniel Vetter Signed-off-by: Sumit Semwal [sumits: fix cosmetic issues] Link: http://patchwork.freedesktop.org/patch/msgid/20161209185309.1682-5-daniel.vetter@ffwll.ch --- Documentation/dma-buf-sharing.txt | 213 ----------------------------------- Documentation/driver-api/dma-buf.rst | 6 + drivers/dma-buf/dma-buf.c | 122 ++++++++++++++++++++ include/linux/dma-buf.h | 91 +++++++++++++-- 4 files changed, 211 insertions(+), 221 deletions(-) (limited to 'include') diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index dca2fb7ac3b4..74c99edb7976 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt @@ -6,205 +6,6 @@ -Kernel cpu access to a dma-buf buffer object --------------------------------------------- - -The motivation to allow cpu access from the kernel to a dma-buf object from the -importers side are: -- fallback operations, e.g. if the devices is connected to a usb bus and the - kernel needs to shuffle the data around first before sending it away. -- full transparency for existing users on the importer side, i.e. userspace - should not notice the difference between a normal object from that subsystem - and an imported one backed by a dma-buf. This is really important for drm - opengl drivers that expect to still use all the existing upload/download - paths. - -Access to a dma_buf from the kernel context involves three steps: - -1. Prepare access, which invalidate any necessary caches and make the object - available for cpu access. -2. Access the object page-by-page with the dma_buf map apis -3. Finish access, which will flush any necessary cpu caches and free reserved - resources. - -1. Prepare access - - Before an importer can access a dma_buf object with the cpu from the kernel - context, it needs to notify the exporter of the access that is about to - happen. - - Interface: - int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction direction) - - This allows the exporter to ensure that the memory is actually available for - cpu access - the exporter might need to allocate or swap-in and pin the - backing storage. The exporter also needs to ensure that cpu access is - coherent for the access direction. The direction can be used by the exporter - to optimize the cache flushing, i.e. access with a different direction (read - instead of write) might return stale or even bogus data (e.g. when the - exporter needs to copy the data to temporary storage). - - This step might fail, e.g. in oom conditions. - -2. Accessing the buffer - - To support dma_buf objects residing in highmem cpu access is page-based using - an api similar to kmap. Accessing a dma_buf is done in aligned chunks of - PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which returns - a pointer in kernel virtual address space. Afterwards the chunk needs to be - unmapped again. There is no limit on how often a given chunk can be mapped - and unmapped, i.e. the importer does not need to call begin_cpu_access again - before mapping the same chunk again. - - Interfaces: - void *dma_buf_kmap(struct dma_buf *, unsigned long); - void dma_buf_kunmap(struct dma_buf *, unsigned long, void *); - - There are also atomic variants of these interfaces. Like for kmap they - facilitate non-blocking fast-paths. Neither the importer nor the exporter (in - the callback) is allowed to block when using these. - - Interfaces: - void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long); - void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *); - - For importers all the restrictions of using kmap apply, like the limited - supply of kmap_atomic slots. Hence an importer shall only hold onto at most 2 - atomic dma_buf kmaps at the same time (in any given process context). - - dma_buf kmap calls outside of the range specified in begin_cpu_access are - undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on - the partial chunks at the beginning and end but may return stale or bogus - data outside of the range (in these partial chunks). - - Note that these calls need to always succeed. The exporter needs to complete - any preparations that might fail in begin_cpu_access. - - For some cases the overhead of kmap can be too high, a vmap interface - is introduced. This interface should be used very carefully, as vmalloc - space is a limited resources on many architectures. - - Interfaces: - void *dma_buf_vmap(struct dma_buf *dmabuf) - void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) - - The vmap call can fail if there is no vmap support in the exporter, or if it - runs out of vmalloc space. Fallback to kmap should be implemented. Note that - the dma-buf layer keeps a reference count for all vmap access and calls down - into the exporter's vmap function only when no vmapping exists, and only - unmaps it once. Protection against concurrent vmap/vunmap calls is provided - by taking the dma_buf->lock mutex. - -3. Finish access - - When the importer is done accessing the CPU, it needs to announce this to - the exporter (to facilitate cache flushing and unpinning of any pinned - resources). The result of any dma_buf kmap calls after end_cpu_access is - undefined. - - Interface: - void dma_buf_end_cpu_access(struct dma_buf *dma_buf, - enum dma_data_direction dir); - - -Direct Userspace Access/mmap Support ------------------------------------- - -Being able to mmap an export dma-buf buffer object has 2 main use-cases: -- CPU fallback processing in a pipeline and -- supporting existing mmap interfaces in importers. - -1. CPU fallback processing in a pipeline - - In many processing pipelines it is sometimes required that the cpu can access - the data in a dma-buf (e.g. for thumbnail creation, snapshots, ...). To avoid - the need to handle this specially in userspace frameworks for buffer sharing - it's ideal if the dma_buf fd itself can be used to access the backing storage - from userspace using mmap. - - Furthermore Android's ION framework already supports this (and is otherwise - rather similar to dma-buf from a userspace consumer side with using fds as - handles, too). So it's beneficial to support this in a similar fashion on - dma-buf to have a good transition path for existing Android userspace. - - No special interfaces, userspace simply calls mmap on the dma-buf fd, making - sure that the cache synchronization ioctl (DMA_BUF_IOCTL_SYNC) is *always* - used when the access happens. Note that DMA_BUF_IOCTL_SYNC can fail with - -EAGAIN or -EINTR, in which case it must be restarted. - - Some systems might need some sort of cache coherency management e.g. when - CPU and GPU domains are being accessed through dma-buf at the same time. To - circumvent this problem there are begin/end coherency markers, that forward - directly to existing dma-buf device drivers vfunc hooks. Userspace can make - use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The sequence - would be used like following: - - mmap dma-buf fd - - for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write - to mmap area 3. SYNC_END ioctl. This can be repeated as often as you - want (with the new data being consumed by the GPU or say scanout device) - - munmap once you don't need the buffer any more - - For correctness and optimal performance, it is always required to use - SYNC_START and SYNC_END before and after, respectively, when accessing the - mapped address. Userspace cannot rely on coherent access, even when there - are systems where it just works without calling these ioctls. - -2. Supporting existing mmap interfaces in importers - - Similar to the motivation for kernel cpu access it is again important that - the userspace code of a given importing subsystem can use the same interfaces - with a imported dma-buf buffer object as with a native buffer object. This is - especially important for drm where the userspace part of contemporary OpenGL, - X, and other drivers is huge, and reworking them to use a different way to - mmap a buffer rather invasive. - - The assumption in the current dma-buf interfaces is that redirecting the - initial mmap is all that's needed. A survey of some of the existing - subsystems shows that no driver seems to do any nefarious thing like syncing - up with outstanding asynchronous processing on the device or allocating - special resources at fault time. So hopefully this is good enough, since - adding interfaces to intercept pagefaults and allow pte shootdowns would - increase the complexity quite a bit. - - Interface: - int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, - unsigned long); - - If the importing subsystem simply provides a special-purpose mmap call to set - up a mapping in userspace, calling do_mmap with dma_buf->file will equally - achieve that for a dma-buf object. - -3. Implementation notes for exporters - - Because dma-buf buffers have invariant size over their lifetime, the dma-buf - core checks whether a vma is too large and rejects such mappings. The - exporter hence does not need to duplicate this check. - - Because existing importing subsystems might presume coherent mappings for - userspace, the exporter needs to set up a coherent mapping. If that's not - possible, it needs to fake coherency by manually shooting down ptes when - leaving the cpu domain and flushing caches at fault time. Note that all the - dma_buf files share the same anon inode, hence the exporter needs to replace - the dma_buf file stored in vma->vm_file with it's own if pte shootdown is - required. This is because the kernel uses the underlying inode's address_space - for vma tracking (and hence pte tracking at shootdown time with - unmap_mapping_range). - - If the above shootdown dance turns out to be too expensive in certain - scenarios, we can extend dma-buf with a more explicit cache tracking scheme - for userspace mappings. But the current assumption is that using mmap is - always a slower path, so some inefficiencies should be acceptable. - - Exporters that shoot down mappings (for any reasons) shall not do any - synchronization at fault time with outstanding device operations. - Synchronization is an orthogonal issue to sharing the backing storage of a - buffer and hence should not be handled by dma-buf itself. This is explicitly - mentioned here because many people seem to want something like this, but if - different exporters handle this differently, buffer sharing can fail in - interesting ways depending upong the exporter (if userspace starts depending - upon this implicit synchronization). - Other Interfaces Exposed to Userspace on the dma-buf FD ------------------------------------------------------ @@ -240,20 +41,6 @@ Miscellaneous notes the exporting driver to create a dmabuf fd must provide a way to let userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd(). -- If an exporter needs to manually flush caches and hence needs to fake - coherency for mmap support, it needs to be able to zap all the ptes pointing - at the backing storage. Now linux mm needs a struct address_space associated - with the struct file stored in vma->vm_file to do that with the function - unmap_mapping_range. But the dma_buf framework only backs every dma_buf fd - with the anon_file struct file, i.e. all dma_bufs share the same file. - - Hence exporters need to setup their own file (and address_space) association - by setting vma->vm_file and adjusting vma->vm_pgoff in the dma_buf mmap - callback. In the specific case of a gem driver the exporter could use the - shmem file already provided by gem (and set vm_pgoff = 0). Exporters can then - zap ptes by unmapping the corresponding range of the struct address_space - associated with their own file. - References: [1] struct dma_buf_ops in include/linux/dma-buf.h [2] All interfaces mentioned above defined in include/linux/dma-buf.h diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst index 906d1532efad..92e417035e16 100644 --- a/Documentation/driver-api/dma-buf.rst +++ b/Documentation/driver-api/dma-buf.rst @@ -52,6 +52,12 @@ Basic Operation and Device DMA Access .. kernel-doc:: drivers/dma-buf/dma-buf.c :doc: dma buf device access +CPU Access to DMA Buffer Objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/dma-buf/dma-buf.c + :doc: cpu access + Kernel Functions and Structures Reference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 09f948fd62ad..eae0846cbd95 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -640,6 +640,122 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, } EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); +/** + * DOC: cpu access + * + * There are mutliple reasons for supporting CPU access to a dma buffer object: + * + * - Fallback operations in the kernel, for example when a device is connected + * over USB and the kernel needs to shuffle the data around first before + * sending it away. Cache coherency is handled by braketing any transactions + * with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() + * access. + * + * To support dma_buf objects residing in highmem cpu access is page-based + * using an api similar to kmap. Accessing a dma_buf is done in aligned chunks + * of PAGE_SIZE size. Before accessing a chunk it needs to be mapped, which + * returns a pointer in kernel virtual address space. Afterwards the chunk + * needs to be unmapped again. There is no limit on how often a given chunk + * can be mapped and unmapped, i.e. the importer does not need to call + * begin_cpu_access again before mapping the same chunk again. + * + * Interfaces:: + * void \*dma_buf_kmap(struct dma_buf \*, unsigned long); + * void dma_buf_kunmap(struct dma_buf \*, unsigned long, void \*); + * + * There are also atomic variants of these interfaces. Like for kmap they + * facilitate non-blocking fast-paths. Neither the importer nor the exporter + * (in the callback) is allowed to block when using these. + * + * Interfaces:: + * void \*dma_buf_kmap_atomic(struct dma_buf \*, unsigned long); + * void dma_buf_kunmap_atomic(struct dma_buf \*, unsigned long, void \*); + * + * For importers all the restrictions of using kmap apply, like the limited + * supply of kmap_atomic slots. Hence an importer shall only hold onto at + * max 2 atomic dma_buf kmaps at the same time (in any given process context). + * + * dma_buf kmap calls outside of the range specified in begin_cpu_access are + * undefined. If the range is not PAGE_SIZE aligned, kmap needs to succeed on + * the partial chunks at the beginning and end but may return stale or bogus + * data outside of the range (in these partial chunks). + * + * Note that these calls need to always succeed. The exporter needs to + * complete any preparations that might fail in begin_cpu_access. + * + * For some cases the overhead of kmap can be too high, a vmap interface + * is introduced. This interface should be used very carefully, as vmalloc + * space is a limited resources on many architectures. + * + * Interfaces:: + * void \*dma_buf_vmap(struct dma_buf \*dmabuf) + * void dma_buf_vunmap(struct dma_buf \*dmabuf, void \*vaddr) + * + * The vmap call can fail if there is no vmap support in the exporter, or if + * it runs out of vmalloc space. Fallback to kmap should be implemented. Note + * that the dma-buf layer keeps a reference count for all vmap access and + * calls down into the exporter's vmap function only when no vmapping exists, + * and only unmaps it once. Protection against concurrent vmap/vunmap calls is + * provided by taking the dma_buf->lock mutex. + * + * - For full compatibility on the importer side with existing userspace + * interfaces, which might already support mmap'ing buffers. This is needed in + * many processing pipelines (e.g. feeding a software rendered image into a + * hardware pipeline, thumbnail creation, snapshots, ...). Also, Android's ION + * framework already supported this and for DMA buffer file descriptors to + * replace ION buffers mmap support was needed. + * + * There is no special interfaces, userspace simply calls mmap on the dma-buf + * fd. But like for CPU access there's a need to braket the actual access, + * which is handled by the ioctl (DMA_BUF_IOCTL_SYNC). Note that + * DMA_BUF_IOCTL_SYNC can fail with -EAGAIN or -EINTR, in which case it must + * be restarted. + * + * Some systems might need some sort of cache coherency management e.g. when + * CPU and GPU domains are being accessed through dma-buf at the same time. + * To circumvent this problem there are begin/end coherency markers, that + * forward directly to existing dma-buf device drivers vfunc hooks. Userspace + * can make use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The + * sequence would be used like following: + * + * - mmap dma-buf fd + * - for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write + * to mmap area 3. SYNC_END ioctl. This can be repeated as often as you + * want (with the new data being consumed by say the GPU or the scanout + * device) + * - munmap once you don't need the buffer any more + * + * For correctness and optimal performance, it is always required to use + * SYNC_START and SYNC_END before and after, respectively, when accessing the + * mapped address. Userspace cannot rely on coherent access, even when there + * are systems where it just works without calling these ioctls. + * + * - And as a CPU fallback in userspace processing pipelines. + * + * Similar to the motivation for kernel cpu access it is again important that + * the userspace code of a given importing subsystem can use the same + * interfaces with a imported dma-buf buffer object as with a native buffer + * object. This is especially important for drm where the userspace part of + * contemporary OpenGL, X, and other drivers is huge, and reworking them to + * use a different way to mmap a buffer rather invasive. + * + * The assumption in the current dma-buf interfaces is that redirecting the + * initial mmap is all that's needed. A survey of some of the existing + * subsystems shows that no driver seems to do any nefarious thing like + * syncing up with outstanding asynchronous processing on the device or + * allocating special resources at fault time. So hopefully this is good + * enough, since adding interfaces to intercept pagefaults and allow pte + * shootdowns would increase the complexity quite a bit. + * + * Interface:: + * int dma_buf_mmap(struct dma_buf \*, struct vm_area_struct \*, + * unsigned long); + * + * If the importing subsystem simply provides a special-purpose mmap call to + * set up a mapping in userspace, calling do_mmap with dma_buf->file will + * equally achieve that for a dma-buf object. + */ + static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction) { @@ -665,6 +781,10 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, * @dmabuf: [in] buffer to prepare cpu access for. * @direction: [in] length of range for cpu access. * + * After the cpu access is complete the caller should call + * dma_buf_end_cpu_access(). Only when cpu access is braketed by both calls is + * it guaranteed to be coherent with other DMA access. + * * Can return negative error values, returns 0 on success. */ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, @@ -697,6 +817,8 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); * @dmabuf: [in] buffer to complete cpu access for. * @direction: [in] length of range for cpu access. * + * This terminates CPU access started with dma_buf_begin_cpu_access(). + * * Can return negative error values, returns 0 on success. */ int dma_buf_end_cpu_access(struct dma_buf *dmabuf, diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 6df170fb243f..57828154e440 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -39,10 +39,6 @@ struct dma_buf_attachment; /** * struct dma_buf_ops - operations possible on struct dma_buf - * @begin_cpu_access: [optional] called before cpu access to invalidate cpu - * caches and allocate backing storage (if not yet done) - * respectively pin the object into memory. - * @end_cpu_access: [optional] called after cpu access to flush caches. * @kmap_atomic: maps a page from the buffer into kernel address * space, users may not block until the subsequent unmap call. * This callback must not sleep. @@ -50,10 +46,6 @@ struct dma_buf_attachment; * This Callback must not sleep. * @kmap: maps a page from the buffer into kernel address space. * @kunmap: [optional] unmaps a page from the buffer. - * @mmap: used to expose the backing storage to userspace. Note that the - * mapping needs to be coherent - if the exporter doesn't directly - * support this, it needs to fake coherency by shooting down any ptes - * when transitioning away from the cpu domain. * @vmap: [optional] creates a virtual mapping for the buffer into kernel * address space. Same restrictions as for vmap and friends apply. * @vunmap: [optional] unmaps a vmap from the buffer @@ -164,13 +156,96 @@ struct dma_buf_ops { */ void (*release)(struct dma_buf *); + /** + * @begin_cpu_access: + * + * This is called from dma_buf_begin_cpu_access() and allows the + * exporter to ensure that the memory is actually available for cpu + * access - the exporter might need to allocate or swap-in and pin the + * backing storage. The exporter also needs to ensure that cpu access is + * coherent for the access direction. The direction can be used by the + * exporter to optimize the cache flushing, i.e. access with a different + * direction (read instead of write) might return stale or even bogus + * data (e.g. when the exporter needs to copy the data to temporary + * storage). + * + * This callback is optional. + * + * FIXME: This is both called through the DMA_BUF_IOCTL_SYNC command + * from userspace (where storage shouldn't be pinned to avoid handing + * de-factor mlock rights to userspace) and for the kernel-internal + * users of the various kmap interfaces, where the backing storage must + * be pinned to guarantee that the atomic kmap calls can succeed. Since + * there's no in-kernel users of the kmap interfaces yet this isn't a + * real problem. + * + * Returns: + * + * 0 on success or a negative error code on failure. This can for + * example fail when the backing storage can't be allocated. Can also + * return -ERESTARTSYS or -EINTR when the call has been interrupted and + * needs to be restarted. + */ int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction); + + /** + * @end_cpu_access: + * + * This is called from dma_buf_end_cpu_access() when the importer is + * done accessing the CPU. The exporter can use this to flush caches and + * unpin any resources pinned in @begin_cpu_access. + * The result of any dma_buf kmap calls after end_cpu_access is + * undefined. + * + * This callback is optional. + * + * Returns: + * + * 0 on success or a negative error code on failure. Can return + * -ERESTARTSYS or -EINTR when the call has been interrupted and needs + * to be restarted. + */ int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); void *(*kmap_atomic)(struct dma_buf *, unsigned long); void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *); void *(*kmap)(struct dma_buf *, unsigned long); void (*kunmap)(struct dma_buf *, unsigned long, void *); + /** + * @mmap: + * + * This callback is used by the dma_buf_mmap() function + * + * Note that the mapping needs to be incoherent, userspace is expected + * to braket CPU access using the DMA_BUF_IOCTL_SYNC interface. + * + * Because dma-buf buffers have invariant size over their lifetime, the + * dma-buf core checks whether a vma is too large and rejects such + * mappings. The exporter hence does not need to duplicate this check. + * Drivers do not need to check this themselves. + * + * If an exporter needs to manually flush caches and hence needs to fake + * coherency for mmap support, it needs to be able to zap all the ptes + * pointing at the backing storage. Now linux mm needs a struct + * address_space associated with the struct file stored in vma->vm_file + * to do that with the function unmap_mapping_range. But the dma_buf + * framework only backs every dma_buf fd with the anon_file struct file, + * i.e. all dma_bufs share the same file. + * + * Hence exporters need to setup their own file (and address_space) + * association by setting vma->vm_file and adjusting vma->vm_pgoff in + * the dma_buf mmap callback. In the specific case of a gem driver the + * exporter could use the shmem file already provided by gem (and set + * vm_pgoff = 0). Exporters can then zap ptes by unmapping the + * corresponding range of the struct address_space associated with their + * own file. + * + * This callback is optional. + * + * Returns: + * + * 0 on success or a negative error code on failure. + */ int (*mmap)(struct dma_buf *, struct vm_area_struct *vma); void *(*vmap)(struct dma_buf *); -- cgit v1.2.3 From af913418261d6d3e7a29f06cf35f04610ead667c Mon Sep 17 00:00:00 2001 From: "Kristian H. Kristensen" Date: Tue, 13 Dec 2016 11:27:52 -0800 Subject: drm_fourcc: Fix DRM_FORMAT_MOD_LINEAR #define We need to define DRM_FORMAT_MOD_VENDOR_NONE for the fourcc_mod_code() macro to work correctly. Signed-off-by: Kristian H. Kristensen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481657272-25975-1-git-send-email-hoegsberg@google.com --- include/uapi/drm/drm_fourcc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 0ccef30e56b6..9e1bb7fabcde 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -154,6 +154,7 @@ extern "C" { /* Vendor Ids: */ #define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE 0 #define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 #define DRM_FORMAT_MOD_VENDOR_AMD 0x02 #define DRM_FORMAT_MOD_VENDOR_NV 0x03 -- cgit v1.2.3 From a3f913ca98925d7e5bae725e9b2b38408215a695 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 14 Dec 2016 22:48:59 +0200 Subject: drm: Pass 'dev' to drm_helper_mode_fill_fb_struct() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the drm_device to drm_helper_mode_fill_fb_struct() so that we can populate fb->dev early. Will make it easier to use the fb before we register it. @@ identifier fb, mode_cmd; @@ void drm_helper_mode_fill_fb_struct( + struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd ); @@ identifier fb, mode_cmd; @@ void drm_helper_mode_fill_fb_struct( + struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd ) { ... } @@ function func; identifier dev; expression E1, E2; @@ func(struct drm_device *dev, ...) { ... drm_helper_mode_fill_fb_struct( + dev, E1, E2); ... } @@ expression E1, E2; @@ drm_helper_mode_fill_fb_struct( + dev, E1, E2); v2: Rerun spatch due to code changes Signed-off-by: Ville Syrjälä Reviewed-by: Laurent Pinchart Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1481748539-18283-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- drivers/gpu/drm/armada/armada_fb.c | 2 +- drivers/gpu/drm/ast/ast_main.c | 2 +- drivers/gpu/drm/bochs/bochs_mm.c | 2 +- drivers/gpu/drm/cirrus/cirrus_main.c | 2 +- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- drivers/gpu/drm/drm_modeset_helper.c | 3 ++- drivers/gpu/drm/exynos/exynos_drm_fb.c | 2 +- drivers/gpu/drm/gma500/framebuffer.c | 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/mediatek/mtk_drm_fb.c | 2 +- drivers/gpu/drm/mgag200/mgag200_main.c | 2 +- drivers/gpu/drm/msm/msm_fb.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/omapdrm/omap_fb.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 +- drivers/gpu/drm/radeon/radeon_display.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 2 +- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/udl/udl_fb.c | 2 +- drivers/gpu/drm/virtio/virtgpu_display.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 4 ++-- include/drm/drm_modeset_helper.h | 3 ++- 24 files changed, 27 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 581601ca6b89..d2036df145b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -508,7 +508,7 @@ amdgpu_framebuffer_init(struct drm_device *dev, { int ret; rfb->obj = obj; - drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd); ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs); if (ret) { rfb->obj = NULL; diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c index f03c212b754d..2a7eb6817c36 100644 --- a/drivers/gpu/drm/armada/armada_fb.c +++ b/drivers/gpu/drm/armada/armada_fb.c @@ -81,7 +81,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev, dfb->mod = config; dfb->obj = obj; - drm_helper_mode_fill_fb_struct(&dfb->fb, mode); + drm_helper_mode_fill_fb_struct(dev, &dfb->fb, mode); ret = drm_framebuffer_init(dev, &dfb->fb, &armada_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 904beaa932d0..d85af0ff2653 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -313,7 +313,7 @@ int ast_framebuffer_init(struct drm_device *dev, { int ret; - drm_helper_mode_fill_fb_struct(&ast_fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &ast_fb->base, mode_cmd); ast_fb->obj = obj; ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 099a3c688c26..ceb1fecf02dd 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -484,7 +484,7 @@ int bochs_framebuffer_init(struct drm_device *dev, { int ret; - drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd); gfb->obj = obj; ret = drm_framebuffer_init(dev, &gfb->base, &bochs_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index 2c3c0d4072ce..52d901fa8687 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -34,7 +34,7 @@ int cirrus_framebuffer_init(struct drm_device *dev, { int ret; - drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd); gfb->obj = obj; ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 81b3558302b5..570f5c6063f3 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -147,7 +147,7 @@ static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev, if (!fb_cma) return ERR_PTR(-ENOMEM); - drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &fb_cma->fb, mode_cmd); for (i = 0; i < num_planes; i++) fb_cma->obj[i] = obj[i]; diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index cc232ac6c950..285ffcba0fe8 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -68,7 +68,8 @@ EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); * This helper can be used in a drivers fb_create callback to pre-fill the fb's * metadata fields. */ -void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, +void drm_helper_mode_fill_fb_struct(struct drm_device *dev, + struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd) { const struct drm_format_info *info; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 23cce0a3f5fc..68d414227533 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -126,7 +126,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev, + mode_cmd->offsets[i]; } - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &exynos_fb->fb, mode_cmd); ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret < 0) { diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 4071b2d1e8cf..6d89ed760941 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -244,7 +244,7 @@ static int psb_framebuffer_init(struct drm_device *dev, if (mode_cmd->pitches[0] & 63) return -EINVAL; - drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &fb->base, mode_cmd); fb->gtt = gt; ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index e76abf61edae..3c6f750389fb 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -512,7 +512,7 @@ hibmc_framebuffer_init(struct drm_device *dev, return ERR_PTR(-ENOMEM); } - drm_helper_mode_fill_fb_struct(&hibmc_fb->fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &hibmc_fb->fb, mode_cmd); hibmc_fb->obj = obj; ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cf5cff7b03b8..0d4a83310231 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15877,7 +15877,7 @@ static int intel_framebuffer_init(struct drm_device *dev, if (mode_cmd->offsets[0] != 0) return -EINVAL; - drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &intel_fb->base, mode_cmd); intel_fb->obj = obj; ret = intel_fill_fb_info(dev_priv, &intel_fb->base); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index 147df85399ab..d4246c9dceae 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -82,7 +82,7 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev, if (!mtk_fb) return ERR_PTR(-ENOMEM); - drm_helper_mode_fill_fb_struct(&mtk_fb->base, mode); + drm_helper_mode_fill_fb_struct(dev, &mtk_fb->base, mode); mtk_fb->gem_obj = obj; diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index e79cbc25ae3c..95d628b9457e 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -34,7 +34,7 @@ int mgag200_framebuffer_init(struct drm_device *dev, { int ret; - drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd); gfb->obj = obj; ret = drm_framebuffer_init(dev, &gfb->base, &mga_fb_funcs); if (ret) { diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 9acf544e7a8f..ccefd6a30f37 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -217,7 +217,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, msm_fb->planes[i] = bos[i]; } - drm_helper_mode_fill_fb_struct(fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); ret = drm_framebuffer_init(dev, fb, &msm_framebuffer_funcs); if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index cef08da1da4e..e0db5d38fb18 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -259,7 +259,7 @@ nouveau_framebuffer_new(struct drm_device *dev, if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL))) return -ENOMEM; - drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &fb->base, mode_cmd); fb->nvbo = nvbo; ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs); diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 5f3337f1e9aa..9875c99be009 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -457,7 +457,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, plane->paddr = 0; } - drm_helper_mode_fill_fb_struct(fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs); if (ret) { diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 4b5eab8a47b3..6cabb47c75b1 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -629,7 +629,7 @@ qxl_framebuffer_init(struct drm_device *dev, qfb->obj = NULL; return ret; } - drm_helper_mode_fill_fb_struct(&qfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &qfb->base, mode_cmd); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e7409e8a9f87..6285355eb5d5 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1327,7 +1327,7 @@ radeon_framebuffer_init(struct drm_device *dev, { int ret; rfb->obj = obj; - drm_helper_mode_fill_fb_struct(&rfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd); ret = drm_framebuffer_init(dev, &rfb->base, &radeon_fb_funcs); if (ret) { rfb->obj = NULL; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 0f6eda023bd0..d5e1f8627d38 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -92,7 +92,7 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm if (!rockchip_fb) return ERR_PTR(-ENOMEM); - drm_helper_mode_fill_fb_struct(&rockchip_fb->fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &rockchip_fb->fb, mode_cmd); for (i = 0; i < num_planes; i++) rockchip_fb->obj[i] = obj[i]; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index e4a5ab0a9677..a0096493f51c 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -114,7 +114,7 @@ static struct tegra_fb *tegra_fb_alloc(struct drm_device *drm, fb->num_planes = num_planes; - drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(drm, &fb->base, mode_cmd); for (i = 0; i < fb->num_planes; i++) fb->planes[i] = planes[i]; diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 167f42c67c7c..fefd87f422ec 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -330,7 +330,7 @@ udl_framebuffer_init(struct drm_device *dev, int ret; ufb->obj = obj; - drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &ufb->base, mode_cmd); ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); return ret; } diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 58048709c34e..8b80fdd0e0a8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -93,7 +93,7 @@ virtio_gpu_framebuffer_init(struct drm_device *dev, vgfb->obj = NULL; return ret; } - drm_helper_mode_fill_fb_struct(&vgfb->base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &vgfb->base, mode_cmd); spin_lock_init(&vgfb->dirty_lock); vgfb->x1 = vgfb->y1 = INT_MAX; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e7daf59bac80..cf22110e9eee 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -583,7 +583,7 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, goto out_err1; } - drm_helper_mode_fill_fb_struct(&vfbs->base.base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &vfbs->base.base, mode_cmd); vfbs->surface = vmw_surface_reference(surface); vfbs->base.user_handle = mode_cmd->handles[0]; vfbs->is_dmabuf_proxy = is_dmabuf_proxy; @@ -864,7 +864,7 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, goto out_err1; } - drm_helper_mode_fill_fb_struct(&vfbd->base.base, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, &vfbd->base.base, mode_cmd); vfbd->base.dmabuf = true; vfbd->buffer = vmw_dmabuf_reference(dmabuf); vfbd->base.user_handle = mode_cmd->handles[0]; diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h index b8051d5abe10..cb0ec92e11e6 100644 --- a/include/drm/drm_modeset_helper.h +++ b/include/drm/drm_modeset_helper.h @@ -27,7 +27,8 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *); -void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, +void drm_helper_mode_fill_fb_struct(struct drm_device *dev, + struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd); int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, -- cgit v1.2.3 From e14c23c647abfc1fed96a55ba376cd9675a54098 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 18 Nov 2016 21:52:55 +0200 Subject: drm: Store a pointer to drm_format_info under drm_framebuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid having to look up the format information struct every time, let's just store a pointer to it under drm_framebuffer. v2: Don't populate the fb->format pointer in drm_framebuffer_init(). instead we'll treat a NULL format as an error later Cc: Laurent Pinchart Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1479498793-31021-20-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Laurent Pinchart --- drivers/gpu/drm/drm_modeset_helper.c | 1 + include/drm/drm_framebuffer.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 57a319e3f780..1aa5e3bcc8a1 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -91,6 +91,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, } fb->dev = dev; + fb->format = info; fb->width = mode_cmd->width; fb->height = mode_cmd->height; for (i = 0; i < 4; i++) { diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 1ddfa2928802..a3d2f25230a8 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -121,6 +121,10 @@ struct drm_framebuffer { * @base: base modeset object structure, contains the reference count. */ struct drm_mode_object base; + /** + * @format: framebuffer format information + */ + const struct drm_format_info *format; /** * @funcs: framebuffer vfunc table */ -- cgit v1.2.3 From 8f8f6a6c3cbe14406780a90e89d7d8742493913c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 18 Nov 2016 21:53:05 +0200 Subject: drm: Add drm_framebuffer_plane_{width,height}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add variants of drm_format_plane_{width,height}() that take an entire fb object instead of just the format. These should be more efficent as they can just look up the format info from the fb->format pointer rather than having to look it up (using a linear search based on the format). Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher Link: http://patchwork.freedesktop.org/patch/msgid/1479498793-31021-30-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_framebuffer.c | 44 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_framebuffer.h | 6 ++++++ 2 files changed, 50 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 892976d974e5..22071d7e3420 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -793,3 +793,47 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) drm_framebuffer_unreference(fb); } EXPORT_SYMBOL(drm_framebuffer_remove); + +/** + * drm_framebuffer_plane_width - width of the plane given the first plane + * @width: width of the first plane + * @fb: the framebuffer + * @plane: plane index + * + * Returns: + * The width of @plane, given that the width of the first plane is @width. + */ +int drm_framebuffer_plane_width(int width, + const struct drm_framebuffer *fb, int plane) +{ + if (plane >= fb->format->num_planes) + return 0; + + if (plane == 0) + return width; + + return width / fb->format->hsub; +} +EXPORT_SYMBOL(drm_framebuffer_plane_width); + +/** + * drm_framebuffer_plane_height - height of the plane given the first plane + * @height: height of the first plane + * @fb: the framebuffer + * @plane: plane index + * + * Returns: + * The height of @plane, given that the height of the first plane is @height. + */ +int drm_framebuffer_plane_height(int height, + const struct drm_framebuffer *fb, int plane) +{ + if (plane >= fb->format->num_planes) + return 0; + + if (plane == 0) + return height; + + return height / fb->format->vsub; +} +EXPORT_SYMBOL(drm_framebuffer_plane_height); diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index a3d2f25230a8..79640c3e7ec4 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -286,4 +286,10 @@ static inline void drm_framebuffer_assign(struct drm_framebuffer **p, struct drm_framebuffer, head); \ &fb->head != (&(dev)->mode_config.fb_list); \ fb = list_next_entry(fb, head)) + +int drm_framebuffer_plane_width(int width, + const struct drm_framebuffer *fb, int plane); +int drm_framebuffer_plane_height(int height, + const struct drm_framebuffer *fb, int plane); + #endif -- cgit v1.2.3 From b00c600e91531df00aaa551049382416c4db745d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 14 Dec 2016 23:31:35 +0200 Subject: drm: Nuke fb->depth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace uses of fb->depth with fb->format->depth. Less duplicate information is a good thing. @@ struct drm_framebuffer *fb; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - fb->depth = E; ... } @@ struct nouveau_framebuffer *fb; @@ - fb->base.depth + fb->base.format->depth @@ struct drm_framebuffer fb; @@ - fb.depth + fb.format->depth @@ struct drm_framebuffer *fb; @@ - fb->depth + fb->format->depth @@ struct drm_framebuffer fb; @@ - (fb.format->depth) + fb.format->depth @@ struct drm_framebuffer *fb; @@ - (fb->format->depth) + fb->format->depth @@ @@ struct drm_framebuffer { ... - unsigned int depth; ... }; v2: Drop the vmw stuff (Daniel) Rerun spatch due to code changes Signed-off-by: Ville Syrjälä Reviewed-by: Laurent Pinchart Reviewed-by: Alex Deucher Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481751095-18249-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 4 ++-- drivers/gpu/drm/armada/armada_fbdev.c | 3 ++- drivers/gpu/drm/ast/ast_fb.c | 2 +- drivers/gpu/drm/bochs/bochs_fbdev.c | 2 +- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 4 ++-- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/drm_framebuffer.c | 2 +- drivers/gpu/drm/drm_modeset_helper.c | 2 -- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 2 +- drivers/gpu/drm/gma500/accel_2d.c | 2 +- drivers/gpu/drm/gma500/framebuffer.c | 2 +- drivers/gpu/drm/gma500/gma_display.c | 2 +- drivers/gpu/drm/gma500/mdfld_intel_display.c | 2 +- drivers/gpu/drm/gma500/oaktrail_crtc.c | 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/intel_fbdev.c | 2 +- drivers/gpu/drm/mgag200/mgag200_fb.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 6 +++--- drivers/gpu/drm/msm/msm_fbdev.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 12 ++++++------ drivers/gpu/drm/nouveau/dispnv04/dfp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 3 ++- drivers/gpu/drm/omapdrm/omap_fbdev.c | 2 +- drivers/gpu/drm/qxl/qxl_fb.c | 5 +++-- drivers/gpu/drm/radeon/radeon_fb.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c | 5 +++-- drivers/gpu/drm/tegra/drm.c | 3 ++- drivers/gpu/drm/tegra/fb.c | 2 +- drivers/gpu/drm/udl/udl_fb.c | 2 +- drivers/gpu/drm/virtio/virtgpu_fb.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 5 +++-- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 5 +++-- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 +- include/drm/drm_framebuffer.h | 6 ------ 36 files changed, 56 insertions(+), 57 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 24629bec181a..838943d0962e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -245,7 +245,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, strcpy(info->fix.id, "amdgpudrmfb"); - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &amdgpufb_ops; @@ -272,7 +272,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)adev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo)); - DRM_INFO("fb depth is %d\n", fb->depth); + DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(adev->ddev->pdev, info); diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index c5dc06a55883..3a58fb600b05 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -89,7 +89,8 @@ static int armada_fb_create(struct drm_fb_helper *fbh, info->screen_base = ptr; fbh->fb = &dfb->fb; - drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth); + drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], + dfb->fb.format->depth); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index d6f5ec64c667..f751792a3c7c 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -237,7 +237,7 @@ static int astfb_create(struct drm_fb_helper *helper, info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0); info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &afbdev->helper, sizes->fb_width, sizes->fb_height); info->screen_base = sysram; diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index da790a1c302a..0317c3df6a22 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -123,7 +123,7 @@ static int bochsfb_create(struct drm_fb_helper *helper, info->flags = FBINFO_DEFAULT; info->fbops = &bochsfb_ops; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width, sizes->fb_height); diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 3a6309d7d8e4..3cac8a03cf4f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -218,7 +218,7 @@ static int cirrusfb_create(struct drm_fb_helper *helper, info->flags = FBINFO_DEFAULT; info->fbops = &cirrusfb_ops; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &gfbdev->helper, sizes->fb_width, sizes->fb_height); @@ -238,7 +238,7 @@ static int cirrusfb_create(struct drm_fb_helper *helper, DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start); DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len); - DRM_INFO("fb depth is %d\n", fb->depth); + DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); return 0; diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 0dc3f5bcbf48..181a9eafe34a 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -464,7 +464,7 @@ int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper, fbi->flags = FBINFO_FLAG_DEFAULT; fbi->fbops = &drm_fbdev_cma_ops; - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); offset = fbi->var.xoffset * bytes_per_pixel; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e934b541feea..96c78b33a999 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1653,7 +1653,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe info->var.height = -1; info->var.width = -1; - switch (fb->depth) { + switch (fb->format->depth) { case 8: info->var.red.offset = 0; info->var.green.offset = 0; diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 22071d7e3420..556a92359c96 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -432,7 +432,7 @@ int drm_mode_getfb(struct drm_device *dev, r->height = fb->height; r->width = fb->width; - r->depth = fb->depth; + r->depth = fb->format->depth; r->bpp = fb->bits_per_pixel; r->pitch = fb->pitches[0]; if (fb->funcs->create_handle) { diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 1aa5e3bcc8a1..e5d19e5fc341 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -83,10 +83,8 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, drm_get_format_name(mode_cmd->pixel_format, &format_name)); - fb->depth = 0; fb->bits_per_pixel = 0; } else { - fb->depth = info->depth; fb->bits_per_pixel = info->cpp[0] * 8; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 9f35deb56170..e68a46f112f6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -90,7 +90,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, fbi->flags = FBINFO_FLAG_DEFAULT; fbi->fbops = &exynos_drm_fb_ops; - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); nr_pages = exynos_gem->size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c index 0d2bb1682508..c51d9259c7a7 100644 --- a/drivers/gpu/drm/gma500/accel_2d.c +++ b/drivers/gpu/drm/gma500/accel_2d.c @@ -254,7 +254,7 @@ static void psbfb_copyarea_accel(struct fb_info *info, offset = psbfb->gtt->offset; stride = fb->pitches[0]; - switch (fb->depth) { + switch (fb->format->depth) { case 8: src_format = PSB_2D_SRC_332RGB; dst_format = PSB_2D_DST_332RGB; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 6d89ed760941..a93b59ce6b41 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -407,7 +407,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, fbdev->psb_fb_helper.fb = fb; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); strcpy(info->fix.id, "psbdrmfb"); info->flags = FBINFO_DEFAULT; diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 05b9a4ceb58d..5b852ad152ae 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -94,7 +94,7 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y, dspcntr |= DISPPLANE_8BPP; break; case 16: - if (fb->depth == 15) + if (fb->format->depth == 15) dspcntr |= DISPPLANE_15_16BPP; else dspcntr |= DISPPLANE_16BPP; diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index e80895285e94..3be3111825cd 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -208,7 +208,7 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, dspcntr |= DISPPLANE_8BPP; break; case 16: - if (fb->depth == 15) + if (fb->format->depth == 15) dspcntr |= DISPPLANE_15_16BPP; else dspcntr |= DISPPLANE_16BPP; diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index a51896544d91..569810d47786 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -630,7 +630,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc, dspcntr |= DISPPLANE_8BPP; break; case 16: - if (fb->depth == 15) + if (fb->format->depth == 15) dspcntr |= DISPPLANE_15_16BPP; else dspcntr |= DISPPLANE_16BPP; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c index 9b0696735ba1..7a6957ae4b44 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c @@ -135,7 +135,7 @@ static int hibmc_drm_fb_create(struct drm_fb_helper *helper, info->fbops = &hibmc_drm_fb_ops; drm_fb_helper_fill_fix(info, hi_fbdev->fb->fb.pitches[0], - hi_fbdev->fb->fb.depth); + hi_fbdev->fb->fb.format->depth); drm_fb_helper_fill_var(info, &priv->fbdev->helper, sizes->fb_width, sizes->fb_height); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 791bfc760075..ce5586451633 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1873,7 +1873,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", fbdev_fb->base.width, fbdev_fb->base.height, - fbdev_fb->base.depth, + fbdev_fb->base.format->depth, fbdev_fb->base.bits_per_pixel, fbdev_fb->base.modifier, drm_framebuffer_read_refcount(&fbdev_fb->base)); @@ -1891,7 +1891,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) seq_printf(m, "user size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ", fb->base.width, fb->base.height, - fb->base.depth, + fb->base.format->depth, fb->base.bits_per_pixel, fb->base.modifier, drm_framebuffer_read_refcount(&fb->base)); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index beb08982dc0b..b726483a460d 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -261,7 +261,7 @@ static int intelfb_create(struct drm_fb_helper *helper, /* This driver doesn't need a VT switch to restore the mode on resume */ info->skip_vt_switch = true; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); /* If the object is shmemfs backed, it will have given us zeroed pages. diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 88dd2214114d..19a78b6b5a1a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -217,7 +217,7 @@ static int mgag200fb_create(struct drm_fb_helper *helper, info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base; info->apertures->ranges[0].size = mdev->mc.vram_size; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &mfbdev->helper, sizes->fb_width, sizes->fb_height); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 34dd38e8a651..9399099d3e39 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -39,10 +39,10 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) WREG8(DAC_INDEX + MGA1064_INDEX, 0); if (fb && fb->bits_per_pixel == 16) { - int inc = (fb->depth == 15) ? 8 : 4; + int inc = (fb->format->depth == 15) ? 8 : 4; u8 r, b; for (i = 0; i < MGAG200_LUT_SIZE; i += inc) { - if (fb->depth == 16) { + if (fb->format->depth == 16) { if (i > (MGAG200_LUT_SIZE >> 1)) { r = b = 0; } else { @@ -947,7 +947,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits; break; case 16: - if (fb->depth == 15) + if (fb->format->depth == 15) dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits; else dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits; diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index bffe93498512..5d68ab362d75 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -148,7 +148,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, strcpy(fbi->fix.id, "msm"); - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); dev->mode_config.fb_base = paddr; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 8286b8ffe109..480e3ab477fd 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -570,7 +570,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) regp->CRTC[NV_CIO_CRE_86] = 0x1; } - regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (fb->depth + 1) / 8; + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (fb->format->depth + 1) / 8; /* Enable slaved mode (called MODE_TV in nv4ref.h) */ if (lvds_output || tmds_output || tv_output) regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); @@ -584,7 +584,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL | NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; - if (fb->depth == 16) + if (fb->format->depth == 16) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; if (drm->device.info.chipset >= 0x11) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; @@ -848,16 +848,16 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, nv_crtc->fb.offset = fb->nvbo->bo.offset; - if (nv_crtc->lut.depth != drm_fb->depth) { - nv_crtc->lut.depth = drm_fb->depth; + if (nv_crtc->lut.depth != drm_fb->format->depth) { + nv_crtc->lut.depth = drm_fb->format->depth; nv_crtc_gamma_load(crtc); } /* Update the framebuffer format. */ regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3; - regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (drm_fb->depth + 1) / 8; + regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (drm_fb->format->depth + 1) / 8; regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; - if (drm_fb->depth == 16) + if (drm_fb->format->depth == 16) regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX); NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 945607b3cd41..2e5bb2afda7c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -416,7 +416,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, /* Output property. */ if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || (nv_connector->dithering_mode == DITHERING_MODE_AUTO && - fb->depth > connector->display_info.bpc * 3)) { + fb->format->depth > connector->display_info.bpc * 3)) { if (drm->device.info.chipset == 0x11) regp->dither = savep->dither | 0x00010000; else { diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2f2a3dcd4ad7..5600f6c64497 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -400,7 +400,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, info->screen_base = nvbo_kmap_obj_iovirtual(fb->nvbo); info->screen_size = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT; - drm_fb_helper_fill_fix(info, fb->base.pitches[0], fb->base.depth); + drm_fb_helper_fill_fix(info, fb->base.pitches[0], + fb->base.format->depth); drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 8d8ac173f55d..aed99a0fc44b 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -190,7 +190,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, strcpy(fbi->fix.id, MODULE_NAME); - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); dev->mode_config.fb_base = paddr; diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index fd7e5e94be5b..e6ade6aab54c 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -279,7 +279,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, qfbdev->shadow = shadow; strcpy(info->fix.id, "qxldrmfb"); - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; info->fbops = &qxlfb_ops; @@ -316,7 +316,8 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, qdev->fbdev_info = info; qdev->fbdev_qfb = &qfbdev->qfb; DRM_INFO("fb mappable at 0x%lX, size %lu\n", info->fix.smem_start, (unsigned long)info->screen_size); - DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", fb->depth, fb->pitches[0], fb->width, fb->height); + DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", + fb->format->depth, fb->pitches[0], fb->width, fb->height); return 0; out_destroy_fbi: diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 899b6a1644bd..6c10a83f3362 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -263,7 +263,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, strcpy(info->fix.id, "radeondrmfb"); - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &radeonfb_ops; @@ -290,7 +290,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); - DRM_INFO("fb depth is %d\n", fb->depth); + DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index 8f639c8597a5..52d1fdf9f9da 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -94,7 +94,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, fbi->fbops = &rockchip_drm_fbdev_ops; fb = helper->fb; - drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); offset = fbi->var.xoffset * bytes_per_pixel; @@ -106,7 +106,8 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper, fbi->fix.smem_len = rk_obj->base.size; DRM_DEBUG_KMS("FB [%dx%d]-%d kvaddr=%p offset=%ld size=%zu\n", - fb->width, fb->height, fb->depth, rk_obj->kvaddr, + fb->width, fb->height, fb->format->depth, + rk_obj->kvaddr, offset, size); fbi->skip_vt_switch = true; diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index b8be3ee4d3b8..d2893f65341a 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -875,7 +875,8 @@ static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) list_for_each_entry(fb, &drm->mode_config.fb_list, head) { seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", - fb->base.id, fb->width, fb->height, fb->depth, + fb->base.id, fb->width, fb->height, + fb->format->depth, fb->bits_per_pixel, drm_framebuffer_read_refcount(fb)); } diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 8a4aea211e94..8df7783cecc2 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -246,7 +246,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &tegra_fb_ops; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, helper, fb->width, fb->height); offset = info->var.xoffset * bytes_per_pixel + diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index fefd87f422ec..e21a3ed3ab2b 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -395,7 +395,7 @@ static int udlfb_create(struct drm_fb_helper *helper, info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &udlfb_ops; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d vmal %p\n", diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index dd21f950e129..9d0da42cc420 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c @@ -333,7 +333,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper, info->screen_base = obj->vmap; info->screen_size = obj->gem_base.size; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &vfbdev->helper, sizes->fb_width, sizes->fb_height); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 723fd763da8e..4a7a7d2997dd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -83,7 +83,7 @@ static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green, return 1; } - switch (par->set_fb->depth) { + switch (par->set_fb->format->depth) { case 24: case 32: pal[regno] = ((red & 0xff00) << 8) | @@ -91,7 +91,8 @@ static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green, ((blue & 0xff00) >> 8); break; default: - DRM_ERROR("Bad depth %u, bpp %u.\n", par->set_fb->depth, + DRM_ERROR("Bad depth %u, bpp %u.\n", + par->set_fb->format->depth, par->set_fb->bits_per_pixel); return 1; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 23ec673d5e16..a3a839a3d441 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -97,7 +97,8 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) fb = entry->base.crtc.primary->fb; return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], - fb->bits_per_pixel, fb->depth); + fb->bits_per_pixel, + fb->format->depth); } if (!list_empty(&lds->active)) { @@ -105,7 +106,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) fb = entry->base.crtc.primary->fb; vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], - fb->bits_per_pixel, fb->depth); + fb->bits_per_pixel, fb->format->depth); } /* Make sure we always show something. */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index f42359084adc..38d7b8a2b78e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -598,7 +598,7 @@ static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, struct vmw_dma_buffer *buf = container_of(framebuffer, struct vmw_framebuffer_dmabuf, base)->buffer; - int depth = framebuffer->base.depth; + int depth = framebuffer->base.format->depth; struct { uint32_t header; SVGAFifoCmdDefineGMRFB body; diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 79640c3e7ec4..0c14f0adf161 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -169,12 +169,6 @@ struct drm_framebuffer { * pixels. */ unsigned int height; - /** - * @depth: Depth in bits per pixel for RGB formats. 0 for everything - * else. Legacy information derived from @pixel_format, it's suggested to use - * the DRM FOURCC codes and helper functions directly instead. - */ - unsigned int depth; /** * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for * everything else. Legacy information derived from @pixel_format, it's -- cgit v1.2.3 From 272725c7db4da1fd3229d944fc76d2e98e3a144e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 14 Dec 2016 23:32:20 +0200 Subject: drm: Nuke fb->bits_per_pixel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace uses of fb->bits_per_pixel with fb->format->cpp[0]*8. Less duplicated information is a good thing. Note that I didn't put parens around the cpp*8 in the below cocci script, on account of not wanting spurious parens all over the place. Instead I did the unsafe way, and tried to look over the entire diff to spot if any dangerous expressions were produced. I didn't see any. There are some cases where previously the code did X*bpp/8, so the division happened after the multiplication. Those are now just X*cpp so the division effectively happens before the multiplication, but that is perfectly fine since bpp is always a multiple of 8. @@ struct drm_framebuffer *FB; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ i9xx_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ ironlake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ skylake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer FB; expression E; @@ ( - E * FB.bits_per_pixel / 8 + E * FB.format->cpp[0] | - FB.bits_per_pixel / 8 + FB.format->cpp[0] | - E * FB.bits_per_pixel >> 3 + E * FB.format->cpp[0] | - FB.bits_per_pixel >> 3 + FB.format->cpp[0] | - (FB.bits_per_pixel + 7) / 8 + FB.format->cpp[0] | - FB.bits_per_pixel + FB.format->cpp[0] * 8 | - FB.format->cpp[0] * 8 != 8 + FB.format->cpp[0] != 1 ) @@ struct drm_framebuffer *FB; expression E; @@ ( - E * FB->bits_per_pixel / 8 + E * FB->format->cpp[0] | - FB->bits_per_pixel / 8 + FB->format->cpp[0] | - E * FB->bits_per_pixel >> 3 + E * FB->format->cpp[0] | - FB->bits_per_pixel >> 3 + FB->format->cpp[0] | - (FB->bits_per_pixel + 7) / 8 + FB->format->cpp[0] | - FB->bits_per_pixel + FB->format->cpp[0] * 8 | - FB->format->cpp[0] * 8 != 8 + FB->format->cpp[0] != 1 ) @@ struct drm_plane_state *state; expression E; @@ ( - E * state->fb->bits_per_pixel / 8 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel / 8 + state->fb->format->cpp[0] | - E * state->fb->bits_per_pixel >> 3 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel >> 3 + state->fb->format->cpp[0] | - (state->fb->bits_per_pixel + 7) / 8 + state->fb->format->cpp[0] | - state->fb->bits_per_pixel + state->fb->format->cpp[0] * 8 | - state->fb->format->cpp[0] * 8 != 8 + state->fb->format->cpp[0] != 1 ) @@ @@ - (8 * 8) + 8 * 8 @@ struct drm_framebuffer FB; @@ - (FB.format->cpp[0]) + FB.format->cpp[0] @@ struct drm_framebuffer *FB; @@ - (FB->format->cpp[0]) + FB->format->cpp[0] @@ @@ struct drm_framebuffer { ... - int bits_per_pixel; ... }; v2: Clean up the 'cpp*8 != 8' and '(8 * 8)' cases (Laurent) v3: Adjusted the semantic patch a bit and regenerated due to code changes Signed-off-by: Ville Syrjälä Reviewed-by: Laurent Pinchart Reviewed-by: Alex Deucher (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1481751140-18352-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 +- drivers/gpu/drm/armada/armada_crtc.c | 2 +- drivers/gpu/drm/armada/armada_fbdev.c | 2 +- drivers/gpu/drm/ast/ast_fb.c | 2 +- drivers/gpu/drm/ast/ast_mode.c | 9 +++++---- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 +- drivers/gpu/drm/cirrus/cirrus_mode.c | 2 +- drivers/gpu/drm/drm_fb_helper.c | 8 ++++---- drivers/gpu/drm/drm_framebuffer.c | 2 +- drivers/gpu/drm/drm_modeset_helper.c | 3 --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 4 ++-- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 6 +++--- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 ++-- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.c | 4 ++-- drivers/gpu/drm/gma500/framebuffer.c | 2 +- drivers/gpu/drm/gma500/gma_display.c | 4 ++-- drivers/gpu/drm/gma500/mdfld_intel_display.c | 6 +++--- drivers/gpu/drm/gma500/oaktrail_crtc.c | 4 ++-- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 6 +++--- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 11 ++++------- drivers/gpu/drm/i915/intel_fbdev.c | 6 +++--- drivers/gpu/drm/mgag200/mgag200_fb.c | 2 +- drivers/gpu/drm/mgag200/mgag200_mode.c | 16 ++++++++-------- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/qxl/qxl_draw.c | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 11 ++++++----- drivers/gpu/drm/radeon/r100.c | 4 ++-- drivers/gpu/drm/radeon/radeon_display.c | 6 +++--- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 14 +++++++------- drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tegra/drm.c | 2 +- drivers/gpu/drm/udl/udl_fb.c | 2 +- drivers/gpu/drm/virtio/virtgpu_fb.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 2 +- include/drm/drm_framebuffer.h | 7 ------- 44 files changed, 90 insertions(+), 101 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 9999dc71b998..8d0ff1c8db8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2220,7 +2220,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width); WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels); dce_v10_0_grph_enable(crtc, true); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index b3d62b909f43..c25edecb46d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2201,7 +2201,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width); WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels); dce_v11_0_grph_enable(crtc, true); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e564442b6393..ffd20f90788c 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1630,7 +1630,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width); WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels); dce_v6_0_grph_enable(crtc, true); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 6ce7fb42dbef..e6f446af3818 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2079,7 +2079,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width); WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels); dce_v8_0_grph_enable(crtc, true); diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 99283f30edc5..426e86f4cf96 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -190,7 +190,7 @@ static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb, unsigned i = 0; DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n", - pitch, x, y, fb->bits_per_pixel); + pitch, x, y, fb->format->cpp[0] * 8); armada_drm_plane_calc_addrs(addrs, fb, x, y); diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 3a58fb600b05..78335100cbc3 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -94,7 +94,7 @@ static int armada_fb_create(struct drm_fb_helper *fbh, drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", - dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel, + dfb->fb.width, dfb->fb.height, dfb->fb.format->cpp[0] * 8, (unsigned long long)obj->phys_addr); return 0; diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index f751792a3c7c..b085140fae95 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -49,7 +49,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev, struct drm_gem_object *obj; struct ast_bo *bo; int src_offset, dst_offset; - int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8; + int bpp = afbdev->afb.base.format->cpp[0]; int ret = -EBUSY; bool unmap = false; bool store_for_later = false; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index e70364a8544e..606cb40f6c7c 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -85,7 +85,7 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo bool check_sync; struct ast_vbios_enhtable *best = NULL; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: vbios_mode->std_table = &vbios_stdtable[VGAModeIndex]; color_index = VGAModeIndex - 1; @@ -208,7 +208,8 @@ static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mo ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00); if (vbios_mode->enh_table->flags & NewModeInfo) { ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8); - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, fb->bits_per_pixel); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, + fb->format->cpp[0] * 8); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8); @@ -400,7 +401,7 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode const struct drm_framebuffer *fb = crtc->primary->fb; u8 jregA0 = 0, jregA3 = 0, jregA8 = 0; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: jregA0 = 0x70; jregA3 = 0x01; @@ -457,7 +458,7 @@ static bool ast_set_dac_reg(struct drm_crtc *crtc, struct drm_display_mode *mode { const struct drm_framebuffer *fb = crtc->primary->fb; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: break; default: diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 3cac8a03cf4f..79a5cd108245 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -22,7 +22,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev, struct drm_gem_object *obj; struct cirrus_bo *bo; int src_offset, dst_offset; - int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8; + int bpp = afbdev->gfb.base.format->cpp[0]; int ret = -EBUSY; bool unmap = false; bool store_for_later = false; diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 06674a9b7665..ed43ab10ac99 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -258,7 +258,7 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, sr07 = RREG8(SEQ_DATA); sr07 &= 0xe0; hdr = 0; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: sr07 |= 0x11; break; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 96c78b33a999..bee5e4149a1c 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1169,7 +1169,7 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, !fb_helper->funcs->gamma_get)) return -EINVAL; - WARN_ON(fb->bits_per_pixel != 8); + WARN_ON(fb->format->cpp[0] != 1); fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); @@ -1252,14 +1252,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, * Changes struct fb_var_screeninfo are currently not pushed back * to KMS, hence fail if different settings are requested. */ - if (var->bits_per_pixel != fb->bits_per_pixel || + if (var->bits_per_pixel != fb->format->cpp[0] * 8 || var->xres != fb->width || var->yres != fb->height || var->xres_virtual != fb->width || var->yres_virtual != fb->height) { DRM_DEBUG("fb userspace requested width/height/bpp different than current fb " "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, var->xres_virtual, var->yres_virtual, - fb->width, fb->height, fb->bits_per_pixel); + fb->width, fb->height, fb->format->cpp[0] * 8); return -EINVAL; } @@ -1645,7 +1645,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe info->pseudo_palette = fb_helper->pseudo_palette; info->var.xres_virtual = fb->width; info->var.yres_virtual = fb->height; - info->var.bits_per_pixel = fb->bits_per_pixel; + info->var.bits_per_pixel = fb->format->cpp[0] * 8; info->var.accel_flags = FB_ACCELF_TEXT; info->var.xoffset = 0; info->var.yoffset = 0; diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 556a92359c96..94ddab41f24f 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -433,7 +433,7 @@ int drm_mode_getfb(struct drm_device *dev, r->height = fb->height; r->width = fb->width; r->depth = fb->format->depth; - r->bpp = fb->bits_per_pixel; + r->bpp = fb->format->cpp[0] * 8; r->pitch = fb->pitches[0]; if (fb->funcs->create_handle) { if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) || diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index e5d19e5fc341..3c44409244dc 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -82,10 +82,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, DRM_DEBUG_KMS("non-RGB pixel format %s\n", drm_get_format_name(mode_cmd->pixel_format, &format_name)); - - fb->bits_per_pixel = 0; } else { - fb->bits_per_pixel = info->cpp[0] * 8; } fb->dev = dev; diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 6ca1f3117fe8..e8ce4a318586 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -226,7 +226,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, return; } - DRM_DEBUG_KMS("bpp = %u\n", fb->bits_per_pixel); + DRM_DEBUG_KMS("bpp = %u\n", fb->format->cpp[0] * 8); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -275,7 +275,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, struct decon_context *ctx = crtc->ctx; struct drm_framebuffer *fb = state->base.fb; unsigned int win = plane->index; - unsigned int bpp = fb->bits_per_pixel >> 3; + unsigned int bpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0); u32 val; diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index f4d5a2133777..58dc9a5196bc 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -330,7 +330,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, break; } - DRM_DEBUG_KMS("bpp = %d\n", fb->bits_per_pixel); + DRM_DEBUG_KMS("bpp = %d\n", fb->format->cpp[0] * 8); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -340,7 +340,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, * movement causes unstable DMA which results into iommu crash/tear. */ - padding = (fb->pitches[0] / (fb->bits_per_pixel >> 3)) - fb->width; + padding = (fb->pitches[0] / fb->format->cpp[0]) - fb->width; if (fb->width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) { val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_8WORD; @@ -407,7 +407,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, unsigned int last_x; unsigned int last_y; unsigned int win = plane->index; - unsigned int bpp = fb->bits_per_pixel >> 3; + unsigned int bpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; if (ctx->suspended) diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index e68a46f112f6..d8808158d418 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -76,7 +76,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, { struct fb_info *fbi; struct drm_framebuffer *fb = helper->fb; - unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); + unsigned int size = fb->width * fb->height * fb->format->cpp[0]; unsigned int nr_pages; unsigned long offset; @@ -103,7 +103,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, return -EIO; } - offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); + offset = fbi->var.xoffset * fb->format->cpp[0]; offset += fbi->var.yoffset * fb->pitches[0]; fbi->screen_base = exynos_gem->kvaddr + offset; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index e2e405170d35..0029065979b8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -738,7 +738,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, unsigned long val, size, offset; unsigned int last_x, last_y, buf_offsize, line_size; unsigned int win = plane->index; - unsigned int bpp = fb->bits_per_pixel >> 3; + unsigned int bpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; if (ctx->suspended) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index edb20a34c66c..b313e61aab65 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -631,7 +631,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, /* converting dma address base and source offset */ dma_addr = exynos_drm_fb_dma_addr(fb, 0) - + (state->src.x * fb->bits_per_pixel >> 3) + + (state->src.x * fb->format->cpp[0]) + (state->src.y * fb->pitches[0]); src_x_offset = 0; src_y_offset = 0; @@ -649,7 +649,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, /* setup geometry */ mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), - fb->pitches[0] / (fb->bits_per_pixel >> 3)); + fb->pitches[0] / fb->format->cpp[0]); /* setup display size */ if (ctx->mxr_ver == MXR_VER_128_0_0_184 && diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index a93b59ce6b41..6bf33ba055b3 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -77,7 +77,7 @@ static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, (transp << info->var.transp.offset); if (regno < 16) { - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 16: ((uint32_t *) info->pseudo_palette)[regno] = v; break; diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 5b852ad152ae..d1c5642b1c1e 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -82,14 +82,14 @@ int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y, if (ret < 0) goto gma_pipe_set_base_exit; start = psbfb->gtt->offset; - offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + offset = y * fb->pitches[0] + x * fb->format->cpp[0]; REG_WRITE(map->stride, fb->pitches[0]); dspcntr = REG_READ(map->cntr); dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: dspcntr |= DISPPLANE_8BPP; break; diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index 3be3111825cd..63c6e08600ae 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -148,7 +148,7 @@ static int check_fb(struct drm_framebuffer *fb) if (!fb) return 0; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: case 16: case 24: @@ -197,13 +197,13 @@ static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return 0; start = psbfb->gtt->offset; - offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + offset = y * fb->pitches[0] + x * fb->format->cpp[0]; REG_WRITE(map->stride, fb->pitches[0]); dspcntr = REG_READ(map->cntr); dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: dspcntr |= DISPPLANE_8BPP; break; diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 569810d47786..0fff269d3fe6 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -618,14 +618,14 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc, return 0; start = psbfb->gtt->offset; - offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); + offset = y * fb->pitches[0] + x * fb->format->cpp[0]; REG_WRITE(map->stride, fb->pitches[0]); dspcntr = REG_READ(map->cntr); dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: dspcntr |= DISPPLANE_8BPP; break; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 2a1386e33126..c655883d3613 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -122,11 +122,11 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane, writel(gpu_addr, priv->mmio + HIBMC_CRT_FB_ADDRESS); - reg = state->fb->width * (state->fb->bits_per_pixel / 8); + reg = state->fb->width * (state->fb->format->cpp[0]); /* now line_pad is 16 */ reg = PADDING(16, reg); - line_l = state->fb->width * state->fb->bits_per_pixel / 8; + line_l = state->fb->width * state->fb->format->cpp[0]; line_l = PADDING(16, line_l); writel(HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_WIDTH, reg) | HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_OFFS, line_l), @@ -136,7 +136,7 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane, reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL); reg &= ~HIBMC_CRT_DISP_CTL_FORMAT_MASK; reg |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_FORMAT, - state->fb->bits_per_pixel / 16); + state->fb->format->cpp[0] * 8 / 16); writel(reg, priv->mmio + HIBMC_CRT_DISP_CTL); } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ce5586451633..ec462dae46bc 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1874,7 +1874,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) fbdev_fb->base.width, fbdev_fb->base.height, fbdev_fb->base.format->depth, - fbdev_fb->base.bits_per_pixel, + fbdev_fb->base.format->cpp[0] * 8, fbdev_fb->base.modifier, drm_framebuffer_read_refcount(&fbdev_fb->base)); describe_obj(m, fbdev_fb->obj); @@ -1892,7 +1892,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) fb->base.width, fb->base.height, fb->base.format->depth, - fb->base.bits_per_pixel, + fb->base.format->cpp[0] * 8, fb->base.modifier, drm_framebuffer_read_refcount(&fb->base)); describe_obj(m, fb->obj); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 87a0bba764c7..4f0675460336 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8715,7 +8715,6 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, pixel_format = val & DISPPLANE_PIXFORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); fb->pixel_format = fourcc; - fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; fb->format = drm_format_info(fourcc); if (INTEL_GEN(dev_priv) >= 4) { @@ -8744,7 +8743,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", pipe_name(pipe), plane, fb->width, fb->height, - fb->bits_per_pixel, base, fb->pitches[0], + fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); plane_config->fb = intel_fb; @@ -9747,7 +9746,6 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, val & PLANE_CTL_ORDER_RGBX, val & PLANE_CTL_ALPHA_MASK); fb->pixel_format = fourcc; - fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; fb->format = drm_format_info(fourcc); tiling = val & PLANE_CTL_TILED_MASK; @@ -9792,7 +9790,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", pipe_name(pipe), fb->width, fb->height, - fb->bits_per_pixel, base, fb->pitches[0], + fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); plane_config->fb = intel_fb; @@ -9863,7 +9861,6 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, pixel_format = val & DISPPLANE_PIXFORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); fb->pixel_format = fourcc; - fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; fb->format = drm_format_info(fourcc); base = I915_READ(DSPSURF(pipe)) & 0xfffff000; @@ -9892,7 +9889,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", pipe_name(pipe), fb->width, fb->height, - fb->bits_per_pixel, base, fb->pitches[0], + fb->format->cpp[0] * 8, base, fb->pitches[0], plane_config->size); plane_config->fb = intel_fb; @@ -11051,7 +11048,7 @@ mode_fits_in_fbdev(struct drm_device *dev, fb = &dev_priv->fbdev->fb->base; if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay, - fb->bits_per_pixel)) + fb->format->cpp[0] * 8)) return NULL; if (obj->base.size < mode->vdisplay * fb->pitches[0]) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index b726483a460d..3f60a4f6f078 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -621,7 +621,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, * rather than the current pipe's, since they differ. */ cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay; - cur_size = cur_size * fb->base.bits_per_pixel / 8; + cur_size = cur_size * fb->base.format->cpp[0]; if (fb->base.pitches[0] < cur_size) { DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n", pipe_name(intel_crtc->pipe), @@ -639,7 +639,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, pipe_name(intel_crtc->pipe), intel_crtc->config->base.adjusted_mode.crtc_hdisplay, intel_crtc->config->base.adjusted_mode.crtc_vdisplay, - fb->base.bits_per_pixel, + fb->base.format->cpp[0] * 8, cur_size); if (cur_size > max_size) { @@ -660,7 +660,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, goto out; } - ifbdev->preferred_bpp = fb->base.bits_per_pixel; + ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8; ifbdev->fb = fb; drm_framebuffer_reference(&ifbdev->fb->base); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c index 19a78b6b5a1a..1a665e1671b8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -24,7 +24,7 @@ static void mga_dirty_update(struct mga_fbdev *mfbdev, struct drm_gem_object *obj; struct mgag200_bo *bo; int src_offset, dst_offset; - int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8; + int bpp = mfbdev->mfb.base.format->cpp[0]; int ret = -EBUSY; bool unmap = false; bool store_for_later = false; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 9399099d3e39..067dfbc91b1c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -38,7 +38,7 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) WREG8(DAC_INDEX + MGA1064_INDEX, 0); - if (fb && fb->bits_per_pixel == 16) { + if (fb && fb->format->cpp[0] * 8 == 16) { int inc = (fb->format->depth == 15) ? 8 : 4; u8 r, b; for (i = 0; i < MGAG200_LUT_SIZE; i += inc) { @@ -903,7 +903,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0 }; - bppshift = mdev->bpp_shifts[(fb->bits_per_pixel >> 3) - 1]; + bppshift = mdev->bpp_shifts[fb->format->cpp[0] - 1]; switch (mdev->type) { case G200_SE_A: @@ -942,7 +942,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, break; } - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits; break; @@ -998,8 +998,8 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, WREG_SEQ(3, 0); WREG_SEQ(4, 0xe); - pitch = fb->pitches[0] / (fb->bits_per_pixel / 8); - if (fb->bits_per_pixel == 24) + pitch = fb->pitches[0] / fb->format->cpp[0]; + if (fb->format->cpp[0] * 8 == 24) pitch = (pitch * 3) >> (4 - bppshift); else pitch = pitch >> (4 - bppshift); @@ -1076,7 +1076,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, ((vdisplay & 0xc00) >> 7) | ((vsyncstart & 0xc00) >> 5) | ((vdisplay & 0x400) >> 3); - if (fb->bits_per_pixel == 24) + if (fb->format->cpp[0] * 8 == 24) ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80; else ext_vga[3] = ((1 << bppshift) - 1) | 0x80; @@ -1139,9 +1139,9 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, u32 bpp; u32 mb; - if (fb->bits_per_pixel > 16) + if (fb->format->cpp[0] * 8 > 16) bpp = 32; - else if (fb->bits_per_pixel > 8) + else if (fb->format->cpp[0] * 8 > 8) bpp = 16; else bpp = 8; diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 480e3ab477fd..a72754d73c84 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -874,11 +874,11 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, /* Update the framebuffer location. */ regp->fb_start = nv_crtc->fb.offset & ~3; - regp->fb_start += (y * drm_fb->pitches[0]) + (x * drm_fb->bits_per_pixel / 8); + regp->fb_start += (y * drm_fb->pitches[0]) + (x * drm_fb->format->cpp[0]); nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); /* Update the arbitration parameters. */ - nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, + nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->format->cpp[0] * 8, &arb_burst, &arb_lwm); regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e0db5d38fb18..c5cf88859b0b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -947,7 +947,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* Initialize a page flip struct */ *s = (struct nouveau_page_flip_state) - { { }, event, crtc, fb->bits_per_pixel, fb->pitches[0], + { { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0], new_bo->bo.offset }; /* Keep vblanks on during flip, for the target crtc of this flip */ diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index 9b728edf1b49..4d8681e84e68 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c @@ -283,7 +283,7 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, struct qxl_rect *rects; int stride = qxl_fb->base.pitches[0]; /* depth is not actually interesting, we don't mask with it */ - int depth = qxl_fb->base.bits_per_pixel; + int depth = qxl_fb->base.format->cpp[0] * 8; uint8_t *surface_base; struct qxl_release *release; struct qxl_bo *clips_bo; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 05f4ebe31ce2..0d7f84f7d71d 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1277,7 +1277,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, /* Calculate the macrotile mode index. */ tile_split_bytes = 64 << tile_split; - tileb = 8 * 8 * target_fb->bits_per_pixel / 8; + tileb = 8 * 8 * target_fb->format->cpp[0]; tileb = min(tile_split_bytes, tileb); for (index = 0; tileb > 64; index++) @@ -1285,13 +1285,14 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, if (index >= 16) { DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n", - target_fb->bits_per_pixel, tile_split); + target_fb->format->cpp[0] * 8, + tile_split); return -EINVAL; } num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3; } else { - switch (target_fb->bits_per_pixel) { + switch (target_fb->format->cpp[0] * 8) { case 8: index = 10; break; @@ -1414,7 +1415,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1); @@ -1621,7 +1622,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width); WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height); - fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); + fb_pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 984b35f43554..e3399310d41d 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3229,7 +3229,7 @@ void r100_bandwidth_update(struct radeon_device *rdev) rdev->mode_info.crtcs[0]->base.primary->fb; mode1 = &rdev->mode_info.crtcs[0]->base.mode; - pixel_bytes1 = fb->bits_per_pixel / 8; + pixel_bytes1 = fb->format->cpp[0]; } if (!(rdev->flags & RADEON_SINGLE_CRTC)) { if (rdev->mode_info.crtcs[1]->base.enabled) { @@ -3237,7 +3237,7 @@ void r100_bandwidth_update(struct radeon_device *rdev) rdev->mode_info.crtcs[1]->base.primary->fb; mode2 = &rdev->mode_info.crtcs[1]->base.mode; - pixel_bytes2 = fb->bits_per_pixel / 8; + pixel_bytes2 = fb->format->cpp[0]; } } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 6285355eb5d5..aea8b62835a4 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -549,19 +549,19 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, if (!ASIC_IS_AVIVO(rdev)) { /* crtc offset is from display base addr not FB location */ base -= radeon_crtc->legacy_display_base_addr; - pitch_pixels = fb->pitches[0] / (fb->bits_per_pixel / 8); + pitch_pixels = fb->pitches[0] / fb->format->cpp[0]; if (tiling_flags & RADEON_TILING_MACRO) { if (ASIC_IS_R300(rdev)) { base &= ~0x7ff; } else { - int byteshift = fb->bits_per_pixel >> 4; + int byteshift = fb->format->cpp[0] * 8 >> 4; int tile_addr = (((crtc->y >> 3) * pitch_pixels + crtc->x) >> (8 - byteshift)) << 11; base += tile_addr + ((crtc->x << byteshift) % 256) + ((crtc->y % 8) << 8); } } else { int offset = crtc->y * pitch_pixels + crtc->x; - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: default: offset *= 1; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 31c03e32a6b5..ce6cb6666212 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -402,7 +402,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, target_fb = crtc->primary->fb; } - switch (target_fb->bits_per_pixel) { + switch (target_fb->format->cpp[0] * 8) { case 8: format = 2; break; @@ -476,9 +476,9 @@ retry: crtc_offset_cntl = 0; - pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8); - crtc_pitch = DIV_ROUND_UP(pitch_pixels * target_fb->bits_per_pixel, - target_fb->bits_per_pixel * 8); + pitch_pixels = target_fb->pitches[0] / target_fb->format->cpp[0]; + crtc_pitch = DIV_ROUND_UP(pitch_pixels * target_fb->format->cpp[0] * 8, + target_fb->format->cpp[0] * 8 * 8); crtc_pitch |= crtc_pitch << 16; crtc_offset_cntl |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; @@ -503,14 +503,14 @@ retry: crtc_tile_x0_y0 = x | (y << 16); base &= ~0x7ff; } else { - int byteshift = target_fb->bits_per_pixel >> 4; + int byteshift = target_fb->format->cpp[0] * 8 >> 4; int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); crtc_offset_cntl |= (y % 16); } } else { int offset = y * pitch_pixels + x; - switch (target_fb->bits_per_pixel) { + switch (target_fb->format->cpp[0] * 8) { case 8: offset *= 1; break; @@ -602,7 +602,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod } } - switch (fb->bits_per_pixel) { + switch (fb->format->cpp[0] * 8) { case 8: format = 2; break; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b60c306190e9..642dcff87e34 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -568,7 +568,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, window.dst.y = plane->state->crtc_y; window.dst.w = plane->state->crtc_w; window.dst.h = plane->state->crtc_h; - window.bits_per_pixel = fb->bits_per_pixel; + window.bits_per_pixel = fb->format->cpp[0] * 8; window.bottom_up = tegra_fb_is_bottom_up(fb); /* copy from state */ diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index d2893f65341a..e289dbc6ad82 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -877,7 +877,7 @@ static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", fb->base.id, fb->width, fb->height, fb->format->depth, - fb->bits_per_pixel, + fb->format->cpp[0] * 8, drm_framebuffer_read_refcount(fb)); } diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index e21a3ed3ab2b..b8dc06d68777 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -89,7 +89,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, int bytes_identical = 0; struct urb *urb; int aligned_x; - int bpp = (fb->base.bits_per_pixel / 8); + int bpp = fb->base.format->cpp[0]; if (!fb->active_16) return 0; diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index 9d0da42cc420..61254b991265 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c @@ -43,7 +43,7 @@ static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, struct drm_device *dev = fb->base.dev; struct virtio_gpu_device *vgdev = dev->dev_private; bool store_for_later = false; - int bpp = fb->base.bits_per_pixel / 8; + int bpp = fb->base.format->cpp[0]; int x2, y2; unsigned long flags; struct virtio_gpu_object *obj = gem_to_virtio_gpu_obj(fb->obj); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 4a7a7d2997dd..58643c5ca1d7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -93,7 +93,7 @@ static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green, default: DRM_ERROR("Bad depth %u, bpp %u.\n", par->set_fb->format->depth, - par->set_fb->bits_per_pixel); + par->set_fb->format->cpp[0] * 8); return 1; } @@ -198,7 +198,7 @@ static void vmw_fb_dirty_flush(struct work_struct *work) * Handle panning when copying from vmalloc to framebuffer. * Clip dirty area to framebuffer. */ - cpp = (cur_fb->bits_per_pixel + 7) / 8; + cpp = cur_fb->format->cpp[0]; max_x = par->fb_x + cur_fb->width; max_y = par->fb_y + cur_fb->height; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index a3a839a3d441..3806148e1bdb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -97,7 +97,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) fb = entry->base.crtc.primary->fb; return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], - fb->bits_per_pixel, + fb->format->cpp[0] * 8, fb->format->depth); } @@ -106,7 +106,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) fb = entry->base.crtc.primary->fb; vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], - fb->bits_per_pixel, fb->format->depth); + fb->format->cpp[0] * 8, fb->format->depth); } /* Make sure we always show something. */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 38d7b8a2b78e..d4268efc37d2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -618,7 +618,7 @@ static int do_dmabuf_define_gmrfb(struct vmw_private *dev_priv, } cmd->header = SVGA_CMD_DEFINE_GMRFB; - cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel; + cmd->body.format.bitsPerPixel = framebuffer->base.format->cpp[0] * 8; cmd->body.format.colorDepth = depth; cmd->body.format.reserved = 0; cmd->body.bytesPerLine = framebuffer->base.pitches[0]; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 94ad8d2acf9a..b27cd18ee66a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -424,7 +424,7 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv, */ if (new_content_type == SEPARATE_DMA) { - switch (new_fb->bits_per_pixel) { + switch (new_fb->format->cpp[0] * 8) { case 32: content_srf.format = SVGA3D_X8R8G8B8; break; diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 0c14f0adf161..72b9b4898915 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -169,13 +169,6 @@ struct drm_framebuffer { * pixels. */ unsigned int height; - /** - * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for - * everything else. Legacy information derived from @pixel_format, it's - * suggested to use the DRM FOURCC codes and helper functions directly - * instead. - */ - int bits_per_pixel; /** * @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or * DRM_MODE_FB_MODIFIERS. -- cgit v1.2.3 From 438b74a5497c36d6d59baded434002e30267cabe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 14 Dec 2016 23:32:55 +0200 Subject: drm: Nuke fb->pixel_format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace uses of fb->pixel_format with fb->format->format. Less duplicated information is a good thing. Note that coccinelle failed to eliminate the "/* fourcc format */" comment from drm_framebuffer.h, so I had to do that part manually. @@ struct drm_framebuffer *FB; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - FB->pixel_format = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ i9xx_get_initial_plane_config(...) { ... - FB->pixel_format = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ ironlake_get_initial_plane_config(...) { ... - FB->pixel_format = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ skylake_get_initial_plane_config(...) { ... - FB->pixel_format = E; ... } @@ struct drm_framebuffer *a; struct drm_framebuffer b; @@ ( - a->pixel_format + a->format->format | - b.pixel_format + b.format->format ) @@ struct drm_plane_state *a; struct drm_plane_state b; @@ ( - a->fb->pixel_format + a->fb->format->format | - b.fb->pixel_format + b.fb->format->format ) @@ struct drm_crtc *CRTC; @@ ( - CRTC->primary->fb->pixel_format + CRTC->primary->fb->format->format | - CRTC->primary->state->fb->pixel_format + CRTC->primary->state->fb->format->format ) @@ struct drm_mode_set *set; @@ ( - set->fb->pixel_format + set->fb->format->format | - set->crtc->primary->fb->pixel_format + set->crtc->primary->fb->format->format ) @@ @@ struct drm_framebuffer { ... - uint32_t pixel_format; ... }; v2: Fix commit message (Laurent) Rebase due to earlier removal of many fb->pixel_format uses, including the 'fb->format = drm_format_info(fb->format->format);' snafu v3: Adjusted the semantic patch a bit and regenerated due to code changes Cc: Laurent Pinchart Signed-off-by: Ville Syrjälä Reviewed-by: Alex Deucher (v1) Reviewed-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1481751175-18463-1-git-send-email-ville.syrjala@linux.intel.com --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 4 +-- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 4 +-- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 4 +-- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 4 +-- drivers/gpu/drm/arc/arcpgu_crtc.c | 2 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 2 +- drivers/gpu/drm/arm/malidp_planes.c | 8 +++--- drivers/gpu/drm/armada/armada_crtc.c | 2 +- drivers/gpu/drm/armada/armada_overlay.c | 2 +- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 18 ++++++------- drivers/gpu/drm/drm_atomic.c | 6 ++--- drivers/gpu/drm/drm_crtc.c | 4 +-- drivers/gpu/drm/drm_crtc_helper.c | 4 +-- drivers/gpu/drm/drm_fb_cma_helper.c | 2 +- drivers/gpu/drm/drm_modeset_helper.c | 1 - drivers/gpu/drm/drm_plane.c | 6 ++--- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 2 +- drivers/gpu/drm/exynos/exynos7_drm_decon.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.c | 8 +++--- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 4 +-- drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 6 ++--- drivers/gpu/drm/i915/i915_debugfs.c | 3 ++- drivers/gpu/drm/i915/intel_atomic_plane.c | 4 +-- drivers/gpu/drm/i915/intel_display.c | 33 +++++++++++------------- drivers/gpu/drm/i915/intel_fbdev.c | 2 +- drivers/gpu/drm/i915/intel_overlay.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 10 ++++---- drivers/gpu/drm/i915/intel_sprite.c | 12 ++++----- drivers/gpu/drm/imx/ipuv3-plane.c | 34 ++++++++++++------------- drivers/gpu/drm/mediatek/mtk_drm_plane.c | 2 +- drivers/gpu/drm/meson/meson_plane.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 2 +- drivers/gpu/drm/msm/msm_fb.c | 2 +- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +++--- drivers/gpu/drm/nouveau/nv50_display.c | 4 +-- drivers/gpu/drm/omapdrm/omap_fb.c | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 8 +++--- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +-- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 4 +-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 18 ++++++------- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 ++--- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 4 +-- drivers/gpu/drm/sti/sti_gdp.c | 8 +++--- drivers/gpu/drm/sti/sti_hqvdp.c | 2 +- drivers/gpu/drm/sun4i/sun4i_backend.c | 3 ++- drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_plane.c | 2 +- drivers/gpu/drm/vc4/vc4_plane.c | 4 +-- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 2 +- drivers/gpu/drm/zte/zx_plane.c | 2 +- include/drm/drm_framebuffer.h | 4 --- 54 files changed, 145 insertions(+), 151 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 8d0ff1c8db8e..84afaae97e65 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2072,7 +2072,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = REG_SET_FIELD(0, GRPH_CONTROL, GRPH_DEPTH, 0); fb_format = REG_SET_FIELD(fb_format, GRPH_CONTROL, GRPH_FORMAT, 0); @@ -2145,7 +2145,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index c25edecb46d4..7a7fa96d2e49 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2053,7 +2053,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = REG_SET_FIELD(0, GRPH_CONTROL, GRPH_DEPTH, 0); fb_format = REG_SET_FIELD(fb_format, GRPH_CONTROL, GRPH_FORMAT, 0); @@ -2126,7 +2126,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index ffd20f90788c..59eff6e9a883 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1501,7 +1501,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, amdgpu_bo_get_tiling_flags(abo, &tiling_flags); amdgpu_bo_unreserve(abo); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = (GRPH_DEPTH(GRPH_DEPTH_8BPP) | GRPH_FORMAT(GRPH_FORMAT_INDEXED)); @@ -1567,7 +1567,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index e6f446af3818..8de832dd981d 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1950,7 +1950,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = ((GRPH_DEPTH_8BPP << GRPH_CONTROL__GRPH_DEPTH__SHIFT) | (GRPH_FORMAT_INDEXED << GRPH_CONTROL__GRPH_FORMAT__SHIFT)); @@ -2016,7 +2016,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index 5c26c5f126a3..ad9a95916f1f 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -36,7 +36,7 @@ static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); const struct drm_framebuffer *fb = crtc->primary->state->fb; - uint32_t pixel_format = fb->pixel_format; + uint32_t pixel_format = fb->format->format; struct simplefb_format *format = NULL; int i; diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index ecdcd99c92cc..20ebfb4fbdfa 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -65,7 +65,7 @@ static int hdlcd_set_pxl_fmt(struct drm_crtc *crtc) struct simplefb_format *format = NULL; int i; - pixel_format = fb->pixel_format; + pixel_format = fb->format->format; for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { if (supported_formats[i].fourcc == pixel_format) diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 533ee2fa64be..eff2fe47e26a 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -112,7 +112,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, fb = state->fb; ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, - fb->pixel_format); + fb->format->format); if (ms->format == MALIDP_INVALID_FORMAT_ID) return -EINVAL; @@ -137,8 +137,8 @@ static int malidp_de_plane_check(struct drm_plane *plane, /* packed RGB888 / BGR888 can't be rotated or flipped */ if (state->rotation != DRM_ROTATE_0 && - (fb->pixel_format == DRM_FORMAT_RGB888 || - fb->pixel_format == DRM_FORMAT_BGR888)) + (fb->format->format == DRM_FORMAT_RGB888 || + fb->format->format == DRM_FORMAT_BGR888)) return -EINVAL; ms->rotmem_size = 0; @@ -147,7 +147,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, val = mp->hwdev->rotmem_required(mp->hwdev, state->crtc_h, state->crtc_w, - fb->pixel_format); + fb->format->format); if (val < 0) return val; diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 426e86f4cf96..41fc6ee9da91 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -1035,7 +1035,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc, int ret; /* We don't support changing the pixel format */ - if (fb->pixel_format != crtc->primary->fb->pixel_format) + if (fb->format->format != crtc->primary->fb->format->format) return -EINVAL; work = kmalloc(sizeof(*work), GFP_KERNEL); diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index a0883a1b3387..34cb73d0db77 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -186,7 +186,7 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y); - pixel_format = fb->pixel_format; + pixel_format = fb->format->format; hsub = drm_format_horz_chroma_subsampling(pixel_format); num_planes = fb->format->num_planes; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 3e00512ef187..bd2791c4b002 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -356,7 +356,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL | ATMEL_HLCDC_LAYER_ITER; - if (atmel_hlcdc_format_embeds_alpha(state->base.fb->pixel_format)) + if (atmel_hlcdc_format_embeds_alpha(state->base.fb->format->format)) cfg |= ATMEL_HLCDC_LAYER_LAEN; else cfg |= ATMEL_HLCDC_LAYER_GAEN | @@ -386,13 +386,13 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, u32 cfg; int ret; - ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->pixel_format, + ret = atmel_hlcdc_format_to_plane_mode(state->base.fb->format->format, &cfg); if (ret) return; - if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 || - state->base.fb->pixel_format == DRM_FORMAT_NV61) && + if ((state->base.fb->format->format == DRM_FORMAT_YUV422 || + state->base.fb->format->format == DRM_FORMAT_NV61) && drm_rotation_90_or_270(state->base.rotation)) cfg |= ATMEL_HLCDC_YUV422ROT; @@ -405,7 +405,7 @@ static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, * Rotation optimization is not working on RGB888 (rotation is still * working but without any optimization). */ - if (state->base.fb->pixel_format == DRM_FORMAT_RGB888) + if (state->base.fb->format->format == DRM_FORMAT_RGB888) cfg = ATMEL_HLCDC_LAYER_DMA_ROTDIS; else cfg = 0; @@ -514,7 +514,7 @@ atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state) ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s); if (!ovl_s->fb || - atmel_hlcdc_format_embeds_alpha(ovl_s->fb->pixel_format) || + atmel_hlcdc_format_embeds_alpha(ovl_s->fb->format->format) || ovl_state->alpha != 255) continue; @@ -664,8 +664,8 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, patched_src_h = DIV_ROUND_CLOSEST(patched_crtc_h * state->src_h, state->crtc_h); - hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); - vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); + hsub = drm_format_horz_chroma_subsampling(fb->format->format); + vsub = drm_format_vert_chroma_subsampling(fb->format->format); for (i = 0; i < state->nplanes; i++) { unsigned int offset = 0; @@ -741,7 +741,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, if ((state->crtc_h != state->src_h || state->crtc_w != state->src_w) && (!layout->memsize || - atmel_hlcdc_format_embeds_alpha(state->base.fb->pixel_format))) + atmel_hlcdc_format_embeds_alpha(state->base.fb->format->format))) return -EINVAL; if (state->crtc_x < 0 || state->crtc_y < 0) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 62f0f57728e1..b602faf28367 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -902,11 +902,11 @@ static int drm_atomic_plane_check(struct drm_plane *plane, } /* Check whether this plane supports the fb pixel format. */ - ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format); + ret = drm_plane_check_pixel_format(plane, state->fb->format->format); if (ret) { struct drm_format_name_buf format_name; DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", - drm_get_format_name(state->fb->pixel_format, + drm_get_format_name(state->fb->format->format, &format_name)); return ret; } @@ -964,7 +964,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, struct drm_format_name_buf format_name; drm_printf(p, "\t\tformat=%s\n", - drm_get_format_name(fb->pixel_format, &format_name)); + drm_get_format_name(fb->format->format, &format_name)); drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier); drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height); drm_printf(p, "\t\tlayers:\n"); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 14c58072651b..080c8d361f1f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -575,11 +575,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, */ if (!crtc->primary->format_default) { ret = drm_plane_check_pixel_format(crtc->primary, - fb->pixel_format); + fb->format->format); if (ret) { struct drm_format_name_buf format_name; DRM_DEBUG_KMS("Invalid pixel format %s\n", - drm_get_format_name(fb->pixel_format, + drm_get_format_name(fb->format->format, &format_name)); goto out; } diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 5d2cb138eba6..94bce0b462aa 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -588,8 +588,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (set->crtc->primary->fb == NULL) { DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); mode_changed = true; - } else if (set->fb->pixel_format != - set->crtc->primary->fb->pixel_format) { + } else if (set->fb->format->format != + set->crtc->primary->fb->format->format) { mode_changed = true; } else fb_changed = true; diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 181a9eafe34a..aab4465307ed 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -307,7 +307,7 @@ static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) int i; seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, - (char *)&fb->pixel_format); + (char *)&fb->format->format); for (i = 0; i < fb->fomat->num_planes; i++) { seq_printf(m, " %d: offset=%d pitch=%d, obj: ", diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 3c44409244dc..639e474e7d43 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -94,7 +94,6 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev, fb->offsets[i] = mode_cmd->offsets[i]; } fb->modifier = mode_cmd->modifier[0]; - fb->pixel_format = mode_cmd->pixel_format; fb->flags = mode_cmd->flags; } EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index c2dc8e6f80ff..f479cda5fc2d 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -482,11 +482,11 @@ static int __setplane_internal(struct drm_plane *plane, } /* Check whether this plane supports the fb pixel format. */ - ret = drm_plane_check_pixel_format(plane, fb->pixel_format); + ret = drm_plane_check_pixel_format(plane, fb->format->format); if (ret) { struct drm_format_name_buf format_name; DRM_DEBUG_KMS("Invalid pixel format %s\n", - drm_get_format_name(fb->pixel_format, + drm_get_format_name(fb->format->format, &format_name)); goto out; } @@ -858,7 +858,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if (ret) goto out; - if (crtc->primary->fb->pixel_format != fb->pixel_format) { + if (crtc->primary->fb->format->format != fb->format->format) { DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); ret = -EINVAL; goto out; diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index e8ce4a318586..c5c01628c715 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -200,7 +200,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, val = readl(ctx->addr + DECON_WINCONx(win)); val &= ~WINCONx_BPPMODE_MASK; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_XRGB1555: val |= WINCONx_BPPMODE_16BPP_I1555; val |= WINCONx_HAWSWP_F; diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index 58dc9a5196bc..f9ab19e205e2 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -281,7 +281,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, val = readl(ctx->regs + WINCON(win)); val &= ~WINCONx_BPPMODE_MASK; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_RGB565: val |= WINCONx_BPPMODE_16BPP_565; val |= WINCONx_BURSTLEN_16WORD; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 0029065979b8..745cfbdf6b39 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -804,7 +804,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); } - fimd_win_set_pixfmt(ctx, win, fb->pixel_format, state->src.w); + fimd_win_set_pixfmt(ctx, win, fb->format->format, state->src.w); /* hardware window 0 doesn't support color key. */ if (win != 0) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index b313e61aab65..a106046e0c93 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -485,7 +485,7 @@ static void vp_video_buffer(struct mixer_context *ctx, bool crcb_mode = false; u32 val; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_NV12: crcb_mode = false; break; @@ -494,7 +494,7 @@ static void vp_video_buffer(struct mixer_context *ctx, break; default: DRM_ERROR("pixel format for vp is wrong [%d].\n", - fb->pixel_format); + fb->format->format); return; } @@ -597,7 +597,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, unsigned int fmt; u32 val; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_XRGB4444: case DRM_FORMAT_ARGB4444: fmt = MXR_FORMAT_ARGB4444; @@ -681,7 +681,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, mixer_cfg_scan(ctx, mode->vdisplay); mixer_cfg_rgb_fmt(ctx, mode->vdisplay); mixer_cfg_layer(ctx, win, priority, true); - mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format)); + mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->format->format)); /* layer update mandatory for mixer 16.0.33.0 */ if (ctx->mxr_ver == MXR_VER_16_0_33_0 || diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index a99f48847420..0a20723aa6e1 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -44,7 +44,7 @@ static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane, if (!state->fb || !state->crtc) return 0; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_RGB565: case DRM_FORMAT_RGB888: case DRM_FORMAT_XRGB8888: @@ -96,7 +96,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, gem = drm_fb_cma_get_gem_obj(fb, 0); - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_RGB565: bpp = FSL_DCU_RGB565; break; diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 3ea70459b901..307d460ab684 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -617,7 +617,7 @@ static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb, ch + 1, y, in_h, stride, (u32)obj->paddr); DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n", addr, fb->width, fb->height, fmt, - drm_get_format_name(fb->pixel_format, &format_name)); + drm_get_format_name(fb->format->format, &format_name)); /* get reg offset */ reg_ctrl = RD_CH_CTRL(ch); @@ -773,7 +773,7 @@ static void ade_update_channel(struct ade_plane *aplane, { struct ade_hw_ctx *ctx = aplane->ctx; void __iomem *base = ctx->base; - u32 fmt = ade_get_format(fb->pixel_format); + u32 fmt = ade_get_format(fb->format->format); u32 ch = aplane->ch; u32 in_w; u32 in_h; @@ -835,7 +835,7 @@ static int ade_plane_atomic_check(struct drm_plane *plane, if (!crtc || !fb) return 0; - fmt = ade_get_format(fb->pixel_format); + fmt = ade_get_format(fb->format->format); if (fmt == ADE_FORMAT_UNSUPPORT) return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ec462dae46bc..b77b53b47acc 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3021,7 +3021,8 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc) state = plane->state; if (state->fb) { - drm_get_format_name(state->fb->pixel_format, &format_name); + drm_get_format_name(state->fb->format->format, + &format_name); } else { sprintf(format_name.str, "N/A"); } diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index dbe9fb41ae53..e049838159a1 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -155,11 +155,11 @@ static int intel_plane_atomic_check(struct drm_plane *plane, * RGB 16-bit 5:6:5, and Indexed 8-bit. * TBD: Add RGB64 case once its added in supported format list. */ - switch (state->fb->pixel_format) { + switch (state->fb->format->format) { case DRM_FORMAT_C8: case DRM_FORMAT_RGB565: DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", - drm_get_format_name(state->fb->pixel_format, + drm_get_format_name(state->fb->format->format, &format_name)); return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4f0675460336..3b56b2cae804 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2455,7 +2455,7 @@ u32 intel_compute_tile_offset(int *x, int *y, u32 alignment; /* AUX_DIST needs only 4K alignment */ - if (fb->pixel_format == DRM_FORMAT_NV12 && plane == 1) + if (fb->format->format == DRM_FORMAT_NV12 && plane == 1) alignment = 4096; else alignment = intel_surf_alignment(dev_priv, fb->modifier); @@ -2700,7 +2700,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, if (plane_config->tiling == I915_TILING_X) obj->tiling_and_stride = fb->pitches[0] | I915_TILING_X; - mode_cmd.pixel_format = fb->pixel_format; + mode_cmd.pixel_format = fb->format->format; mode_cmd.width = fb->width; mode_cmd.height = fb->height; mode_cmd.pitches[0] = fb->pitches[0]; @@ -2976,7 +2976,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) * Handle the AUX surface first since * the main surface setup depends on it. */ - if (fb->pixel_format == DRM_FORMAT_NV12) { + if (fb->format->format == DRM_FORMAT_NV12) { ret = skl_check_nv12_aux_surface(plane_state); if (ret) return ret; @@ -3031,7 +3031,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, I915_WRITE(PRIMCNSTALPHA(plane), 0); } - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_C8: dspcntr |= DISPPLANE_8BPP; break; @@ -3146,7 +3146,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_C8: dspcntr |= DISPPLANE_8BPP; break; @@ -3282,7 +3282,7 @@ u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, stride /= intel_tile_height(dev_priv, fb->modifier, cpp); } else { stride /= intel_fb_stride_alignment(dev_priv, fb->modifier, - fb->pixel_format); + fb->format->format); } return stride; @@ -3396,7 +3396,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane, PLANE_CTL_PIPE_GAMMA_ENABLE | PLANE_CTL_PIPE_CSC_ENABLE; - plane_ctl |= skl_plane_ctl_format(fb->pixel_format); + plane_ctl |= skl_plane_ctl_format(fb->format->format); plane_ctl |= skl_plane_ctl_tiling(fb->modifier); plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; plane_ctl |= skl_plane_ctl_rotation(rotation); @@ -4768,7 +4768,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, } /* Check src format */ - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_RGB565: case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XRGB8888: @@ -4784,7 +4784,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, default: DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", intel_plane->base.base.id, intel_plane->base.name, - fb->base.id, fb->pixel_format); + fb->base.id, fb->format->format); return -EINVAL; } @@ -8714,7 +8714,6 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, pixel_format = val & DISPPLANE_PIXFORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); - fb->pixel_format = fourcc; fb->format = drm_format_info(fourcc); if (INTEL_GEN(dev_priv) >= 4) { @@ -8736,7 +8735,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc, fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(dev, fb->height, - fb->pixel_format, + fb->format->format, fb->modifier); plane_config->size = fb->pitches[0] * aligned_height; @@ -9745,7 +9744,6 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, fourcc = skl_format_to_fourcc(pixel_format, val & PLANE_CTL_ORDER_RGBX, val & PLANE_CTL_ALPHA_MASK); - fb->pixel_format = fourcc; fb->format = drm_format_info(fourcc); tiling = val & PLANE_CTL_TILED_MASK; @@ -9779,11 +9777,11 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc, val = I915_READ(PLANE_STRIDE(pipe, 0)); stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier, - fb->pixel_format); + fb->format->format); fb->pitches[0] = (val & 0x3ff) * stride_mult; aligned_height = intel_fb_align_height(dev, fb->height, - fb->pixel_format, + fb->format->format, fb->modifier); plane_config->size = fb->pitches[0] * aligned_height; @@ -9860,7 +9858,6 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, pixel_format = val & DISPPLANE_PIXFORMAT_MASK; fourcc = i9xx_format_to_fourcc(pixel_format); - fb->pixel_format = fourcc; fb->format = drm_format_info(fourcc); base = I915_READ(DSPSURF(pipe)) & 0xfffff000; @@ -9882,7 +9879,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, fb->pitches[0] = val & 0xffffffc0; aligned_height = intel_fb_align_height(dev, fb->height, - fb->pixel_format, + fb->format->format, fb->modifier); plane_config->size = fb->pitches[0] * aligned_height; @@ -12150,7 +12147,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return -EBUSY; /* Can't change pixel format via MI display flips. */ - if (fb->pixel_format != crtc->primary->fb->pixel_format) + if (fb->format->format != crtc->primary->fb->format->format) return -EINVAL; /* @@ -12847,7 +12844,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d, fb = %ux%u format = %s\n", plane->base.id, plane->name, fb->base.id, fb->width, fb->height, - drm_get_format_name(fb->pixel_format, &format_name)); + drm_get_format_name(fb->format->format, &format_name)); if (INTEL_GEN(dev_priv) >= 9) DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n", state->scaler_id, diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 3f60a4f6f078..570c07d59d1a 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -632,7 +632,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay; cur_size = intel_fb_align_height(dev, cur_size, - fb->base.pixel_format, + fb->base.format->format, fb->base.modifier); cur_size *= fb->base.pitches[0]; DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n", diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index ce3667c18e18..568d194435fd 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -667,7 +667,7 @@ static void update_colorkey(struct intel_overlay *overlay, if (overlay->color_key_enabled) flags |= DST_KEY_ENABLE; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_C8: key = 0; flags |= CLK_RGB8I_MASK; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f6406ebd533c..ce03d9d5aca6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3241,7 +3241,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate, return 0; fb = pstate->fb; - format = fb->pixel_format; + format = fb->format->format; if (pstate->plane->type == DRM_PLANE_TYPE_CURSOR) return 0; @@ -3330,7 +3330,7 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, return 0; /* For packed formats, no y-plane, return 0 */ - if (y && fb->pixel_format != DRM_FORMAT_NV12) + if (y && fb->format->format != DRM_FORMAT_NV12) return 0; /* For Non Y-tile return 8-blocks */ @@ -3345,12 +3345,12 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate, swap(src_w, src_h); /* Halve UV plane width and height for NV12 */ - if (fb->pixel_format == DRM_FORMAT_NV12 && !y) { + if (fb->format->format == DRM_FORMAT_NV12 && !y) { src_w /= 2; src_h /= 2; } - if (fb->pixel_format == DRM_FORMAT_NV12 && !y) + if (fb->format->format == DRM_FORMAT_NV12 && !y) plane_bpp = fb->format->cpp[1]; else plane_bpp = fb->format->cpp[0]; @@ -3617,7 +3617,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); if (drm_rotation_90_or_270(pstate->rotation)) { - int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? + int cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : fb->format->cpp[0]; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b46c1794d3ac..ff766c0cb873 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -223,7 +223,7 @@ skl_update_plane(struct drm_plane *drm_plane, PLANE_CTL_PIPE_GAMMA_ENABLE | PLANE_CTL_PIPE_CSC_ENABLE; - plane_ctl |= skl_plane_ctl_format(fb->pixel_format); + plane_ctl |= skl_plane_ctl_format(fb->format->format); plane_ctl |= skl_plane_ctl_tiling(fb->modifier); plane_ctl |= skl_plane_ctl_rotation(rotation); @@ -357,7 +357,7 @@ vlv_update_plane(struct drm_plane *dplane, sprctl = SP_ENABLE; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_YUYV: sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; break; @@ -443,7 +443,7 @@ vlv_update_plane(struct drm_plane *dplane, sprctl |= SP_SOURCE_KEY; if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) - chv_update_csc(intel_plane, fb->pixel_format); + chv_update_csc(intel_plane, fb->format->format); I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); @@ -502,7 +502,7 @@ ivb_update_plane(struct drm_plane *plane, sprctl = SPRITE_ENABLE; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_XBGR8888: sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; break; @@ -640,7 +640,7 @@ ilk_update_plane(struct drm_plane *plane, dvscntr = DVS_ENABLE; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_XBGR8888: dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; break; @@ -866,7 +866,7 @@ intel_check_sprite_plane(struct drm_plane *plane, src_y = src->y1 >> 16; src_h = drm_rect_height(src) >> 16; - if (format_is_yuv(fb->pixel_format)) { + if (format_is_yuv(fb->format->format)) { src_x &= ~1; src_w &= ~1; diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index f44a83656310..0b945f077344 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -92,8 +92,8 @@ drm_plane_state_to_ubo(struct drm_plane_state *state) cma_obj = drm_fb_cma_get_gem_obj(fb, 1); BUG_ON(!cma_obj); - x /= drm_format_horz_chroma_subsampling(fb->pixel_format); - y /= drm_format_vert_chroma_subsampling(fb->pixel_format); + x /= drm_format_horz_chroma_subsampling(fb->format->format); + y /= drm_format_vert_chroma_subsampling(fb->format->format); return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y + fb->format->cpp[1] * x - eba; @@ -111,8 +111,8 @@ drm_plane_state_to_vbo(struct drm_plane_state *state) cma_obj = drm_fb_cma_get_gem_obj(fb, 2); BUG_ON(!cma_obj); - x /= drm_format_horz_chroma_subsampling(fb->pixel_format); - y /= drm_format_vert_chroma_subsampling(fb->pixel_format); + x /= drm_format_horz_chroma_subsampling(fb->format->format); + y /= drm_format_vert_chroma_subsampling(fb->format->format); return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y + fb->format->cpp[2] * x - eba; @@ -281,7 +281,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, */ if (old_fb && (state->src_w != old_state->src_w || state->src_h != old_state->src_h || - fb->pixel_format != old_fb->pixel_format)) + fb->format->format != old_fb->format->format)) crtc_state->mode_changed = true; eba = drm_plane_state_to_eba(state); @@ -295,7 +295,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (old_fb && fb->pitches[0] != old_fb->pitches[0]) crtc_state->mode_changed = true; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: case DRM_FORMAT_YUV422: @@ -315,7 +315,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (vbo & 0x7 || vbo > 0xfffff8) return -EINVAL; - if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { + if (old_fb && (fb->format->format == old_fb->format->format)) { old_vbo = drm_plane_state_to_vbo(old_state); if (vbo != old_vbo) crtc_state->mode_changed = true; @@ -332,7 +332,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (ubo & 0x7 || ubo > 0xfffff8) return -EINVAL; - if (old_fb && (fb->pixel_format == old_fb->pixel_format)) { + if (old_fb && (fb->format->format == old_fb->format->format)) { old_ubo = drm_plane_state_to_ubo(old_state); if (ubo != old_ubo) crtc_state->mode_changed = true; @@ -348,8 +348,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, * The x/y offsets must be even in case of horizontal/vertical * chroma subsampling. */ - hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); - vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); + hsub = drm_format_horz_chroma_subsampling(fb->format->format); + vsub = drm_format_vert_chroma_subsampling(fb->format->format); if (((state->src_x >> 16) & (hsub - 1)) || ((state->src_y >> 16) & (vsub - 1))) return -EINVAL; @@ -392,13 +392,13 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true); break; case IPU_DP_FLOW_SYNC_FG: - ics = ipu_drm_fourcc_to_colorspace(state->fb->pixel_format); + ics = ipu_drm_fourcc_to_colorspace(state->fb->format->format); ipu_dp_setup_channel(ipu_plane->dp, ics, IPUV3_COLORSPACE_UNKNOWN); ipu_dp_set_window_pos(ipu_plane->dp, state->crtc_x, state->crtc_y); /* Enable local alpha on partial plane */ - switch (state->fb->pixel_format) { + switch (state->fb->format->format) { case DRM_FORMAT_ARGB1555: case DRM_FORMAT_ABGR1555: case DRM_FORMAT_RGBA5551: @@ -421,11 +421,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, ipu_cpmem_zero(ipu_plane->ipu_ch); ipu_cpmem_set_resolution(ipu_plane->ipu_ch, state->src_w >> 16, state->src_h >> 16); - ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->pixel_format); + ipu_cpmem_set_fmt(ipu_plane->ipu_ch, state->fb->format->format); ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1); ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: case DRM_FORMAT_YUV422: @@ -434,9 +434,9 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, case DRM_FORMAT_YVU444: ubo = drm_plane_state_to_ubo(state); vbo = drm_plane_state_to_vbo(state); - if (fb->pixel_format == DRM_FORMAT_YVU420 || - fb->pixel_format == DRM_FORMAT_YVU422 || - fb->pixel_format == DRM_FORMAT_YVU444) + if (fb->format->format == DRM_FORMAT_YVU420 || + fb->format->format == DRM_FORMAT_YVU422 || + fb->format->format == DRM_FORMAT_YVU444) swap(ubo, vbo); ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index 71421923c592..e405e89ed5e5 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -133,7 +133,7 @@ static void mtk_plane_atomic_update(struct drm_plane *plane, mtk_gem = to_mtk_gem_obj(gem); addr = mtk_gem->dma_addr; pitch = fb->pitches[0]; - format = fb->pixel_format; + format = fb->format->format; addr += (plane->state->src.x1 >> 16) * fb->format->cpp[0]; addr += (plane->state->src.y1 >> 16) * pitch; diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 4942ca090b46..642b2fab42ff 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -113,7 +113,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane, if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_XRGB8888: /* For XRGB, replace the pixel's alpha by 0xFF */ writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN, diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 911e4690d36a..53619d07677e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c @@ -43,7 +43,7 @@ enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb) if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) is_tile = true; - if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile) + if (fb->format->format == DRM_FORMAT_NV12 && is_tile) return FRAME_TILE_YCBCR_420; return FRAME_LINEAR; diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 0649863d7fd7..5cf165c9c3a9 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -68,7 +68,7 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) int i, n = fb->format->num_planes; seq_printf(m, "fb: %dx%d@%4.4s (%2d, ID:%d)\n", - fb->width, fb->height, (char *)&fb->pixel_format, + fb->width, fb->height, (char *)&fb->format->format, drm_framebuffer_read_refcount(fb), fb->base.id); for (i = 0; i < n; i++) { diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 081890336ce7..e10a4eda4078 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -46,7 +46,7 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) { struct drm_crtc *crtc = &mxsfb->pipe.crtc; struct drm_device *drm = crtc->dev; - const u32 format = crtc->primary->state->fb->pixel_format; + const u32 format = crtc->primary->state->fb->format->format; u32 ctrl, ctrl1; ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER; diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index a79514d440b3..6275c270df25 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -145,16 +145,16 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, nvif_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x); nvif_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w); - if (fb->pixel_format != DRM_FORMAT_UYVY) + if (fb->format->format != DRM_FORMAT_UYVY) format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8; - if (fb->pixel_format == DRM_FORMAT_NV12) + if (fb->format->format == DRM_FORMAT_NV12) format |= NV_PVIDEO_FORMAT_PLANAR; if (nv_plane->iturbt_709) format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; if (nv_plane->colorkey & (1 << 24)) format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; - if (fb->pixel_format == DRM_FORMAT_NV12) { + if (fb->format->format == DRM_FORMAT_NV12) { nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0); nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset + fb->offsets[1]); @@ -411,7 +411,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, if (nv_plane->colorkey & (1 << 24)) overlay |= 0x10; - if (fb->pixel_format == DRM_FORMAT_YUYV) + if (fb->format->format == DRM_FORMAT_YUYV) overlay |= 0x100; nvif_wr32(dev, NV_PVIDEO_OVERLAY, overlay); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index b617e5d3277a..cb85cb72dc1c 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1153,7 +1153,7 @@ nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, if (asyw->state.fb->width != asyw->state.fb->height) return -EINVAL; - switch (asyw->state.fb->pixel_format) { + switch (asyw->state.fb->format->format) { case DRM_FORMAT_ARGB8888: asyh->curs.format = 1; break; default: WARN_ON(1); @@ -1438,7 +1438,7 @@ nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, asyh->base.w = asyw->state.fb->width; asyh->base.h = asyw->state.fb->height; - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_C8 : asyw->image.format = 0x1e; break; case DRM_FORMAT_RGB565 : asyw->image.format = 0xe8; break; case DRM_FORMAT_XRGB1555 : diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index c6ef457b9fca..bd6b94c38613 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -346,7 +346,7 @@ void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) int i, n = fb->format->num_planes; seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, - (char *)&fb->pixel_format); + (char *)&fb->format->format); for (i = 0; i < n; i++) { struct plane *plane = &omap_fb->planes[i]; diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 0d7f84f7d71d..3c492a0aa6bd 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1195,7 +1195,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); radeon_bo_unreserve(rbo); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED)); @@ -1261,7 +1261,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } @@ -1511,7 +1511,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); radeon_bo_unreserve(rbo); - switch (target_fb->pixel_format) { + switch (target_fb->format->format) { case DRM_FORMAT_C8: fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | @@ -1564,7 +1564,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, break; default: DRM_ERROR("Unsupported screen format %s\n", - drm_get_format_name(target_fb->pixel_format, &format_name)); + drm_get_format_name(target_fb->format->format, &format_name)); return -EINVAL; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index a74f8ed8ca2e..dcde6288da6c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -567,10 +567,10 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } - rstate->format = rcar_du_format_info(state->fb->pixel_format); + rstate->format = rcar_du_format_info(state->fb->format->format); if (rstate->format == NULL) { dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__, - state->fb->pixel_format); + state->fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 83ebd162f3ef..b5bfbe50bd87 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -201,10 +201,10 @@ static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, return -EINVAL; } - rstate->format = rcar_du_format_info(state->fb->pixel_format); + rstate->format = rcar_du_format_info(state->fb->format->format); if (rstate->format == NULL) { dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__, - state->fb->pixel_format); + state->fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 50e085e74214..fb5f001f51c3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -668,7 +668,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, if (!state->visible) return 0; - ret = vop_convert_format(fb->pixel_format); + ret = vop_convert_format(fb->format->format); if (ret < 0) return ret; @@ -676,7 +676,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, * Src.x1 can be odd when do clip, but yuv plane start point * need align with 2 pixel. */ - if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2)) + if (is_yuv_support(fb->format->format) && ((state->src.x1 >> 16) % 2)) return -EINVAL; return 0; @@ -753,16 +753,16 @@ static void vop_plane_atomic_update(struct drm_plane *plane, offset += (src->y1 >> 16) * fb->pitches[0]; dma_addr = rk_obj->dma_addr + offset + fb->offsets[0]; - format = vop_convert_format(fb->pixel_format); + format = vop_convert_format(fb->format->format); spin_lock(&vop->reg_lock); VOP_WIN_SET(vop, win, format, format); VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2); VOP_WIN_SET(vop, win, yrgb_mst, dma_addr); - if (is_yuv_support(fb->pixel_format)) { - int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); - int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); + if (is_yuv_support(fb->format->format)) { + int hsub = drm_format_horz_chroma_subsampling(fb->format->format); + int vsub = drm_format_vert_chroma_subsampling(fb->format->format); int bpp = fb->format->cpp[1]; uv_obj = rockchip_fb_get_gem_obj(fb, 1); @@ -779,16 +779,16 @@ static void vop_plane_atomic_update(struct drm_plane *plane, if (win->phy->scl) scl_vop_cal_scl_fac(vop, win, actual_w, actual_h, drm_rect_width(dest), drm_rect_height(dest), - fb->pixel_format); + fb->format->format); VOP_WIN_SET(vop, win, act_info, act_info); VOP_WIN_SET(vop, win, dsp_info, dsp_info); VOP_WIN_SET(vop, win, dsp_st, dsp_st); - rb_swap = has_rb_swapped(fb->pixel_format); + rb_swap = has_rb_swapped(fb->format->format); VOP_WIN_SET(vop, win, rb_swap, rb_swap); - if (is_alpha_support(fb->pixel_format)) { + if (is_alpha_support(fb->format->format)) { VOP_WIN_SET(vop, win, dst_alpha_ctl, DST_FACTOR_M0(ALPHA_SRC_INVERSE)); val = SRC_ALPHA_EN(1) | SRC_COLOR_M0(ALPHA_SRC_PRE_MUL) | diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index dddbdd62bed0..445476551695 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -174,7 +174,7 @@ static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc) if (scrtc->started) return; - format = shmob_drm_format_info(crtc->primary->fb->pixel_format); + format = shmob_drm_format_info(crtc->primary->fb->format->format); if (WARN_ON(format == NULL)) return; @@ -376,10 +376,10 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc, const struct shmob_drm_format_info *format; void *cache; - format = shmob_drm_format_info(crtc->primary->fb->pixel_format); + format = shmob_drm_format_info(crtc->primary->fb->format->format); if (format == NULL) { dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n", - crtc->primary->fb->pixel_format); + crtc->primary->fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 1805bb23b113..2023a93cee2b 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -183,10 +183,10 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, struct shmob_drm_device *sdev = plane->dev->dev_private; const struct shmob_drm_format_info *format; - format = shmob_drm_format_info(fb->pixel_format); + format = shmob_drm_format_info(fb->format->format); if (format == NULL) { dev_dbg(sdev->dev, "update_plane: unsupported format %08x\n", - fb->pixel_format); + fb->format->format); return -EINVAL; } diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 58316bd6d7d6..877d053d86f4 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -636,10 +636,10 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX); src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX); - format = sti_gdp_fourcc2format(fb->pixel_format); + format = sti_gdp_fourcc2format(fb->format->format); if (format == -1) { DRM_ERROR("Format not supported by GDP %.4s\n", - (char *)&fb->pixel_format); + (char *)&fb->format->format); return -EINVAL; } @@ -745,7 +745,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, /* build the top field */ top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE; top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC; - format = sti_gdp_fourcc2format(fb->pixel_format); + format = sti_gdp_fourcc2format(fb->format->format); top_field->gam_gdp_ctl |= format; top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format); top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE; @@ -753,7 +753,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, cma_obj = drm_fb_cma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, - (char *)&fb->pixel_format, + (char *)&fb->format->format, (unsigned long)cma_obj->paddr); /* pixel memory location */ diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index f88130f2eb48..becf10d255c4 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c @@ -1147,7 +1147,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, cma_obj = drm_fb_cma_get_gem_obj(fb, 0); DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, - (char *)&fb->pixel_format, + (char *)&fb->format->format, (unsigned long)cma_obj->paddr); /* Buffer planes address */ diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index a606207d4e25..a278e1f44661 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -189,7 +189,8 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", interlaced ? "on" : "off"); - ret = sun4i_backend_drm_format_to_layer(plane, fb->pixel_format, &val); + ret = sun4i_backend_drm_format_to_layer(plane, fb->format->format, + &val); if (ret) { DRM_DEBUG_DRIVER("Invalid format\n"); return val; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 642dcff87e34..7561a95a54e3 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -511,7 +511,7 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, if (!state->crtc) return 0; - err = tegra_dc_format(state->fb->pixel_format, &plane_state->format, + err = tegra_dc_format(state->fb->format->format, &plane_state->format, &plane_state->swap); if (err < 0) return err; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 0dc96e12fd06..47c2fe659fe3 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -399,7 +399,7 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) if (info->tft_alt_mode) reg |= LCDC_TFT_ALT_ENABLE; if (priv->rev == 2) { - switch (fb->pixel_format) { + switch (fb->format->format) { case DRM_FORMAT_BGR565: case DRM_FORMAT_RGB565: break; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index c0fc874e91cf..4b7519dfd1b9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -77,7 +77,7 @@ static int tilcdc_plane_atomic_check(struct drm_plane *plane, } if (state->fb && old_state->fb && - state->fb->pixel_format != old_state->fb->pixel_format) { + state->fb->format->format != old_state->fb->format->format) { dev_dbg(plane->dev->dev, "%s(): pixel format change requires mode_change\n", __func__); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index f84f6bddd015..110d1518f5d5 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -295,7 +295,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) struct drm_framebuffer *fb = state->fb; struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); u32 subpixel_src_mask = (1 << 16) - 1; - u32 format = fb->pixel_format; + u32 format = fb->format->format; int num_planes = fb->format->num_planes; u32 h_subsample = 1; u32 v_subsample = 1; @@ -496,7 +496,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); struct drm_framebuffer *fb = state->fb; u32 ctl0_offset = vc4_state->dlist_count; - const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format); + const struct hvs_format *format = vc4_get_hvs_format(fb->format->format); int num_planes = drm_format_num_planes(format->drm); u32 scl0, scl1; u32 lbm_size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 58643c5ca1d7..867a8442220c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -488,7 +488,7 @@ static int vmw_fb_kms_framebuffer(struct fb_info *info) cur_fb = par->set_fb; if (cur_fb && cur_fb->width == mode_cmd.width && cur_fb->height == mode_cmd.height && - cur_fb->pixel_format == mode_cmd.pixel_format && + cur_fb->format->format == mode_cmd.pixel_format && cur_fb->pitches[0] == mode_cmd.pitches[0]) return 0; diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index 72d27b0a48b2..b634b090cdc1 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -146,7 +146,7 @@ static void zx_gl_plane_atomic_update(struct drm_plane *plane, if (!fb) return; - format = fb->pixel_format; + format = fb->format->format; stride = fb->pitches[0]; src_x = plane->state->src_x >> 16; diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index 72b9b4898915..f0dde1d02be4 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -174,10 +174,6 @@ struct drm_framebuffer { * DRM_MODE_FB_MODIFIERS. */ int flags; - /** - * @pixel_format: DRM FOURCC code describing the pixel format. - */ - uint32_t pixel_format; /* fourcc format */ /** * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR -- cgit v1.2.3 From 56e3d1cd05cc7b24cfcae8714b0661bf607aaba3 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 15 Dec 2016 06:01:10 +0100 Subject: kref: prefer atomic_inc_not_zero to atomic_add_unless On most platforms, there exists this ifdef: #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) This makes this patch functionally useless. However, on PPC, there is actually an explicit definition of atomic_inc_not_zero with its own assembly that is slightly more optimized than atomic_add_unless. So, this patch changes kref to use atomic_inc_not_zero instead, for PPC and any future platforms that might provide an explicit implementation. This also puts this usage of kref more in line with a verbatim reading of the examples in Paul McKenney's paper [1] in the section titled "2.4 Atomic Counting With Check and Release Memory Barrier", which uses atomic_inc_not_zero. [1] http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2167.pdf Signed-off-by: Jason A. Donenfeld Reviewed-by: Thomas Hellstrom Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161215050110.3241-1-Jason@zx2c4.com --- include/linux/kref.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/kref.h b/include/linux/kref.h index e15828fd71f1..62f0a84ae94e 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -133,6 +133,6 @@ static inline int kref_put_mutex(struct kref *kref, */ static inline int __must_check kref_get_unless_zero(struct kref *kref) { - return atomic_add_unless(&kref->refcount, 1, 0); + return atomic_inc_not_zero(&kref->refcount); } #endif /* _KREF_H_ */ -- cgit v1.2.3 From ad579002c8ec429930721c5bb8bd763e6c0c6286 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 16 Dec 2016 07:46:41 +0000 Subject: drm: Add drm_mm_for_each_node_safe() A complement to drm_mm_for_each_node(), wraps list_for_each_entry_safe() for walking the list of nodes safe against removal. Note from Joonas: "Most of the diff is about __drm_mm_nodes(mm), which could be split into own patch and keep the R-b's." But I don't feel like insisting on the resend. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen [danvet: Add note.] Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161216074718.32500-4-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_mm.c | 9 ++++----- include/drm/drm_mm.h | 19 ++++++++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index ca1e344f318d..6e0735539545 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -138,7 +138,7 @@ static void show_leaks(struct drm_mm *mm) if (!buf) return; - list_for_each_entry(node, &mm->head_node.node_list, node_list) { + list_for_each_entry(node, __drm_mm_nodes(mm), node_list) { struct stack_trace trace = { .entries = entries, .max_entries = STACKDEPTH @@ -320,8 +320,7 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) if (hole->start < end) return -ENOSPC; } else { - hole = list_entry(&mm->head_node.node_list, - typeof(*hole), node_list); + hole = list_entry(__drm_mm_nodes(mm), typeof(*hole), node_list); } hole = list_last_entry(&hole->node_list, typeof(*hole), node_list); @@ -884,7 +883,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block); */ bool drm_mm_clean(struct drm_mm * mm) { - struct list_head *head = &mm->head_node.node_list; + struct list_head *head = __drm_mm_nodes(mm); return (head->next->next == head); } @@ -930,7 +929,7 @@ EXPORT_SYMBOL(drm_mm_init); */ void drm_mm_takedown(struct drm_mm *mm) { - if (WARN(!list_empty(&mm->head_node.node_list), + if (WARN(!list_empty(__drm_mm_nodes(mm)), "Memory manager not clean during takedown.\n")) show_leaks(mm); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 0b8371795aeb..0cc1b78c9ec2 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -179,6 +179,8 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node) return __drm_mm_hole_node_end(hole_node); } +#define __drm_mm_nodes(mm) (&(mm)->head_node.node_list) + /** * drm_mm_for_each_node - iterator to walk over all allocated nodes * @entry: drm_mm_node structure to assign to in each iteration step @@ -187,9 +189,20 @@ static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node) * This iterator walks over all nodes in the range allocator. It is implemented * with list_for_each, so not save against removal of elements. */ -#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ - &(mm)->head_node.node_list, \ - node_list) +#define drm_mm_for_each_node(entry, mm) \ + list_for_each_entry(entry, __drm_mm_nodes(mm), node_list) + +/** + * drm_mm_for_each_node_safe - iterator to walk over all allocated nodes + * @entry: drm_mm_node structure to assign to in each iteration step + * @next: drm_mm_node structure to store the next step + * @mm: drm_mm allocator to walk + * + * This iterator walks over all nodes in the range allocator. It is implemented + * with list_for_each_safe, so save against removal of elements. + */ +#define drm_mm_for_each_node_safe(entry, next, mm) \ + list_for_each_entry_safe(entry, next, __drm_mm_nodes(mm), node_list) #define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \ for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \ -- cgit v1.2.3 From 45b186f111f1623b257d183920cd4aab16a1acd5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 16 Dec 2016 07:46:42 +0000 Subject: drm: Constify the drm_mm API Mark up the pointers as constant through the API where appropriate. Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20161216074718.32500-5-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_mm.c | 24 ++++++++++++------------ drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- include/drm/drm_mm.h | 27 +++++++++++++-------------- 3 files changed, 26 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 6e0735539545..7573661302a4 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -174,9 +174,9 @@ INTERVAL_TREE_DEFINE(struct drm_mm_node, rb, START, LAST, static inline, drm_mm_interval_tree) struct drm_mm_node * -__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last) +__drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last) { - return drm_mm_interval_tree_iter_first(&mm->interval_tree, + return drm_mm_interval_tree_iter_first((struct rb_root *)&mm->interval_tree, start, last); } EXPORT_SYMBOL(__drm_mm_interval_first); @@ -881,9 +881,9 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block); * True if the allocator is completely free, false if there's still a node * allocated in it. */ -bool drm_mm_clean(struct drm_mm * mm) +bool drm_mm_clean(const struct drm_mm *mm) { - struct list_head *head = __drm_mm_nodes(mm); + const struct list_head *head = __drm_mm_nodes(mm); return (head->next->next == head); } @@ -897,7 +897,7 @@ EXPORT_SYMBOL(drm_mm_clean); * * Note that @mm must be cleared to 0 before calling this function. */ -void drm_mm_init(struct drm_mm * mm, u64 start, u64 size) +void drm_mm_init(struct drm_mm *mm, u64 start, u64 size) { INIT_LIST_HEAD(&mm->hole_stack); mm->scanned_blocks = 0; @@ -936,8 +936,8 @@ void drm_mm_takedown(struct drm_mm *mm) } EXPORT_SYMBOL(drm_mm_takedown); -static u64 drm_mm_debug_hole(struct drm_mm_node *entry, - const char *prefix) +static u64 drm_mm_debug_hole(const struct drm_mm_node *entry, + const char *prefix) { u64 hole_start, hole_end, hole_size; @@ -958,9 +958,9 @@ static u64 drm_mm_debug_hole(struct drm_mm_node *entry, * @mm: drm_mm allocator to dump * @prefix: prefix to use for dumping to dmesg */ -void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) +void drm_mm_debug_table(const struct drm_mm *mm, const char *prefix) { - struct drm_mm_node *entry; + const struct drm_mm_node *entry; u64 total_used = 0, total_free = 0, total = 0; total_free += drm_mm_debug_hole(&mm->head_node, prefix); @@ -979,7 +979,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) EXPORT_SYMBOL(drm_mm_debug_table); #if defined(CONFIG_DEBUG_FS) -static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) +static u64 drm_mm_dump_hole(struct seq_file *m, const struct drm_mm_node *entry) { u64 hole_start, hole_end, hole_size; @@ -1000,9 +1000,9 @@ static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) * @m: seq_file to dump to * @mm: drm_mm allocator to dump */ -int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) +int drm_mm_dump_table(struct seq_file *m, const struct drm_mm *mm) { - struct drm_mm_node *entry; + const struct drm_mm_node *entry; u64 total_used = 0, total_free = 0, total = 0; total_free += drm_mm_dump_hole(m, &mm->head_node); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index b4bde1452f2a..8983b30d0e64 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2721,7 +2721,7 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL); } -static void i915_gtt_color_adjust(struct drm_mm_node *node, +static void i915_gtt_color_adjust(const struct drm_mm_node *node, unsigned long color, u64 *start, u64 *end) diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 0cc1b78c9ec2..5c7f15875b6a 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -102,7 +102,8 @@ struct drm_mm { u64 scan_end; struct drm_mm_node *prev_scanned_node; - void (*color_adjust)(struct drm_mm_node *node, unsigned long color, + void (*color_adjust)(const struct drm_mm_node *node, + unsigned long color, u64 *start, u64 *end); }; @@ -116,7 +117,7 @@ struct drm_mm { * Returns: * True if the @node is allocated. */ -static inline bool drm_mm_node_allocated(struct drm_mm_node *node) +static inline bool drm_mm_node_allocated(const struct drm_mm_node *node) { return node->allocated; } @@ -131,12 +132,12 @@ static inline bool drm_mm_node_allocated(struct drm_mm_node *node) * Returns: * True if the @mm is initialized. */ -static inline bool drm_mm_initialized(struct drm_mm *mm) +static inline bool drm_mm_initialized(const struct drm_mm *mm) { return mm->hole_stack.next; } -static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node) +static inline u64 __drm_mm_hole_node_start(const struct drm_mm_node *hole_node) { return hole_node->start + hole_node->size; } @@ -152,13 +153,13 @@ static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node) * Returns: * Start of the subsequent hole. */ -static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node) +static inline u64 drm_mm_hole_node_start(const struct drm_mm_node *hole_node) { BUG_ON(!hole_node->hole_follows); return __drm_mm_hole_node_start(hole_node); } -static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node) +static inline u64 __drm_mm_hole_node_end(const struct drm_mm_node *hole_node) { return list_next_entry(hole_node, node_list)->start; } @@ -174,7 +175,7 @@ static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node) * Returns: * End of the subsequent hole. */ -static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node) +static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) { return __drm_mm_hole_node_end(hole_node); } @@ -314,14 +315,12 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm, void drm_mm_remove_node(struct drm_mm_node *node); void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); -void drm_mm_init(struct drm_mm *mm, - u64 start, - u64 size); +void drm_mm_init(struct drm_mm *mm, u64 start, u64 size); void drm_mm_takedown(struct drm_mm *mm); -bool drm_mm_clean(struct drm_mm *mm); +bool drm_mm_clean(const struct drm_mm *mm); struct drm_mm_node * -__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last); +__drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last); /** * drm_mm_for_each_node_in_range - iterator to walk over a range of @@ -355,9 +354,9 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, bool drm_mm_scan_add_block(struct drm_mm_node *node); bool drm_mm_scan_remove_block(struct drm_mm_node *node); -void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); +void drm_mm_debug_table(const struct drm_mm *mm, const char *prefix); #ifdef CONFIG_DEBUG_FS -int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm); +int drm_mm_dump_table(struct seq_file *m, const struct drm_mm *mm); #endif #endif -- cgit v1.2.3 From 9338203c4f03ffe323b67f0b2fa17b9811fa9bb6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 28 Nov 2016 20:51:09 +0200 Subject: drm: Don't include in used to define most of the in-kernel KMS API. It has now been split into separate files for each object type, but still includes most other KMS headers to avoid breaking driver compilation. As a step towards fixing that problem, remove the inclusion of from and include it instead where appropriate. Also remove the forward declarations of the drm_encoder and drm_encoder_helper_funcs structures from as they're not needed in the header. now has to include and contain a forward declaration of struct drm_encoder in order to allow including it as the first header in a compilation unit. Signed-off-by: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Sinclair Yeh # For vmwgfx Reviewed-by: Alex Deucher Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1481709550-29226-2-git-send-email-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 + drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/bochs/bochs.h | 1 + drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/drm_connector.c | 1 + drivers/gpu/drm/drm_crtc_helper.c | 1 + drivers/gpu/drm/drm_edid.c | 1 + drivers/gpu/drm/drm_mode_config.c | 1 + drivers/gpu/drm/drm_of.c | 1 + drivers/gpu/drm/drm_plane_helper.c | 1 + drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h | 2 ++ drivers/gpu/drm/gma500/psb_intel_drv.h | 1 + drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/qxl/qxl_drv.h | 1 + drivers/gpu/drm/radeon/radeon_mode.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 1 + drivers/gpu/drm/shmobile/shmob_drm_crtc.h | 1 + drivers/gpu/drm/tegra/drm.h | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 + include/drm/drm_crtc.h | 3 --- include/drm/drm_encoder.h | 3 +++ include/drm/drm_encoder_slave.h | 1 + include/drm/drm_modeset_helper_vtables.h | 1 + 27 files changed, 30 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 202b4176b74e..b60346792bf8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 908011d2c8f5..6f3b6f50cf52 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -28,6 +28,7 @@ #ifndef __AST_DRV_H__ #define __AST_DRV_H__ +#include #include #include diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 32dfe418cc98..f626bab7f5e3 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 2188d6b61b3e..b59aeef4635a 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h @@ -13,6 +13,7 @@ #include