[PATCH] drm: refcnt drm_display_mode

Rob Clark robdclark at gmail.com
Sun Jul 27 09:20:45 PDT 2014


On Sun, Jul 27, 2014 at 11:17 AM, Daniel Vetter <daniel at ffwll.ch> wrote:
> On Sat, Jul 26, 2014 at 12:51 AM, Rob Clark <robdclark at gmail.com> wrote:
>> We're going to need this for atomic.
>>
>> Signed-off-by: Rob Clark <robdclark at gmail.com>
>
> I disagree. Iiui correctly Rob's concern is that the additional stuff
> to keep track of mode lists (list_head and the idr stuff) could
> confuse driver writers into doing stupid stuff when they embed
> drm_display_mode into some other stuff. Imo the right fix would be to
> just remove them (but that's fairly invasive to the mode list code).

bleh, all the deep copies seem ugly either way, I still think
refcnt'ing and shallow copies is the better idea

> Now wrt atomic we only need refcounting because currently
> drm_atomic_state is refcounted. And we don't need that afaics (and I'm
> working on the draft code to show how). So without a clear need for
> refcounting I really prefer we don't add this complexity - doing
> refcounting for fbs wasn't fun at all ;-)

Well, that was somewhat different, because there were some side-effects of rmfb

BR,
-R

> -Daniel
>> ---
>>  drivers/gpu/drm/drm_crtc.c                    |  4 +--
>>  drivers/gpu/drm/drm_crtc_helper.c             |  2 +-
>>  drivers/gpu/drm/drm_edid.c                    |  6 ++--
>>  drivers/gpu/drm/drm_fb_helper.c               |  6 ++--
>>  drivers/gpu/drm/drm_modes.c                   | 41 ++++++++++++++++++++-------
>>  drivers/gpu/drm/exynos/exynos_drm_connector.c |  2 +-
>>  drivers/gpu/drm/gma500/psb_intel_sdvo.c       |  3 +-
>>  drivers/gpu/drm/i915/intel_panel.c            |  8 ++----
>>  drivers/gpu/drm/i915/intel_sdvo.c             |  3 +-
>>  drivers/gpu/drm/nouveau/nouveau_connector.c   |  2 +-
>>  drivers/gpu/drm/omapdrm/omap_connector.c      |  2 +-
>>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c           |  4 +--
>>  include/drm/drm_modes.h                       |  5 +++-
>>  13 files changed, 52 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>> index 1ccf5cb..7a7fced 100644
>> --- a/drivers/gpu/drm/drm_crtc.c
>> +++ b/drivers/gpu/drm/drm_crtc.c
>> @@ -822,7 +822,7 @@ static void drm_mode_remove(struct drm_connector *connector,
>>                             struct drm_display_mode *mode)
>>  {
>>         list_del(&mode->head);
>> -       drm_mode_destroy(connector->dev, mode);
>> +       drm_mode_unreference(mode);
>>  }
>>
>>  /**
>> @@ -2602,7 +2602,7 @@ out:
>>                 drm_framebuffer_unreference(fb);
>>
>>         kfree(connector_set);
>> -       drm_mode_destroy(dev, mode);
>> +       drm_mode_unreference(mode);
>>         drm_modeset_unlock_all(dev);
>>         return ret;
>>  }
>> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
>> index 6c65a0a..757de8b 100644
>> --- a/drivers/gpu/drm/drm_crtc_helper.c
>> +++ b/drivers/gpu/drm/drm_crtc_helper.c
>> @@ -384,7 +384,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
>>
>>         /* FIXME: add subpixel order */
>>  done:
>> -       drm_mode_destroy(dev, adjusted_mode);
>> +       drm_mode_unreference(adjusted_mode);
>>         if (!ret) {
>>                 crtc->enabled = saved_enabled;
>>                 crtc->mode = saved_mode;
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 087d608..cbc021d 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -1705,7 +1705,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid,
>>                 if (!mode)
>>                         return NULL;
>>                 if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
>> -                       drm_mode_destroy(dev, mode);
>> +                       drm_mode_unreference(mode);
>>                         mode = drm_gtf_mode_complex(dev, hsize, vsize,
>>                                                     vrefresh_rate, 0, 0,
>>                                                     drm_gtf2_m(edid),
>> @@ -2021,7 +2021,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
>>                 fixup_mode_1366x768(newmode);
>>                 if (!mode_in_range(newmode, edid, timing) ||
>>                     !valid_inferred_mode(connector, newmode)) {
>> -                       drm_mode_destroy(dev, newmode);
>> +                       drm_mode_unreference(newmode);
>>                         continue;
>>                 }
>>
>> @@ -2050,7 +2050,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
>>                 fixup_mode_1366x768(newmode);
>>                 if (!mode_in_range(newmode, edid, timing) ||
>>                     !valid_inferred_mode(connector, newmode)) {
>> -                       drm_mode_destroy(dev, newmode);
>> +                       drm_mode_unreference(newmode);
>>                         continue;
>>                 }
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
>> index 3144db9..5c96a6a 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -588,7 +588,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
>>         for (i = 0; i < helper->crtc_count; i++) {
>>                 kfree(helper->crtc_info[i].mode_set.connectors);
>>                 if (helper->crtc_info[i].mode_set.mode)
>> -                       drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode);
>> +                       drm_mode_unreference(helper->crtc_info[i].mode_set.mode);
>>         }
>>         kfree(helper->crtc_info);
>>  }
>> @@ -1606,7 +1606,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
>>                                       mode->name, fb_crtc->mode_set.crtc->base.id);
>>                         fb_crtc->desired_mode = mode;
>>                         if (modeset->mode)
>> -                               drm_mode_destroy(dev, modeset->mode);
>> +                               drm_mode_unreference(modeset->mode);
>>                         modeset->mode = drm_mode_duplicate(dev,
>>                                                            fb_crtc->desired_mode);
>>                         modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
>> @@ -1621,7 +1621,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
>>                         BUG_ON(modeset->fb);
>>                         BUG_ON(modeset->num_connectors);
>>                         if (modeset->mode)
>> -                               drm_mode_destroy(dev, modeset->mode);
>> +                               drm_mode_unreference(modeset->mode);
>>                         modeset->mode = NULL;
>>                 }
>>         }
>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>> index bedf189..55d51ed 100644
>> --- a/drivers/gpu/drm/drm_modes.c
>> +++ b/drivers/gpu/drm/drm_modes.c
>> @@ -82,27 +82,46 @@ struct drm_display_mode *drm_mode_create(struct drm_device *dev)
>>                 return NULL;
>>         }
>>
>> +       kref_init(&nmode->refcount);
>> +       nmode->dev = dev;
>> +
>>         return nmode;
>>  }
>>  EXPORT_SYMBOL(drm_mode_create);
>>
>>  /**
>> - * drm_mode_destroy - remove a mode
>> - * @dev: DRM device
>> + * drm_mode_reference - incr the mode's refcnt
>> + * @mode: display mode
>> + *
>> + * This functions increments the mode's refcount.
>> + */
>> +void drm_mode_reference(struct drm_display_mode *mode)
>> +{
>> +       kref_get(&mode->refcount);
>> +}
>> +EXPORT_SYMBOL(drm_mode_reference);
>> +
>> +static void drm_mode_free(struct kref *kref)
>> +{
>> +       struct drm_display_mode *mode =
>> +                       container_of(kref, struct drm_display_mode, refcount);
>> +       drm_mode_object_put(mode->dev, &mode->base);
>> +       kfree(mode);
>> +}
>> +
>> +/**
>> + * drm_mode_unreference - decrement the mode's refcnt
>>   * @mode: mode to remove
>>   *
>> - * Release @mode's unique ID, then free it @mode structure itself using kfree.
>> + * Decrement the mode's refcount, freeing it after last ref is dropped.
>>   */
>> -void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
>> +void drm_mode_unreference(struct drm_display_mode *mode)
>>  {
>>         if (!mode)
>>                 return;
>> -
>> -       drm_mode_object_put(dev, &mode->base);
>> -
>> -       kfree(mode);
>> +       kref_put(&mode->refcount, drm_mode_free);
>>  }
>> -EXPORT_SYMBOL(drm_mode_destroy);
>> +EXPORT_SYMBOL(drm_mode_unreference);
>>
>>  /**
>>   * drm_mode_probed_add - add a mode to a connector's probed_mode list
>> @@ -957,7 +976,7 @@ void drm_mode_prune_invalid(struct drm_device *dev,
>>                                 DRM_DEBUG_KMS("Not using %s mode %d\n",
>>                                         mode->name, mode->status);
>>                         }
>> -                       drm_mode_destroy(dev, mode);
>> +                       drm_mode_unreference(mode);
>>                 }
>>         }
>>  }
>> @@ -1046,7 +1065,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector,
>>                                 else
>>                                         mode->type = pmode->type;
>>                                 list_del(&pmode->head);
>> -                               drm_mode_destroy(connector->dev, pmode);
>> +                               drm_mode_unreference(pmode);
>>                                 break;
>>                         }
>>                 }
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
>> index ba9b3d5..3f9d44a 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
>> @@ -72,7 +72,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
>>                 if (display->ops->get_panel)
>>                         panel = display->ops->get_panel(display);
>>                 else {
>> -                       drm_mode_destroy(connector->dev, mode);
>> +                       drm_mode_unreference(mode);
>>                         return 0;
>>                 }
>>
>> diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
>> index 0be96fd..00eb0f63 100644
>> --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
>> +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
>> @@ -1905,8 +1905,7 @@ static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
>>         struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder);
>>
>>         if (psb_intel_sdvo->sdvo_lvds_fixed_mode != NULL)
>> -               drm_mode_destroy(encoder->dev,
>> -                                psb_intel_sdvo->sdvo_lvds_fixed_mode);
>> +               drm_mode_unreference(psb_intel_sdvo->sdvo_lvds_fixed_mode);
>>
>>         i2c_del_adapter(&psb_intel_sdvo->ddc);
>>         gma_encoder_destroy(encoder);
>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>> index 38a9857..cbf63e0 100644
>> --- a/drivers/gpu/drm/i915/intel_panel.c
>> +++ b/drivers/gpu/drm/i915/intel_panel.c
>> @@ -1205,13 +1205,9 @@ int intel_panel_init(struct intel_panel *panel,
>>
>>  void intel_panel_fini(struct intel_panel *panel)
>>  {
>> -       struct intel_connector *intel_connector =
>> -               container_of(panel, struct intel_connector, panel);
>> -
>>         if (panel->fixed_mode)
>> -               drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
>> +               drm_mode_unreference(panel->fixed_mode);
>>
>>         if (panel->downclock_mode)
>> -               drm_mode_destroy(intel_connector->base.dev,
>> -                               panel->downclock_mode);
>> +               drm_mode_unreference(panel->downclock_mode);
>>  }
>> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
>> index 9350edd..7049ac7 100644
>> --- a/drivers/gpu/drm/i915/intel_sdvo.c
>> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
>> @@ -2248,8 +2248,7 @@ static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
>>         struct intel_sdvo *intel_sdvo = to_sdvo(to_intel_encoder(encoder));
>>
>>         if (intel_sdvo->sdvo_lvds_fixed_mode != NULL)
>> -               drm_mode_destroy(encoder->dev,
>> -                                intel_sdvo->sdvo_lvds_fixed_mode);
>> +               drm_mode_unreference(intel_sdvo->sdvo_lvds_fixed_mode);
>>
>>         i2c_del_adapter(&intel_sdvo->ddc);
>>         intel_encoder_destroy(encoder);
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
>> index dbdc9ad..876ae75 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_connector.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
>> @@ -739,7 +739,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
>>         /* destroy the native mode, the attached monitor could have changed.
>>          */
>>         if (nv_connector->native_mode) {
>> -               drm_mode_destroy(dev, nv_connector->native_mode);
>> +               drm_mode_unreference(nv_connector->native_mode);
>>                 nv_connector->native_mode = NULL;
>>         }
>>
>> diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
>> index 36bc5cc..222d42a 100644
>> --- a/drivers/gpu/drm/omapdrm/omap_connector.c
>> +++ b/drivers/gpu/drm/omapdrm/omap_connector.c
>> @@ -224,7 +224,7 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
>>                 new_mode->vrefresh = 0;
>>                 if (mode->vrefresh == drm_mode_vrefresh(new_mode))
>>                         ret = MODE_OK;
>> -               drm_mode_destroy(dev, new_mode);
>> +               drm_mode_unreference(new_mode);
>>         }
>>
>>         DBG("connector: mode %s: "
>> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
>> index d2bc2b0..d726a81 100644
>> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
>> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
>> @@ -1964,13 +1964,13 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
>>                                                mode->vdisplay)) {
>>                         drm_mode_probed_add(connector, mode);
>>                 } else {
>> -                       drm_mode_destroy(dev, mode);
>> +                       drm_mode_unreference(mode);
>>                         mode = NULL;
>>                 }
>>
>>                 if (du->pref_mode) {
>>                         list_del_init(&du->pref_mode->head);
>> -                       drm_mode_destroy(dev, du->pref_mode);
>> +                       drm_mode_unreference(du->pref_mode);
>>                 }
>>
>>                 /* mode might be null here, this is intended */
>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
>> index 91d0582..ef552c9 100644
>> --- a/include/drm/drm_modes.h
>> +++ b/include/drm/drm_modes.h
>> @@ -97,6 +97,8 @@ struct drm_display_mode {
>>         /* Header */
>>         struct list_head head;
>>         struct drm_mode_object base;
>> +       struct kref refcount;
>> +       struct drm_device *dev;
>>
>>         char name[DRM_DISPLAY_MODE_LEN];
>>
>> @@ -178,7 +180,8 @@ struct drm_connector;
>>  struct drm_cmdline_mode;
>>
>>  struct drm_display_mode *drm_mode_create(struct drm_device *dev);
>> -void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode);
>> +void drm_mode_reference(struct drm_display_mode *mode);
>> +void drm_mode_unreference(struct drm_display_mode *mode);
>>  void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
>>  void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
>>
>> --
>> 1.9.3
>>
>
>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch


More information about the dri-devel mailing list