diff mbox

[RFC,25/37] drm: mode: Allow userspace to fetch mode as blob

Message ID 1426739616-10635-25-git-send-email-daniels@collabora.com (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Stone March 19, 2015, 4:33 a.m. UTC
Overload the getblob ioctl to allow passing in a mode ID, which will
return the userspace representation (drm_mode_modeinfo) of that mode.

Signed-off-by: Daniel Stone <daniels@collabora.com>
---
 drivers/gpu/drm/drm_crtc.c | 26 ++++++++++++++++++++------
 include/drm/drm_crtc.h     |  8 ++++++++
 2 files changed, 28 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index af9628b..e50eda2 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -4163,9 +4163,12 @@  int drm_mode_getblob_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv)
 {
 	struct drm_mode_get_blob *out_resp = data;
-	struct drm_property_blob *blob;
+	const struct drm_property_blob *blob = NULL;
+	const struct drm_display_mode *mode = NULL;
+	void __user *user_ptr = (void __user *)(unsigned long)out_resp->data;
+	u32 length;
+	const void *data_src;
 	int ret = 0;
-	void __user *blob_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -4173,18 +4176,29 @@  int drm_mode_getblob_ioctl(struct drm_device *dev,
 	drm_modeset_lock_all(dev);
 	blob = drm_property_blob_find(dev, out_resp->blob_id);
 	if (!blob) {
+		/* If we don't find a blob, they might be trying to get a mode
+		 * instead. */
+		mode = drm_mode_find(dev, out_resp->blob_id);
+	}
+
+	if (blob) {
+		length = blob->length;
+		data_src = blob->data;
+	} else if (mode) {
+		length = sizeof(mode->umode);
+		data_src = &mode->umode;
+	} else {
 		ret = -ENOENT;
 		goto done;
 	}
 
-	if (out_resp->length == blob->length) {
-		blob_ptr = (void __user *)(unsigned long)out_resp->data;
-		if (copy_to_user(blob_ptr, blob->data, blob->length)) {
+	if (out_resp->length == length) {
+		if (copy_to_user(user_ptr, data_src, length)) {
 			ret = -EFAULT;
 			goto done;
 		}
 	}
-	out_resp->length = blob->length;
+	out_resp->length = length;
 
 done:
 	drm_modeset_unlock_all(dev);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7683527..3ab70a7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1533,6 +1533,14 @@  drm_property_blob_find(struct drm_device *dev, uint32_t id)
 	return mo ? obj_to_blob(mo) : NULL;
 }
 
+static inline struct drm_display_mode *drm_mode_find(struct drm_device *dev,
+		uint32_t id)
+{
+	struct drm_mode_object *mo;
+	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_MODE);
+	return mo ? obj_to_mode(mo) : NULL;
+}
+
 /* Plane list iterator for legacy (overlay only) planes. */
 #define drm_for_each_legacy_plane(plane, planelist) \
 	list_for_each_entry(plane, planelist, head) \