drm/amd/display: Add debugfs dpcd interface

[Why]
We need arbitrary read/write over DP AUX DPCD
for debugging

[How]
Three debugfs entries

Set the target address by writing to
"aux_dpcd_address"
(The first four bytes written are used)

Set the transaction size in bytes by writing to
"aux_dpcd_size"
(The first four bytes written are used)

Start a transaction by reading/writing
"aux_dpcd_data"

Do note: there is no concerrency protection at all
Accessing these entries in quick succession can lead
to strange behaviour

Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
David Francis 2019-03-05 10:04:15 -05:00 committed by Alex Deucher
parent c7ba3653e9
commit f258fee6c3
3 changed files with 112 additions and 1 deletions

View File

@ -4395,6 +4395,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
DRM_ERROR("Failed to create debugfs for connector"); DRM_ERROR("Failed to create debugfs for connector");
goto out_free; goto out_free;
} }
aconnector->debugfs_dpcd_address = 0;
aconnector->debugfs_dpcd_size = 0;
#endif #endif
if (connector_type == DRM_MODE_CONNECTOR_DisplayPort if (connector_type == DRM_MODE_CONNECTOR_DisplayPort

View File

@ -238,6 +238,10 @@ struct amdgpu_dm_connector {
struct mutex hpd_lock; struct mutex hpd_lock;
bool fake_enable; bool fake_enable;
#ifdef CONFIG_DEBUG_FS
uint32_t debugfs_dpcd_address;
uint32_t debugfs_dpcd_size;
#endif
}; };
#define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base)

View File

@ -29,6 +29,7 @@
#include "amdgpu.h" #include "amdgpu.h"
#include "amdgpu_dm.h" #include "amdgpu_dm.h"
#include "amdgpu_dm_debugfs.h" #include "amdgpu_dm_debugfs.h"
#include "dm_helpers.h"
/* function description /* function description
* get/ set DP configuration: lane_count, link_rate, spread_spectrum * get/ set DP configuration: lane_count, link_rate, spread_spectrum
@ -731,6 +732,88 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b
DEFINE_SHOW_ATTRIBUTE(vrr_range); DEFINE_SHOW_ATTRIBUTE(vrr_range);
static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
int r;
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
if (size < sizeof(connector->debugfs_dpcd_address))
return 0;
r = copy_from_user(&connector->debugfs_dpcd_address,
buf, sizeof(connector->debugfs_dpcd_address));
return size - r;
}
static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
int r;
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
if (size < sizeof(connector->debugfs_dpcd_size))
return 0;
r = copy_from_user(&connector->debugfs_dpcd_size,
buf, sizeof(connector->debugfs_dpcd_size));
if (connector->debugfs_dpcd_size > 256)
connector->debugfs_dpcd_size = 0;
return size - r;
}
static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
{
int r;
char *data;
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
struct dc_link *link = connector->dc_link;
uint32_t write_size = connector->debugfs_dpcd_size;
if (size < write_size)
return 0;
data = kzalloc(write_size, GFP_KERNEL);
if (!data)
return 0;
r = copy_from_user(data, buf, write_size);
dm_helpers_dp_write_dpcd(link->ctx, link,
connector->debugfs_dpcd_address, data, write_size - r);
kfree(data);
return write_size - r;
}
static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf,
size_t size, loff_t *pos)
{
int r;
char *data;
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
struct dc_link *link = connector->dc_link;
uint32_t read_size = connector->debugfs_dpcd_size;
if (size < read_size)
return 0;
data = kzalloc(read_size, GFP_KERNEL);
if (!data)
return 0;
dm_helpers_dp_read_dpcd(link->ctx, link,
connector->debugfs_dpcd_address, data, read_size);
r = copy_to_user(buf, data, read_size);
kfree(data);
return read_size - r;
}
static const struct file_operations dp_link_settings_debugfs_fops = { static const struct file_operations dp_link_settings_debugfs_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = dp_link_settings_read, .read = dp_link_settings_read,
@ -757,6 +840,25 @@ static const struct file_operations sdp_message_fops = {
.llseek = default_llseek .llseek = default_llseek
}; };
static const struct file_operations dp_dpcd_address_debugfs_fops = {
.owner = THIS_MODULE,
.write = dp_dpcd_address_write,
.llseek = default_llseek
};
static const struct file_operations dp_dpcd_size_debugfs_fops = {
.owner = THIS_MODULE,
.write = dp_dpcd_size_write,
.llseek = default_llseek
};
static const struct file_operations dp_dpcd_data_debugfs_fops = {
.owner = THIS_MODULE,
.read = dp_dpcd_data_read,
.write = dp_dpcd_data_write,
.llseek = default_llseek
};
static const struct { static const struct {
char *name; char *name;
const struct file_operations *fops; const struct file_operations *fops;
@ -765,7 +867,10 @@ static const struct {
{"phy_settings", &dp_phy_settings_debugfs_fop}, {"phy_settings", &dp_phy_settings_debugfs_fop},
{"test_pattern", &dp_phy_test_pattern_fops}, {"test_pattern", &dp_phy_test_pattern_fops},
{"vrr_range", &vrr_range_fops}, {"vrr_range", &vrr_range_fops},
{"sdp_message", &sdp_message_fops} {"sdp_message", &sdp_message_fops},
{"aux_dpcd_address", &dp_dpcd_address_debugfs_fops},
{"aux_dpcd_size", &dp_dpcd_size_debugfs_fops},
{"aux_dpcd_data", &dp_dpcd_data_debugfs_fops}
}; };
int connector_debugfs_init(struct amdgpu_dm_connector *connector) int connector_debugfs_init(struct amdgpu_dm_connector *connector)