Commit f002abc19acb6f7cdb3d320f3b6f1a565c0be63e

Authored by Thierry Reding
1 parent dee8268f8f

drm/tegra: Properly cleanup and zero out resources

When the DRM driver is unloaded, all the associated resources must be
cleaned up and zeroed out. This is necessary because of the architecture
of the Tegra DRM driver, where not all subdrivers are unloaded along
with the DRM driver. Therefore device-managed managed won't be freed and
memory cannot be assumed to have been cleared (because it hasn't been
reallocated using kzalloc()) by the time the DRM driver is reloaded. It
is therefore necessary to zero out the structures to prevent strange
errors (such as slab corruptions) from occurring.

Signed-off-by: Thierry Reding <treding@nvidia.com>

Showing 3 changed files with 36 additions and 5 deletions Side-by-side Diff

drivers/gpu/drm/tegra/dc.c
... ... @@ -93,8 +93,11 @@
93 93  
94 94 static void tegra_plane_destroy(struct drm_plane *plane)
95 95 {
  96 + struct tegra_plane *p = to_tegra_plane(plane);
  97 +
96 98 tegra_plane_disable(plane);
97 99 drm_plane_cleanup(plane);
  100 + kfree(p);
98 101 }
99 102  
100 103 static const struct drm_plane_funcs tegra_plane_funcs = {
... ... @@ -120,7 +123,7 @@
120 123 for (i = 0; i < 2; i++) {
121 124 struct tegra_plane *plane;
122 125  
123   - plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
  126 + plane = kzalloc(sizeof(*plane), GFP_KERNEL);
124 127 if (!plane)
125 128 return -ENOMEM;
126 129  
127 130  
... ... @@ -129,8 +132,10 @@
129 132 err = drm_plane_init(drm, &plane->base, 1 << dc->pipe,
130 133 &tegra_plane_funcs, plane_formats,
131 134 ARRAY_SIZE(plane_formats), false);
132   - if (err < 0)
  135 + if (err < 0) {
  136 + kfree(plane);
133 137 return err;
  138 + }
134 139 }
135 140  
136 141 return 0;
137 142  
138 143  
... ... @@ -251,14 +256,26 @@
251 256 return 0;
252 257 }
253 258  
  259 +static void drm_crtc_clear(struct drm_crtc *crtc)
  260 +{
  261 + memset(crtc, 0, sizeof(*crtc));
  262 +}
  263 +
  264 +static void tegra_dc_destroy(struct drm_crtc *crtc)
  265 +{
  266 + drm_crtc_cleanup(crtc);
  267 + drm_crtc_clear(crtc);
  268 +}
  269 +
254 270 static const struct drm_crtc_funcs tegra_crtc_funcs = {
255 271 .page_flip = tegra_dc_page_flip,
256 272 .set_config = drm_crtc_helper_set_config,
257   - .destroy = drm_crtc_cleanup,
  273 + .destroy = tegra_dc_destroy,
258 274 };
259 275  
260 276 static void tegra_crtc_disable(struct drm_crtc *crtc)
261 277 {
  278 + struct tegra_dc *dc = to_tegra_dc(crtc);
262 279 struct drm_device *drm = crtc->dev;
263 280 struct drm_plane *plane;
264 281  
... ... @@ -273,6 +290,8 @@
273 290 }
274 291 }
275 292 }
  293 +
  294 + drm_vblank_off(drm, dc->pipe);
276 295 }
277 296  
278 297 static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc,
drivers/gpu/drm/tegra/drm.c
... ... @@ -72,12 +72,12 @@
72 72  
73 73 drm_kms_helper_poll_fini(drm);
74 74 tegra_drm_fb_exit(drm);
  75 + drm_vblank_cleanup(drm);
  76 + drm_mode_config_cleanup(drm);
75 77  
76 78 err = host1x_device_exit(device);
77 79 if (err < 0)
78 80 return err;
79   -
80   - drm_mode_config_cleanup(drm);
81 81  
82 82 return 0;
83 83 }
drivers/gpu/drm/tegra/output.c
... ... @@ -79,10 +79,16 @@
79 79 return status;
80 80 }
81 81  
  82 +static void drm_connector_clear(struct drm_connector *connector)
  83 +{
  84 + memset(connector, 0, sizeof(*connector));
  85 +}
  86 +
82 87 static void tegra_connector_destroy(struct drm_connector *connector)
83 88 {
84 89 drm_sysfs_connector_remove(connector);
85 90 drm_connector_cleanup(connector);
  91 + drm_connector_clear(connector);
86 92 }
87 93  
88 94 static const struct drm_connector_funcs connector_funcs = {
89 95  
... ... @@ -92,9 +98,15 @@
92 98 .destroy = tegra_connector_destroy,
93 99 };
94 100  
  101 +static void drm_encoder_clear(struct drm_encoder *encoder)
  102 +{
  103 + memset(encoder, 0, sizeof(*encoder));
  104 +}
  105 +
95 106 static void tegra_encoder_destroy(struct drm_encoder *encoder)
96 107 {
97 108 drm_encoder_cleanup(encoder);
  109 + drm_encoder_clear(encoder);
98 110 }
99 111  
100 112 static const struct drm_encoder_funcs encoder_funcs = {