linux/drivers/gpu/drm/drm_mode_config.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 Intel Corporation
   3 *
   4 * Permission to use, copy, modify, distribute, and sell this software and its
   5 * documentation for any purpose is hereby granted without fee, provided that
   6 * the above copyright notice appear in all copies and that both that copyright
   7 * notice and this permission notice appear in supporting documentation, and
   8 * that the name of the copyright holders not be used in advertising or
   9 * publicity pertaining to distribution of the software without specific,
  10 * written prior permission.  The copyright holders make no representations
  11 * about the suitability of this software for any purpose.  It is provided "as
  12 * is" without express or implied warranty.
  13 *
  14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20 * OF THIS SOFTWARE.
  21 */
  22
  23#include <linux/uaccess.h>
  24
  25#include <drm/drm_drv.h>
  26#include <drm/drm_encoder.h>
  27#include <drm/drm_file.h>
  28#include <drm/drm_mode_config.h>
  29#include <drm/drm_print.h>
  30#include <linux/dma-resv.h>
  31
  32#include "drm_crtc_internal.h"
  33#include "drm_internal.h"
  34
  35int drm_modeset_register_all(struct drm_device *dev)
  36{
  37        int ret;
  38
  39        ret = drm_plane_register_all(dev);
  40        if (ret)
  41                goto err_plane;
  42
  43        ret = drm_crtc_register_all(dev);
  44        if  (ret)
  45                goto err_crtc;
  46
  47        ret = drm_encoder_register_all(dev);
  48        if (ret)
  49                goto err_encoder;
  50
  51        ret = drm_connector_register_all(dev);
  52        if (ret)
  53                goto err_connector;
  54
  55        return 0;
  56
  57err_connector:
  58        drm_encoder_unregister_all(dev);
  59err_encoder:
  60        drm_crtc_unregister_all(dev);
  61err_crtc:
  62        drm_plane_unregister_all(dev);
  63err_plane:
  64        return ret;
  65}
  66
  67void drm_modeset_unregister_all(struct drm_device *dev)
  68{
  69        drm_connector_unregister_all(dev);
  70        drm_encoder_unregister_all(dev);
  71        drm_crtc_unregister_all(dev);
  72        drm_plane_unregister_all(dev);
  73}
  74
  75/**
  76 * drm_mode_getresources - get graphics configuration
  77 * @dev: drm device for the ioctl
  78 * @data: data pointer for the ioctl
  79 * @file_priv: drm file for the ioctl call
  80 *
  81 * Construct a set of configuration description structures and return
  82 * them to the user, including CRTC, connector and framebuffer configuration.
  83 *
  84 * Called by the user via ioctl.
  85 *
  86 * Returns:
  87 * Zero on success, negative errno on failure.
  88 */
  89int drm_mode_getresources(struct drm_device *dev, void *data,
  90                          struct drm_file *file_priv)
  91{
  92        struct drm_mode_card_res *card_res = data;
  93        struct drm_framebuffer *fb;
  94        struct drm_connector *connector;
  95        struct drm_crtc *crtc;
  96        struct drm_encoder *encoder;
  97        int count, ret = 0;
  98        uint32_t __user *fb_id;
  99        uint32_t __user *crtc_id;
 100        uint32_t __user *connector_id;
 101        uint32_t __user *encoder_id;
 102        struct drm_connector_list_iter conn_iter;
 103
 104        if (!drm_core_check_feature(dev, DRIVER_MODESET))
 105                return -EOPNOTSUPP;
 106
 107        mutex_lock(&file_priv->fbs_lock);
 108        count = 0;
 109        fb_id = u64_to_user_ptr(card_res->fb_id_ptr);
 110        list_for_each_entry(fb, &file_priv->fbs, filp_head) {
 111                if (count < card_res->count_fbs &&
 112                    put_user(fb->base.id, fb_id + count)) {
 113                        mutex_unlock(&file_priv->fbs_lock);
 114                        return -EFAULT;
 115                }
 116                count++;
 117        }
 118        card_res->count_fbs = count;
 119        mutex_unlock(&file_priv->fbs_lock);
 120
 121        card_res->max_height = dev->mode_config.max_height;
 122        card_res->min_height = dev->mode_config.min_height;
 123        card_res->max_width = dev->mode_config.max_width;
 124        card_res->min_width = dev->mode_config.min_width;
 125
 126        count = 0;
 127        crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
 128        drm_for_each_crtc(crtc, dev) {
 129                if (drm_lease_held(file_priv, crtc->base.id)) {
 130                        if (count < card_res->count_crtcs &&
 131                            put_user(crtc->base.id, crtc_id + count))
 132                                return -EFAULT;
 133                        count++;
 134                }
 135        }
 136        card_res->count_crtcs = count;
 137
 138        count = 0;
 139        encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
 140        drm_for_each_encoder(encoder, dev) {
 141                if (count < card_res->count_encoders &&
 142                    put_user(encoder->base.id, encoder_id + count))
 143                        return -EFAULT;
 144                count++;
 145        }
 146        card_res->count_encoders = count;
 147
 148        drm_connector_list_iter_begin(dev, &conn_iter);
 149        count = 0;
 150        connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
 151        drm_for_each_connector_iter(connector, &conn_iter) {
 152                /* only expose writeback connectors if userspace understands them */
 153                if (!file_priv->writeback_connectors &&
 154                    (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK))
 155                        continue;
 156
 157                if (drm_lease_held(file_priv, connector->base.id)) {
 158                        if (count < card_res->count_connectors &&
 159                            put_user(connector->base.id, connector_id + count)) {
 160                                drm_connector_list_iter_end(&conn_iter);
 161                                return -EFAULT;
 162                        }
 163                        count++;
 164                }
 165        }
 166        card_res->count_connectors = count;
 167        drm_connector_list_iter_end(&conn_iter);
 168
 169        return ret;
 170}
 171
 172/**
 173 * drm_mode_config_reset - call ->reset callbacks
 174 * @dev: drm device
 175 *
 176 * This functions calls all the crtc's, encoder's and connector's ->reset
 177 * callback. Drivers can use this in e.g. their driver load or resume code to
 178 * reset hardware and software state.
 179 */
 180void drm_mode_config_reset(struct drm_device *dev)
 181{
 182        struct drm_crtc *crtc;
 183        struct drm_plane *plane;
 184        struct drm_encoder *encoder;
 185        struct drm_connector *connector;
 186        struct drm_connector_list_iter conn_iter;
 187
 188        drm_for_each_plane(plane, dev)
 189                if (plane->funcs->reset)
 190                        plane->funcs->reset(plane);
 191
 192        drm_for_each_crtc(crtc, dev)
 193                if (crtc->funcs->reset)
 194                        crtc->funcs->reset(crtc);
 195
 196        drm_for_each_encoder(encoder, dev)
 197                if (encoder->funcs->reset)
 198                        encoder->funcs->reset(encoder);
 199
 200        drm_connector_list_iter_begin(dev, &conn_iter);
 201        drm_for_each_connector_iter(connector, &conn_iter)
 202                if (connector->funcs->reset)
 203                        connector->funcs->reset(connector);
 204        drm_connector_list_iter_end(&conn_iter);
 205}
 206EXPORT_SYMBOL(drm_mode_config_reset);
 207
 208/*
 209 * Global properties
 210 */
 211static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
 212        { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
 213        { DRM_PLANE_TYPE_PRIMARY, "Primary" },
 214        { DRM_PLANE_TYPE_CURSOR, "Cursor" },
 215};
 216
 217static int drm_mode_create_standard_properties(struct drm_device *dev)
 218{
 219        struct drm_property *prop;
 220        int ret;
 221
 222        ret = drm_connector_create_standard_properties(dev);
 223        if (ret)
 224                return ret;
 225
 226        prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
 227                                        "type", drm_plane_type_enum_list,
 228                                        ARRAY_SIZE(drm_plane_type_enum_list));
 229        if (!prop)
 230                return -ENOMEM;
 231        dev->mode_config.plane_type_property = prop;
 232
 233        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 234                        "SRC_X", 0, UINT_MAX);
 235        if (!prop)
 236                return -ENOMEM;
 237        dev->mode_config.prop_src_x = prop;
 238
 239        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 240                        "SRC_Y", 0, UINT_MAX);
 241        if (!prop)
 242                return -ENOMEM;
 243        dev->mode_config.prop_src_y = prop;
 244
 245        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 246                        "SRC_W", 0, UINT_MAX);
 247        if (!prop)
 248                return -ENOMEM;
 249        dev->mode_config.prop_src_w = prop;
 250
 251        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 252                        "SRC_H", 0, UINT_MAX);
 253        if (!prop)
 254                return -ENOMEM;
 255        dev->mode_config.prop_src_h = prop;
 256
 257        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 258                        "CRTC_X", INT_MIN, INT_MAX);
 259        if (!prop)
 260                return -ENOMEM;
 261        dev->mode_config.prop_crtc_x = prop;
 262
 263        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 264                        "CRTC_Y", INT_MIN, INT_MAX);
 265        if (!prop)
 266                return -ENOMEM;
 267        dev->mode_config.prop_crtc_y = prop;
 268
 269        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 270                        "CRTC_W", 0, INT_MAX);
 271        if (!prop)
 272                return -ENOMEM;
 273        dev->mode_config.prop_crtc_w = prop;
 274
 275        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 276                        "CRTC_H", 0, INT_MAX);
 277        if (!prop)
 278                return -ENOMEM;
 279        dev->mode_config.prop_crtc_h = prop;
 280
 281        prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
 282                        "FB_ID", DRM_MODE_OBJECT_FB);
 283        if (!prop)
 284                return -ENOMEM;
 285        dev->mode_config.prop_fb_id = prop;
 286
 287        prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
 288                        "IN_FENCE_FD", -1, INT_MAX);
 289        if (!prop)
 290                return -ENOMEM;
 291        dev->mode_config.prop_in_fence_fd = prop;
 292
 293        prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 294                        "OUT_FENCE_PTR", 0, U64_MAX);
 295        if (!prop)
 296                return -ENOMEM;
 297        dev->mode_config.prop_out_fence_ptr = prop;
 298
 299        prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
 300                        "CRTC_ID", DRM_MODE_OBJECT_CRTC);
 301        if (!prop)
 302                return -ENOMEM;
 303        dev->mode_config.prop_crtc_id = prop;
 304
 305        prop = drm_property_create(dev,
 306                        DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
 307                        "FB_DAMAGE_CLIPS", 0);
 308        if (!prop)
 309                return -ENOMEM;
 310        dev->mode_config.prop_fb_damage_clips = prop;
 311
 312        prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
 313                        "ACTIVE");
 314        if (!prop)
 315                return -ENOMEM;
 316        dev->mode_config.prop_active = prop;
 317
 318        prop = drm_property_create(dev,
 319                        DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
 320                        "MODE_ID", 0);
 321        if (!prop)
 322                return -ENOMEM;
 323        dev->mode_config.prop_mode_id = prop;
 324
 325        prop = drm_property_create_bool(dev, 0,
 326                        "VRR_ENABLED");
 327        if (!prop)
 328                return -ENOMEM;
 329        dev->mode_config.prop_vrr_enabled = prop;
 330
 331        prop = drm_property_create(dev,
 332                        DRM_MODE_PROP_BLOB,
 333                        "DEGAMMA_LUT", 0);
 334        if (!prop)
 335                return -ENOMEM;
 336        dev->mode_config.degamma_lut_property = prop;
 337
 338        prop = drm_property_create_range(dev,
 339                        DRM_MODE_PROP_IMMUTABLE,
 340                        "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
 341        if (!prop)
 342                return -ENOMEM;
 343        dev->mode_config.degamma_lut_size_property = prop;
 344
 345        prop = drm_property_create(dev,
 346                        DRM_MODE_PROP_BLOB,
 347                        "CTM", 0);
 348        if (!prop)
 349                return -ENOMEM;
 350        dev->mode_config.ctm_property = prop;
 351
 352        prop = drm_property_create(dev,
 353                        DRM_MODE_PROP_BLOB,
 354                        "GAMMA_LUT", 0);
 355        if (!prop)
 356                return -ENOMEM;
 357        dev->mode_config.gamma_lut_property = prop;
 358
 359        prop = drm_property_create_range(dev,
 360                        DRM_MODE_PROP_IMMUTABLE,
 361                        "GAMMA_LUT_SIZE", 0, UINT_MAX);
 362        if (!prop)
 363                return -ENOMEM;
 364        dev->mode_config.gamma_lut_size_property = prop;
 365
 366        prop = drm_property_create(dev,
 367                                   DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB,
 368                                   "IN_FORMATS", 0);
 369        if (!prop)
 370                return -ENOMEM;
 371        dev->mode_config.modifiers_property = prop;
 372
 373        return 0;
 374}
 375
 376/**
 377 * drm_mode_config_init - initialize DRM mode_configuration structure
 378 * @dev: DRM device
 379 *
 380 * Initialize @dev's mode_config structure, used for tracking the graphics
 381 * configuration of @dev.
 382 *
 383 * Since this initializes the modeset locks, no locking is possible. Which is no
 384 * problem, since this should happen single threaded at init time. It is the
 385 * driver's problem to ensure this guarantee.
 386 *
 387 */
 388void drm_mode_config_init(struct drm_device *dev)
 389{
 390        mutex_init(&dev->mode_config.mutex);
 391        drm_modeset_lock_init(&dev->mode_config.connection_mutex);
 392        mutex_init(&dev->mode_config.idr_mutex);
 393        mutex_init(&dev->mode_config.fb_lock);
 394        mutex_init(&dev->mode_config.blob_lock);
 395        INIT_LIST_HEAD(&dev->mode_config.fb_list);
 396        INIT_LIST_HEAD(&dev->mode_config.crtc_list);
 397        INIT_LIST_HEAD(&dev->mode_config.connector_list);
 398        INIT_LIST_HEAD(&dev->mode_config.encoder_list);
 399        INIT_LIST_HEAD(&dev->mode_config.property_list);
 400        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
 401        INIT_LIST_HEAD(&dev->mode_config.plane_list);
 402        INIT_LIST_HEAD(&dev->mode_config.privobj_list);
 403        idr_init(&dev->mode_config.object_idr);
 404        idr_init(&dev->mode_config.tile_idr);
 405        ida_init(&dev->mode_config.connector_ida);
 406        spin_lock_init(&dev->mode_config.connector_list_lock);
 407
 408        init_llist_head(&dev->mode_config.connector_free_list);
 409        INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn);
 410
 411        drm_mode_create_standard_properties(dev);
 412
 413        /* Just to be sure */
 414        dev->mode_config.num_fb = 0;
 415        dev->mode_config.num_connector = 0;
 416        dev->mode_config.num_crtc = 0;
 417        dev->mode_config.num_encoder = 0;
 418        dev->mode_config.num_total_plane = 0;
 419
 420        if (IS_ENABLED(CONFIG_LOCKDEP)) {
 421                struct drm_modeset_acquire_ctx modeset_ctx;
 422                struct ww_acquire_ctx resv_ctx;
 423                struct dma_resv resv;
 424                int ret;
 425
 426                dma_resv_init(&resv);
 427
 428                drm_modeset_acquire_init(&modeset_ctx, 0);
 429                ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
 430                                       &modeset_ctx);
 431                if (ret == -EDEADLK)
 432                        ret = drm_modeset_backoff(&modeset_ctx);
 433
 434                ww_acquire_init(&resv_ctx, &reservation_ww_class);
 435                ret = dma_resv_lock(&resv, &resv_ctx);
 436                if (ret == -EDEADLK)
 437                        dma_resv_lock_slow(&resv, &resv_ctx);
 438
 439                dma_resv_unlock(&resv);
 440                ww_acquire_fini(&resv_ctx);
 441
 442                drm_modeset_drop_locks(&modeset_ctx);
 443                drm_modeset_acquire_fini(&modeset_ctx);
 444                dma_resv_fini(&resv);
 445        }
 446}
 447EXPORT_SYMBOL(drm_mode_config_init);
 448
 449/**
 450 * drm_mode_config_cleanup - free up DRM mode_config info
 451 * @dev: DRM device
 452 *
 453 * Free up all the connectors and CRTCs associated with this DRM device, then
 454 * free up the framebuffers and associated buffer objects.
 455 *
 456 * Note that since this /should/ happen single-threaded at driver/device
 457 * teardown time, no locking is required. It's the driver's job to ensure that
 458 * this guarantee actually holds true.
 459 */
 460void drm_mode_config_cleanup(struct drm_device *dev)
 461{
 462        struct drm_connector *connector;
 463        struct drm_connector_list_iter conn_iter;
 464        struct drm_crtc *crtc, *ct;
 465        struct drm_encoder *encoder, *enct;
 466        struct drm_framebuffer *fb, *fbt;
 467        struct drm_property *property, *pt;
 468        struct drm_property_blob *blob, *bt;
 469        struct drm_plane *plane, *plt;
 470
 471        list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
 472                                 head) {
 473                encoder->funcs->destroy(encoder);
 474        }
 475
 476        drm_connector_list_iter_begin(dev, &conn_iter);
 477        drm_for_each_connector_iter(connector, &conn_iter) {
 478                /* drm_connector_list_iter holds an full reference to the
 479                 * current connector itself, which means it is inherently safe
 480                 * against unreferencing the current connector - but not against
 481                 * deleting it right away. */
 482                drm_connector_put(connector);
 483        }
 484        drm_connector_list_iter_end(&conn_iter);
 485        /* connector_iter drops references in a work item. */
 486        flush_work(&dev->mode_config.connector_free_work);
 487        if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) {
 488                drm_connector_list_iter_begin(dev, &conn_iter);
 489                drm_for_each_connector_iter(connector, &conn_iter)
 490                        DRM_ERROR("connector %s leaked!\n", connector->name);
 491                drm_connector_list_iter_end(&conn_iter);
 492        }
 493
 494        list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
 495                                 head) {
 496                drm_property_destroy(dev, property);
 497        }
 498
 499        list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
 500                                 head) {
 501                plane->funcs->destroy(plane);
 502        }
 503
 504        list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
 505                crtc->funcs->destroy(crtc);
 506        }
 507
 508        list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
 509                                 head_global) {
 510                drm_property_blob_put(blob);
 511        }
 512
 513        /*
 514         * Single-threaded teardown context, so it's not required to grab the
 515         * fb_lock to protect against concurrent fb_list access. Contrary, it
 516         * would actually deadlock with the drm_framebuffer_cleanup function.
 517         *
 518         * Also, if there are any framebuffers left, that's a driver leak now,
 519         * so politely WARN about this.
 520         */
 521        WARN_ON(!list_empty(&dev->mode_config.fb_list));
 522        list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
 523                struct drm_printer p = drm_debug_printer("[leaked fb]");
 524                drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
 525                drm_framebuffer_print_info(&p, 1, fb);
 526                drm_framebuffer_free(&fb->base.refcount);
 527        }
 528
 529        ida_destroy(&dev->mode_config.connector_ida);
 530        idr_destroy(&dev->mode_config.tile_idr);
 531        idr_destroy(&dev->mode_config.object_idr);
 532        drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
 533}
 534EXPORT_SYMBOL(drm_mode_config_cleanup);
 535