Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/atomic: integrate modeset lock with private objects

Follow the same pattern of locking as with other state objects. This
avoids boilerplate in the driver.

Signed-off-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20181022123122.30468-1-boris.brezillon@bootlin.com

authored by

Rob Clark and committed by
Boris Brezillon
b962a120 cb8ce711

+74 -9
+15 -4
drivers/gpu/drm/drm_atomic.c
··· 676 676 677 677 /** 678 678 * drm_atomic_private_obj_init - initialize private object 679 + * @dev: DRM device this object will be attached to 679 680 * @obj: private object 680 681 * @state: initial private object state 681 682 * @funcs: pointer to the struct of function pointers that identify the object ··· 686 685 * driver private object that needs its own atomic state. 687 686 */ 688 687 void 689 - drm_atomic_private_obj_init(struct drm_private_obj *obj, 688 + drm_atomic_private_obj_init(struct drm_device *dev, 689 + struct drm_private_obj *obj, 690 690 struct drm_private_state *state, 691 691 const struct drm_private_state_funcs *funcs) 692 692 { 693 693 memset(obj, 0, sizeof(*obj)); 694 694 695 + drm_modeset_lock_init(&obj->lock); 696 + 695 697 obj->state = state; 696 698 obj->funcs = funcs; 699 + list_add_tail(&obj->head, &dev->mode_config.privobj_list); 697 700 } 698 701 EXPORT_SYMBOL(drm_atomic_private_obj_init); 699 702 ··· 710 705 void 711 706 drm_atomic_private_obj_fini(struct drm_private_obj *obj) 712 707 { 708 + list_del(&obj->head); 713 709 obj->funcs->atomic_destroy_state(obj, obj->state); 710 + drm_modeset_lock_fini(&obj->lock); 714 711 } 715 712 EXPORT_SYMBOL(drm_atomic_private_obj_fini); 716 713 ··· 722 715 * @obj: private object to get the state for 723 716 * 724 717 * This function returns the private object state for the given private object, 725 - * allocating the state if needed. It does not grab any locks as the caller is 726 - * expected to care of any required locking. 718 + * allocating the state if needed. It will also grab the relevant private 719 + * object lock to make sure that the state is consistent. 727 720 * 728 721 * RETURNS: 729 722 * ··· 733 726 drm_atomic_get_private_obj_state(struct drm_atomic_state *state, 734 727 struct drm_private_obj *obj) 735 728 { 736 - int index, num_objs, i; 729 + int index, num_objs, i, ret; 737 730 size_t size; 738 731 struct __drm_private_objs_state *arr; 739 732 struct drm_private_state *obj_state; ··· 741 734 for (i = 0; i < state->num_private_objs; i++) 742 735 if (obj == state->private_objs[i].ptr) 743 736 return state->private_objs[i].state; 737 + 738 + ret = drm_modeset_lock(&obj->lock, state->acquire_ctx); 739 + if (ret) 740 + return ERR_PTR(ret); 744 741 745 742 num_objs = state->num_private_objs + 1; 746 743 size = sizeof(*state->private_objs) * num_objs;
+1 -1
drivers/gpu/drm/drm_dp_mst_topology.c
··· 3221 3221 /* max. time slots - one slot for MTP header */ 3222 3222 mst_state->avail_slots = 63; 3223 3223 3224 - drm_atomic_private_obj_init(&mgr->base, 3224 + drm_atomic_private_obj_init(dev, &mgr->base, 3225 3225 &mst_state->base, 3226 3226 &mst_state_funcs); 3227 3227
+1
drivers/gpu/drm/drm_mode_config.c
··· 381 381 INIT_LIST_HEAD(&dev->mode_config.property_list); 382 382 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 383 383 INIT_LIST_HEAD(&dev->mode_config.plane_list); 384 + INIT_LIST_HEAD(&dev->mode_config.privobj_list); 384 385 idr_init(&dev->mode_config.crtc_idr); 385 386 idr_init(&dev->mode_config.tile_idr); 386 387 ida_init(&dev->mode_config.connector_ida);
+8
drivers/gpu/drm/drm_modeset_lock.c
··· 22 22 */ 23 23 24 24 #include <drm/drmP.h> 25 + #include <drm/drm_atomic.h> 25 26 #include <drm/drm_crtc.h> 26 27 #include <drm/drm_modeset_lock.h> 27 28 ··· 395 394 int drm_modeset_lock_all_ctx(struct drm_device *dev, 396 395 struct drm_modeset_acquire_ctx *ctx) 397 396 { 397 + struct drm_private_obj *privobj; 398 398 struct drm_crtc *crtc; 399 399 struct drm_plane *plane; 400 400 int ret; ··· 412 410 413 411 drm_for_each_plane(plane, dev) { 414 412 ret = drm_modeset_lock(&plane->mutex, ctx); 413 + if (ret) 414 + return ret; 415 + } 416 + 417 + drm_for_each_privobj(privobj, dev) { 418 + ret = drm_modeset_lock(&privobj->lock, ctx); 415 419 if (ret) 416 420 return ret; 417 421 }
+1 -1
drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
··· 144 144 145 145 state->mdp5_kms = mdp5_kms; 146 146 147 - drm_atomic_private_obj_init(&mdp5_kms->glob_state, 147 + drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state, 148 148 &state->base, 149 149 &mdp5_global_state_funcs); 150 150 return 0;
+1 -1
drivers/gpu/drm/tegra/hub.c
··· 716 716 if (!state) 717 717 return -ENOMEM; 718 718 719 - drm_atomic_private_obj_init(&hub->base, &state->base, 719 + drm_atomic_private_obj_init(drm, &hub->base, &state->base, 720 720 &tegra_display_hub_state_funcs); 721 721 722 722 tegra->hub = hub;
+2 -1
drivers/gpu/drm/vc4/vc4_kms.c
··· 432 432 ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL); 433 433 if (!ctm_state) 434 434 return -ENOMEM; 435 - drm_atomic_private_obj_init(&vc4->ctm_manager, &ctm_state->base, 435 + 436 + drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base, 436 437 &vc4_ctm_state_funcs); 437 438 438 439 drm_mode_config_reset(dev);
+36 -1
include/drm/drm_atomic.h
··· 228 228 * Currently only tracks the state update functions and the opaque driver 229 229 * private state itself, but in the future might also track which 230 230 * &drm_modeset_lock is required to duplicate and update this object's state. 231 + * 232 + * All private objects must be initialized before the DRM device they are 233 + * attached to is registered to the DRM subsystem (call to drm_dev_register()) 234 + * and should stay around until this DRM device is unregistered (call to 235 + * drm_dev_unregister()). In other words, private objects lifetime is tied 236 + * to the DRM device lifetime. This implies that: 237 + * 238 + * 1/ all calls to drm_atomic_private_obj_init() must be done before calling 239 + * drm_dev_register() 240 + * 2/ all calls to drm_atomic_private_obj_fini() must be done after calling 241 + * drm_dev_unregister() 231 242 */ 232 243 struct drm_private_obj { 244 + /** 245 + * @head: List entry used to attach a private object to a &drm_device 246 + * (queued to &drm_mode_config.privobj_list). 247 + */ 248 + struct list_head head; 249 + 250 + /** 251 + * @lock: Modeset lock to protect the state object. 252 + */ 253 + struct drm_modeset_lock lock; 254 + 233 255 /** 234 256 * @state: Current atomic state for this driver private object. 235 257 */ ··· 265 243 */ 266 244 const struct drm_private_state_funcs *funcs; 267 245 }; 246 + 247 + /** 248 + * drm_for_each_privobj() - private object iterator 249 + * 250 + * @privobj: pointer to the current private object. Updated after each 251 + * iteration 252 + * @dev: the DRM device we want get private objects from 253 + * 254 + * Allows one to iterate over all private objects attached to @dev 255 + */ 256 + #define drm_for_each_privobj(privobj, dev) \ 257 + list_for_each_entry(privobj, &(dev)->mode_config.privobj_list, head) 268 258 269 259 /** 270 260 * struct drm_private_state - base struct for driver private object state ··· 434 400 drm_atomic_get_connector_state(struct drm_atomic_state *state, 435 401 struct drm_connector *connector); 436 402 437 - void drm_atomic_private_obj_init(struct drm_private_obj *obj, 403 + void drm_atomic_private_obj_init(struct drm_device *dev, 404 + struct drm_private_obj *obj, 438 405 struct drm_private_state *state, 439 406 const struct drm_private_state_funcs *funcs); 440 407 void drm_atomic_private_obj_fini(struct drm_private_obj *obj);
+9
include/drm/drm_mode_config.h
··· 512 512 */ 513 513 struct list_head property_list; 514 514 515 + /** 516 + * @privobj_list: 517 + * 518 + * List of private objects linked with &drm_private_obj.head. This is 519 + * invariant over the lifetime of a device and hence doesn't need any 520 + * locks. 521 + */ 522 + struct list_head privobj_list; 523 + 515 524 int min_width, min_height; 516 525 int max_width, max_height; 517 526 const struct drm_mode_config_funcs *funcs;