Merge tag 'drm-misc-fixes-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes before holidays:

- fixup for the lease fixup (Keith)
- fb leak in the ww mutex fallback code (Maarten)
- sun4i fixes (Maxime, Hans)

* tag 'drm-misc-fixes-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc:
drm: move lease init after validation in drm_lease_create
drm/plane: Make framebuffer refcounting the responsibility of setplane_internal callers
drm/sun4i: hdmi: Move the mode_valid callback to the encoder
drm/sun4i: Fix error path handling
drm/sun4i: validate modes for HDMI

+53 -35
+11 -11
drivers/gpu/drm/drm_lease.c
··· 220 220 221 221 mutex_lock(&dev->mode_config.idr_mutex); 222 222 223 - /* Insert the new lessee into the tree */ 224 - id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); 225 - if (id < 0) { 226 - error = id; 227 - goto out_lessee; 228 - } 229 - 230 - lessee->lessee_id = id; 231 - lessee->lessor = drm_master_get(lessor); 232 - list_add_tail(&lessee->lessee_list, &lessor->lessees); 233 - 234 223 idr_for_each_entry(leases, entry, object) { 235 224 error = 0; 236 225 if (!idr_find(&dev->mode_config.crtc_idr, object)) ··· 234 245 goto out_lessee; 235 246 } 236 247 } 248 + 249 + /* Insert the new lessee into the tree */ 250 + id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); 251 + if (id < 0) { 252 + error = id; 253 + goto out_lessee; 254 + } 255 + 256 + lessee->lessee_id = id; 257 + lessee->lessor = drm_master_get(lessor); 258 + list_add_tail(&lessee->lessee_list, &lessor->lessees); 237 259 238 260 /* Move the leases over */ 239 261 lessee->leases = *leases;
+20 -22
drivers/gpu/drm/drm_plane.c
··· 558 558 } 559 559 560 560 /* 561 - * setplane_internal - setplane handler for internal callers 561 + * __setplane_internal - setplane handler for internal callers 562 562 * 563 - * Note that we assume an extra reference has already been taken on fb. If the 564 - * update fails, this reference will be dropped before return; if it succeeds, 565 - * the previous framebuffer (if any) will be unreferenced instead. 563 + * This function will take a reference on the new fb for the plane 564 + * on success. 566 565 * 567 566 * src_{x,y,w,h} are provided in 16.16 fixed point format 568 567 */ ··· 629 630 if (!ret) { 630 631 plane->crtc = crtc; 631 632 plane->fb = fb; 632 - fb = NULL; 633 + drm_framebuffer_get(plane->fb); 633 634 } else { 634 635 plane->old_fb = NULL; 635 636 } 636 637 637 638 out: 638 - if (fb) 639 - drm_framebuffer_put(fb); 640 639 if (plane->old_fb) 641 640 drm_framebuffer_put(plane->old_fb); 642 641 plane->old_fb = NULL; ··· 682 685 struct drm_plane *plane; 683 686 struct drm_crtc *crtc = NULL; 684 687 struct drm_framebuffer *fb = NULL; 688 + int ret; 685 689 686 690 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 687 691 return -EINVAL; ··· 715 717 } 716 718 } 717 719 718 - /* 719 - * setplane_internal will take care of deref'ing either the old or new 720 - * framebuffer depending on success. 721 - */ 722 - return setplane_internal(plane, crtc, fb, 723 - plane_req->crtc_x, plane_req->crtc_y, 724 - plane_req->crtc_w, plane_req->crtc_h, 725 - plane_req->src_x, plane_req->src_y, 726 - plane_req->src_w, plane_req->src_h); 720 + ret = setplane_internal(plane, crtc, fb, 721 + plane_req->crtc_x, plane_req->crtc_y, 722 + plane_req->crtc_w, plane_req->crtc_h, 723 + plane_req->src_x, plane_req->src_y, 724 + plane_req->src_w, plane_req->src_h); 725 + 726 + if (fb) 727 + drm_framebuffer_put(fb); 728 + 729 + return ret; 727 730 } 728 731 729 732 static int drm_mode_cursor_universal(struct drm_crtc *crtc, ··· 787 788 src_h = fb->height << 16; 788 789 } 789 790 790 - /* 791 - * setplane_internal will take care of deref'ing either the old or new 792 - * framebuffer depending on success. 793 - */ 794 791 ret = __setplane_internal(crtc->cursor, crtc, fb, 795 - crtc_x, crtc_y, crtc_w, crtc_h, 796 - 0, 0, src_w, src_h, ctx); 792 + crtc_x, crtc_y, crtc_w, crtc_h, 793 + 0, 0, src_w, src_h, ctx); 794 + 795 + if (fb) 796 + drm_framebuffer_put(fb); 797 797 798 798 /* Update successful; save new cursor position, if necessary */ 799 799 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
+20
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
··· 175 175 writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); 176 176 } 177 177 178 + static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder, 179 + const struct drm_display_mode *mode) 180 + { 181 + struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 182 + unsigned long rate = mode->clock * 1000; 183 + unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */ 184 + long rounded_rate; 185 + 186 + /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */ 187 + if (rate > 165000000) 188 + return MODE_CLOCK_HIGH; 189 + rounded_rate = clk_round_rate(hdmi->tmds_clk, rate); 190 + if (rounded_rate > 0 && 191 + max_t(unsigned long, rounded_rate, rate) - 192 + min_t(unsigned long, rounded_rate, rate) < diff) 193 + return MODE_OK; 194 + return MODE_NOCLOCK; 195 + } 196 + 178 197 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { 179 198 .atomic_check = sun4i_hdmi_atomic_check, 180 199 .disable = sun4i_hdmi_disable, 181 200 .enable = sun4i_hdmi_enable, 182 201 .mode_set = sun4i_hdmi_mode_set, 202 + .mode_valid = sun4i_hdmi_mode_valid, 183 203 }; 184 204 185 205 static const struct drm_encoder_funcs sun4i_hdmi_funcs = {
+2 -2
drivers/gpu/drm/sun4i/sun4i_tcon.c
··· 724 724 if (IS_ERR(tcon->crtc)) { 725 725 dev_err(dev, "Couldn't create our CRTC\n"); 726 726 ret = PTR_ERR(tcon->crtc); 727 - goto err_free_clocks; 727 + goto err_free_dotclock; 728 728 } 729 729 730 730 ret = sun4i_rgb_init(drm, tcon); 731 731 if (ret < 0) 732 - goto err_free_clocks; 732 + goto err_free_dotclock; 733 733 734 734 if (tcon->quirks->needs_de_be_mux) { 735 735 /*