diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 581 |
1 files changed, 400 insertions, 181 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e79c8d3700d8..5213da499d39 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -683,7 +683,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | |||
683 | drm_modeset_lock_init(&crtc->mutex); | 683 | drm_modeset_lock_init(&crtc->mutex); |
684 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); | 684 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
685 | if (ret) | 685 | if (ret) |
686 | goto out; | 686 | return ret; |
687 | 687 | ||
688 | crtc->base.properties = &crtc->properties; | 688 | crtc->base.properties = &crtc->properties; |
689 | 689 | ||
@@ -697,9 +697,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | |||
697 | if (cursor) | 697 | if (cursor) |
698 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); | 698 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
699 | 699 | ||
700 | out: | 700 | return 0; |
701 | |||
702 | return ret; | ||
703 | } | 701 | } |
704 | EXPORT_SYMBOL(drm_crtc_init_with_planes); | 702 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
705 | 703 | ||
@@ -723,6 +721,12 @@ void drm_crtc_cleanup(struct drm_crtc *crtc) | |||
723 | drm_mode_object_put(dev, &crtc->base); | 721 | drm_mode_object_put(dev, &crtc->base); |
724 | list_del(&crtc->head); | 722 | list_del(&crtc->head); |
725 | dev->mode_config.num_crtc--; | 723 | dev->mode_config.num_crtc--; |
724 | |||
725 | WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); | ||
726 | if (crtc->state && crtc->funcs->atomic_destroy_state) | ||
727 | crtc->funcs->atomic_destroy_state(crtc, crtc->state); | ||
728 | |||
729 | memset(crtc, 0, sizeof(*crtc)); | ||
726 | } | 730 | } |
727 | EXPORT_SYMBOL(drm_crtc_cleanup); | 731 | EXPORT_SYMBOL(drm_crtc_cleanup); |
728 | 732 | ||
@@ -766,7 +770,6 @@ static void drm_mode_remove(struct drm_connector *connector, | |||
766 | /** | 770 | /** |
767 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode | 771 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode |
768 | * @connector: connector to quwery | 772 | * @connector: connector to quwery |
769 | * @mode: returned mode | ||
770 | * | 773 | * |
771 | * The kernel supports per-connector configration of its consoles through | 774 | * The kernel supports per-connector configration of its consoles through |
772 | * use of the video= parameter. This function parses that option and | 775 | * use of the video= parameter. This function parses that option and |
@@ -870,6 +873,8 @@ int drm_connector_init(struct drm_device *dev, | |||
870 | 873 | ||
871 | drm_connector_get_cmdline_mode(connector); | 874 | drm_connector_get_cmdline_mode(connector); |
872 | 875 | ||
876 | /* We should add connectors at the end to avoid upsetting the connector | ||
877 | * index too much. */ | ||
873 | list_add_tail(&connector->head, &dev->mode_config.connector_list); | 878 | list_add_tail(&connector->head, &dev->mode_config.connector_list); |
874 | dev->mode_config.num_connector++; | 879 | dev->mode_config.num_connector++; |
875 | 880 | ||
@@ -905,6 +910,11 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
905 | struct drm_device *dev = connector->dev; | 910 | struct drm_device *dev = connector->dev; |
906 | struct drm_display_mode *mode, *t; | 911 | struct drm_display_mode *mode, *t; |
907 | 912 | ||
913 | if (connector->tile_group) { | ||
914 | drm_mode_put_tile_group(dev, connector->tile_group); | ||
915 | connector->tile_group = NULL; | ||
916 | } | ||
917 | |||
908 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) | 918 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) |
909 | drm_mode_remove(connector, mode); | 919 | drm_mode_remove(connector, mode); |
910 | 920 | ||
@@ -919,6 +929,13 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
919 | connector->name = NULL; | 929 | connector->name = NULL; |
920 | list_del(&connector->head); | 930 | list_del(&connector->head); |
921 | dev->mode_config.num_connector--; | 931 | dev->mode_config.num_connector--; |
932 | |||
933 | WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); | ||
934 | if (connector->state && connector->funcs->atomic_destroy_state) | ||
935 | connector->funcs->atomic_destroy_state(connector, | ||
936 | connector->state); | ||
937 | |||
938 | memset(connector, 0, sizeof(*connector)); | ||
922 | } | 939 | } |
923 | EXPORT_SYMBOL(drm_connector_cleanup); | 940 | EXPORT_SYMBOL(drm_connector_cleanup); |
924 | 941 | ||
@@ -933,6 +950,9 @@ unsigned int drm_connector_index(struct drm_connector *connector) | |||
933 | { | 950 | { |
934 | unsigned int index = 0; | 951 | unsigned int index = 0; |
935 | struct drm_connector *tmp; | 952 | struct drm_connector *tmp; |
953 | struct drm_mode_config *config = &connector->dev->mode_config; | ||
954 | |||
955 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); | ||
936 | 956 | ||
937 | list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) { | 957 | list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) { |
938 | if (tmp == connector) | 958 | if (tmp == connector) |
@@ -1057,6 +1077,8 @@ void drm_bridge_cleanup(struct drm_bridge *bridge) | |||
1057 | list_del(&bridge->head); | 1077 | list_del(&bridge->head); |
1058 | dev->mode_config.num_bridge--; | 1078 | dev->mode_config.num_bridge--; |
1059 | drm_modeset_unlock_all(dev); | 1079 | drm_modeset_unlock_all(dev); |
1080 | |||
1081 | memset(bridge, 0, sizeof(*bridge)); | ||
1060 | } | 1082 | } |
1061 | EXPORT_SYMBOL(drm_bridge_cleanup); | 1083 | EXPORT_SYMBOL(drm_bridge_cleanup); |
1062 | 1084 | ||
@@ -1123,10 +1145,11 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) | |||
1123 | drm_modeset_lock_all(dev); | 1145 | drm_modeset_lock_all(dev); |
1124 | drm_mode_object_put(dev, &encoder->base); | 1146 | drm_mode_object_put(dev, &encoder->base); |
1125 | kfree(encoder->name); | 1147 | kfree(encoder->name); |
1126 | encoder->name = NULL; | ||
1127 | list_del(&encoder->head); | 1148 | list_del(&encoder->head); |
1128 | dev->mode_config.num_encoder--; | 1149 | dev->mode_config.num_encoder--; |
1129 | drm_modeset_unlock_all(dev); | 1150 | drm_modeset_unlock_all(dev); |
1151 | |||
1152 | memset(encoder, 0, sizeof(*encoder)); | ||
1130 | } | 1153 | } |
1131 | EXPORT_SYMBOL(drm_encoder_cleanup); | 1154 | EXPORT_SYMBOL(drm_encoder_cleanup); |
1132 | 1155 | ||
@@ -1153,11 +1176,11 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1153 | { | 1176 | { |
1154 | int ret; | 1177 | int ret; |
1155 | 1178 | ||
1156 | drm_modeset_lock_all(dev); | ||
1157 | |||
1158 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); | 1179 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
1159 | if (ret) | 1180 | if (ret) |
1160 | goto out; | 1181 | return ret; |
1182 | |||
1183 | drm_modeset_lock_init(&plane->mutex); | ||
1161 | 1184 | ||
1162 | plane->base.properties = &plane->properties; | 1185 | plane->base.properties = &plane->properties; |
1163 | plane->dev = dev; | 1186 | plane->dev = dev; |
@@ -1167,8 +1190,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1167 | if (!plane->format_types) { | 1190 | if (!plane->format_types) { |
1168 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); | 1191 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1169 | drm_mode_object_put(dev, &plane->base); | 1192 | drm_mode_object_put(dev, &plane->base); |
1170 | ret = -ENOMEM; | 1193 | return -ENOMEM; |
1171 | goto out; | ||
1172 | } | 1194 | } |
1173 | 1195 | ||
1174 | memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); | 1196 | memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); |
@@ -1185,10 +1207,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1185 | dev->mode_config.plane_type_property, | 1207 | dev->mode_config.plane_type_property, |
1186 | plane->type); | 1208 | plane->type); |
1187 | 1209 | ||
1188 | out: | 1210 | return 0; |
1189 | drm_modeset_unlock_all(dev); | ||
1190 | |||
1191 | return ret; | ||
1192 | } | 1211 | } |
1193 | EXPORT_SYMBOL(drm_universal_plane_init); | 1212 | EXPORT_SYMBOL(drm_universal_plane_init); |
1194 | 1213 | ||
@@ -1246,6 +1265,12 @@ void drm_plane_cleanup(struct drm_plane *plane) | |||
1246 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) | 1265 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1247 | dev->mode_config.num_overlay_plane--; | 1266 | dev->mode_config.num_overlay_plane--; |
1248 | drm_modeset_unlock_all(dev); | 1267 | drm_modeset_unlock_all(dev); |
1268 | |||
1269 | WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); | ||
1270 | if (plane->state && plane->funcs->atomic_destroy_state) | ||
1271 | plane->funcs->atomic_destroy_state(plane, plane->state); | ||
1272 | |||
1273 | memset(plane, 0, sizeof(*plane)); | ||
1249 | } | 1274 | } |
1250 | EXPORT_SYMBOL(drm_plane_cleanup); | 1275 | EXPORT_SYMBOL(drm_plane_cleanup); |
1251 | 1276 | ||
@@ -1328,6 +1353,11 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) | |||
1328 | "PATH", 0); | 1353 | "PATH", 0); |
1329 | dev->mode_config.path_property = dev_path; | 1354 | dev->mode_config.path_property = dev_path; |
1330 | 1355 | ||
1356 | dev->mode_config.tile_property = drm_property_create(dev, | ||
1357 | DRM_MODE_PROP_BLOB | | ||
1358 | DRM_MODE_PROP_IMMUTABLE, | ||
1359 | "TILE", 0); | ||
1360 | |||
1331 | return 0; | 1361 | return 0; |
1332 | } | 1362 | } |
1333 | 1363 | ||
@@ -1388,12 +1418,13 @@ EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); | |||
1388 | * responsible for allocating a list of format names and passing them to | 1418 | * responsible for allocating a list of format names and passing them to |
1389 | * this routine. | 1419 | * this routine. |
1390 | */ | 1420 | */ |
1391 | int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, | 1421 | int drm_mode_create_tv_properties(struct drm_device *dev, |
1422 | unsigned int num_modes, | ||
1392 | char *modes[]) | 1423 | char *modes[]) |
1393 | { | 1424 | { |
1394 | struct drm_property *tv_selector; | 1425 | struct drm_property *tv_selector; |
1395 | struct drm_property *tv_subconnector; | 1426 | struct drm_property *tv_subconnector; |
1396 | int i; | 1427 | unsigned int i; |
1397 | 1428 | ||
1398 | if (dev->mode_config.tv_select_subconnector_property) | 1429 | if (dev->mode_config.tv_select_subconnector_property) |
1399 | return 0; | 1430 | return 0; |
@@ -1491,7 +1522,7 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); | |||
1491 | * connectors. | 1522 | * connectors. |
1492 | * | 1523 | * |
1493 | * Returns: | 1524 | * Returns: |
1494 | * Zero on success, errno on failure. | 1525 | * Zero on success, negative errno on failure. |
1495 | */ | 1526 | */ |
1496 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) | 1527 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) |
1497 | { | 1528 | { |
@@ -1535,6 +1566,30 @@ int drm_mode_create_dirty_info_property(struct drm_device *dev) | |||
1535 | } | 1566 | } |
1536 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); | 1567 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); |
1537 | 1568 | ||
1569 | /** | ||
1570 | * drm_mode_create_suggested_offset_properties - create suggests offset properties | ||
1571 | * @dev: DRM device | ||
1572 | * | ||
1573 | * Create the the suggested x/y offset property for connectors. | ||
1574 | */ | ||
1575 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev) | ||
1576 | { | ||
1577 | if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property) | ||
1578 | return 0; | ||
1579 | |||
1580 | dev->mode_config.suggested_x_property = | ||
1581 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff); | ||
1582 | |||
1583 | dev->mode_config.suggested_y_property = | ||
1584 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff); | ||
1585 | |||
1586 | if (dev->mode_config.suggested_x_property == NULL || | ||
1587 | dev->mode_config.suggested_y_property == NULL) | ||
1588 | return -ENOMEM; | ||
1589 | return 0; | ||
1590 | } | ||
1591 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); | ||
1592 | |||
1538 | static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) | 1593 | static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) |
1539 | { | 1594 | { |
1540 | uint32_t total_objects = 0; | 1595 | uint32_t total_objects = 0; |
@@ -1651,7 +1706,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, | |||
1651 | * the caller. | 1706 | * the caller. |
1652 | * | 1707 | * |
1653 | * Returns: | 1708 | * Returns: |
1654 | * Zero on success, errno on failure. | 1709 | * Zero on success, negative errno on failure. |
1655 | */ | 1710 | */ |
1656 | static int drm_crtc_convert_umode(struct drm_display_mode *out, | 1711 | static int drm_crtc_convert_umode(struct drm_display_mode *out, |
1657 | const struct drm_mode_modeinfo *in) | 1712 | const struct drm_mode_modeinfo *in) |
@@ -1694,7 +1749,7 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out, | |||
1694 | * Called by the user via ioctl. | 1749 | * Called by the user via ioctl. |
1695 | * | 1750 | * |
1696 | * Returns: | 1751 | * Returns: |
1697 | * Zero on success, errno on failure. | 1752 | * Zero on success, negative errno on failure. |
1698 | */ | 1753 | */ |
1699 | int drm_mode_getresources(struct drm_device *dev, void *data, | 1754 | int drm_mode_getresources(struct drm_device *dev, void *data, |
1700 | struct drm_file *file_priv) | 1755 | struct drm_file *file_priv) |
@@ -1745,7 +1800,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1745 | card_res->count_fbs = fb_count; | 1800 | card_res->count_fbs = fb_count; |
1746 | mutex_unlock(&file_priv->fbs_lock); | 1801 | mutex_unlock(&file_priv->fbs_lock); |
1747 | 1802 | ||
1748 | drm_modeset_lock_all(dev); | 1803 | /* mode_config.mutex protects the connector list against e.g. DP MST |
1804 | * connector hot-adding. CRTC/Plane lists are invariant. */ | ||
1805 | mutex_lock(&dev->mode_config.mutex); | ||
1749 | if (!drm_is_primary_client(file_priv)) { | 1806 | if (!drm_is_primary_client(file_priv)) { |
1750 | 1807 | ||
1751 | mode_group = NULL; | 1808 | mode_group = NULL; |
@@ -1865,7 +1922,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data, | |||
1865 | card_res->count_connectors, card_res->count_encoders); | 1922 | card_res->count_connectors, card_res->count_encoders); |
1866 | 1923 | ||
1867 | out: | 1924 | out: |
1868 | drm_modeset_unlock_all(dev); | 1925 | mutex_unlock(&dev->mode_config.mutex); |
1869 | return ret; | 1926 | return ret; |
1870 | } | 1927 | } |
1871 | 1928 | ||
@@ -1880,26 +1937,22 @@ out: | |||
1880 | * Called by the user via ioctl. | 1937 | * Called by the user via ioctl. |
1881 | * | 1938 | * |
1882 | * Returns: | 1939 | * Returns: |
1883 | * Zero on success, errno on failure. | 1940 | * Zero on success, negative errno on failure. |
1884 | */ | 1941 | */ |
1885 | int drm_mode_getcrtc(struct drm_device *dev, | 1942 | int drm_mode_getcrtc(struct drm_device *dev, |
1886 | void *data, struct drm_file *file_priv) | 1943 | void *data, struct drm_file *file_priv) |
1887 | { | 1944 | { |
1888 | struct drm_mode_crtc *crtc_resp = data; | 1945 | struct drm_mode_crtc *crtc_resp = data; |
1889 | struct drm_crtc *crtc; | 1946 | struct drm_crtc *crtc; |
1890 | int ret = 0; | ||
1891 | 1947 | ||
1892 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 1948 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1893 | return -EINVAL; | 1949 | return -EINVAL; |
1894 | 1950 | ||
1895 | drm_modeset_lock_all(dev); | ||
1896 | |||
1897 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); | 1951 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); |
1898 | if (!crtc) { | 1952 | if (!crtc) |
1899 | ret = -ENOENT; | 1953 | return -ENOENT; |
1900 | goto out; | ||
1901 | } | ||
1902 | 1954 | ||
1955 | drm_modeset_lock_crtc(crtc, crtc->primary); | ||
1903 | crtc_resp->x = crtc->x; | 1956 | crtc_resp->x = crtc->x; |
1904 | crtc_resp->y = crtc->y; | 1957 | crtc_resp->y = crtc->y; |
1905 | crtc_resp->gamma_size = crtc->gamma_size; | 1958 | crtc_resp->gamma_size = crtc->gamma_size; |
@@ -1916,10 +1969,9 @@ int drm_mode_getcrtc(struct drm_device *dev, | |||
1916 | } else { | 1969 | } else { |
1917 | crtc_resp->mode_valid = 0; | 1970 | crtc_resp->mode_valid = 0; |
1918 | } | 1971 | } |
1972 | drm_modeset_unlock_crtc(crtc); | ||
1919 | 1973 | ||
1920 | out: | 1974 | return 0; |
1921 | drm_modeset_unlock_all(dev); | ||
1922 | return ret; | ||
1923 | } | 1975 | } |
1924 | 1976 | ||
1925 | static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | 1977 | static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, |
@@ -1935,6 +1987,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | |||
1935 | return true; | 1987 | return true; |
1936 | } | 1988 | } |
1937 | 1989 | ||
1990 | static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) | ||
1991 | { | ||
1992 | /* For atomic drivers only state objects are synchronously updated and | ||
1993 | * protected by modeset locks, so check those first. */ | ||
1994 | if (connector->state) | ||
1995 | return connector->state->best_encoder; | ||
1996 | return connector->encoder; | ||
1997 | } | ||
1998 | |||
1938 | /** | 1999 | /** |
1939 | * drm_mode_getconnector - get connector configuration | 2000 | * drm_mode_getconnector - get connector configuration |
1940 | * @dev: drm device for the ioctl | 2001 | * @dev: drm device for the ioctl |
@@ -1946,13 +2007,14 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, | |||
1946 | * Called by the user via ioctl. | 2007 | * Called by the user via ioctl. |
1947 | * | 2008 | * |
1948 | * Returns: | 2009 | * Returns: |
1949 | * Zero on success, errno on failure. | 2010 | * Zero on success, negative errno on failure. |
1950 | */ | 2011 | */ |
1951 | int drm_mode_getconnector(struct drm_device *dev, void *data, | 2012 | int drm_mode_getconnector(struct drm_device *dev, void *data, |
1952 | struct drm_file *file_priv) | 2013 | struct drm_file *file_priv) |
1953 | { | 2014 | { |
1954 | struct drm_mode_get_connector *out_resp = data; | 2015 | struct drm_mode_get_connector *out_resp = data; |
1955 | struct drm_connector *connector; | 2016 | struct drm_connector *connector; |
2017 | struct drm_encoder *encoder; | ||
1956 | struct drm_display_mode *mode; | 2018 | struct drm_display_mode *mode; |
1957 | int mode_count = 0; | 2019 | int mode_count = 0; |
1958 | int props_count = 0; | 2020 | int props_count = 0; |
@@ -2008,8 +2070,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2008 | out_resp->subpixel = connector->display_info.subpixel_order; | 2070 | out_resp->subpixel = connector->display_info.subpixel_order; |
2009 | out_resp->connection = connector->status; | 2071 | out_resp->connection = connector->status; |
2010 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | 2072 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2011 | if (connector->encoder) | 2073 | |
2012 | out_resp->encoder_id = connector->encoder->base.id; | 2074 | encoder = drm_connector_get_encoder(connector); |
2075 | if (encoder) | ||
2076 | out_resp->encoder_id = encoder->base.id; | ||
2013 | else | 2077 | else |
2014 | out_resp->encoder_id = 0; | 2078 | out_resp->encoder_id = 0; |
2015 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 2079 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
@@ -2079,6 +2143,33 @@ out: | |||
2079 | return ret; | 2143 | return ret; |
2080 | } | 2144 | } |
2081 | 2145 | ||
2146 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) | ||
2147 | { | ||
2148 | struct drm_connector *connector; | ||
2149 | struct drm_device *dev = encoder->dev; | ||
2150 | bool uses_atomic = false; | ||
2151 | |||
2152 | /* For atomic drivers only state objects are synchronously updated and | ||
2153 | * protected by modeset locks, so check those first. */ | ||
2154 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
2155 | if (!connector->state) | ||
2156 | continue; | ||
2157 | |||
2158 | uses_atomic = true; | ||
2159 | |||
2160 | if (connector->state->best_encoder != encoder) | ||
2161 | continue; | ||
2162 | |||
2163 | return connector->state->crtc; | ||
2164 | } | ||
2165 | |||
2166 | /* Don't return stale data (e.g. pending async disable). */ | ||
2167 | if (uses_atomic) | ||
2168 | return NULL; | ||
2169 | |||
2170 | return encoder->crtc; | ||
2171 | } | ||
2172 | |||
2082 | /** | 2173 | /** |
2083 | * drm_mode_getencoder - get encoder configuration | 2174 | * drm_mode_getencoder - get encoder configuration |
2084 | * @dev: drm device for the ioctl | 2175 | * @dev: drm device for the ioctl |
@@ -2090,37 +2181,38 @@ out: | |||
2090 | * Called by the user via ioctl. | 2181 | * Called by the user via ioctl. |
2091 | * | 2182 | * |
2092 | * Returns: | 2183 | * Returns: |
2093 | * Zero on success, errno on failure. | 2184 | * Zero on success, negative errno on failure. |
2094 | */ | 2185 | */ |
2095 | int drm_mode_getencoder(struct drm_device *dev, void *data, | 2186 | int drm_mode_getencoder(struct drm_device *dev, void *data, |
2096 | struct drm_file *file_priv) | 2187 | struct drm_file *file_priv) |
2097 | { | 2188 | { |
2098 | struct drm_mode_get_encoder *enc_resp = data; | 2189 | struct drm_mode_get_encoder *enc_resp = data; |
2099 | struct drm_encoder *encoder; | 2190 | struct drm_encoder *encoder; |
2100 | int ret = 0; | 2191 | struct drm_crtc *crtc; |
2101 | 2192 | ||
2102 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2193 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2103 | return -EINVAL; | 2194 | return -EINVAL; |
2104 | 2195 | ||
2105 | drm_modeset_lock_all(dev); | ||
2106 | encoder = drm_encoder_find(dev, enc_resp->encoder_id); | 2196 | encoder = drm_encoder_find(dev, enc_resp->encoder_id); |
2107 | if (!encoder) { | 2197 | if (!encoder) |
2108 | ret = -ENOENT; | 2198 | return -ENOENT; |
2109 | goto out; | ||
2110 | } | ||
2111 | 2199 | ||
2112 | if (encoder->crtc) | 2200 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2201 | crtc = drm_encoder_get_crtc(encoder); | ||
2202 | if (crtc) | ||
2203 | enc_resp->crtc_id = crtc->base.id; | ||
2204 | else if (encoder->crtc) | ||
2113 | enc_resp->crtc_id = encoder->crtc->base.id; | 2205 | enc_resp->crtc_id = encoder->crtc->base.id; |
2114 | else | 2206 | else |
2115 | enc_resp->crtc_id = 0; | 2207 | enc_resp->crtc_id = 0; |
2208 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
2209 | |||
2116 | enc_resp->encoder_type = encoder->encoder_type; | 2210 | enc_resp->encoder_type = encoder->encoder_type; |
2117 | enc_resp->encoder_id = encoder->base.id; | 2211 | enc_resp->encoder_id = encoder->base.id; |
2118 | enc_resp->possible_crtcs = encoder->possible_crtcs; | 2212 | enc_resp->possible_crtcs = encoder->possible_crtcs; |
2119 | enc_resp->possible_clones = encoder->possible_clones; | 2213 | enc_resp->possible_clones = encoder->possible_clones; |
2120 | 2214 | ||
2121 | out: | 2215 | return 0; |
2122 | drm_modeset_unlock_all(dev); | ||
2123 | return ret; | ||
2124 | } | 2216 | } |
2125 | 2217 | ||
2126 | /** | 2218 | /** |
@@ -2134,7 +2226,7 @@ out: | |||
2134 | * Called by the user via ioctl. | 2226 | * Called by the user via ioctl. |
2135 | * | 2227 | * |
2136 | * Returns: | 2228 | * Returns: |
2137 | * Zero on success, errno on failure. | 2229 | * Zero on success, negative errno on failure. |
2138 | */ | 2230 | */ |
2139 | int drm_mode_getplane_res(struct drm_device *dev, void *data, | 2231 | int drm_mode_getplane_res(struct drm_device *dev, void *data, |
2140 | struct drm_file *file_priv) | 2232 | struct drm_file *file_priv) |
@@ -2143,13 +2235,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
2143 | struct drm_mode_config *config; | 2235 | struct drm_mode_config *config; |
2144 | struct drm_plane *plane; | 2236 | struct drm_plane *plane; |
2145 | uint32_t __user *plane_ptr; | 2237 | uint32_t __user *plane_ptr; |
2146 | int copied = 0, ret = 0; | 2238 | int copied = 0; |
2147 | unsigned num_planes; | 2239 | unsigned num_planes; |
2148 | 2240 | ||
2149 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2241 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2150 | return -EINVAL; | 2242 | return -EINVAL; |
2151 | 2243 | ||
2152 | drm_modeset_lock_all(dev); | ||
2153 | config = &dev->mode_config; | 2244 | config = &dev->mode_config; |
2154 | 2245 | ||
2155 | if (file_priv->universal_planes) | 2246 | if (file_priv->universal_planes) |
@@ -2165,6 +2256,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
2165 | (plane_resp->count_planes >= num_planes)) { | 2256 | (plane_resp->count_planes >= num_planes)) { |
2166 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; | 2257 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
2167 | 2258 | ||
2259 | /* Plane lists are invariant, no locking needed. */ | ||
2168 | list_for_each_entry(plane, &config->plane_list, head) { | 2260 | list_for_each_entry(plane, &config->plane_list, head) { |
2169 | /* | 2261 | /* |
2170 | * Unless userspace set the 'universal planes' | 2262 | * Unless userspace set the 'universal planes' |
@@ -2174,18 +2266,14 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, | |||
2174 | !file_priv->universal_planes) | 2266 | !file_priv->universal_planes) |
2175 | continue; | 2267 | continue; |
2176 | 2268 | ||
2177 | if (put_user(plane->base.id, plane_ptr + copied)) { | 2269 | if (put_user(plane->base.id, plane_ptr + copied)) |
2178 | ret = -EFAULT; | 2270 | return -EFAULT; |
2179 | goto out; | ||
2180 | } | ||
2181 | copied++; | 2271 | copied++; |
2182 | } | 2272 | } |
2183 | } | 2273 | } |
2184 | plane_resp->count_planes = num_planes; | 2274 | plane_resp->count_planes = num_planes; |
2185 | 2275 | ||
2186 | out: | 2276 | return 0; |
2187 | drm_modeset_unlock_all(dev); | ||
2188 | return ret; | ||
2189 | } | 2277 | } |
2190 | 2278 | ||
2191 | /** | 2279 | /** |
@@ -2199,7 +2287,7 @@ out: | |||
2199 | * Called by the user via ioctl. | 2287 | * Called by the user via ioctl. |
2200 | * | 2288 | * |
2201 | * Returns: | 2289 | * Returns: |
2202 | * Zero on success, errno on failure. | 2290 | * Zero on success, negative errno on failure. |
2203 | */ | 2291 | */ |
2204 | int drm_mode_getplane(struct drm_device *dev, void *data, | 2292 | int drm_mode_getplane(struct drm_device *dev, void *data, |
2205 | struct drm_file *file_priv) | 2293 | struct drm_file *file_priv) |
@@ -2207,18 +2295,15 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
2207 | struct drm_mode_get_plane *plane_resp = data; | 2295 | struct drm_mode_get_plane *plane_resp = data; |
2208 | struct drm_plane *plane; | 2296 | struct drm_plane *plane; |
2209 | uint32_t __user *format_ptr; | 2297 | uint32_t __user *format_ptr; |
2210 | int ret = 0; | ||
2211 | 2298 | ||
2212 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2299 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2213 | return -EINVAL; | 2300 | return -EINVAL; |
2214 | 2301 | ||
2215 | drm_modeset_lock_all(dev); | ||
2216 | plane = drm_plane_find(dev, plane_resp->plane_id); | 2302 | plane = drm_plane_find(dev, plane_resp->plane_id); |
2217 | if (!plane) { | 2303 | if (!plane) |
2218 | ret = -ENOENT; | 2304 | return -ENOENT; |
2219 | goto out; | ||
2220 | } | ||
2221 | 2305 | ||
2306 | drm_modeset_lock(&plane->mutex, NULL); | ||
2222 | if (plane->crtc) | 2307 | if (plane->crtc) |
2223 | plane_resp->crtc_id = plane->crtc->base.id; | 2308 | plane_resp->crtc_id = plane->crtc->base.id; |
2224 | else | 2309 | else |
@@ -2228,6 +2313,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
2228 | plane_resp->fb_id = plane->fb->base.id; | 2313 | plane_resp->fb_id = plane->fb->base.id; |
2229 | else | 2314 | else |
2230 | plane_resp->fb_id = 0; | 2315 | plane_resp->fb_id = 0; |
2316 | drm_modeset_unlock(&plane->mutex); | ||
2231 | 2317 | ||
2232 | plane_resp->plane_id = plane->base.id; | 2318 | plane_resp->plane_id = plane->base.id; |
2233 | plane_resp->possible_crtcs = plane->possible_crtcs; | 2319 | plane_resp->possible_crtcs = plane->possible_crtcs; |
@@ -2243,15 +2329,12 @@ int drm_mode_getplane(struct drm_device *dev, void *data, | |||
2243 | if (copy_to_user(format_ptr, | 2329 | if (copy_to_user(format_ptr, |
2244 | plane->format_types, | 2330 | plane->format_types, |
2245 | sizeof(uint32_t) * plane->format_count)) { | 2331 | sizeof(uint32_t) * plane->format_count)) { |
2246 | ret = -EFAULT; | 2332 | return -EFAULT; |
2247 | goto out; | ||
2248 | } | 2333 | } |
2249 | } | 2334 | } |
2250 | plane_resp->count_format_types = plane->format_count; | 2335 | plane_resp->count_format_types = plane->format_count; |
2251 | 2336 | ||
2252 | out: | 2337 | return 0; |
2253 | drm_modeset_unlock_all(dev); | ||
2254 | return ret; | ||
2255 | } | 2338 | } |
2256 | 2339 | ||
2257 | /* | 2340 | /* |
@@ -2274,7 +2357,7 @@ static int __setplane_internal(struct drm_plane *plane, | |||
2274 | { | 2357 | { |
2275 | int ret = 0; | 2358 | int ret = 0; |
2276 | unsigned int fb_width, fb_height; | 2359 | unsigned int fb_width, fb_height; |
2277 | int i; | 2360 | unsigned int i; |
2278 | 2361 | ||
2279 | /* No fb means shut it down */ | 2362 | /* No fb means shut it down */ |
2280 | if (!fb) { | 2363 | if (!fb) { |
@@ -2378,13 +2461,12 @@ static int setplane_internal(struct drm_plane *plane, | |||
2378 | * valid crtc). | 2461 | * valid crtc). |
2379 | * | 2462 | * |
2380 | * Returns: | 2463 | * Returns: |
2381 | * Zero on success, errno on failure. | 2464 | * Zero on success, negative errno on failure. |
2382 | */ | 2465 | */ |
2383 | int drm_mode_setplane(struct drm_device *dev, void *data, | 2466 | int drm_mode_setplane(struct drm_device *dev, void *data, |
2384 | struct drm_file *file_priv) | 2467 | struct drm_file *file_priv) |
2385 | { | 2468 | { |
2386 | struct drm_mode_set_plane *plane_req = data; | 2469 | struct drm_mode_set_plane *plane_req = data; |
2387 | struct drm_mode_object *obj; | ||
2388 | struct drm_plane *plane; | 2470 | struct drm_plane *plane; |
2389 | struct drm_crtc *crtc = NULL; | 2471 | struct drm_crtc *crtc = NULL; |
2390 | struct drm_framebuffer *fb = NULL; | 2472 | struct drm_framebuffer *fb = NULL; |
@@ -2407,14 +2489,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2407 | * First, find the plane, crtc, and fb objects. If not available, | 2489 | * First, find the plane, crtc, and fb objects. If not available, |
2408 | * we don't bother to call the driver. | 2490 | * we don't bother to call the driver. |
2409 | */ | 2491 | */ |
2410 | obj = drm_mode_object_find(dev, plane_req->plane_id, | 2492 | plane = drm_plane_find(dev, plane_req->plane_id); |
2411 | DRM_MODE_OBJECT_PLANE); | 2493 | if (!plane) { |
2412 | if (!obj) { | ||
2413 | DRM_DEBUG_KMS("Unknown plane ID %d\n", | 2494 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
2414 | plane_req->plane_id); | 2495 | plane_req->plane_id); |
2415 | return -ENOENT; | 2496 | return -ENOENT; |
2416 | } | 2497 | } |
2417 | plane = obj_to_plane(obj); | ||
2418 | 2498 | ||
2419 | if (plane_req->fb_id) { | 2499 | if (plane_req->fb_id) { |
2420 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); | 2500 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); |
@@ -2424,14 +2504,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2424 | return -ENOENT; | 2504 | return -ENOENT; |
2425 | } | 2505 | } |
2426 | 2506 | ||
2427 | obj = drm_mode_object_find(dev, plane_req->crtc_id, | 2507 | crtc = drm_crtc_find(dev, plane_req->crtc_id); |
2428 | DRM_MODE_OBJECT_CRTC); | 2508 | if (!crtc) { |
2429 | if (!obj) { | ||
2430 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", | 2509 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", |
2431 | plane_req->crtc_id); | 2510 | plane_req->crtc_id); |
2432 | return -ENOENT; | 2511 | return -ENOENT; |
2433 | } | 2512 | } |
2434 | crtc = obj_to_crtc(obj); | ||
2435 | } | 2513 | } |
2436 | 2514 | ||
2437 | /* | 2515 | /* |
@@ -2453,7 +2531,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2453 | * interface. The only thing it adds is correct refcounting dance. | 2531 | * interface. The only thing it adds is correct refcounting dance. |
2454 | * | 2532 | * |
2455 | * Returns: | 2533 | * Returns: |
2456 | * Zero on success, errno on failure. | 2534 | * Zero on success, negative errno on failure. |
2457 | */ | 2535 | */ |
2458 | int drm_mode_set_config_internal(struct drm_mode_set *set) | 2536 | int drm_mode_set_config_internal(struct drm_mode_set *set) |
2459 | { | 2537 | { |
@@ -2546,7 +2624,7 @@ EXPORT_SYMBOL(drm_crtc_check_viewport); | |||
2546 | * Called by the user via ioctl. | 2624 | * Called by the user via ioctl. |
2547 | * | 2625 | * |
2548 | * Returns: | 2626 | * Returns: |
2549 | * Zero on success, errno on failure. | 2627 | * Zero on success, negative errno on failure. |
2550 | */ | 2628 | */ |
2551 | int drm_mode_setcrtc(struct drm_device *dev, void *data, | 2629 | int drm_mode_setcrtc(struct drm_device *dev, void *data, |
2552 | struct drm_file *file_priv) | 2630 | struct drm_file *file_priv) |
@@ -2709,7 +2787,7 @@ out: | |||
2709 | * userspace wants to make use of these capabilities. | 2787 | * userspace wants to make use of these capabilities. |
2710 | * | 2788 | * |
2711 | * Returns: | 2789 | * Returns: |
2712 | * Zero on success, errno on failure. | 2790 | * Zero on success, negative errno on failure. |
2713 | */ | 2791 | */ |
2714 | static int drm_mode_cursor_universal(struct drm_crtc *crtc, | 2792 | static int drm_mode_cursor_universal(struct drm_crtc *crtc, |
2715 | struct drm_mode_cursor2 *req, | 2793 | struct drm_mode_cursor2 *req, |
@@ -2810,7 +2888,7 @@ static int drm_mode_cursor_common(struct drm_device *dev, | |||
2810 | * If this crtc has a universal cursor plane, call that plane's update | 2888 | * If this crtc has a universal cursor plane, call that plane's update |
2811 | * handler rather than using legacy cursor handlers. | 2889 | * handler rather than using legacy cursor handlers. |
2812 | */ | 2890 | */ |
2813 | drm_modeset_lock_crtc(crtc); | 2891 | drm_modeset_lock_crtc(crtc, crtc->cursor); |
2814 | if (crtc->cursor) { | 2892 | if (crtc->cursor) { |
2815 | ret = drm_mode_cursor_universal(crtc, req, file_priv); | 2893 | ret = drm_mode_cursor_universal(crtc, req, file_priv); |
2816 | goto out; | 2894 | goto out; |
@@ -2857,7 +2935,7 @@ out: | |||
2857 | * Called by the user via ioctl. | 2935 | * Called by the user via ioctl. |
2858 | * | 2936 | * |
2859 | * Returns: | 2937 | * Returns: |
2860 | * Zero on success, errno on failure. | 2938 | * Zero on success, negative errno on failure. |
2861 | */ | 2939 | */ |
2862 | int drm_mode_cursor_ioctl(struct drm_device *dev, | 2940 | int drm_mode_cursor_ioctl(struct drm_device *dev, |
2863 | void *data, struct drm_file *file_priv) | 2941 | void *data, struct drm_file *file_priv) |
@@ -2884,7 +2962,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, | |||
2884 | * Called by the user via ioctl. | 2962 | * Called by the user via ioctl. |
2885 | * | 2963 | * |
2886 | * Returns: | 2964 | * Returns: |
2887 | * Zero on success, errno on failure. | 2965 | * Zero on success, negative errno on failure. |
2888 | */ | 2966 | */ |
2889 | int drm_mode_cursor2_ioctl(struct drm_device *dev, | 2967 | int drm_mode_cursor2_ioctl(struct drm_device *dev, |
2890 | void *data, struct drm_file *file_priv) | 2968 | void *data, struct drm_file *file_priv) |
@@ -2943,23 +3021,21 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format); | |||
2943 | * @file_priv: drm file for the ioctl call | 3021 | * @file_priv: drm file for the ioctl call |
2944 | * | 3022 | * |
2945 | * Add a new FB to the specified CRTC, given a user request. This is the | 3023 | * Add a new FB to the specified CRTC, given a user request. This is the |
2946 | * original addfb ioclt which only supported RGB formats. | 3024 | * original addfb ioctl which only supported RGB formats. |
2947 | * | 3025 | * |
2948 | * Called by the user via ioctl. | 3026 | * Called by the user via ioctl. |
2949 | * | 3027 | * |
2950 | * Returns: | 3028 | * Returns: |
2951 | * Zero on success, errno on failure. | 3029 | * Zero on success, negative errno on failure. |
2952 | */ | 3030 | */ |
2953 | int drm_mode_addfb(struct drm_device *dev, | 3031 | int drm_mode_addfb(struct drm_device *dev, |
2954 | void *data, struct drm_file *file_priv) | 3032 | void *data, struct drm_file *file_priv) |
2955 | { | 3033 | { |
2956 | struct drm_mode_fb_cmd *or = data; | 3034 | struct drm_mode_fb_cmd *or = data; |
2957 | struct drm_mode_fb_cmd2 r = {}; | 3035 | struct drm_mode_fb_cmd2 r = {}; |
2958 | struct drm_mode_config *config = &dev->mode_config; | 3036 | int ret; |
2959 | struct drm_framebuffer *fb; | ||
2960 | int ret = 0; | ||
2961 | 3037 | ||
2962 | /* Use new struct with format internally */ | 3038 | /* convert to new format and call new ioctl */ |
2963 | r.fb_id = or->fb_id; | 3039 | r.fb_id = or->fb_id; |
2964 | r.width = or->width; | 3040 | r.width = or->width; |
2965 | r.height = or->height; | 3041 | r.height = or->height; |
@@ -2967,28 +3043,13 @@ int drm_mode_addfb(struct drm_device *dev, | |||
2967 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | 3043 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
2968 | r.handles[0] = or->handle; | 3044 | r.handles[0] = or->handle; |
2969 | 3045 | ||
2970 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3046 | ret = drm_mode_addfb2(dev, &r, file_priv); |
2971 | return -EINVAL; | 3047 | if (ret) |
2972 | 3048 | return ret; | |
2973 | if ((config->min_width > r.width) || (r.width > config->max_width)) | ||
2974 | return -EINVAL; | ||
2975 | |||
2976 | if ((config->min_height > r.height) || (r.height > config->max_height)) | ||
2977 | return -EINVAL; | ||
2978 | 3049 | ||
2979 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); | 3050 | or->fb_id = r.fb_id; |
2980 | if (IS_ERR(fb)) { | ||
2981 | DRM_DEBUG_KMS("could not create framebuffer\n"); | ||
2982 | return PTR_ERR(fb); | ||
2983 | } | ||
2984 | 3051 | ||
2985 | mutex_lock(&file_priv->fbs_lock); | 3052 | return 0; |
2986 | or->fb_id = fb->base.id; | ||
2987 | list_add(&fb->filp_head, &file_priv->fbs); | ||
2988 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); | ||
2989 | mutex_unlock(&file_priv->fbs_lock); | ||
2990 | |||
2991 | return ret; | ||
2992 | } | 3053 | } |
2993 | 3054 | ||
2994 | static int format_check(const struct drm_mode_fb_cmd2 *r) | 3055 | static int format_check(const struct drm_mode_fb_cmd2 *r) |
@@ -3080,7 +3141,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) | |||
3080 | num_planes = drm_format_num_planes(r->pixel_format); | 3141 | num_planes = drm_format_num_planes(r->pixel_format); |
3081 | 3142 | ||
3082 | if (r->width == 0 || r->width % hsub) { | 3143 | if (r->width == 0 || r->width % hsub) { |
3083 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); | 3144 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); |
3084 | return -EINVAL; | 3145 | return -EINVAL; |
3085 | } | 3146 | } |
3086 | 3147 | ||
@@ -3170,7 +3231,7 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, | |||
3170 | * Called by the user via ioctl. | 3231 | * Called by the user via ioctl. |
3171 | * | 3232 | * |
3172 | * Returns: | 3233 | * Returns: |
3173 | * Zero on success, errno on failure. | 3234 | * Zero on success, negative errno on failure. |
3174 | */ | 3235 | */ |
3175 | int drm_mode_addfb2(struct drm_device *dev, | 3236 | int drm_mode_addfb2(struct drm_device *dev, |
3176 | void *data, struct drm_file *file_priv) | 3237 | void *data, struct drm_file *file_priv) |
@@ -3198,7 +3259,7 @@ int drm_mode_addfb2(struct drm_device *dev, | |||
3198 | * Called by the user via ioctl. | 3259 | * Called by the user via ioctl. |
3199 | * | 3260 | * |
3200 | * Returns: | 3261 | * Returns: |
3201 | * Zero on success, errno on failure. | 3262 | * Zero on success, negative errno on failure. |
3202 | */ | 3263 | */ |
3203 | int drm_mode_rmfb(struct drm_device *dev, | 3264 | int drm_mode_rmfb(struct drm_device *dev, |
3204 | void *data, struct drm_file *file_priv) | 3265 | void *data, struct drm_file *file_priv) |
@@ -3252,7 +3313,7 @@ fail_lookup: | |||
3252 | * Called by the user via ioctl. | 3313 | * Called by the user via ioctl. |
3253 | * | 3314 | * |
3254 | * Returns: | 3315 | * Returns: |
3255 | * Zero on success, errno on failure. | 3316 | * Zero on success, negative errno on failure. |
3256 | */ | 3317 | */ |
3257 | int drm_mode_getfb(struct drm_device *dev, | 3318 | int drm_mode_getfb(struct drm_device *dev, |
3258 | void *data, struct drm_file *file_priv) | 3319 | void *data, struct drm_file *file_priv) |
@@ -3313,7 +3374,7 @@ int drm_mode_getfb(struct drm_device *dev, | |||
3313 | * Called by the user via ioctl. | 3374 | * Called by the user via ioctl. |
3314 | * | 3375 | * |
3315 | * Returns: | 3376 | * Returns: |
3316 | * Zero on success, errno on failure. | 3377 | * Zero on success, negative errno on failure. |
3317 | */ | 3378 | */ |
3318 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | 3379 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, |
3319 | void *data, struct drm_file *file_priv) | 3380 | void *data, struct drm_file *file_priv) |
@@ -3393,7 +3454,7 @@ out_err1: | |||
3393 | * Called by the user via ioctl. | 3454 | * Called by the user via ioctl. |
3394 | * | 3455 | * |
3395 | * Returns: | 3456 | * Returns: |
3396 | * Zero on success, errno on failure. | 3457 | * Zero on success, negative errno on failure. |
3397 | */ | 3458 | */ |
3398 | void drm_fb_release(struct drm_file *priv) | 3459 | void drm_fb_release(struct drm_file *priv) |
3399 | { | 3460 | { |
@@ -3402,7 +3463,7 @@ void drm_fb_release(struct drm_file *priv) | |||
3402 | 3463 | ||
3403 | /* | 3464 | /* |
3404 | * When the file gets released that means no one else can access the fb | 3465 | * When the file gets released that means no one else can access the fb |
3405 | * list any more, so no need to grab fpriv->fbs_lock. And we need to to | 3466 | * list any more, so no need to grab fpriv->fbs_lock. And we need to |
3406 | * avoid upsetting lockdep since the universal cursor code adds a | 3467 | * avoid upsetting lockdep since the universal cursor code adds a |
3407 | * framebuffer while holding mutex locks. | 3468 | * framebuffer while holding mutex locks. |
3408 | * | 3469 | * |
@@ -3435,6 +3496,10 @@ void drm_fb_release(struct drm_file *priv) | |||
3435 | * object with drm_object_attach_property. The returned property object must be | 3496 | * object with drm_object_attach_property. The returned property object must be |
3436 | * freed with drm_property_destroy. | 3497 | * freed with drm_property_destroy. |
3437 | * | 3498 | * |
3499 | * Note that the DRM core keeps a per-device list of properties and that, if | ||
3500 | * drm_mode_config_cleanup() is called, it will destroy all properties created | ||
3501 | * by the driver. | ||
3502 | * | ||
3438 | * Returns: | 3503 | * Returns: |
3439 | * A pointer to the newly created property on success, NULL on failure. | 3504 | * A pointer to the newly created property on success, NULL on failure. |
3440 | */ | 3505 | */ |
@@ -3462,7 +3527,7 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, | |||
3462 | 3527 | ||
3463 | property->flags = flags; | 3528 | property->flags = flags; |
3464 | property->num_values = num_values; | 3529 | property->num_values = num_values; |
3465 | INIT_LIST_HEAD(&property->enum_blob_list); | 3530 | INIT_LIST_HEAD(&property->enum_list); |
3466 | 3531 | ||
3467 | if (name) { | 3532 | if (name) { |
3468 | strncpy(property->name, name, DRM_PROP_NAME_LEN); | 3533 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
@@ -3611,7 +3676,7 @@ static struct drm_property *property_create_range(struct drm_device *dev, | |||
3611 | * object with drm_object_attach_property. The returned property object must be | 3676 | * object with drm_object_attach_property. The returned property object must be |
3612 | * freed with drm_property_destroy. | 3677 | * freed with drm_property_destroy. |
3613 | * | 3678 | * |
3614 | * Userspace is allowed to set any interger value in the (min, max) range | 3679 | * Userspace is allowed to set any integer value in the (min, max) range |
3615 | * inclusive. | 3680 | * inclusive. |
3616 | * | 3681 | * |
3617 | * Returns: | 3682 | * Returns: |
@@ -3684,8 +3749,8 @@ int drm_property_add_enum(struct drm_property *property, int index, | |||
3684 | (value > 63)) | 3749 | (value > 63)) |
3685 | return -EINVAL; | 3750 | return -EINVAL; |
3686 | 3751 | ||
3687 | if (!list_empty(&property->enum_blob_list)) { | 3752 | if (!list_empty(&property->enum_list)) { |
3688 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { | 3753 | list_for_each_entry(prop_enum, &property->enum_list, head) { |
3689 | if (prop_enum->value == value) { | 3754 | if (prop_enum->value == value) { |
3690 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); | 3755 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); |
3691 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; | 3756 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; |
@@ -3703,7 +3768,7 @@ int drm_property_add_enum(struct drm_property *property, int index, | |||
3703 | prop_enum->value = value; | 3768 | prop_enum->value = value; |
3704 | 3769 | ||
3705 | property->values[index] = value; | 3770 | property->values[index] = value; |
3706 | list_add_tail(&prop_enum->head, &property->enum_blob_list); | 3771 | list_add_tail(&prop_enum->head, &property->enum_list); |
3707 | return 0; | 3772 | return 0; |
3708 | } | 3773 | } |
3709 | EXPORT_SYMBOL(drm_property_add_enum); | 3774 | EXPORT_SYMBOL(drm_property_add_enum); |
@@ -3720,7 +3785,7 @@ void drm_property_destroy(struct drm_device *dev, struct drm_property *property) | |||
3720 | { | 3785 | { |
3721 | struct drm_property_enum *prop_enum, *pt; | 3786 | struct drm_property_enum *prop_enum, *pt; |
3722 | 3787 | ||
3723 | list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { | 3788 | list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) { |
3724 | list_del(&prop_enum->head); | 3789 | list_del(&prop_enum->head); |
3725 | kfree(prop_enum); | 3790 | kfree(prop_enum); |
3726 | } | 3791 | } |
@@ -3823,17 +3888,20 @@ int drm_object_property_get_value(struct drm_mode_object *obj, | |||
3823 | EXPORT_SYMBOL(drm_object_property_get_value); | 3888 | EXPORT_SYMBOL(drm_object_property_get_value); |
3824 | 3889 | ||
3825 | /** | 3890 | /** |
3826 | * drm_mode_getproperty_ioctl - get the current value of a connector's property | 3891 | * drm_mode_getproperty_ioctl - get the property metadata |
3827 | * @dev: DRM device | 3892 | * @dev: DRM device |
3828 | * @data: ioctl data | 3893 | * @data: ioctl data |
3829 | * @file_priv: DRM file info | 3894 | * @file_priv: DRM file info |
3830 | * | 3895 | * |
3831 | * This function retrieves the current value for an connectors's property. | 3896 | * This function retrieves the metadata for a given property, like the different |
3897 | * possible values for an enum property or the limits for a range property. | ||
3898 | * | ||
3899 | * Blob properties are special | ||
3832 | * | 3900 | * |
3833 | * Called by the user via ioctl. | 3901 | * Called by the user via ioctl. |
3834 | * | 3902 | * |
3835 | * Returns: | 3903 | * Returns: |
3836 | * Zero on success, errno on failure. | 3904 | * Zero on success, negative errno on failure. |
3837 | */ | 3905 | */ |
3838 | int drm_mode_getproperty_ioctl(struct drm_device *dev, | 3906 | int drm_mode_getproperty_ioctl(struct drm_device *dev, |
3839 | void *data, struct drm_file *file_priv) | 3907 | void *data, struct drm_file *file_priv) |
@@ -3841,16 +3909,12 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3841 | struct drm_mode_get_property *out_resp = data; | 3909 | struct drm_mode_get_property *out_resp = data; |
3842 | struct drm_property *property; | 3910 | struct drm_property *property; |
3843 | int enum_count = 0; | 3911 | int enum_count = 0; |
3844 | int blob_count = 0; | ||
3845 | int value_count = 0; | 3912 | int value_count = 0; |
3846 | int ret = 0, i; | 3913 | int ret = 0, i; |
3847 | int copied; | 3914 | int copied; |
3848 | struct drm_property_enum *prop_enum; | 3915 | struct drm_property_enum *prop_enum; |
3849 | struct drm_mode_property_enum __user *enum_ptr; | 3916 | struct drm_mode_property_enum __user *enum_ptr; |
3850 | struct drm_property_blob *prop_blob; | ||
3851 | uint32_t __user *blob_id_ptr; | ||
3852 | uint64_t __user *values_ptr; | 3917 | uint64_t __user *values_ptr; |
3853 | uint32_t __user *blob_length_ptr; | ||
3854 | 3918 | ||
3855 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 3919 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3856 | return -EINVAL; | 3920 | return -EINVAL; |
@@ -3864,11 +3928,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3864 | 3928 | ||
3865 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || | 3929 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3866 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { | 3930 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3867 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) | 3931 | list_for_each_entry(prop_enum, &property->enum_list, head) |
3868 | enum_count++; | 3932 | enum_count++; |
3869 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { | ||
3870 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) | ||
3871 | blob_count++; | ||
3872 | } | 3933 | } |
3873 | 3934 | ||
3874 | value_count = property->num_values; | 3935 | value_count = property->num_values; |
@@ -3893,7 +3954,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3893 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { | 3954 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
3894 | copied = 0; | 3955 | copied = 0; |
3895 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; | 3956 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; |
3896 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { | 3957 | list_for_each_entry(prop_enum, &property->enum_list, head) { |
3897 | 3958 | ||
3898 | if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { | 3959 | if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { |
3899 | ret = -EFAULT; | 3960 | ret = -EFAULT; |
@@ -3911,35 +3972,24 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, | |||
3911 | out_resp->count_enum_blobs = enum_count; | 3972 | out_resp->count_enum_blobs = enum_count; |
3912 | } | 3973 | } |
3913 | 3974 | ||
3914 | if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { | 3975 | /* |
3915 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { | 3976 | * NOTE: The idea seems to have been to use this to read all the blob |
3916 | copied = 0; | 3977 | * property values. But nothing ever added them to the corresponding |
3917 | blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; | 3978 | * list, userspace always used the special-purpose get_blob ioctl to |
3918 | blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; | 3979 | * read the value for a blob property. It also doesn't make a lot of |
3919 | 3980 | * sense to return values here when everything else is just metadata for | |
3920 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) { | 3981 | * the property itself. |
3921 | if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { | 3982 | */ |
3922 | ret = -EFAULT; | 3983 | if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) |
3923 | goto done; | 3984 | out_resp->count_enum_blobs = 0; |
3924 | } | ||
3925 | |||
3926 | if (put_user(prop_blob->length, blob_length_ptr + copied)) { | ||
3927 | ret = -EFAULT; | ||
3928 | goto done; | ||
3929 | } | ||
3930 | |||
3931 | copied++; | ||
3932 | } | ||
3933 | } | ||
3934 | out_resp->count_enum_blobs = blob_count; | ||
3935 | } | ||
3936 | done: | 3985 | done: |
3937 | drm_modeset_unlock_all(dev); | 3986 | drm_modeset_unlock_all(dev); |
3938 | return ret; | 3987 | return ret; |
3939 | } | 3988 | } |
3940 | 3989 | ||
3941 | static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, | 3990 | static struct drm_property_blob * |
3942 | void *data) | 3991 | drm_property_create_blob(struct drm_device *dev, size_t length, |
3992 | const void *data) | ||
3943 | { | 3993 | { |
3944 | struct drm_property_blob *blob; | 3994 | struct drm_property_blob *blob; |
3945 | int ret; | 3995 | int ret; |
@@ -3985,7 +4035,7 @@ static void drm_property_destroy_blob(struct drm_device *dev, | |||
3985 | * Called by the user via ioctl. | 4035 | * Called by the user via ioctl. |
3986 | * | 4036 | * |
3987 | * Returns: | 4037 | * Returns: |
3988 | * Zero on success, errno on failure. | 4038 | * Zero on success, negative errno on failure. |
3989 | */ | 4039 | */ |
3990 | int drm_mode_getblob_ioctl(struct drm_device *dev, | 4040 | int drm_mode_getblob_ioctl(struct drm_device *dev, |
3991 | void *data, struct drm_file *file_priv) | 4041 | void *data, struct drm_file *file_priv) |
@@ -4019,12 +4069,25 @@ done: | |||
4019 | return ret; | 4069 | return ret; |
4020 | } | 4070 | } |
4021 | 4071 | ||
4072 | /** | ||
4073 | * drm_mode_connector_set_path_property - set tile property on connector | ||
4074 | * @connector: connector to set property on. | ||
4075 | * @path: path to use for property. | ||
4076 | * | ||
4077 | * This creates a property to expose to userspace to specify a | ||
4078 | * connector path. This is mainly used for DisplayPort MST where | ||
4079 | * connectors have a topology and we want to allow userspace to give | ||
4080 | * them more meaningful names. | ||
4081 | * | ||
4082 | * Returns: | ||
4083 | * Zero on success, negative errno on failure. | ||
4084 | */ | ||
4022 | int drm_mode_connector_set_path_property(struct drm_connector *connector, | 4085 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
4023 | char *path) | 4086 | const char *path) |
4024 | { | 4087 | { |
4025 | struct drm_device *dev = connector->dev; | 4088 | struct drm_device *dev = connector->dev; |
4026 | int ret, size; | 4089 | size_t size = strlen(path) + 1; |
4027 | size = strlen(path) + 1; | 4090 | int ret; |
4028 | 4091 | ||
4029 | connector->path_blob_ptr = drm_property_create_blob(connector->dev, | 4092 | connector->path_blob_ptr = drm_property_create_blob(connector->dev, |
4030 | size, path); | 4093 | size, path); |
@@ -4039,6 +4102,52 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector, | |||
4039 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); | 4102 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); |
4040 | 4103 | ||
4041 | /** | 4104 | /** |
4105 | * drm_mode_connector_set_tile_property - set tile property on connector | ||
4106 | * @connector: connector to set property on. | ||
4107 | * | ||
4108 | * This looks up the tile information for a connector, and creates a | ||
4109 | * property for userspace to parse if it exists. The property is of | ||
4110 | * the form of 8 integers using ':' as a separator. | ||
4111 | * | ||
4112 | * Returns: | ||
4113 | * Zero on success, errno on failure. | ||
4114 | */ | ||
4115 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) | ||
4116 | { | ||
4117 | struct drm_device *dev = connector->dev; | ||
4118 | int ret, size; | ||
4119 | char tile[256]; | ||
4120 | |||
4121 | if (connector->tile_blob_ptr) | ||
4122 | drm_property_destroy_blob(dev, connector->tile_blob_ptr); | ||
4123 | |||
4124 | if (!connector->has_tile) { | ||
4125 | connector->tile_blob_ptr = NULL; | ||
4126 | ret = drm_object_property_set_value(&connector->base, | ||
4127 | dev->mode_config.tile_property, 0); | ||
4128 | return ret; | ||
4129 | } | ||
4130 | |||
4131 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", | ||
4132 | connector->tile_group->id, connector->tile_is_single_monitor, | ||
4133 | connector->num_h_tile, connector->num_v_tile, | ||
4134 | connector->tile_h_loc, connector->tile_v_loc, | ||
4135 | connector->tile_h_size, connector->tile_v_size); | ||
4136 | size = strlen(tile) + 1; | ||
4137 | |||
4138 | connector->tile_blob_ptr = drm_property_create_blob(connector->dev, | ||
4139 | size, tile); | ||
4140 | if (!connector->tile_blob_ptr) | ||
4141 | return -EINVAL; | ||
4142 | |||
4143 | ret = drm_object_property_set_value(&connector->base, | ||
4144 | dev->mode_config.tile_property, | ||
4145 | connector->tile_blob_ptr->base.id); | ||
4146 | return ret; | ||
4147 | } | ||
4148 | EXPORT_SYMBOL(drm_mode_connector_set_tile_property); | ||
4149 | |||
4150 | /** | ||
4042 | * drm_mode_connector_update_edid_property - update the edid property of a connector | 4151 | * drm_mode_connector_update_edid_property - update the edid property of a connector |
4043 | * @connector: drm connector | 4152 | * @connector: drm connector |
4044 | * @edid: new value of the edid property | 4153 | * @edid: new value of the edid property |
@@ -4047,13 +4156,14 @@ EXPORT_SYMBOL(drm_mode_connector_set_path_property); | |||
4047 | * connector's edid property. | 4156 | * connector's edid property. |
4048 | * | 4157 | * |
4049 | * Returns: | 4158 | * Returns: |
4050 | * Zero on success, errno on failure. | 4159 | * Zero on success, negative errno on failure. |
4051 | */ | 4160 | */ |
4052 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, | 4161 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
4053 | struct edid *edid) | 4162 | const struct edid *edid) |
4054 | { | 4163 | { |
4055 | struct drm_device *dev = connector->dev; | 4164 | struct drm_device *dev = connector->dev; |
4056 | int ret, size; | 4165 | size_t size; |
4166 | int ret; | ||
4057 | 4167 | ||
4058 | /* ignore requests to set edid when overridden */ | 4168 | /* ignore requests to set edid when overridden */ |
4059 | if (connector->override_edid) | 4169 | if (connector->override_edid) |
@@ -4143,7 +4253,7 @@ static bool drm_property_change_is_valid(struct drm_property *property, | |||
4143 | * Called by the user via ioctl. | 4253 | * Called by the user via ioctl. |
4144 | * | 4254 | * |
4145 | * Returns: | 4255 | * Returns: |
4146 | * Zero on success, errno on failure. | 4256 | * Zero on success, negative errno on failure. |
4147 | */ | 4257 | */ |
4148 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | 4258 | int drm_mode_connector_property_set_ioctl(struct drm_device *dev, |
4149 | void *data, struct drm_file *file_priv) | 4259 | void *data, struct drm_file *file_priv) |
@@ -4226,7 +4336,7 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane, | |||
4226 | EXPORT_SYMBOL(drm_mode_plane_set_obj_prop); | 4336 | EXPORT_SYMBOL(drm_mode_plane_set_obj_prop); |
4227 | 4337 | ||
4228 | /** | 4338 | /** |
4229 | * drm_mode_getproperty_ioctl - get the current value of a object's property | 4339 | * drm_mode_obj_get_properties_ioctl - get the current value of a object's property |
4230 | * @dev: DRM device | 4340 | * @dev: DRM device |
4231 | * @data: ioctl data | 4341 | * @data: ioctl data |
4232 | * @file_priv: DRM file info | 4342 | * @file_priv: DRM file info |
@@ -4238,7 +4348,7 @@ EXPORT_SYMBOL(drm_mode_plane_set_obj_prop); | |||
4238 | * Called by the user via ioctl. | 4348 | * Called by the user via ioctl. |
4239 | * | 4349 | * |
4240 | * Returns: | 4350 | * Returns: |
4241 | * Zero on success, errno on failure. | 4351 | * Zero on success, negative errno on failure. |
4242 | */ | 4352 | */ |
4243 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | 4353 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, |
4244 | struct drm_file *file_priv) | 4354 | struct drm_file *file_priv) |
@@ -4310,7 +4420,7 @@ out: | |||
4310 | * Called by the user via ioctl. | 4420 | * Called by the user via ioctl. |
4311 | * | 4421 | * |
4312 | * Returns: | 4422 | * Returns: |
4313 | * Zero on success, errno on failure. | 4423 | * Zero on success, negative errno on failure. |
4314 | */ | 4424 | */ |
4315 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | 4425 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, |
4316 | struct drm_file *file_priv) | 4426 | struct drm_file *file_priv) |
@@ -4382,7 +4492,7 @@ out: | |||
4382 | * possible_clones and possible_crtcs bitmasks. | 4492 | * possible_clones and possible_crtcs bitmasks. |
4383 | * | 4493 | * |
4384 | * Returns: | 4494 | * Returns: |
4385 | * Zero on success, errno on failure. | 4495 | * Zero on success, negative errno on failure. |
4386 | */ | 4496 | */ |
4387 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, | 4497 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, |
4388 | struct drm_encoder *encoder) | 4498 | struct drm_encoder *encoder) |
@@ -4409,7 +4519,7 @@ EXPORT_SYMBOL(drm_mode_connector_attach_encoder); | |||
4409 | * fixed gamma table size. | 4519 | * fixed gamma table size. |
4410 | * | 4520 | * |
4411 | * Returns: | 4521 | * Returns: |
4412 | * Zero on success, errno on failure. | 4522 | * Zero on success, negative errno on failure. |
4413 | */ | 4523 | */ |
4414 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, | 4524 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
4415 | int gamma_size) | 4525 | int gamma_size) |
@@ -4438,7 +4548,7 @@ EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); | |||
4438 | * Called by the user via ioctl. | 4548 | * Called by the user via ioctl. |
4439 | * | 4549 | * |
4440 | * Returns: | 4550 | * Returns: |
4441 | * Zero on success, errno on failure. | 4551 | * Zero on success, negative errno on failure. |
4442 | */ | 4552 | */ |
4443 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, | 4553 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, |
4444 | void *data, struct drm_file *file_priv) | 4554 | void *data, struct drm_file *file_priv) |
@@ -4510,7 +4620,7 @@ out: | |||
4510 | * Called by the user via ioctl. | 4620 | * Called by the user via ioctl. |
4511 | * | 4621 | * |
4512 | * Returns: | 4622 | * Returns: |
4513 | * Zero on success, errno on failure. | 4623 | * Zero on success, negative errno on failure. |
4514 | */ | 4624 | */ |
4515 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, | 4625 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
4516 | void *data, struct drm_file *file_priv) | 4626 | void *data, struct drm_file *file_priv) |
@@ -4576,7 +4686,7 @@ out: | |||
4576 | * Called by the user via ioctl. | 4686 | * Called by the user via ioctl. |
4577 | * | 4687 | * |
4578 | * Returns: | 4688 | * Returns: |
4579 | * Zero on success, errno on failure. | 4689 | * Zero on success, negative errno on failure. |
4580 | */ | 4690 | */ |
4581 | int drm_mode_page_flip_ioctl(struct drm_device *dev, | 4691 | int drm_mode_page_flip_ioctl(struct drm_device *dev, |
4582 | void *data, struct drm_file *file_priv) | 4692 | void *data, struct drm_file *file_priv) |
@@ -4599,7 +4709,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
4599 | if (!crtc) | 4709 | if (!crtc) |
4600 | return -ENOENT; | 4710 | return -ENOENT; |
4601 | 4711 | ||
4602 | drm_modeset_lock_crtc(crtc); | 4712 | drm_modeset_lock_crtc(crtc, crtc->primary); |
4603 | if (crtc->primary->fb == NULL) { | 4713 | if (crtc->primary->fb == NULL) { |
4604 | /* The framebuffer is currently unbound, presumably | 4714 | /* The framebuffer is currently unbound, presumably |
4605 | * due to a hotplug event, that userspace has not | 4715 | * due to a hotplug event, that userspace has not |
@@ -4742,7 +4852,7 @@ EXPORT_SYMBOL(drm_mode_config_reset); | |||
4742 | * Called by the user via ioctl. | 4852 | * Called by the user via ioctl. |
4743 | * | 4853 | * |
4744 | * Returns: | 4854 | * Returns: |
4745 | * Zero on success, errno on failure. | 4855 | * Zero on success, negative errno on failure. |
4746 | */ | 4856 | */ |
4747 | int drm_mode_create_dumb_ioctl(struct drm_device *dev, | 4857 | int drm_mode_create_dumb_ioctl(struct drm_device *dev, |
4748 | void *data, struct drm_file *file_priv) | 4858 | void *data, struct drm_file *file_priv) |
@@ -4769,6 +4879,16 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, | |||
4769 | if (PAGE_ALIGN(size) == 0) | 4879 | if (PAGE_ALIGN(size) == 0) |
4770 | return -EINVAL; | 4880 | return -EINVAL; |
4771 | 4881 | ||
4882 | /* | ||
4883 | * handle, pitch and size are output parameters. Zero them out to | ||
4884 | * prevent drivers from accidentally using uninitialized data. Since | ||
4885 | * not all existing userspace is clearing these fields properly we | ||
4886 | * cannot reject IOCTL with garbage in them. | ||
4887 | */ | ||
4888 | args->handle = 0; | ||
4889 | args->pitch = 0; | ||
4890 | args->size = 0; | ||
4891 | |||
4772 | return dev->driver->dumb_create(file_priv, dev, args); | 4892 | return dev->driver->dumb_create(file_priv, dev, args); |
4773 | } | 4893 | } |
4774 | 4894 | ||
@@ -4784,7 +4904,7 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, | |||
4784 | * Called by the user via ioctl. | 4904 | * Called by the user via ioctl. |
4785 | * | 4905 | * |
4786 | * Returns: | 4906 | * Returns: |
4787 | * Zero on success, errno on failure. | 4907 | * Zero on success, negative errno on failure. |
4788 | */ | 4908 | */ |
4789 | int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, | 4909 | int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, |
4790 | void *data, struct drm_file *file_priv) | 4910 | void *data, struct drm_file *file_priv) |
@@ -4811,7 +4931,7 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, | |||
4811 | * Called by the user via ioctl. | 4931 | * Called by the user via ioctl. |
4812 | * | 4932 | * |
4813 | * Returns: | 4933 | * Returns: |
4814 | * Zero on success, errno on failure. | 4934 | * Zero on success, negative errno on failure. |
4815 | */ | 4935 | */ |
4816 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, | 4936 | int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, |
4817 | void *data, struct drm_file *file_priv) | 4937 | void *data, struct drm_file *file_priv) |
@@ -5097,6 +5217,7 @@ void drm_mode_config_init(struct drm_device *dev) | |||
5097 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); | 5217 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
5098 | INIT_LIST_HEAD(&dev->mode_config.plane_list); | 5218 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
5099 | idr_init(&dev->mode_config.crtc_idr); | 5219 | idr_init(&dev->mode_config.crtc_idr); |
5220 | idr_init(&dev->mode_config.tile_idr); | ||
5100 | 5221 | ||
5101 | drm_modeset_lock_all(dev); | 5222 | drm_modeset_lock_all(dev); |
5102 | drm_mode_create_standard_connector_properties(dev); | 5223 | drm_mode_create_standard_connector_properties(dev); |
@@ -5184,6 +5305,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
5184 | crtc->funcs->destroy(crtc); | 5305 | crtc->funcs->destroy(crtc); |
5185 | } | 5306 | } |
5186 | 5307 | ||
5308 | idr_destroy(&dev->mode_config.tile_idr); | ||
5187 | idr_destroy(&dev->mode_config.crtc_idr); | 5309 | idr_destroy(&dev->mode_config.crtc_idr); |
5188 | drm_modeset_lock_fini(&dev->mode_config.connection_mutex); | 5310 | drm_modeset_lock_fini(&dev->mode_config.connection_mutex); |
5189 | } | 5311 | } |
@@ -5206,3 +5328,100 @@ struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, | |||
5206 | supported_rotations); | 5328 | supported_rotations); |
5207 | } | 5329 | } |
5208 | EXPORT_SYMBOL(drm_mode_create_rotation_property); | 5330 | EXPORT_SYMBOL(drm_mode_create_rotation_property); |
5331 | |||
5332 | /** | ||
5333 | * DOC: Tile group | ||
5334 | * | ||
5335 | * Tile groups are used to represent tiled monitors with a unique | ||
5336 | * integer identifier. Tiled monitors using DisplayID v1.3 have | ||
5337 | * a unique 8-byte handle, we store this in a tile group, so we | ||
5338 | * have a common identifier for all tiles in a monitor group. | ||
5339 | */ | ||
5340 | static void drm_tile_group_free(struct kref *kref) | ||
5341 | { | ||
5342 | struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount); | ||
5343 | struct drm_device *dev = tg->dev; | ||
5344 | mutex_lock(&dev->mode_config.idr_mutex); | ||
5345 | idr_remove(&dev->mode_config.tile_idr, tg->id); | ||
5346 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
5347 | kfree(tg); | ||
5348 | } | ||
5349 | |||
5350 | /** | ||
5351 | * drm_mode_put_tile_group - drop a reference to a tile group. | ||
5352 | * @dev: DRM device | ||
5353 | * @tg: tile group to drop reference to. | ||
5354 | * | ||
5355 | * drop reference to tile group and free if 0. | ||
5356 | */ | ||
5357 | void drm_mode_put_tile_group(struct drm_device *dev, | ||
5358 | struct drm_tile_group *tg) | ||
5359 | { | ||
5360 | kref_put(&tg->refcount, drm_tile_group_free); | ||
5361 | } | ||
5362 | |||
5363 | /** | ||
5364 | * drm_mode_get_tile_group - get a reference to an existing tile group | ||
5365 | * @dev: DRM device | ||
5366 | * @topology: 8-bytes unique per monitor. | ||
5367 | * | ||
5368 | * Use the unique bytes to get a reference to an existing tile group. | ||
5369 | * | ||
5370 | * RETURNS: | ||
5371 | * tile group or NULL if not found. | ||
5372 | */ | ||
5373 | struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, | ||
5374 | char topology[8]) | ||
5375 | { | ||
5376 | struct drm_tile_group *tg; | ||
5377 | int id; | ||
5378 | mutex_lock(&dev->mode_config.idr_mutex); | ||
5379 | idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { | ||
5380 | if (!memcmp(tg->group_data, topology, 8)) { | ||
5381 | if (!kref_get_unless_zero(&tg->refcount)) | ||
5382 | tg = NULL; | ||
5383 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
5384 | return tg; | ||
5385 | } | ||
5386 | } | ||
5387 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
5388 | return NULL; | ||
5389 | } | ||
5390 | |||
5391 | /** | ||
5392 | * drm_mode_create_tile_group - create a tile group from a displayid description | ||
5393 | * @dev: DRM device | ||
5394 | * @topology: 8-bytes unique per monitor. | ||
5395 | * | ||
5396 | * Create a tile group for the unique monitor, and get a unique | ||
5397 | * identifier for the tile group. | ||
5398 | * | ||
5399 | * RETURNS: | ||
5400 | * new tile group or error. | ||
5401 | */ | ||
5402 | struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, | ||
5403 | char topology[8]) | ||
5404 | { | ||
5405 | struct drm_tile_group *tg; | ||
5406 | int ret; | ||
5407 | |||
5408 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); | ||
5409 | if (!tg) | ||
5410 | return ERR_PTR(-ENOMEM); | ||
5411 | |||
5412 | kref_init(&tg->refcount); | ||
5413 | memcpy(tg->group_data, topology, 8); | ||
5414 | tg->dev = dev; | ||
5415 | |||
5416 | mutex_lock(&dev->mode_config.idr_mutex); | ||
5417 | ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL); | ||
5418 | if (ret >= 0) { | ||
5419 | tg->id = ret; | ||
5420 | } else { | ||
5421 | kfree(tg); | ||
5422 | tg = ERR_PTR(ret); | ||
5423 | } | ||
5424 | |||
5425 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
5426 | return tg; | ||
5427 | } | ||