diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 12b47c30fe2e..1ba301cebe16 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -156,6 +156,43 @@ other hand, a driver requires shared state between clients which is visible to user-space and accessible beyond open-file boundaries, they cannot support render nodes. +Validating changes with IGT +=========================== + +There's a collection of tests that aims to cover the whole functionality of +DRM drivers and that can be used to check that changes to DRM drivers or the +core don't regress existing functionality. This test suite is called IGT and +its code can be found in https://cgit.freedesktop.org/drm/igt-gpu-tools/. + +To build IGT, start by installing its build dependencies. In Debian-based +systems:: + + # apt-get build-dep intel-gpu-tools + +And in Fedora-based systems:: + + # dnf builddep intel-gpu-tools + +Then clone the repository:: + + $ git clone git://anongit.freedesktop.org/drm/igt-gpu-tools + +Configure the build system and start the build:: + + $ cd igt-gpu-tools && ./autogen.sh && make -j6 + +Download the piglit dependency:: + + $ ./scripts/run-tests.sh -d + +And run the tests:: + + $ ./scripts/run-tests.sh -t kms -t core -s + +run-tests.sh is a wrapper around piglit that will execute the tests matching +the -t options. A report in HTML format will be available in +./results/html/index.html. Results can be compared with piglit. + VBlank event handling ===================== diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5cb2e22d5d55..a5126e5c05ee 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1609,7 +1609,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_crtc_state *crtc_state; unsigned plane_mask; int ret = 0; - unsigned int i, j; + unsigned int i, j, k; /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) @@ -1691,6 +1691,15 @@ retry: goto out; } + for (k = 0; k < obj->properties->count; k++) + if (obj->properties->properties[k]->base.id == prop_id) + break; + + if (k == obj->properties->count) { + ret = -EINVAL; + goto out; + } + prop = drm_property_find(dev, prop_id); if (!prop) { drm_mode_object_unreference(obj); diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index a33dab27bb0d..631691bae01d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2044,7 +2044,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, } out: - if (ret) + if (ret && crtc->funcs->page_flip_target) drm_crtc_vblank_put(crtc); if (fb) drm_framebuffer_unreference(fb); diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c index 7b30b307674b..dae18e58e79b 100644 --- a/drivers/gpu/drm/drm_hashtab.c +++ b/drivers/gpu/drm/drm_hashtab.c @@ -142,7 +142,7 @@ int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *it unsigned long add) { int ret; - unsigned long mask = (1 << bits) - 1; + unsigned long mask = (1UL << bits) - 1; unsigned long first, unshifted_key; unshifted_key = hash_long(seed, bits); diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index 4139afbcc267..a4d81cf4ffa0 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -870,8 +870,20 @@ bool drm_property_change_valid_get(struct drm_property *property, for (i = 0; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]); return !(value & ~valid_mask); - } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB) || - drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { + } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { + struct drm_property_blob *blob; + + if (value == 0) + return true; + + blob = drm_property_lookup_blob(property->dev, value); + if (blob) { + *ref = &blob->base; + return true; + } else { + return false; + } + } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { /* a zero value for an object property translates to null: */ if (value == 0) return true; @@ -888,12 +900,13 @@ bool drm_property_change_valid_get(struct drm_property *property, } void drm_property_change_valid_put(struct drm_property *property, - struct drm_mode_object *ref) + struct drm_mode_object *ref) { if (!ref) return; - if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT) || - drm_property_type_is(property, DRM_MODE_PROP_BLOB)) + if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { drm_mode_object_unreference(ref); + } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) + drm_property_unreference_blob(obj_to_blob(ref)); } diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 17d34e0edbdd..f0851db6ba6c 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -16,6 +16,20 @@ static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m) return 0; } +static int udl_usb_suspend(struct usb_interface *interface, + pm_message_t message) +{ + return 0; +} + +static int udl_usb_resume(struct usb_interface *interface) +{ + struct drm_device *dev = usb_get_intfdata(interface); + + udl_modeset_restore(dev); + return 0; +} + static const struct vm_operations_struct udl_gem_vm_ops = { .fault = udl_gem_fault, .open = drm_gem_vm_open, @@ -122,6 +136,8 @@ static struct usb_driver udl_driver = { .name = "udl", .probe = udl_usb_probe, .disconnect = udl_usb_disconnect, + .suspend = udl_usb_suspend, + .resume = udl_usb_resume, .id_table = id_table, }; module_usb_driver(udl_driver); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 0b03d34ffdee..f338a576efc8 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -52,6 +52,7 @@ struct udl_device { struct device *dev; struct drm_device *ddev; struct usb_device *udev; + struct drm_crtc *crtc; int sku_pixel_limit; @@ -87,6 +88,7 @@ struct udl_framebuffer { /* modeset */ int udl_modeset_init(struct drm_device *dev); +void udl_modeset_restore(struct drm_device *dev); void udl_modeset_cleanup(struct drm_device *dev); int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 73695127c573..f2b2481cad52 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -309,6 +309,8 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc, char *wrptr; int color_depth = 0; + udl->crtc = crtc; + buf = (char *)udl->mode_buf; /* for now we just clip 24 -> 16 - if we fix that fix this */ @@ -450,6 +452,18 @@ int udl_modeset_init(struct drm_device *dev) return 0; } +void udl_modeset_restore(struct drm_device *dev) +{ + struct udl_device *udl = dev->dev_private; + struct udl_framebuffer *ufb; + + if (!udl->crtc || !udl->crtc->primary->fb) + return; + udl_crtc_commit(udl->crtc); + ufb = to_udl_fb(udl->crtc->primary->fb); + udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height); +} + void udl_modeset_cleanup(struct drm_device *dev) { drm_mode_config_cleanup(dev);