Lyude Paul
2018-Aug-28 17:10 UTC
[Nouveau] [PATCH v2 0/4] drm/dp_mst: Add DP MST debugfs nodes for all drivers
This is the next version of my patch series for teaching DRM how to automatically create debugfs nodes for drivers with MST topologies. This was originally intended just for nouveau, but has since been expanded to all DRM drivers. Changes since previous version: - Fix documentation error that got noticed by the kbuild bot in "drm/dp_mst: Pass entire connector to drm_dp_mst_topology_mgr_init()" Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com> Cc: Daniel Stone <daniel at fooishbar.org> Lyude Paul (4): drm/debugfs: Add support for dynamic debugfs initialization drm/dp_mst: Pass entire connector to drm_dp_mst_topology_mgr_init() drm/dp_mst: Add dp_mst_status debugfs node for all drivers drm/i915: Remove i915_drm_dp_mst_status .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- drivers/gpu/drm/drm_debugfs.c | 173 +++++++++++++++++- drivers/gpu/drm/drm_dp_mst_topology.c | 116 +++++++++++- drivers/gpu/drm/drm_drv.c | 3 + drivers/gpu/drm/drm_internal.h | 5 + drivers/gpu/drm/i915/i915_debugfs.c | 32 ---- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 6 +- drivers/gpu/drm/i915/intel_drv.h | 3 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 6 +- drivers/gpu/drm/radeon/radeon_dp_mst.c | 2 +- include/drm/drm_debugfs.h | 27 +++ include/drm/drm_dp_mst_helper.h | 17 +- include/drm/drm_file.h | 4 + 14 files changed, 343 insertions(+), 55 deletions(-) -- 2.17.1
Lyude Paul
2018-Aug-28 17:10 UTC
[Nouveau] [PATCH v2 1/4] drm/debugfs: Add support for dynamic debugfs initialization
Currently all debugfs related initialization for the DRM core happens in drm_debugfs_init(), which is called when registering the minor device. While this works fine for features such as atomic modesetting and GEM, this doesn't work at all for resources like DP MST topology managers which can potentially be created both before and after the minor device has been registered. So, in order to add driver-wide debugfs files for MST we'll need to be able to handle debugfs initialization for such resources. We do so by introducing drm_debugfs_callback_register() and drm_debugfs_callback_unregister(). These functions allow driver-agnostic parts of DRM to add additional debugfs initialization callbacks at any point during a DRM driver's lifetime. Signed-off-by: Lyude Paul <lyude at redhat.com> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com> Cc: Daniel Stone <daniel at fooishbar.org> --- drivers/gpu/drm/drm_debugfs.c | 173 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/drm_drv.c | 3 + drivers/gpu/drm/drm_internal.h | 5 + include/drm/drm_debugfs.h | 27 +++++ include/drm/drm_file.h | 4 + 5 files changed, 203 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 6f28fe58f169..a53a454b167f 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -39,6 +39,13 @@ #if defined(CONFIG_DEBUG_FS) +struct drm_debugfs_callback { + void (*init)(void *data); + void (*cleanup_cb)(void *data); + void *data; + struct list_head list; +}; + /*************************************************** * Initialization, etc. **************************************************/ @@ -67,6 +74,113 @@ static const struct file_operations drm_debugfs_fops = { .release = single_release, }; +/** + * drm_debugfs_register_callback - Register a callback for initializing + * dynamic driver-agnostic debugfs files + * @minor: device minor number + * @init: The callback to invoke to perform the debugfs initialization + * @cleanup_cb: The callback to invoke to cleanup any resources for the + * callback + * @data: Data to pass to @init and @cleanup_cb + * @out: Where to store the pointer to the callback struct + * + * Register an initialization callback with debugfs. This callback can be used + * to creating debugfs nodes for DRM resources that might get created before + * the debugfs node for @minor has been created. + * + * When a callback is registered with this function before the debugfs root + * has been created, the callback's execution will be delayed until all other + * debugfs nodes (including those owned by the DRM device's driver) have been + * instantiated. If a callback is registered with this function after the + * debugfs root has been created, @init and @cleanup_cb will be executed + * immediately without creating a &struct drm_debugfs_callback. + * + * In the event that debugfs creation for the device fails; all registered + * debugfs callbacks will have their @cleanup_cb callbacks invoked without + * having their @init callbacks invoked. This is to ensure that no resources + * are leaked during initialization of debugfs, even if the initialization + * process fails. Likewise; any callbacks that are registered after DRM has + * failed to initialize it's debugfs files will have their @cleanup_cb + * callbacks invoked immediately and all of their respective resources + * destroyed. + * + * Implementations of @cleanup_cb should clean up all resources for the + * callback, with the exception of freeing the memory for @out. Freeing @out + * will be handled by the DRM core automatically. + * + * Users of this function should take care to add a symmetric call to + * @drm_debugfs_unregister_callback to handle destroying a registered callback + * in case the resources for the user of this function are destroyed before + * debugfs root is initialized. + * + */ +int +drm_debugfs_register_callback(struct drm_minor *minor, + void (*init)(void *), + void (*cleanup_cb)(void *), + void *data, struct drm_debugfs_callback **out) +{ + int ret = 0; + + mutex_lock(&minor->debugfs_callback_lock); + if (minor->debugfs_callbacks_done) { + /* debugfs is already setup, so just handle the callback + * immediately + */ + if (minor->debugfs_root) + (*init)(data); + (*cleanup_cb)(data); + goto out_unlock; + } + + *out = kzalloc(sizeof(**out), GFP_KERNEL); + if (!*out) { + ret = -ENOMEM; + goto out_unlock; + } + + (*out)->init = init; + (*out)->cleanup_cb = cleanup_cb; + (*out)->data = data; + list_add(&(*out)->list, &minor->debugfs_callback_list); + +out_unlock: + mutex_unlock(&minor->debugfs_callback_lock); + return ret; +} +EXPORT_SYMBOL(drm_debugfs_register_callback); + +/** + * drm_debugfs_unregister_callback - Unregister and release the resources + * associated with a debugfs init callback + * @minor: device minor number + * @cb: A pointer to the &struct drm_debugfs_callback struct returned by + * drm_debugfs_register_callback(). May be NULL + * + * Unregisters a &struct drm_debugfs_callback struct with debugfs and destroys + * all of it's associated resources. This includes a call to the callback's + * @cleanup_cb implementation. + * + * Once the debugfs root is initialized or has failed initialization, all + * registered callbacks are automatically destroyed. If this function is + * called after that point; it will automatically be a no-op. + */ +void +drm_debugfs_unregister_callback(struct drm_minor *minor, + struct drm_debugfs_callback *cb) +{ + mutex_lock(&minor->debugfs_callback_lock); + /* We don't have to do anything if we've already completed any + * registered callbacks, as they will have already been destroyed + */ + if (!minor->debugfs_callbacks_done) { + cb->cleanup_cb(cb->data); + list_del(&cb->list); + kfree(cb); + } + mutex_unlock(&minor->debugfs_callback_lock); +} +EXPORT_SYMBOL(drm_debugfs_unregister_callback); /** * drm_debugfs_create_files - Initialize a given set of debugfs files for DRM @@ -126,12 +240,24 @@ int drm_debugfs_create_files(const struct drm_info_list *files, int count, } EXPORT_SYMBOL(drm_debugfs_create_files); +int drm_debugfs_alloc(struct drm_minor *minor) +{ + INIT_LIST_HEAD(&minor->debugfs_callback_list); + mutex_init(&minor->debugfs_callback_lock); + return 0; +} + int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root) { struct drm_device *dev = minor->dev; + struct drm_debugfs_callback *pos, *tmp; char name[64]; - int ret; + int ret = 0; + + /* Don't allow any more callbacks to be registered while we setup */ + mutex_lock(&minor->debugfs_callback_lock); + minor->debugfs_callbacks_done = true; INIT_LIST_HEAD(&minor->debugfs_list); mutex_init(&minor->debugfs_lock); @@ -139,7 +265,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, minor->debugfs_root = debugfs_create_dir(name, root); if (!minor->debugfs_root) { DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s\n", name); - return -1; + ret = -1; + goto out_unlock; } ret = drm_debugfs_create_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, @@ -148,14 +275,14 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, debugfs_remove(minor->debugfs_root); minor->debugfs_root = NULL; DRM_ERROR("Failed to create core drm debugfs files\n"); - return ret; + goto out_unlock; } if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { ret = drm_atomic_debugfs_init(minor); if (ret) { DRM_ERROR("Failed to create atomic debugfs files\n"); - return ret; + goto out_unlock; } } @@ -163,13 +290,13 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, ret = drm_framebuffer_debugfs_init(minor); if (ret) { DRM_ERROR("Failed to create framebuffer debugfs file\n"); - return ret; + goto out_unlock; } ret = drm_client_debugfs_init(minor); if (ret) { DRM_ERROR("Failed to create client debugfs file\n"); - return ret; + goto out_unlock; } } @@ -178,10 +305,23 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, if (ret) { DRM_ERROR("DRM: Driver failed to initialize " "/sys/kernel/debug/dri.\n"); - return ret; + goto out_unlock; } } - return 0; + +out_unlock: + /* Execute any delayed callbacks if we succeeded, or just clean them + * up without running them if we failed + */ + list_for_each_entry_safe(pos, tmp, &minor->debugfs_callback_list, + list) { + if (!ret) + pos->init(pos->data); + pos->cleanup_cb(pos->data); + kfree(pos); + } + mutex_unlock(&minor->debugfs_callback_lock); + return ret; } @@ -223,14 +363,29 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor) int drm_debugfs_cleanup(struct drm_minor *minor) { + struct drm_debugfs_callback *pos, *tmp; + + mutex_lock(&minor->debugfs_callback_lock); + if (!minor->debugfs_callbacks_done) { + list_for_each_entry_safe(pos, tmp, + &minor->debugfs_callback_list, + list) { + pos->cleanup_cb(pos->data); + kfree(pos); + } + } + minor->debugfs_callbacks_done = true; + if (!minor->debugfs_root) - return 0; + goto out; drm_debugfs_remove_all_files(minor); debugfs_remove_recursive(minor->debugfs_root); minor->debugfs_root = NULL; +out: + mutex_unlock(&minor->debugfs_callback_lock); return 0; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index ea4941da9b27..7041b3137229 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -118,6 +118,9 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type) minor->type = type; minor->dev = dev; + r = drm_debugfs_alloc(minor); + if (r) + goto err_free; idr_preload(GFP_KERNEL); spin_lock_irqsave(&drm_minor_lock, flags); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 40179c5fc6b8..d6394246967d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -118,6 +118,7 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent, /* drm_debugfs.c drm_debugfs_crc.c */ #if defined(CONFIG_DEBUG_FS) +int drm_debugfs_alloc(struct drm_minor *minor); int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root); int drm_debugfs_cleanup(struct drm_minor *minor); @@ -127,6 +128,10 @@ int drm_debugfs_crtc_add(struct drm_crtc *crtc); void drm_debugfs_crtc_remove(struct drm_crtc *crtc); int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc); #else +static inline int drm_debugfs_alloc(struct drm_minor *minor) +{ + return 0; +} static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root) { diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h index ac0f75df1ac9..6ac45d96fcd1 100644 --- a/include/drm/drm_debugfs.h +++ b/include/drm/drm_debugfs.h @@ -77,12 +77,23 @@ struct drm_info_node { struct dentry *dent; }; +struct drm_debugfs_callback; + #if defined(CONFIG_DEBUG_FS) int drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor); int drm_debugfs_remove_files(const struct drm_info_list *files, int count, struct drm_minor *minor); + +int drm_debugfs_register_callback(struct drm_minor *minor, + void (*init)(void *), + void (*cleanup_cb)(void *), + void *data, + struct drm_debugfs_callback **out); +void drm_debugfs_unregister_callback(struct drm_minor *minor, + struct drm_debugfs_callback *cb); + #else static inline int drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, @@ -96,6 +107,22 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files, { return 0; } + +static inline int +drm_debugfs_register_callback(struct drm_minor *minor, + void (*init)(void *), + void (*cleanup_cb)(void *), + void *data, + struct drm_debugfs_callback **out) +{ + return 0; +} + +static inline void +drm_debugfs_unregister_callback(struct drm_minor *minor, + struct drm_debugfs_callback *cb) +{ +} #endif #endif /* _DRM_DEBUGFS_H_ */ diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 26485acc51d7..180052b51712 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -74,6 +74,10 @@ struct drm_minor { struct dentry *debugfs_root; + bool debugfs_callbacks_done; + struct list_head debugfs_callback_list; + struct mutex debugfs_callback_lock; + struct list_head debugfs_list; struct mutex debugfs_lock; /* Protects debugfs_list. */ }; -- 2.17.1
Lyude Paul
2018-Aug-28 17:10 UTC
[Nouveau] [PATCH v2 2/4] drm/dp_mst: Pass entire connector to drm_dp_mst_topology_mgr_init()
There's no actual reason we pass the connector ID instead of a pointer to the connector itself, and we're going to need the entire connector (but only temporarily) in order to name MST debugfs folders properly since connector IDs can't be looked up until the driver has been registered with userspace which happens after debugfs init. So, just pass the entire drm_connector struct instead of just its id. Signed-off-by: Lyude Paul <lyude at redhat.com> --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- drivers/gpu/drm/drm_dp_mst_topology.c | 10 ++++++---- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_dp_mst.c | 6 ++++-- drivers/gpu/drm/i915/intel_drv.h | 3 ++- drivers/gpu/drm/nouveau/dispnv50/disp.c | 6 +++--- drivers/gpu/drm/radeon/radeon_dp_mst.c | 2 +- include/drm/drm_dp_mst_helper.h | 3 ++- 8 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 9a300732ba37..60da7e8fcca7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -503,6 +503,6 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, &aconnector->dm_dp_aux.aux, 16, 4, - aconnector->connector_id); + &aconnector->base); } diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 7780567aa669..acb7633f3f70 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3161,14 +3161,16 @@ EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); * @aux: DP helper aux channel to talk to this device * @max_dpcd_transaction_bytes: hw specific DPCD transaction limit * @max_payloads: maximum number of payloads this GPU can source - * @conn_base_id: the connector object ID the MST device is connected to. + * @connector: the &struct drm_connector the MST device is connected to. * * Return 0 for success, or negative error code on failure */ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, - struct drm_device *dev, struct drm_dp_aux *aux, + struct drm_device *dev, + struct drm_dp_aux *aux, int max_dpcd_transaction_bytes, - int max_payloads, int conn_base_id) + int max_payloads, + struct drm_connector *connector) { struct drm_dp_mst_topology_state *mst_state; @@ -3186,7 +3188,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, mgr->aux = aux; mgr->max_dpcd_transaction_bytes = max_dpcd_transaction_bytes; mgr->max_payloads = max_payloads; - mgr->conn_base_id = conn_base_id; + mgr->conn_base_id = connector->base.id; if (max_payloads + 1 > sizeof(mgr->payload_mask) * 8 || max_payloads + 1 > sizeof(mgr->vcpi_mask) * 8) return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index cd0f649b57a5..3688df38dbe7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6247,7 +6247,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, (port == PORT_B || port == PORT_C || port == PORT_D || port == PORT_F)) intel_dp_mst_encoder_init(intel_dig_port, - intel_connector->base.base.id); + &intel_connector->base); if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 7e3e01607643..6c07c29235df 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -583,7 +583,8 @@ intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port) } int -intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id) +intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, + struct drm_connector *connector) { struct intel_dp *intel_dp = &intel_dig_port->dp; struct drm_device *dev = intel_dig_port->base.base.dev; @@ -595,7 +596,8 @@ intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_ba /* create encoders */ intel_dp_create_fake_mst_encoders(intel_dig_port); ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev, - &intel_dp->aux, 16, 3, conn_base_id); + &intel_dp->aux, 16, 3, + connector); if (ret) { intel_dp->can_mst = false; return ret; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8fc61e96754f..af7a6111ff74 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1749,7 +1749,8 @@ bool intel_digital_port_connected(struct intel_encoder *encoder); int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector); /* intel_dp_mst.c */ -int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id); +int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, + struct drm_connector *connector); void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port); /* vlv_dsi.c */ void vlv_dsi_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 7139b962c6fd..918f2519859b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1226,7 +1226,7 @@ nv50_mstm_del(struct nv50_mstm **pmstm) static int nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, - int conn_base_id, struct nv50_mstm **pmstm) + struct drm_connector *connector, struct nv50_mstm **pmstm) { const int max_payloads = hweight8(outp->dcb->heads); struct drm_device *dev = outp->base.base.dev; @@ -1250,7 +1250,7 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, mstm->mgr.cbs = &nv50_mstm; ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev, aux, aux_max, - max_payloads, conn_base_id); + max_payloads, connector); if (ret) return ret; @@ -1496,7 +1496,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) if ((data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) && ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04)) { ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16, - nv_connector->base.base.id, + &nv_connector->base, &nv_encoder->dp.mstm); if (ret) return ret; diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index f920be236cc9..3c66b1d26f88 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -664,7 +664,7 @@ radeon_dp_mst_init(struct radeon_connector *radeon_connector) radeon_connector->mst_mgr.cbs = &mst_cbs; return drm_dp_mst_topology_mgr_init(&radeon_connector->mst_mgr, dev, &radeon_connector->ddc_bus->aux, 16, 6, - radeon_connector->base.base.id); + &radeon_connector->base); } int diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 7f78d26a0766..ef8ba093ae8a 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -573,7 +573,8 @@ struct drm_dp_mst_topology_mgr { int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, struct drm_device *dev, struct drm_dp_aux *aux, int max_dpcd_transaction_bytes, - int max_payloads, int conn_base_id); + int max_payloads, + struct drm_connector *connector); void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); -- 2.17.1
Lyude Paul
2018-Aug-28 17:10 UTC
[Nouveau] [PATCH v2 3/4] drm/dp_mst: Add dp_mst_status debugfs node for all drivers
Originally I was just going to be adding dp_mst_status for nouveau until Daniel Stone pointed out that we should probably just make this so it's magically added for every DRM driver that's using the DRM DP MST helpers. So, let's do that! Signed-off-by: Lyude Paul <lyude at redhat.com> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com> Cc: Daniel Stone <daniel at fooishbar.org> --- drivers/gpu/drm/drm_dp_mst_topology.c | 106 ++++++++++++++++++++++++++ include/drm/drm_dp_mst_helper.h | 14 ++++ 2 files changed, 120 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index acb7633f3f70..a6a2c03af62a 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -27,6 +27,7 @@ #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/i2c.h> +#include <linux/debugfs.h> #include <drm/drm_dp_mst_helper.h> #include <drm/drmP.h> @@ -3154,6 +3155,104 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a } EXPORT_SYMBOL(drm_atomic_get_mst_topology_state); +#ifdef CONFIG_DEBUG_FS +static int drm_dp_mst_debugfs_state_show(struct seq_file *m, void *data) +{ + drm_dp_mst_dump_topology(m, m->private); + return 0; +} + +static int drm_dp_mst_debugfs_state_open(struct inode *inode, + struct file *file) +{ + struct drm_dp_mst_topology_mgr *mgr = inode->i_private; + + return single_open(file, drm_dp_mst_debugfs_state_show, mgr); +} + +static const struct file_operations drm_dp_mst_debugfs_state_fops = { + .owner = THIS_MODULE, + .open = drm_dp_mst_debugfs_state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +struct drm_dp_mst_debugfs_init_data { + struct drm_dp_mst_topology_mgr *mgr; + char *connector_name; +}; + +static void +drm_dp_mst_debugfs_init(void *data) +{ + struct drm_dp_mst_debugfs_init_data *init_data = data; + struct drm_dp_mst_topology_mgr *mgr = init_data->mgr; + struct drm_minor *minor = mgr->dev->primary; + struct dentry *root; + bool put_ref = false; + + /* Create the dp_mst directory for this device if it doesn't exist + * already + */ + root = debugfs_lookup("dp_mst", minor->debugfs_root); + if (root) { + put_ref = true; + } else { + root = debugfs_create_dir("dp_mst", minor->debugfs_root); + if (!root || IS_ERR(root)) + return; + } + + mgr->debugfs = debugfs_create_dir(init_data->connector_name, root); + if (!mgr->debugfs) + goto out_dput; + + debugfs_create_file("state", 0444, mgr->debugfs, mgr, + &drm_dp_mst_debugfs_state_fops); + +out_dput: + if (put_ref) + dput(root); +} + +static void +drm_dp_mst_debugfs_cleanup_cb(void *data) +{ + struct drm_dp_mst_debugfs_init_data *init_data = data; + + init_data->mgr->debugfs_init_cb = NULL; + kfree(init_data->connector_name); + kfree(init_data); +} + +static void +drm_dp_mst_debugfs_register(struct drm_dp_mst_topology_mgr *mgr, + struct drm_connector *connector) +{ + struct drm_dp_mst_debugfs_init_data *init_data; + + if (!connector) + return; + + init_data = kmalloc(sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return; + + init_data->mgr = mgr; + init_data->connector_name = kstrdup(connector->name, GFP_KERNEL); + if (!init_data->connector_name) { + kfree(init_data); + return; + } + + drm_debugfs_register_callback(mgr->dev->primary, + drm_dp_mst_debugfs_init, + drm_dp_mst_debugfs_cleanup_cb, + init_data, &mgr->debugfs_init_cb); +} +#endif + /** * drm_dp_mst_topology_mgr_init - initialise a topology manager * @mgr: manager struct to initialise @@ -3214,6 +3313,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, drm_atomic_private_obj_init(&mgr->base, &mst_state->base, &mst_state_funcs); +#ifdef CONFIG_DEBUG_FS + drm_dp_mst_debugfs_register(mgr, connector); +#endif return 0; } @@ -3225,6 +3327,10 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); */ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) { +#ifdef CONFIG_DEBUG_FS + drm_debugfs_unregister_callback(mgr->dev->primary, + mgr->debugfs_init_cb); +#endif flush_work(&mgr->work); flush_work(&mgr->destroy_connector_work); mutex_lock(&mgr->payload_lock); diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index ef8ba093ae8a..c70b81cd78b1 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -25,6 +25,7 @@ #include <linux/types.h> #include <drm/drm_dp_helper.h> #include <drm/drm_atomic.h> +#include <drm/drm_debugfs.h> struct drm_dp_mst_branch; @@ -568,6 +569,19 @@ struct drm_dp_mst_topology_mgr { * avoid locking inversion. */ struct work_struct destroy_connector_work; +#ifdef CONFIG_DEBUG_FS + /** + * @debugfs_init_cb: Pending debugfs callback for initializing the + * debugfs files for this topology. + */ + struct drm_debugfs_callback *debugfs_init_cb; + + /** + * @debugfs_entry: dentry for dp_mst_status located in connector's + * debugfs directory. + */ + struct dentry *debugfs; +#endif }; int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, -- 2.17.1
Lyude Paul
2018-Aug-28 17:10 UTC
[Nouveau] [PATCH v2 4/4] drm/i915: Remove i915_drm_dp_mst_status
Now that DRM can create these debugfs nodes automatically; this isn't needed. Signed-off-by: Lyude Paul <lyude at redhat.com> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com> Cc: Daniel Stone <daniel at fooishbar.org> --- drivers/gpu/drm/i915/i915_debugfs.c | 32 ----------------------------- 1 file changed, 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index f9ce35da4123..5014828ca022 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3534,37 +3534,6 @@ static int i915_drrs_status(struct seq_file *m, void *unused) return 0; } -static int i915_dp_mst_info(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_encoder *intel_encoder; - struct intel_digital_port *intel_dig_port; - struct drm_connector *connector; - struct drm_connector_list_iter conn_iter; - - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) - continue; - - intel_encoder = intel_attached_encoder(connector); - if (!intel_encoder || intel_encoder->type == INTEL_OUTPUT_DP_MST) - continue; - - intel_dig_port = enc_to_dig_port(&intel_encoder->base); - if (!intel_dig_port->dp.can_mst) - continue; - - seq_printf(m, "MST Source Port %c\n", - port_name(intel_dig_port->base.port)); - drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr); - } - drm_connector_list_iter_end(&conn_iter); - - return 0; -} - static ssize_t i915_displayport_test_active_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) @@ -4733,7 +4702,6 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_rcs_topology", i915_rcs_topology, 0}, {"i915_shrinker_info", i915_shrinker_info, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, - {"i915_dp_mst_info", i915_dp_mst_info, 0}, {"i915_wa_registers", i915_wa_registers, 0}, {"i915_ddb_info", i915_ddb_info, 0}, {"i915_sseu_status", i915_sseu_status, 0}, -- 2.17.1
Reasonably Related Threads
- [PATCH v2 1/4] drm/debugfs: Add support for dynamic debugfs initialization
- [PATCH v2 3/4] drm/dp_mst: Add dp_mst_status debugfs node for all drivers
- [PATCH] drm: serialize access to debugs_nodes.list
- [PATCH 0/4] drm/dp_mst: Add DP MST debugfs nodes for all drivers
- [PATCH v5 00/10] Implement proper MST fallback retraining in i915