diff options
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 28 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 32 |
3 files changed, 72 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 69adcf3944cc..e4879d34c280 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -156,6 +156,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) | |||
156 | state->connector_states[i]); | 156 | state->connector_states[i]); |
157 | state->connectors[i] = NULL; | 157 | state->connectors[i] = NULL; |
158 | state->connector_states[i] = NULL; | 158 | state->connector_states[i] = NULL; |
159 | drm_connector_unreference(connector); | ||
159 | } | 160 | } |
160 | 161 | ||
161 | for (i = 0; i < config->num_crtc; i++) { | 162 | for (i = 0; i < config->num_crtc; i++) { |
@@ -932,6 +933,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state, | |||
932 | if (!connector_state) | 933 | if (!connector_state) |
933 | return ERR_PTR(-ENOMEM); | 934 | return ERR_PTR(-ENOMEM); |
934 | 935 | ||
936 | drm_connector_reference(connector); | ||
935 | state->connector_states[index] = connector_state; | 937 | state->connector_states[index] = connector_state; |
936 | state->connectors[index] = connector; | 938 | state->connectors[index] = connector; |
937 | connector_state->state = state; | 939 | connector_state->state = state; |
@@ -1622,12 +1624,19 @@ retry: | |||
1622 | } | 1624 | } |
1623 | 1625 | ||
1624 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); | 1626 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); |
1625 | if (!obj || !obj->properties) { | 1627 | if (!obj) { |
1628 | ret = -ENOENT; | ||
1629 | goto out; | ||
1630 | } | ||
1631 | |||
1632 | if (!obj->properties) { | ||
1633 | drm_mode_object_unreference(obj); | ||
1626 | ret = -ENOENT; | 1634 | ret = -ENOENT; |
1627 | goto out; | 1635 | goto out; |
1628 | } | 1636 | } |
1629 | 1637 | ||
1630 | if (get_user(count_props, count_props_ptr + copied_objs)) { | 1638 | if (get_user(count_props, count_props_ptr + copied_objs)) { |
1639 | drm_mode_object_unreference(obj); | ||
1631 | ret = -EFAULT; | 1640 | ret = -EFAULT; |
1632 | goto out; | 1641 | goto out; |
1633 | } | 1642 | } |
@@ -1640,12 +1649,14 @@ retry: | |||
1640 | struct drm_property *prop; | 1649 | struct drm_property *prop; |
1641 | 1650 | ||
1642 | if (get_user(prop_id, props_ptr + copied_props)) { | 1651 | if (get_user(prop_id, props_ptr + copied_props)) { |
1652 | drm_mode_object_unreference(obj); | ||
1643 | ret = -EFAULT; | 1653 | ret = -EFAULT; |
1644 | goto out; | 1654 | goto out; |
1645 | } | 1655 | } |
1646 | 1656 | ||
1647 | prop = drm_property_find(dev, prop_id); | 1657 | prop = drm_property_find(dev, prop_id); |
1648 | if (!prop) { | 1658 | if (!prop) { |
1659 | drm_mode_object_unreference(obj); | ||
1649 | ret = -ENOENT; | 1660 | ret = -ENOENT; |
1650 | goto out; | 1661 | goto out; |
1651 | } | 1662 | } |
@@ -1653,13 +1664,16 @@ retry: | |||
1653 | if (copy_from_user(&prop_value, | 1664 | if (copy_from_user(&prop_value, |
1654 | prop_values_ptr + copied_props, | 1665 | prop_values_ptr + copied_props, |
1655 | sizeof(prop_value))) { | 1666 | sizeof(prop_value))) { |
1667 | drm_mode_object_unreference(obj); | ||
1656 | ret = -EFAULT; | 1668 | ret = -EFAULT; |
1657 | goto out; | 1669 | goto out; |
1658 | } | 1670 | } |
1659 | 1671 | ||
1660 | ret = atomic_set_prop(state, obj, prop, prop_value); | 1672 | ret = atomic_set_prop(state, obj, prop, prop_value); |
1661 | if (ret) | 1673 | if (ret) { |
1674 | drm_mode_object_unreference(obj); | ||
1662 | goto out; | 1675 | goto out; |
1676 | } | ||
1663 | 1677 | ||
1664 | copied_props++; | 1678 | copied_props++; |
1665 | } | 1679 | } |
@@ -1670,6 +1684,7 @@ retry: | |||
1670 | plane_mask |= (1 << drm_plane_index(plane)); | 1684 | plane_mask |= (1 << drm_plane_index(plane)); |
1671 | plane->old_fb = plane->fb; | 1685 | plane->old_fb = plane->fb; |
1672 | } | 1686 | } |
1687 | drm_mode_object_unreference(obj); | ||
1673 | } | 1688 | } |
1674 | 1689 | ||
1675 | if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { | 1690 | if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c8253ebad680..a9c0a4348322 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -864,6 +864,16 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector) | |||
864 | mode->interlace ? " interlaced" : ""); | 864 | mode->interlace ? " interlaced" : ""); |
865 | } | 865 | } |
866 | 866 | ||
867 | static void drm_connector_free(struct kref *kref) | ||
868 | { | ||
869 | struct drm_connector *connector = | ||
870 | container_of(kref, struct drm_connector, base.refcount); | ||
871 | struct drm_device *dev = connector->dev; | ||
872 | |||
873 | drm_mode_object_unregister(dev, &connector->base); | ||
874 | connector->funcs->destroy(connector); | ||
875 | } | ||
876 | |||
867 | /** | 877 | /** |
868 | * drm_connector_init - Init a preallocated connector | 878 | * drm_connector_init - Init a preallocated connector |
869 | * @dev: DRM device | 879 | * @dev: DRM device |
@@ -889,7 +899,9 @@ int drm_connector_init(struct drm_device *dev, | |||
889 | 899 | ||
890 | drm_modeset_lock_all(dev); | 900 | drm_modeset_lock_all(dev); |
891 | 901 | ||
892 | ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false, NULL); | 902 | ret = drm_mode_object_get_reg(dev, &connector->base, |
903 | DRM_MODE_OBJECT_CONNECTOR, | ||
904 | false, drm_connector_free); | ||
893 | if (ret) | 905 | if (ret) |
894 | goto out_unlock; | 906 | goto out_unlock; |
895 | 907 | ||
@@ -2137,7 +2149,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2137 | 2149 | ||
2138 | mutex_lock(&dev->mode_config.mutex); | 2150 | mutex_lock(&dev->mode_config.mutex); |
2139 | 2151 | ||
2140 | connector = drm_connector_find(dev, out_resp->connector_id); | 2152 | connector = drm_connector_lookup(dev, out_resp->connector_id); |
2141 | if (!connector) { | 2153 | if (!connector) { |
2142 | ret = -ENOENT; | 2154 | ret = -ENOENT; |
2143 | goto out_unlock; | 2155 | goto out_unlock; |
@@ -2221,6 +2233,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2221 | out: | 2233 | out: |
2222 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 2234 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
2223 | 2235 | ||
2236 | drm_connector_unreference(connector); | ||
2224 | out_unlock: | 2237 | out_unlock: |
2225 | mutex_unlock(&dev->mode_config.mutex); | 2238 | mutex_unlock(&dev->mode_config.mutex); |
2226 | 2239 | ||
@@ -2865,13 +2878,14 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2865 | } | 2878 | } |
2866 | 2879 | ||
2867 | for (i = 0; i < crtc_req->count_connectors; i++) { | 2880 | for (i = 0; i < crtc_req->count_connectors; i++) { |
2881 | connector_set[i] = NULL; | ||
2868 | set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; | 2882 | set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; |
2869 | if (get_user(out_id, &set_connectors_ptr[i])) { | 2883 | if (get_user(out_id, &set_connectors_ptr[i])) { |
2870 | ret = -EFAULT; | 2884 | ret = -EFAULT; |
2871 | goto out; | 2885 | goto out; |
2872 | } | 2886 | } |
2873 | 2887 | ||
2874 | connector = drm_connector_find(dev, out_id); | 2888 | connector = drm_connector_lookup(dev, out_id); |
2875 | if (!connector) { | 2889 | if (!connector) { |
2876 | DRM_DEBUG_KMS("Connector id %d unknown\n", | 2890 | DRM_DEBUG_KMS("Connector id %d unknown\n", |
2877 | out_id); | 2891 | out_id); |
@@ -2899,6 +2913,12 @@ out: | |||
2899 | if (fb) | 2913 | if (fb) |
2900 | drm_framebuffer_unreference(fb); | 2914 | drm_framebuffer_unreference(fb); |
2901 | 2915 | ||
2916 | if (connector_set) { | ||
2917 | for (i = 0; i < crtc_req->count_connectors; i++) { | ||
2918 | if (connector_set[i]) | ||
2919 | drm_connector_unreference(connector_set[i]); | ||
2920 | } | ||
2921 | } | ||
2902 | kfree(connector_set); | 2922 | kfree(connector_set); |
2903 | drm_mode_destroy(dev, mode); | 2923 | drm_mode_destroy(dev, mode); |
2904 | drm_modeset_unlock_all(dev); | 2924 | drm_modeset_unlock_all(dev); |
@@ -4989,7 +5009,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
4989 | property = obj_to_property(prop_obj); | 5009 | property = obj_to_property(prop_obj); |
4990 | 5010 | ||
4991 | if (!drm_property_change_valid_get(property, arg->value, &ref)) | 5011 | if (!drm_property_change_valid_get(property, arg->value, &ref)) |
4992 | goto out; | 5012 | goto out_unref; |
4993 | 5013 | ||
4994 | switch (arg_obj->type) { | 5014 | switch (arg_obj->type) { |
4995 | case DRM_MODE_OBJECT_CONNECTOR: | 5015 | case DRM_MODE_OBJECT_CONNECTOR: |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 0cc1eb7b4fd2..4acdaf5e283d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -2571,7 +2571,15 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, | |||
2571 | return mo ? obj_to_encoder(mo) : NULL; | 2571 | return mo ? obj_to_encoder(mo) : NULL; |
2572 | } | 2572 | } |
2573 | 2573 | ||
2574 | static inline struct drm_connector *drm_connector_find(struct drm_device *dev, | 2574 | /** |
2575 | * drm_connector_lookup - lookup connector object | ||
2576 | * @dev: DRM device | ||
2577 | * @id: connector object id | ||
2578 | * | ||
2579 | * This function looks up the connector object specified by id | ||
2580 | * add takes a reference to it. | ||
2581 | */ | ||
2582 | static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev, | ||
2575 | uint32_t id) | 2583 | uint32_t id) |
2576 | { | 2584 | { |
2577 | struct drm_mode_object *mo; | 2585 | struct drm_mode_object *mo; |
@@ -2639,6 +2647,28 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb) | |||
2639 | return atomic_read(&fb->base.refcount.refcount); | 2647 | return atomic_read(&fb->base.refcount.refcount); |
2640 | } | 2648 | } |
2641 | 2649 | ||
2650 | /** | ||
2651 | * drm_connector_reference - incr the connector refcnt | ||
2652 | * @connector: connector | ||
2653 | * | ||
2654 | * This function increments the connector's refcount. | ||
2655 | */ | ||
2656 | static inline void drm_connector_reference(struct drm_connector *connector) | ||
2657 | { | ||
2658 | drm_mode_object_reference(&connector->base); | ||
2659 | } | ||
2660 | |||
2661 | /** | ||
2662 | * drm_connector_unreference - unref a connector | ||
2663 | * @connector: connector to unref | ||
2664 | * | ||
2665 | * This function decrements the connector's refcount and frees it if it drops to zero. | ||
2666 | */ | ||
2667 | static inline void drm_connector_unreference(struct drm_connector *connector) | ||
2668 | { | ||
2669 | drm_mode_object_unreference(&connector->base); | ||
2670 | } | ||
2671 | |||
2642 | /* Plane list iterator for legacy (overlay only) planes. */ | 2672 | /* Plane list iterator for legacy (overlay only) planes. */ |
2643 | #define drm_for_each_legacy_plane(plane, dev) \ | 2673 | #define drm_for_each_legacy_plane(plane, dev) \ |
2644 | list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ | 2674 | list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \ |