Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: Clean up reference counting and pinning of the cursor BOs

Take a GEM reference for and pin the new cursor BO, unpin and drop the
GEM reference for the old cursor BO in radeon_crtc_cursor_set2, and use
radeon_crtc->cursor_addr in radeon_set_cursor.

This fixes radeon_cursor_reset accidentally incrementing the cursor BO
pin count, and cleans up the code a little.

Cc: stable@vger.kernel.org
Reviewed-by: Grigori Goronzy <greg@chown.ath.cx>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Michel Dänzer and committed by
Alex Deucher
cd404af0 866a9204

+37 -48
+37 -47
drivers/gpu/drm/radeon/radeon_cursor.c
··· 205 205 | (x << 16) 206 206 | y)); 207 207 /* offset is from DISP(2)_BASE_ADDRESS */ 208 - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + 209 - (yorigin * 256))); 208 + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, 209 + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr + 210 + yorigin * 256); 210 211 } 211 212 212 213 radeon_crtc->cursor_x = x; ··· 228 227 return ret; 229 228 } 230 229 231 - static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) 230 + static void radeon_set_cursor(struct drm_crtc *crtc) 232 231 { 233 232 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 234 233 struct radeon_device *rdev = crtc->dev->dev_private; 235 - struct radeon_bo *robj = gem_to_radeon_bo(obj); 236 - uint64_t gpu_addr; 237 - int ret; 238 - 239 - ret = radeon_bo_reserve(robj, false); 240 - if (unlikely(ret != 0)) 241 - goto fail; 242 - /* Only 27 bit offset for legacy cursor */ 243 - ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, 244 - ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, 245 - &gpu_addr); 246 - radeon_bo_unreserve(robj); 247 - if (ret) 248 - goto fail; 249 234 250 235 if (ASIC_IS_DCE4(rdev)) { 251 236 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 252 - upper_32_bits(gpu_addr)); 237 + upper_32_bits(radeon_crtc->cursor_addr)); 253 238 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 254 - gpu_addr & 0xffffffff); 239 + lower_32_bits(radeon_crtc->cursor_addr)); 255 240 } else if (ASIC_IS_AVIVO(rdev)) { 256 241 if (rdev->family >= CHIP_RV770) { 257 242 if (radeon_crtc->crtc_id) 258 - WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); 243 + WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 244 + upper_32_bits(radeon_crtc->cursor_addr)); 259 245 else 260 - WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); 246 + WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 247 + upper_32_bits(radeon_crtc->cursor_addr)); 261 248 } 262 249 WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 263 - gpu_addr & 0xffffffff); 250 + lower_32_bits(radeon_crtc->cursor_addr)); 264 251 } else { 265 - radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; 266 252 /* offset is from DISP(2)_BASE_ADDRESS */ 267 - WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); 253 + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, 254 + radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr); 268 255 } 269 - 270 - return 0; 271 - 272 - fail: 273 - drm_gem_object_unreference_unlocked(obj); 274 - 275 - return ret; 276 256 } 277 257 278 258 int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ··· 265 283 int32_t hot_y) 266 284 { 267 285 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 286 + struct radeon_device *rdev = crtc->dev->dev_private; 268 287 struct drm_gem_object *obj; 288 + struct radeon_bo *robj; 269 289 int ret; 270 290 271 291 if (!handle) { ··· 289 305 return -ENOENT; 290 306 } 291 307 308 + robj = gem_to_radeon_bo(obj); 309 + ret = radeon_bo_reserve(robj, false); 310 + if (ret != 0) { 311 + drm_gem_object_unreference_unlocked(obj); 312 + return ret; 313 + } 314 + /* Only 27 bit offset for legacy cursor */ 315 + ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, 316 + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, 317 + &radeon_crtc->cursor_addr); 318 + radeon_bo_unreserve(robj); 319 + if (ret) { 320 + DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret); 321 + drm_gem_object_unreference_unlocked(obj); 322 + return ret; 323 + } 324 + 292 325 radeon_crtc->cursor_width = width; 293 326 radeon_crtc->cursor_height = height; 294 327 ··· 324 323 radeon_crtc->cursor_hot_y = hot_y; 325 324 } 326 325 327 - ret = radeon_set_cursor(crtc, obj); 328 - 329 - if (ret) 330 - DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n", 331 - ret); 332 - else 333 - radeon_show_cursor(crtc); 326 + radeon_set_cursor(crtc); 327 + radeon_show_cursor(crtc); 334 328 335 329 radeon_lock_cursor(crtc, false); 336 330 ··· 337 341 radeon_bo_unpin(robj); 338 342 radeon_bo_unreserve(robj); 339 343 } 340 - if (radeon_crtc->cursor_bo != obj) 341 - drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); 344 + drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); 342 345 } 343 346 344 347 radeon_crtc->cursor_bo = obj; ··· 355 360 void radeon_cursor_reset(struct drm_crtc *crtc) 356 361 { 357 362 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 358 - int ret; 359 363 360 364 if (radeon_crtc->cursor_bo) { 361 365 radeon_lock_cursor(crtc, true); ··· 362 368 radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, 363 369 radeon_crtc->cursor_y); 364 370 365 - ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); 366 - if (ret) 367 - DRM_ERROR("radeon_set_cursor returned %d, not showing " 368 - "cursor\n", ret); 369 - else 370 - radeon_show_cursor(crtc); 371 + radeon_set_cursor(crtc); 372 + radeon_show_cursor(crtc); 371 373 372 374 radeon_lock_cursor(crtc, false); 373 375 }
-1
drivers/gpu/drm/radeon/radeon_mode.h
··· 343 343 int max_cursor_width; 344 344 int max_cursor_height; 345 345 uint32_t legacy_display_base_addr; 346 - uint32_t legacy_cursor_offset; 347 346 enum radeon_rmx_type rmx_type; 348 347 u8 h_border; 349 348 u8 v_border;