aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_atomic.c19
-rw-r--r--drivers/gpu/drm/drm_crtc.c28
-rw-r--r--include/drm/drm_crtc.h32
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
867static 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,
2221out: 2233out:
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);
2224out_unlock: 2237out_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
2574static 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 */
2582static 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 */
2656static 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 */
2667static 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) \