Skip to content

Commit

Permalink
drm/amdgpu: Iterate through DRM connectors correctly
Browse files Browse the repository at this point in the history
Currently, every single piece of code in amdgpu that loops through
connectors does it incorrectly and doesn't use the proper list iteration
helpers, drm_connector_list_iter_begin() and
drm_connector_list_iter_end(). Yeesh.

So, do that.

Cc: Juston Li <juston.li@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Harry Wentland <hwentlan@amd.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191022023641.8026-12-lyude@redhat.com
  • Loading branch information
Lyude Paul committed Oct 24, 2019
1 parent ac0de16 commit 6857f87
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 73 deletions.
13 changes: 11 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,8 +1019,12 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
*/
if (amdgpu_connector->shared_ddc && (ret == connector_status_connected)) {
struct drm_connector *list_connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *list_amdgpu_connector;
list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {

drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(list_connector,
&iter) {
if (connector == list_connector)
continue;
list_amdgpu_connector = to_amdgpu_connector(list_connector);
Expand All @@ -1037,6 +1041,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
}
}
}
drm_connector_list_iter_end(&iter);
}
}
}
Expand Down Expand Up @@ -1494,6 +1499,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector;
struct amdgpu_connector_atom_dig *amdgpu_dig_connector;
struct drm_encoder *encoder;
Expand All @@ -1508,10 +1514,12 @@ amdgpu_connector_add(struct amdgpu_device *adev,
return;

/* see if we already added it */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
amdgpu_connector = to_amdgpu_connector(connector);
if (amdgpu_connector->connector_id == connector_id) {
amdgpu_connector->devices |= supported_device;
drm_connector_list_iter_end(&iter);
return;
}
if (amdgpu_connector->ddc_bus && i2c_bus->valid) {
Expand All @@ -1526,6 +1534,7 @@ amdgpu_connector_add(struct amdgpu_device *adev,
}
}
}
drm_connector_list_iter_end(&iter);

/* check if it's a dp bridge */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
Expand Down
20 changes: 14 additions & 6 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -3007,6 +3007,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
struct amdgpu_device *adev;
struct drm_crtc *crtc;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
int r;

if (dev == NULL || dev->dev_private == NULL) {
Expand All @@ -3029,9 +3030,11 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
if (!amdgpu_device_has_dc_support(adev)) {
/* turn off display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
}
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter)
drm_helper_connector_dpms(connector,
DRM_MODE_DPMS_OFF);
drm_connector_list_iter_end(&iter);
drm_modeset_unlock_all(dev);
/* unpin the front buffers and cursors */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
Expand Down Expand Up @@ -3110,6 +3113,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
{
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_device *adev = dev->dev_private;
struct drm_crtc *crtc;
int r = 0;
Expand Down Expand Up @@ -3180,9 +3184,13 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)

/* turn on display hw */
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}

drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter)
drm_helper_connector_dpms(connector,
DRM_MODE_DPMS_ON);
drm_connector_list_iter_end(&iter);

drm_modeset_unlock_all(dev);
}
amdgpu_fbdev_set_suspend(adev, 0);
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,11 +370,13 @@ void amdgpu_display_print_display_setup(struct drm_device *dev)
struct amdgpu_connector *amdgpu_connector;
struct drm_encoder *encoder;
struct amdgpu_encoder *amdgpu_encoder;
struct drm_connector_list_iter iter;
uint32_t devices;
int i = 0;

drm_connector_list_iter_begin(dev, &iter);
DRM_INFO("AMDGPU Display Connectors\n");
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_for_each_connector_iter(connector, &iter) {
amdgpu_connector = to_amdgpu_connector(connector);
DRM_INFO("Connector %d:\n", i);
DRM_INFO(" %s\n", connector->name);
Expand Down Expand Up @@ -438,6 +440,7 @@ void amdgpu_display_print_display_setup(struct drm_device *dev)
}
i++;
}
drm_connector_list_iter_end(&iter);
}

/**
Expand Down
40 changes: 28 additions & 12 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
{
struct amdgpu_device *adev = dev->dev_private;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector;
struct drm_encoder *encoder;
struct amdgpu_encoder *amdgpu_encoder;

drm_connector_list_iter_begin(dev, &iter);
/* walk the list and link encoders to connectors */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_for_each_connector_iter(connector, &iter) {
amdgpu_connector = to_amdgpu_connector(connector);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
amdgpu_encoder = to_amdgpu_encoder(encoder);
Expand All @@ -55,15 +57,18 @@ amdgpu_link_encoder_connector(struct drm_device *dev)
}
}
}
drm_connector_list_iter_end(&iter);
}

void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct drm_connector *connector;
struct drm_connector_list_iter iter;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
if (connector->encoder == encoder) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
amdgpu_encoder->active_device = amdgpu_encoder->devices & amdgpu_connector->devices;
Expand All @@ -72,38 +77,49 @@ void amdgpu_encoder_set_active_device(struct drm_encoder *encoder)
amdgpu_connector->devices, encoder->encoder_type);
}
}
drm_connector_list_iter_end(&iter);
}

struct drm_connector *
amdgpu_get_connector_for_encoder(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct drm_connector *connector;
struct drm_connector *connector, *found = NULL;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
amdgpu_connector = to_amdgpu_connector(connector);
if (amdgpu_encoder->active_device & amdgpu_connector->devices)
return connector;
if (amdgpu_encoder->active_device & amdgpu_connector->devices) {
found = connector;
break;
}
}
return NULL;
drm_connector_list_iter_end(&iter);
return found;
}

struct drm_connector *
amdgpu_get_connector_for_encoder_init(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct drm_connector *connector;
struct drm_connector *connector, *found = NULL;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
amdgpu_connector = to_amdgpu_connector(connector);
if (amdgpu_encoder->devices & amdgpu_connector->devices)
return connector;
if (amdgpu_encoder->devices & amdgpu_connector->devices) {
found = connector;
break;
}
}
return NULL;
drm_connector_list_iter_end(&iter);
return found;
}

struct drm_encoder *amdgpu_get_external_encoder(struct drm_encoder *encoder)
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,13 @@ static void amdgpu_hotplug_work_func(struct work_struct *work)
struct drm_device *dev = adev->ddev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
struct drm_connector_list_iter iter;

mutex_lock(&mode_config->mutex);
list_for_each_entry(connector, &mode_config->connector_list, head)
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter)
amdgpu_connector_hotplug(connector);
drm_connector_list_iter_end(&iter);
mutex_unlock(&mode_config->mutex);
/* Just fire off a uevent and let userspace tell us what to do */
drm_helper_hpd_irq_event(dev);
Expand Down
34 changes: 26 additions & 8 deletions drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,11 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
u32 tmp;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);

if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
Expand Down Expand Up @@ -368,6 +370,7 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev)
amdgpu_irq_get(adev, &adev->hpd_irq,
amdgpu_connector->hpd.hpd);
}
drm_connector_list_iter_end(&iter);
}

/**
Expand All @@ -382,9 +385,11 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev)
{
struct drm_device *dev = adev->ddev;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
u32 tmp;

list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);

if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
Expand All @@ -397,6 +402,7 @@ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev)
amdgpu_irq_put(adev, &adev->hpd_irq,
amdgpu_connector->hpd.hpd);
}
drm_connector_list_iter_end(&iter);
}

static u32 dce_v10_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
Expand Down Expand Up @@ -1219,23 +1225,27 @@ static void dce_v10_0_afmt_audio_select_pin(struct drm_encoder *encoder)
static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct amdgpu_device *adev = encoder->dev->dev_private;
struct drm_device *dev = encoder->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector = NULL;
u32 tmp;
int interlace = 0;

if (!dig || !dig->afmt || !dig->afmt->pin)
return;

list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
if (connector->encoder == encoder) {
amdgpu_connector = to_amdgpu_connector(connector);
break;
}
}
drm_connector_list_iter_end(&iter);

if (!amdgpu_connector) {
DRM_ERROR("Couldn't find encoder's connector\n");
Expand All @@ -1261,10 +1271,12 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder,

static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder)
{
struct amdgpu_device *adev = encoder->dev->dev_private;
struct drm_device *dev = encoder->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector = NULL;
u32 tmp;
u8 *sadb = NULL;
Expand All @@ -1273,12 +1285,14 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder
if (!dig || !dig->afmt || !dig->afmt->pin)
return;

list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
if (connector->encoder == encoder) {
amdgpu_connector = to_amdgpu_connector(connector);
break;
}
}
drm_connector_list_iter_end(&iter);

if (!amdgpu_connector) {
DRM_ERROR("Couldn't find encoder's connector\n");
Expand Down Expand Up @@ -1313,10 +1327,12 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder

static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
{
struct amdgpu_device *adev = encoder->dev->dev_private;
struct drm_device *dev = encoder->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
struct drm_connector *connector;
struct drm_connector_list_iter iter;
struct amdgpu_connector *amdgpu_connector = NULL;
struct cea_sad *sads;
int i, sad_count;
Expand All @@ -1339,12 +1355,14 @@ static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder)
if (!dig || !dig->afmt || !dig->afmt->pin)
return;

list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &iter);
drm_for_each_connector_iter(connector, &iter) {
if (connector->encoder == encoder) {
amdgpu_connector = to_amdgpu_connector(connector);
break;
}
}
drm_connector_list_iter_end(&iter);

if (!amdgpu_connector) {
DRM_ERROR("Couldn't find encoder's connector\n");
Expand Down
Loading

0 comments on commit 6857f87

Please sign in to comment.