diff options
32 files changed, 849 insertions, 512 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3963b3c1081a..4231d6db72ec 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -1020,6 +1020,9 @@ bool drm_helper_initial_config(struct drm_device *dev) | |||
| 1020 | { | 1020 | { |
| 1021 | int count = 0; | 1021 | int count = 0; |
| 1022 | 1022 | ||
| 1023 | /* disable all the possible outputs/crtcs before entering KMS mode */ | ||
| 1024 | drm_helper_disable_unused_functions(dev); | ||
| 1025 | |||
| 1023 | drm_fb_helper_parse_command_line(dev); | 1026 | drm_fb_helper_parse_command_line(dev); |
| 1024 | 1027 | ||
| 1025 | count = drm_helper_probe_connector_modes(dev, | 1028 | count = drm_helper_probe_connector_modes(dev, |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 1f0d717dbad6..d7d7eac3ddd2 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, | |||
| 226 | } | 226 | } |
| 227 | EXPORT_SYMBOL(drm_mm_get_block_generic); | 227 | EXPORT_SYMBOL(drm_mm_get_block_generic); |
| 228 | 228 | ||
| 229 | struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node, | ||
| 230 | unsigned long size, | ||
| 231 | unsigned alignment, | ||
| 232 | unsigned long start, | ||
| 233 | unsigned long end, | ||
| 234 | int atomic) | ||
| 235 | { | ||
| 236 | struct drm_mm_node *align_splitoff = NULL; | ||
| 237 | unsigned tmp = 0; | ||
| 238 | unsigned wasted = 0; | ||
| 239 | |||
| 240 | if (node->start < start) | ||
| 241 | wasted += start - node->start; | ||
| 242 | if (alignment) | ||
| 243 | tmp = ((node->start + wasted) % alignment); | ||
| 244 | |||
| 245 | if (tmp) | ||
| 246 | wasted += alignment - tmp; | ||
| 247 | if (wasted) { | ||
| 248 | align_splitoff = drm_mm_split_at_start(node, wasted, atomic); | ||
| 249 | if (unlikely(align_splitoff == NULL)) | ||
| 250 | return NULL; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (node->size == size) { | ||
| 254 | list_del_init(&node->fl_entry); | ||
| 255 | node->free = 0; | ||
| 256 | } else { | ||
| 257 | node = drm_mm_split_at_start(node, size, atomic); | ||
| 258 | } | ||
| 259 | |||
| 260 | if (align_splitoff) | ||
| 261 | drm_mm_put_block(align_splitoff); | ||
| 262 | |||
| 263 | return node; | ||
| 264 | } | ||
| 265 | EXPORT_SYMBOL(drm_mm_get_block_range_generic); | ||
| 266 | |||
| 229 | /* | 267 | /* |
| 230 | * Put a block. Merge with the previous and / or next block if they are free. | 268 | * Put a block. Merge with the previous and / or next block if they are free. |
| 231 | * Otherwise add to the free stack. | 269 | * Otherwise add to the free stack. |
| @@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | |||
| 331 | } | 369 | } |
| 332 | EXPORT_SYMBOL(drm_mm_search_free); | 370 | EXPORT_SYMBOL(drm_mm_search_free); |
| 333 | 371 | ||
| 372 | struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, | ||
| 373 | unsigned long size, | ||
| 374 | unsigned alignment, | ||
| 375 | unsigned long start, | ||
| 376 | unsigned long end, | ||
| 377 | int best_match) | ||
| 378 | { | ||
| 379 | struct list_head *list; | ||
| 380 | const struct list_head *free_stack = &mm->fl_entry; | ||
| 381 | struct drm_mm_node *entry; | ||
| 382 | struct drm_mm_node *best; | ||
| 383 | unsigned long best_size; | ||
| 384 | unsigned wasted; | ||
| 385 | |||
| 386 | best = NULL; | ||
| 387 | best_size = ~0UL; | ||
| 388 | |||
| 389 | list_for_each(list, free_stack) { | ||
| 390 | entry = list_entry(list, struct drm_mm_node, fl_entry); | ||
| 391 | wasted = 0; | ||
| 392 | |||
| 393 | if (entry->size < size) | ||
| 394 | continue; | ||
| 395 | |||
| 396 | if (entry->start > end || (entry->start+entry->size) < start) | ||
| 397 | continue; | ||
| 398 | |||
| 399 | if (entry->start < start) | ||
| 400 | wasted += start - entry->start; | ||
| 401 | |||
| 402 | if (alignment) { | ||
| 403 | register unsigned tmp = (entry->start + wasted) % alignment; | ||
| 404 | if (tmp) | ||
| 405 | wasted += alignment - tmp; | ||
| 406 | } | ||
| 407 | |||
| 408 | if (entry->size >= size + wasted) { | ||
| 409 | if (!best_match) | ||
| 410 | return entry; | ||
| 411 | if (size < best_size) { | ||
| 412 | best = entry; | ||
| 413 | best_size = entry->size; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | return best; | ||
| 419 | } | ||
| 420 | EXPORT_SYMBOL(drm_mm_search_free_in_range); | ||
| 421 | |||
| 334 | int drm_mm_clean(struct drm_mm * mm) | 422 | int drm_mm_clean(struct drm_mm * mm) |
| 335 | { | 423 | { |
| 336 | struct list_head *head = &mm->ml_entry; | 424 | struct list_head *head = &mm->ml_entry; |
| @@ -381,6 +469,26 @@ void drm_mm_takedown(struct drm_mm * mm) | |||
| 381 | } | 469 | } |
| 382 | EXPORT_SYMBOL(drm_mm_takedown); | 470 | EXPORT_SYMBOL(drm_mm_takedown); |
| 383 | 471 | ||
| 472 | void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) | ||
| 473 | { | ||
| 474 | struct drm_mm_node *entry; | ||
| 475 | int total_used = 0, total_free = 0, total = 0; | ||
| 476 | |||
| 477 | list_for_each_entry(entry, &mm->ml_entry, ml_entry) { | ||
| 478 | printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n", | ||
| 479 | prefix, entry->start, entry->start + entry->size, | ||
| 480 | entry->size, entry->free ? "free" : "used"); | ||
| 481 | total += entry->size; | ||
| 482 | if (entry->free) | ||
| 483 | total_free += entry->size; | ||
| 484 | else | ||
| 485 | total_used += entry->size; | ||
| 486 | } | ||
| 487 | printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total, | ||
| 488 | total_used, total_free); | ||
| 489 | } | ||
| 490 | EXPORT_SYMBOL(drm_mm_debug_table); | ||
| 491 | |||
| 384 | #if defined(CONFIG_DEBUG_FS) | 492 | #if defined(CONFIG_DEBUG_FS) |
| 385 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) | 493 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) |
| 386 | { | 494 | { |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index fba3c96b915b..260fcf59f00c 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -499,8 +499,18 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
| 499 | else | 499 | else |
| 500 | pll = &rdev->clock.p2pll; | 500 | pll = &rdev->clock.p2pll; |
| 501 | 501 | ||
| 502 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 502 | if (ASIC_IS_AVIVO(rdev)) { |
| 503 | &ref_div, &post_div, pll_flags); | 503 | if (radeon_new_pll) |
| 504 | radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, | ||
| 505 | &fb_div, &frac_fb_div, | ||
| 506 | &ref_div, &post_div, pll_flags); | ||
| 507 | else | ||
| 508 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, | ||
| 509 | &fb_div, &frac_fb_div, | ||
| 510 | &ref_div, &post_div, pll_flags); | ||
| 511 | } else | ||
| 512 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | ||
| 513 | &ref_div, &post_div, pll_flags); | ||
| 504 | 514 | ||
| 505 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | 515 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
| 506 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 516 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
| @@ -599,8 +609,6 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 599 | } | 609 | } |
| 600 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 610 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); |
| 601 | radeon_bo_unreserve(rbo); | 611 | radeon_bo_unreserve(rbo); |
| 602 | if (tiling_flags & RADEON_TILING_MACRO) | ||
| 603 | fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; | ||
| 604 | 612 | ||
| 605 | switch (crtc->fb->bits_per_pixel) { | 613 | switch (crtc->fb->bits_per_pixel) { |
| 606 | case 8: | 614 | case 8: |
| @@ -630,6 +638,9 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
| 630 | return -EINVAL; | 638 | return -EINVAL; |
| 631 | } | 639 | } |
| 632 | 640 | ||
| 641 | if (tiling_flags & RADEON_TILING_MACRO) | ||
| 642 | fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; | ||
| 643 | |||
| 633 | if (tiling_flags & RADEON_TILING_MICRO) | 644 | if (tiling_flags & RADEON_TILING_MICRO) |
| 634 | fb_format |= AVIVO_D1GRPH_TILED; | 645 | fb_format |= AVIVO_D1GRPH_TILED; |
| 635 | 646 | ||
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index b7baf16c11d7..824cc6480a06 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -3299,6 +3299,8 @@ int r100_resume(struct radeon_device *rdev) | |||
| 3299 | radeon_combios_asic_init(rdev->ddev); | 3299 | radeon_combios_asic_init(rdev->ddev); |
| 3300 | /* Resume clock after posting */ | 3300 | /* Resume clock after posting */ |
| 3301 | r100_clock_startup(rdev); | 3301 | r100_clock_startup(rdev); |
| 3302 | /* Initialize surface registers */ | ||
| 3303 | radeon_surface_init(rdev); | ||
| 3302 | return r100_startup(rdev); | 3304 | return r100_startup(rdev); |
| 3303 | } | 3305 | } |
| 3304 | 3306 | ||
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 86065dcc1982..83378c39d0e3 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -1250,6 +1250,8 @@ int r300_resume(struct radeon_device *rdev) | |||
| 1250 | radeon_combios_asic_init(rdev->ddev); | 1250 | radeon_combios_asic_init(rdev->ddev); |
| 1251 | /* Resume clock after posting */ | 1251 | /* Resume clock after posting */ |
| 1252 | r300_clock_startup(rdev); | 1252 | r300_clock_startup(rdev); |
| 1253 | /* Initialize surface registers */ | ||
| 1254 | radeon_surface_init(rdev); | ||
| 1253 | return r300_startup(rdev); | 1255 | return r300_startup(rdev); |
| 1254 | } | 1256 | } |
| 1255 | 1257 | ||
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 162c3902fe69..c05a7270cf0c 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -231,7 +231,8 @@ int r420_resume(struct radeon_device *rdev) | |||
| 231 | } | 231 | } |
| 232 | /* Resume clock after posting */ | 232 | /* Resume clock after posting */ |
| 233 | r420_clock_resume(rdev); | 233 | r420_clock_resume(rdev); |
| 234 | 234 | /* Initialize surface registers */ | |
| 235 | radeon_surface_init(rdev); | ||
| 235 | return r420_startup(rdev); | 236 | return r420_startup(rdev); |
| 236 | } | 237 | } |
| 237 | 238 | ||
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 788eef5c2a08..0f3843b6dac7 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c | |||
| @@ -220,6 +220,8 @@ int r520_resume(struct radeon_device *rdev) | |||
| 220 | atom_asic_init(rdev->mode_info.atom_context); | 220 | atom_asic_init(rdev->mode_info.atom_context); |
| 221 | /* Resume clock after posting */ | 221 | /* Resume clock after posting */ |
| 222 | rv515_clock_startup(rdev); | 222 | rv515_clock_startup(rdev); |
| 223 | /* Initialize surface registers */ | ||
| 224 | radeon_surface_init(rdev); | ||
| 223 | return r520_startup(rdev); | 225 | return r520_startup(rdev); |
| 224 | } | 226 | } |
| 225 | 227 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 250ec3fe1a16..f5cf874dc62a 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -1845,6 +1845,14 @@ int r600_startup(struct radeon_device *rdev) | |||
| 1845 | { | 1845 | { |
| 1846 | int r; | 1846 | int r; |
| 1847 | 1847 | ||
| 1848 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
| 1849 | r = r600_init_microcode(rdev); | ||
| 1850 | if (r) { | ||
| 1851 | DRM_ERROR("Failed to load firmware!\n"); | ||
| 1852 | return r; | ||
| 1853 | } | ||
| 1854 | } | ||
| 1855 | |||
| 1848 | r600_mc_program(rdev); | 1856 | r600_mc_program(rdev); |
| 1849 | if (rdev->flags & RADEON_IS_AGP) { | 1857 | if (rdev->flags & RADEON_IS_AGP) { |
| 1850 | r600_agp_enable(rdev); | 1858 | r600_agp_enable(rdev); |
| @@ -2026,25 +2034,17 @@ int r600_init(struct radeon_device *rdev) | |||
| 2026 | rdev->ih.ring_obj = NULL; | 2034 | rdev->ih.ring_obj = NULL; |
| 2027 | r600_ih_ring_init(rdev, 64 * 1024); | 2035 | r600_ih_ring_init(rdev, 64 * 1024); |
| 2028 | 2036 | ||
| 2029 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
| 2030 | r = r600_init_microcode(rdev); | ||
| 2031 | if (r) { | ||
| 2032 | DRM_ERROR("Failed to load firmware!\n"); | ||
| 2033 | return r; | ||
| 2034 | } | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | r = r600_pcie_gart_init(rdev); | 2037 | r = r600_pcie_gart_init(rdev); |
| 2038 | if (r) | 2038 | if (r) |
| 2039 | return r; | 2039 | return r; |
| 2040 | 2040 | ||
| 2041 | rdev->accel_working = true; | ||
| 2042 | r = r600_blit_init(rdev); | 2041 | r = r600_blit_init(rdev); |
| 2043 | if (r) { | 2042 | if (r) { |
| 2044 | DRM_ERROR("radeon: failled blitter (%d).\n", r); | 2043 | DRM_ERROR("radeon: failed blitter (%d).\n", r); |
| 2045 | return r; | 2044 | return r; |
| 2046 | } | 2045 | } |
| 2047 | 2046 | ||
| 2047 | rdev->accel_working = true; | ||
| 2048 | r = r600_startup(rdev); | 2048 | r = r600_startup(rdev); |
| 2049 | if (r) { | 2049 | if (r) { |
| 2050 | r600_suspend(rdev); | 2050 | r600_suspend(rdev); |
| @@ -2056,12 +2056,12 @@ int r600_init(struct radeon_device *rdev) | |||
| 2056 | if (rdev->accel_working) { | 2056 | if (rdev->accel_working) { |
| 2057 | r = radeon_ib_pool_init(rdev); | 2057 | r = radeon_ib_pool_init(rdev); |
| 2058 | if (r) { | 2058 | if (r) { |
| 2059 | DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); | 2059 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); |
| 2060 | rdev->accel_working = false; | 2060 | rdev->accel_working = false; |
| 2061 | } | 2061 | } |
| 2062 | r = r600_ib_test(rdev); | 2062 | r = r600_ib_test(rdev); |
| 2063 | if (r) { | 2063 | if (r) { |
| 2064 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | 2064 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); |
| 2065 | rdev->accel_working = false; | 2065 | rdev->accel_working = false; |
| 2066 | } | 2066 | } |
| 2067 | } | 2067 | } |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a15cf9ceb9a7..c938bb54123c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -88,6 +88,7 @@ extern int radeon_benchmarking; | |||
| 88 | extern int radeon_testing; | 88 | extern int radeon_testing; |
| 89 | extern int radeon_connector_table; | 89 | extern int radeon_connector_table; |
| 90 | extern int radeon_tv; | 90 | extern int radeon_tv; |
| 91 | extern int radeon_new_pll; | ||
| 91 | 92 | ||
| 92 | /* | 93 | /* |
| 93 | * Copy from radeon_drv.h so we don't have to include both and have conflicting | 94 | * Copy from radeon_drv.h so we don't have to include both and have conflicting |
| @@ -208,6 +209,8 @@ struct radeon_bo { | |||
| 208 | /* Protected by gem.mutex */ | 209 | /* Protected by gem.mutex */ |
| 209 | struct list_head list; | 210 | struct list_head list; |
| 210 | /* Protected by tbo.reserved */ | 211 | /* Protected by tbo.reserved */ |
| 212 | u32 placements[3]; | ||
| 213 | struct ttm_placement placement; | ||
| 211 | struct ttm_buffer_object tbo; | 214 | struct ttm_buffer_object tbo; |
| 212 | struct ttm_bo_kmap_obj kmap; | 215 | struct ttm_bo_kmap_obj kmap; |
| 213 | unsigned pin_count; | 216 | unsigned pin_count; |
| @@ -1012,6 +1015,7 @@ extern void radeon_surface_init(struct radeon_device *rdev); | |||
| 1012 | extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); | 1015 | extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); |
| 1013 | extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); | 1016 | extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); |
| 1014 | extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); | 1017 | extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); |
| 1018 | extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); | ||
| 1015 | 1019 | ||
| 1016 | /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ | 1020 | /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ |
| 1017 | struct r100_mc_save { | 1021 | struct r100_mc_save { |
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index d7b0feb7d47f..12a0c760e7ff 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -70,6 +70,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
| 70 | int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); | 70 | int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); |
| 71 | struct _ATOM_GPIO_I2C_INFO *i2c_info; | 71 | struct _ATOM_GPIO_I2C_INFO *i2c_info; |
| 72 | uint16_t data_offset; | 72 | uint16_t data_offset; |
| 73 | int i; | ||
| 73 | 74 | ||
| 74 | memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); | 75 | memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); |
| 75 | i2c.valid = false; | 76 | i2c.valid = false; |
| @@ -78,38 +79,43 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev | |||
| 78 | 79 | ||
| 79 | i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); | 80 | i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); |
| 80 | 81 | ||
| 81 | gpio = &i2c_info->asGPIO_Info[id]; | ||
| 82 | |||
| 83 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | ||
| 84 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | ||
| 85 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; | ||
| 86 | i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; | ||
| 87 | i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; | ||
| 88 | i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; | ||
| 89 | i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; | ||
| 90 | i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; | ||
| 91 | i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); | ||
| 92 | i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); | ||
| 93 | i2c.en_clk_mask = (1 << gpio->ucClkEnShift); | ||
| 94 | i2c.en_data_mask = (1 << gpio->ucDataEnShift); | ||
| 95 | i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); | ||
| 96 | i2c.y_data_mask = (1 << gpio->ucDataY_Shift); | ||
| 97 | i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); | ||
| 98 | i2c.a_data_mask = (1 << gpio->ucDataA_Shift); | ||
| 99 | |||
| 100 | if (gpio->sucI2cId.sbfAccess.bfHW_Capable) | ||
| 101 | i2c.hw_capable = true; | ||
| 102 | else | ||
| 103 | i2c.hw_capable = false; | ||
| 104 | 82 | ||
| 105 | if (gpio->sucI2cId.ucAccess == 0xa0) | 83 | for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { |
| 106 | i2c.mm_i2c = true; | 84 | gpio = &i2c_info->asGPIO_Info[i]; |
| 107 | else | 85 | |
| 108 | i2c.mm_i2c = false; | 86 | if (gpio->sucI2cId.ucAccess == id) { |
| 87 | i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; | ||
| 88 | i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; | ||
| 89 | i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; | ||
| 90 | i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4; | ||
| 91 | i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4; | ||
| 92 | i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4; | ||
| 93 | i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4; | ||
| 94 | i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4; | ||
| 95 | i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift); | ||
| 96 | i2c.mask_data_mask = (1 << gpio->ucDataMaskShift); | ||
| 97 | i2c.en_clk_mask = (1 << gpio->ucClkEnShift); | ||
| 98 | i2c.en_data_mask = (1 << gpio->ucDataEnShift); | ||
| 99 | i2c.y_clk_mask = (1 << gpio->ucClkY_Shift); | ||
| 100 | i2c.y_data_mask = (1 << gpio->ucDataY_Shift); | ||
| 101 | i2c.a_clk_mask = (1 << gpio->ucClkA_Shift); | ||
| 102 | i2c.a_data_mask = (1 << gpio->ucDataA_Shift); | ||
| 103 | |||
| 104 | if (gpio->sucI2cId.sbfAccess.bfHW_Capable) | ||
| 105 | i2c.hw_capable = true; | ||
| 106 | else | ||
| 107 | i2c.hw_capable = false; | ||
| 109 | 108 | ||
| 110 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | 109 | if (gpio->sucI2cId.ucAccess == 0xa0) |
| 110 | i2c.mm_i2c = true; | ||
| 111 | else | ||
| 112 | i2c.mm_i2c = false; | ||
| 113 | |||
| 114 | i2c.i2c_id = gpio->sucI2cId.ucAccess; | ||
| 111 | 115 | ||
| 112 | i2c.valid = true; | 116 | i2c.valid = true; |
| 117 | } | ||
| 118 | } | ||
| 113 | 119 | ||
| 114 | return i2c; | 120 | return i2c; |
| 115 | } | 121 | } |
| @@ -503,6 +509,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 503 | usRecordOffset)); | 509 | usRecordOffset)); |
| 504 | ATOM_I2C_RECORD *i2c_record; | 510 | ATOM_I2C_RECORD *i2c_record; |
| 505 | ATOM_HPD_INT_RECORD *hpd_record; | 511 | ATOM_HPD_INT_RECORD *hpd_record; |
| 512 | ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; | ||
| 506 | hpd.hpd = RADEON_HPD_NONE; | 513 | hpd.hpd = RADEON_HPD_NONE; |
| 507 | 514 | ||
| 508 | while (record->ucRecordType > 0 | 515 | while (record->ucRecordType > 0 |
| @@ -514,10 +521,12 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | |||
| 514 | i2c_record = | 521 | i2c_record = |
| 515 | (ATOM_I2C_RECORD *) | 522 | (ATOM_I2C_RECORD *) |
| 516 | record; | 523 | record; |
| 524 | i2c_config = | ||
| 525 | (ATOM_I2C_ID_CONFIG_ACCESS *) | ||
| 526 | &i2c_record->sucI2cId; | ||
| 517 | ddc_bus = radeon_lookup_i2c_gpio(rdev, | 527 | ddc_bus = radeon_lookup_i2c_gpio(rdev, |
| 518 | i2c_record-> | 528 | i2c_config-> |
| 519 | sucI2cId. | 529 | ucAccess); |
| 520 | bfI2C_LineMux); | ||
| 521 | break; | 530 | break; |
| 522 | case ATOM_HPD_INT_RECORD_TYPE: | 531 | case ATOM_HPD_INT_RECORD_TYPE: |
| 523 | hpd_record = | 532 | hpd_record = |
| @@ -670,22 +679,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
| 670 | 679 | ||
| 671 | dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; | 680 | dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; |
| 672 | 681 | ||
| 673 | if ((rdev->family == CHIP_RS690) || | 682 | bios_connectors[i].line_mux = |
| 674 | (rdev->family == CHIP_RS740)) { | 683 | ci.sucI2cId.ucAccess; |
| 675 | if ((i == ATOM_DEVICE_DFP2_INDEX) | ||
| 676 | && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2)) | ||
| 677 | bios_connectors[i].line_mux = | ||
| 678 | ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; | ||
| 679 | else if ((i == ATOM_DEVICE_DFP3_INDEX) | ||
| 680 | && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1)) | ||
| 681 | bios_connectors[i].line_mux = | ||
| 682 | ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; | ||
| 683 | else | ||
| 684 | bios_connectors[i].line_mux = | ||
| 685 | ci.sucI2cId.sbfAccess.bfI2C_LineMux; | ||
| 686 | } else | ||
| 687 | bios_connectors[i].line_mux = | ||
| 688 | ci.sucI2cId.sbfAccess.bfI2C_LineMux; | ||
| 689 | 684 | ||
| 690 | /* give tv unique connector ids */ | 685 | /* give tv unique connector ids */ |
| 691 | if (i == ATOM_DEVICE_TV1_INDEX) { | 686 | if (i == ATOM_DEVICE_TV1_INDEX) { |
| @@ -876,7 +871,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) | |||
| 876 | * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per | 871 | * pre-DCE 3.0 r6xx hardware. This might need to be adjusted per |
| 877 | * family. | 872 | * family. |
| 878 | */ | 873 | */ |
| 879 | p1pll->pll_out_min = 64800; | 874 | if (!radeon_new_pll) |
| 875 | p1pll->pll_out_min = 64800; | ||
| 880 | } | 876 | } |
| 881 | 877 | ||
| 882 | p1pll->pll_in_min = | 878 | p1pll->pll_in_min = |
| @@ -1006,6 +1002,7 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | |||
| 1006 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; | 1002 | struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info; |
| 1007 | uint8_t frev, crev; | 1003 | uint8_t frev, crev; |
| 1008 | struct radeon_atom_ss *ss = NULL; | 1004 | struct radeon_atom_ss *ss = NULL; |
| 1005 | int i; | ||
| 1009 | 1006 | ||
| 1010 | if (id > ATOM_MAX_SS_ENTRY) | 1007 | if (id > ATOM_MAX_SS_ENTRY) |
| 1011 | return NULL; | 1008 | return NULL; |
| @@ -1023,12 +1020,17 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct | |||
| 1023 | if (!ss) | 1020 | if (!ss) |
| 1024 | return NULL; | 1021 | return NULL; |
| 1025 | 1022 | ||
| 1026 | ss->percentage = le16_to_cpu(ss_info->asSS_Info[id].usSpreadSpectrumPercentage); | 1023 | for (i = 0; i < ATOM_MAX_SS_ENTRY; i++) { |
| 1027 | ss->type = ss_info->asSS_Info[id].ucSpreadSpectrumType; | 1024 | if (ss_info->asSS_Info[i].ucSS_Id == id) { |
| 1028 | ss->step = ss_info->asSS_Info[id].ucSS_Step; | 1025 | ss->percentage = |
| 1029 | ss->delay = ss_info->asSS_Info[id].ucSS_Delay; | 1026 | le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage); |
| 1030 | ss->range = ss_info->asSS_Info[id].ucSS_Range; | 1027 | ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType; |
| 1031 | ss->refdiv = ss_info->asSS_Info[id].ucRecommendedRef_Div; | 1028 | ss->step = ss_info->asSS_Info[i].ucSS_Step; |
| 1029 | ss->delay = ss_info->asSS_Info[i].ucSS_Delay; | ||
| 1030 | ss->range = ss_info->asSS_Info[i].ucSS_Range; | ||
| 1031 | ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; | ||
| 1032 | } | ||
| 1033 | } | ||
| 1032 | } | 1034 | } |
| 1033 | return ss; | 1035 | return ss; |
| 1034 | } | 1036 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index cfa2ebb259fe..5eece186e03c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -1103,10 +1103,12 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1103 | drm_connector_attach_property(&radeon_connector->base, | 1103 | drm_connector_attach_property(&radeon_connector->base, |
| 1104 | rdev->mode_info.coherent_mode_property, | 1104 | rdev->mode_info.coherent_mode_property, |
| 1105 | 1); | 1105 | 1); |
| 1106 | radeon_connector->dac_load_detect = true; | 1106 | if (connector_type == DRM_MODE_CONNECTOR_DVII) { |
| 1107 | drm_connector_attach_property(&radeon_connector->base, | 1107 | radeon_connector->dac_load_detect = true; |
| 1108 | rdev->mode_info.load_detect_property, | 1108 | drm_connector_attach_property(&radeon_connector->base, |
| 1109 | 1); | 1109 | rdev->mode_info.load_detect_property, |
| 1110 | 1); | ||
| 1111 | } | ||
| 1110 | break; | 1112 | break; |
| 1111 | case DRM_MODE_CONNECTOR_HDMIA: | 1113 | case DRM_MODE_CONNECTOR_HDMIA: |
| 1112 | case DRM_MODE_CONNECTOR_HDMIB: | 1114 | case DRM_MODE_CONNECTOR_HDMIB: |
| @@ -1141,14 +1143,19 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1141 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); | 1143 | ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); |
| 1142 | if (ret) | 1144 | if (ret) |
| 1143 | goto failed; | 1145 | goto failed; |
| 1144 | /* add DP i2c bus */ | ||
| 1145 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | ||
| 1146 | if (i2c_bus->valid) { | 1146 | if (i2c_bus->valid) { |
| 1147 | /* add DP i2c bus */ | ||
| 1148 | radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); | ||
| 1149 | if (!radeon_dig_connector->dp_i2c_bus) | ||
| 1150 | goto failed; | ||
| 1147 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); | 1151 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); |
| 1148 | if (!radeon_connector->ddc_bus) | 1152 | if (!radeon_connector->ddc_bus) |
| 1149 | goto failed; | 1153 | goto failed; |
| 1150 | } | 1154 | } |
| 1151 | subpixel_order = SubPixelHorizontalRGB; | 1155 | subpixel_order = SubPixelHorizontalRGB; |
| 1156 | drm_connector_attach_property(&radeon_connector->base, | ||
| 1157 | rdev->mode_info.coherent_mode_property, | ||
| 1158 | 1); | ||
| 1152 | break; | 1159 | break; |
| 1153 | case DRM_MODE_CONNECTOR_SVIDEO: | 1160 | case DRM_MODE_CONNECTOR_SVIDEO: |
| 1154 | case DRM_MODE_CONNECTOR_Composite: | 1161 | case DRM_MODE_CONNECTOR_Composite: |
| @@ -1183,7 +1190,6 @@ radeon_add_atom_connector(struct drm_device *dev, | |||
| 1183 | if (!radeon_connector->ddc_bus) | 1190 | if (!radeon_connector->ddc_bus) |
| 1184 | goto failed; | 1191 | goto failed; |
| 1185 | } | 1192 | } |
| 1186 | drm_mode_create_scaling_mode_property(dev); | ||
| 1187 | drm_connector_attach_property(&radeon_connector->base, | 1193 | drm_connector_attach_property(&radeon_connector->base, |
| 1188 | dev->mode_config.scaling_mode_property, | 1194 | dev->mode_config.scaling_mode_property, |
| 1189 | DRM_MODE_SCALE_FULLSCREEN); | 1195 | DRM_MODE_SCALE_FULLSCREEN); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7e55647f118e..02bcdb1240c0 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -44,10 +44,11 @@ void radeon_surface_init(struct radeon_device *rdev) | |||
| 44 | if (rdev->family < CHIP_R600) { | 44 | if (rdev->family < CHIP_R600) { |
| 45 | int i; | 45 | int i; |
| 46 | 46 | ||
| 47 | for (i = 0; i < 8; i++) { | 47 | for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) { |
| 48 | WREG32(RADEON_SURFACE0_INFO + | 48 | if (rdev->surface_regs[i].bo) |
| 49 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | 49 | radeon_bo_get_surface_reg(rdev->surface_regs[i].bo); |
| 50 | 0); | 50 | else |
| 51 | radeon_clear_surface_reg(rdev, i); | ||
| 51 | } | 52 | } |
| 52 | /* enable surfaces */ | 53 | /* enable surfaces */ |
| 53 | WREG32(RADEON_SURFACE_CNTL, 0); | 54 | WREG32(RADEON_SURFACE_CNTL, 0); |
| @@ -487,8 +488,10 @@ int radeon_atombios_init(struct radeon_device *rdev) | |||
| 487 | 488 | ||
| 488 | void radeon_atombios_fini(struct radeon_device *rdev) | 489 | void radeon_atombios_fini(struct radeon_device *rdev) |
| 489 | { | 490 | { |
| 490 | kfree(rdev->mode_info.atom_context->scratch); | 491 | if (rdev->mode_info.atom_context) { |
| 491 | kfree(rdev->mode_info.atom_context); | 492 | kfree(rdev->mode_info.atom_context->scratch); |
| 493 | kfree(rdev->mode_info.atom_context); | ||
| 494 | } | ||
| 492 | kfree(rdev->mode_info.atom_card_info); | 495 | kfree(rdev->mode_info.atom_card_info); |
| 493 | } | 496 | } |
| 494 | 497 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c115f2e442eb..a133b833e45d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -560,6 +560,98 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
| 560 | *post_div_p = best_post_div; | 560 | *post_div_p = best_post_div; |
| 561 | } | 561 | } |
| 562 | 562 | ||
| 563 | void radeon_compute_pll_avivo(struct radeon_pll *pll, | ||
| 564 | uint64_t freq, | ||
| 565 | uint32_t *dot_clock_p, | ||
| 566 | uint32_t *fb_div_p, | ||
| 567 | uint32_t *frac_fb_div_p, | ||
| 568 | uint32_t *ref_div_p, | ||
| 569 | uint32_t *post_div_p, | ||
| 570 | int flags) | ||
| 571 | { | ||
| 572 | fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; | ||
| 573 | fixed20_12 pll_out_max, pll_out_min; | ||
| 574 | fixed20_12 pll_in_max, pll_in_min; | ||
| 575 | fixed20_12 reference_freq; | ||
| 576 | fixed20_12 error, ffreq, a, b; | ||
| 577 | |||
| 578 | pll_out_max.full = rfixed_const(pll->pll_out_max); | ||
| 579 | pll_out_min.full = rfixed_const(pll->pll_out_min); | ||
| 580 | pll_in_max.full = rfixed_const(pll->pll_in_max); | ||
| 581 | pll_in_min.full = rfixed_const(pll->pll_in_min); | ||
| 582 | reference_freq.full = rfixed_const(pll->reference_freq); | ||
| 583 | do_div(freq, 10); | ||
| 584 | ffreq.full = rfixed_const(freq); | ||
| 585 | error.full = rfixed_const(100 * 100); | ||
| 586 | |||
| 587 | /* max p */ | ||
| 588 | p.full = rfixed_div(pll_out_max, ffreq); | ||
| 589 | p.full = rfixed_floor(p); | ||
| 590 | |||
| 591 | /* min m */ | ||
| 592 | m.full = rfixed_div(reference_freq, pll_in_max); | ||
| 593 | m.full = rfixed_ceil(m); | ||
| 594 | |||
| 595 | while (1) { | ||
| 596 | n.full = rfixed_div(ffreq, reference_freq); | ||
| 597 | n.full = rfixed_mul(n, m); | ||
| 598 | n.full = rfixed_mul(n, p); | ||
| 599 | |||
| 600 | f_vco.full = rfixed_div(n, m); | ||
| 601 | f_vco.full = rfixed_mul(f_vco, reference_freq); | ||
| 602 | |||
| 603 | f_pclk.full = rfixed_div(f_vco, p); | ||
| 604 | |||
| 605 | if (f_pclk.full > ffreq.full) | ||
| 606 | error.full = f_pclk.full - ffreq.full; | ||
| 607 | else | ||
| 608 | error.full = ffreq.full - f_pclk.full; | ||
| 609 | error.full = rfixed_div(error, f_pclk); | ||
| 610 | a.full = rfixed_const(100 * 100); | ||
| 611 | error.full = rfixed_mul(error, a); | ||
| 612 | |||
| 613 | a.full = rfixed_mul(m, p); | ||
| 614 | a.full = rfixed_div(n, a); | ||
| 615 | best_freq.full = rfixed_mul(reference_freq, a); | ||
| 616 | |||
| 617 | if (rfixed_trunc(error) < 25) | ||
| 618 | break; | ||
| 619 | |||
| 620 | a.full = rfixed_const(1); | ||
| 621 | m.full = m.full + a.full; | ||
| 622 | a.full = rfixed_div(reference_freq, m); | ||
| 623 | if (a.full >= pll_in_min.full) | ||
| 624 | continue; | ||
| 625 | |||
| 626 | m.full = rfixed_div(reference_freq, pll_in_max); | ||
| 627 | m.full = rfixed_ceil(m); | ||
| 628 | a.full= rfixed_const(1); | ||
| 629 | p.full = p.full - a.full; | ||
| 630 | a.full = rfixed_mul(p, ffreq); | ||
| 631 | if (a.full >= pll_out_min.full) | ||
| 632 | continue; | ||
| 633 | else { | ||
| 634 | DRM_ERROR("Unable to find pll dividers\n"); | ||
| 635 | break; | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | a.full = rfixed_const(10); | ||
| 640 | b.full = rfixed_mul(n, a); | ||
| 641 | |||
| 642 | frac_n.full = rfixed_floor(n); | ||
| 643 | frac_n.full = rfixed_mul(frac_n, a); | ||
| 644 | frac_n.full = b.full - frac_n.full; | ||
| 645 | |||
| 646 | *dot_clock_p = rfixed_trunc(best_freq); | ||
| 647 | *fb_div_p = rfixed_trunc(n); | ||
| 648 | *frac_fb_div_p = rfixed_trunc(frac_n); | ||
| 649 | *ref_div_p = rfixed_trunc(m); | ||
| 650 | *post_div_p = rfixed_trunc(p); | ||
| 651 | |||
| 652 | DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p * 10, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); | ||
| 653 | } | ||
| 654 | |||
| 563 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | 655 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |
| 564 | { | 656 | { |
| 565 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); | 657 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); |
| @@ -660,7 +752,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) | |||
| 660 | return -ENOMEM; | 752 | return -ENOMEM; |
| 661 | 753 | ||
| 662 | rdev->mode_info.coherent_mode_property->values[0] = 0; | 754 | rdev->mode_info.coherent_mode_property->values[0] = 0; |
| 663 | rdev->mode_info.coherent_mode_property->values[0] = 1; | 755 | rdev->mode_info.coherent_mode_property->values[1] = 1; |
| 664 | } | 756 | } |
| 665 | 757 | ||
| 666 | if (!ASIC_IS_AVIVO(rdev)) { | 758 | if (!ASIC_IS_AVIVO(rdev)) { |
| @@ -684,7 +776,7 @@ int radeon_modeset_create_props(struct radeon_device *rdev) | |||
| 684 | if (!rdev->mode_info.load_detect_property) | 776 | if (!rdev->mode_info.load_detect_property) |
| 685 | return -ENOMEM; | 777 | return -ENOMEM; |
| 686 | rdev->mode_info.load_detect_property->values[0] = 0; | 778 | rdev->mode_info.load_detect_property->values[0] = 0; |
| 687 | rdev->mode_info.load_detect_property->values[0] = 1; | 779 | rdev->mode_info.load_detect_property->values[1] = 1; |
| 688 | 780 | ||
| 689 | drm_mode_create_scaling_mode_property(rdev->ddev); | 781 | drm_mode_create_scaling_mode_property(rdev->ddev); |
| 690 | 782 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 7f50fb864af8..28077247f4f3 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -86,6 +86,7 @@ int radeon_benchmarking = 0; | |||
| 86 | int radeon_testing = 0; | 86 | int radeon_testing = 0; |
| 87 | int radeon_connector_table = 0; | 87 | int radeon_connector_table = 0; |
| 88 | int radeon_tv = 1; | 88 | int radeon_tv = 1; |
| 89 | int radeon_new_pll = 1; | ||
| 89 | 90 | ||
| 90 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); | 91 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); |
| 91 | module_param_named(no_wb, radeon_no_wb, int, 0444); | 92 | module_param_named(no_wb, radeon_no_wb, int, 0444); |
| @@ -120,6 +121,9 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); | |||
| 120 | MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); | 121 | MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); |
| 121 | module_param_named(tv, radeon_tv, int, 0444); | 122 | module_param_named(tv, radeon_tv, int, 0444); |
| 122 | 123 | ||
| 124 | MODULE_PARM_DESC(r4xx_atom, "Select new PLL code for AVIVO chips"); | ||
| 125 | module_param_named(new_pll, radeon_new_pll, int, 0444); | ||
| 126 | |||
| 123 | static int radeon_suspend(struct drm_device *dev, pm_message_t state) | 127 | static int radeon_suspend(struct drm_device *dev, pm_message_t state) |
| 124 | { | 128 | { |
| 125 | drm_radeon_private_t *dev_priv = dev->dev_private; | 129 | drm_radeon_private_t *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 2ac31633d72c..cb4cd97ae39f 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -197,9 +197,8 @@ retry: | |||
| 197 | r = wait_event_interruptible_timeout(rdev->fence_drv.queue, | 197 | r = wait_event_interruptible_timeout(rdev->fence_drv.queue, |
| 198 | radeon_fence_signaled(fence), timeout); | 198 | radeon_fence_signaled(fence), timeout); |
| 199 | radeon_irq_kms_sw_irq_put(rdev); | 199 | radeon_irq_kms_sw_irq_put(rdev); |
| 200 | if (unlikely(r == -ERESTARTSYS)) { | 200 | if (unlikely(r < 0)) |
| 201 | return -EBUSY; | 201 | return r; |
| 202 | } | ||
| 203 | } else { | 202 | } else { |
| 204 | radeon_irq_kms_sw_irq_get(rdev); | 203 | radeon_irq_kms_sw_irq_get(rdev); |
| 205 | r = wait_event_timeout(rdev->fence_drv.queue, | 204 | r = wait_event_timeout(rdev->fence_drv.queue, |
diff --git a/drivers/gpu/drm/radeon/radeon_fixed.h b/drivers/gpu/drm/radeon/radeon_fixed.h index 90187d173847..3d4d84e078ac 100644 --- a/drivers/gpu/drm/radeon/radeon_fixed.h +++ b/drivers/gpu/drm/radeon/radeon_fixed.h | |||
| @@ -38,6 +38,23 @@ typedef union rfixed { | |||
| 38 | #define fixed_init_half(A) { .full = rfixed_const_half((A)) } | 38 | #define fixed_init_half(A) { .full = rfixed_const_half((A)) } |
| 39 | #define rfixed_trunc(A) ((A).full >> 12) | 39 | #define rfixed_trunc(A) ((A).full >> 12) |
| 40 | 40 | ||
| 41 | static inline u32 rfixed_floor(fixed20_12 A) | ||
| 42 | { | ||
| 43 | u32 non_frac = rfixed_trunc(A); | ||
| 44 | |||
| 45 | return rfixed_const(non_frac); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline u32 rfixed_ceil(fixed20_12 A) | ||
| 49 | { | ||
| 50 | u32 non_frac = rfixed_trunc(A); | ||
| 51 | |||
| 52 | if (A.full > rfixed_const(non_frac)) | ||
| 53 | return rfixed_const(non_frac + 1); | ||
| 54 | else | ||
| 55 | return rfixed_const(non_frac); | ||
| 56 | } | ||
| 57 | |||
| 41 | static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B) | 58 | static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B) |
| 42 | { | 59 | { |
| 43 | u64 tmp = ((u64)A.full << 13); | 60 | u64 tmp = ((u64)A.full << 13); |
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index ba128621057a..f23b05606eb5 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -30,10 +30,19 @@ | |||
| 30 | #include "radeon.h" | 30 | #include "radeon.h" |
| 31 | #include "radeon_drm.h" | 31 | #include "radeon_drm.h" |
| 32 | 32 | ||
| 33 | int radeon_driver_unload_kms(struct drm_device *dev) | ||
| 34 | { | ||
| 35 | struct radeon_device *rdev = dev->dev_private; | ||
| 36 | |||
| 37 | if (rdev == NULL) | ||
| 38 | return 0; | ||
| 39 | radeon_modeset_fini(rdev); | ||
| 40 | radeon_device_fini(rdev); | ||
| 41 | kfree(rdev); | ||
| 42 | dev->dev_private = NULL; | ||
| 43 | return 0; | ||
| 44 | } | ||
| 33 | 45 | ||
| 34 | /* | ||
| 35 | * Driver load/unload | ||
| 36 | */ | ||
| 37 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | 46 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) |
| 38 | { | 47 | { |
| 39 | struct radeon_device *rdev; | 48 | struct radeon_device *rdev; |
| @@ -62,31 +71,20 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | |||
| 62 | */ | 71 | */ |
| 63 | r = radeon_device_init(rdev, dev, dev->pdev, flags); | 72 | r = radeon_device_init(rdev, dev, dev->pdev, flags); |
| 64 | if (r) { | 73 | if (r) { |
| 65 | DRM_ERROR("Fatal error while trying to initialize radeon.\n"); | 74 | dev_err(&dev->pdev->dev, "Fatal error during GPU init\n"); |
| 66 | return r; | 75 | goto out; |
| 67 | } | 76 | } |
| 68 | /* Again modeset_init should fail only on fatal error | 77 | /* Again modeset_init should fail only on fatal error |
| 69 | * otherwise it should provide enough functionalities | 78 | * otherwise it should provide enough functionalities |
| 70 | * for shadowfb to run | 79 | * for shadowfb to run |
| 71 | */ | 80 | */ |
| 72 | r = radeon_modeset_init(rdev); | 81 | r = radeon_modeset_init(rdev); |
| 73 | if (r) { | 82 | if (r) |
| 74 | return r; | 83 | dev_err(&dev->pdev->dev, "Fatal error during modeset init\n"); |
| 75 | } | 84 | out: |
| 76 | return 0; | 85 | if (r) |
| 77 | } | 86 | radeon_driver_unload_kms(dev); |
| 78 | 87 | return r; | |
| 79 | int radeon_driver_unload_kms(struct drm_device *dev) | ||
| 80 | { | ||
| 81 | struct radeon_device *rdev = dev->dev_private; | ||
| 82 | |||
| 83 | if (rdev == NULL) | ||
| 84 | return 0; | ||
| 85 | radeon_modeset_fini(rdev); | ||
| 86 | radeon_device_fini(rdev); | ||
| 87 | kfree(rdev); | ||
| 88 | dev->dev_private = NULL; | ||
| 89 | return 0; | ||
| 90 | } | 88 | } |
| 91 | 89 | ||
| 92 | 90 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 15ec7ca18a95..44d4b652ea12 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -437,6 +437,15 @@ extern void radeon_compute_pll(struct radeon_pll *pll, | |||
| 437 | uint32_t *post_div_p, | 437 | uint32_t *post_div_p, |
| 438 | int flags); | 438 | int flags); |
| 439 | 439 | ||
| 440 | extern void radeon_compute_pll_avivo(struct radeon_pll *pll, | ||
| 441 | uint64_t freq, | ||
| 442 | uint32_t *dot_clock_p, | ||
| 443 | uint32_t *fb_div_p, | ||
| 444 | uint32_t *frac_fb_div_p, | ||
| 445 | uint32_t *ref_div_p, | ||
| 446 | uint32_t *post_div_p, | ||
| 447 | int flags); | ||
| 448 | |||
| 440 | extern void radeon_setup_encoder_clones(struct drm_device *dev); | 449 | extern void radeon_setup_encoder_clones(struct drm_device *dev); |
| 441 | 450 | ||
| 442 | struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); | 451 | struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bec494384825..2040937682fd 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -75,6 +75,25 @@ static inline u32 radeon_ttm_flags_from_domain(u32 domain) | |||
| 75 | return flags; | 75 | return flags; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | ||
| 79 | { | ||
| 80 | u32 c = 0; | ||
| 81 | |||
| 82 | rbo->placement.fpfn = 0; | ||
| 83 | rbo->placement.lpfn = 0; | ||
| 84 | rbo->placement.placement = rbo->placements; | ||
| 85 | rbo->placement.busy_placement = rbo->placements; | ||
| 86 | if (domain & RADEON_GEM_DOMAIN_VRAM) | ||
| 87 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | | ||
| 88 | TTM_PL_FLAG_VRAM; | ||
| 89 | if (domain & RADEON_GEM_DOMAIN_GTT) | ||
| 90 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; | ||
| 91 | if (domain & RADEON_GEM_DOMAIN_CPU) | ||
| 92 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; | ||
| 93 | rbo->placement.num_placement = c; | ||
| 94 | rbo->placement.num_busy_placement = c; | ||
| 95 | } | ||
| 96 | |||
| 78 | int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, | 97 | int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, |
| 79 | unsigned long size, bool kernel, u32 domain, | 98 | unsigned long size, bool kernel, u32 domain, |
| 80 | struct radeon_bo **bo_ptr) | 99 | struct radeon_bo **bo_ptr) |
| @@ -102,16 +121,15 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, | |||
| 102 | INIT_LIST_HEAD(&bo->list); | 121 | INIT_LIST_HEAD(&bo->list); |
| 103 | 122 | ||
| 104 | flags = radeon_ttm_flags_from_domain(domain); | 123 | flags = radeon_ttm_flags_from_domain(domain); |
| 105 | retry: | 124 | /* Kernel allocation are uninterruptible */ |
| 106 | r = ttm_buffer_object_init(&rdev->mman.bdev, &bo->tbo, size, type, | 125 | r = ttm_buffer_object_init(&rdev->mman.bdev, &bo->tbo, size, type, |
| 107 | flags, 0, 0, true, NULL, size, | 126 | flags, 0, 0, !kernel, NULL, size, |
| 108 | &radeon_ttm_bo_destroy); | 127 | &radeon_ttm_bo_destroy); |
| 109 | if (unlikely(r != 0)) { | 128 | if (unlikely(r != 0)) { |
| 110 | if (r == -ERESTART) | 129 | if (r != -ERESTARTSYS) |
| 111 | goto retry; | 130 | dev_err(rdev->dev, |
| 112 | /* ttm call radeon_ttm_object_object_destroy if error happen */ | 131 | "object_init failed for (%ld, 0x%08X)\n", |
| 113 | dev_err(rdev->dev, "object_init failed for (%ld, 0x%08X)\n", | 132 | size, flags); |
| 114 | size, flags); | ||
| 115 | return r; | 133 | return r; |
| 116 | } | 134 | } |
| 117 | *bo_ptr = bo; | 135 | *bo_ptr = bo; |
| @@ -169,40 +187,32 @@ void radeon_bo_unref(struct radeon_bo **bo) | |||
| 169 | 187 | ||
| 170 | int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) | 188 | int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) |
| 171 | { | 189 | { |
| 172 | u32 flags; | 190 | int r, i; |
| 173 | u32 tmp; | ||
| 174 | int r; | ||
| 175 | 191 | ||
| 176 | flags = radeon_ttm_flags_from_domain(domain); | 192 | radeon_ttm_placement_from_domain(bo, domain); |
| 177 | if (bo->pin_count) { | 193 | if (bo->pin_count) { |
| 178 | bo->pin_count++; | 194 | bo->pin_count++; |
| 179 | if (gpu_addr) | 195 | if (gpu_addr) |
| 180 | *gpu_addr = radeon_bo_gpu_offset(bo); | 196 | *gpu_addr = radeon_bo_gpu_offset(bo); |
| 181 | return 0; | 197 | return 0; |
| 182 | } | 198 | } |
| 183 | tmp = bo->tbo.mem.placement; | 199 | radeon_ttm_placement_from_domain(bo, domain); |
| 184 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); | 200 | for (i = 0; i < bo->placement.num_placement; i++) |
| 185 | bo->tbo.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | | 201 | bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; |
| 186 | TTM_PL_MASK_CACHING; | 202 | r = ttm_buffer_object_validate(&bo->tbo, &bo->placement, false, false); |
| 187 | retry: | ||
| 188 | r = ttm_buffer_object_validate(&bo->tbo, bo->tbo.proposed_placement, | ||
| 189 | true, false); | ||
| 190 | if (likely(r == 0)) { | 203 | if (likely(r == 0)) { |
| 191 | bo->pin_count = 1; | 204 | bo->pin_count = 1; |
| 192 | if (gpu_addr != NULL) | 205 | if (gpu_addr != NULL) |
| 193 | *gpu_addr = radeon_bo_gpu_offset(bo); | 206 | *gpu_addr = radeon_bo_gpu_offset(bo); |
| 194 | } | 207 | } |
| 195 | if (unlikely(r != 0)) { | 208 | if (unlikely(r != 0)) |
| 196 | if (r == -ERESTART) | ||
| 197 | goto retry; | ||
| 198 | dev_err(bo->rdev->dev, "%p pin failed\n", bo); | 209 | dev_err(bo->rdev->dev, "%p pin failed\n", bo); |
| 199 | } | ||
| 200 | return r; | 210 | return r; |
| 201 | } | 211 | } |
| 202 | 212 | ||
| 203 | int radeon_bo_unpin(struct radeon_bo *bo) | 213 | int radeon_bo_unpin(struct radeon_bo *bo) |
| 204 | { | 214 | { |
| 205 | int r; | 215 | int r, i; |
| 206 | 216 | ||
| 207 | if (!bo->pin_count) { | 217 | if (!bo->pin_count) { |
| 208 | dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo); | 218 | dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo); |
| @@ -211,18 +221,12 @@ int radeon_bo_unpin(struct radeon_bo *bo) | |||
| 211 | bo->pin_count--; | 221 | bo->pin_count--; |
| 212 | if (bo->pin_count) | 222 | if (bo->pin_count) |
| 213 | return 0; | 223 | return 0; |
| 214 | bo->tbo.proposed_placement = bo->tbo.mem.placement & | 224 | for (i = 0; i < bo->placement.num_placement; i++) |
| 215 | ~TTM_PL_FLAG_NO_EVICT; | 225 | bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT; |
| 216 | retry: | 226 | r = ttm_buffer_object_validate(&bo->tbo, &bo->placement, false, false); |
| 217 | r = ttm_buffer_object_validate(&bo->tbo, bo->tbo.proposed_placement, | 227 | if (unlikely(r != 0)) |
| 218 | true, false); | ||
| 219 | if (unlikely(r != 0)) { | ||
| 220 | if (r == -ERESTART) | ||
| 221 | goto retry; | ||
| 222 | dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo); | 228 | dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo); |
| 223 | return r; | 229 | return r; |
| 224 | } | ||
| 225 | return 0; | ||
| 226 | } | 230 | } |
| 227 | 231 | ||
| 228 | int radeon_bo_evict_vram(struct radeon_device *rdev) | 232 | int radeon_bo_evict_vram(struct radeon_device *rdev) |
| @@ -326,21 +330,17 @@ int radeon_bo_list_validate(struct list_head *head, void *fence) | |||
| 326 | bo = lobj->bo; | 330 | bo = lobj->bo; |
| 327 | if (!bo->pin_count) { | 331 | if (!bo->pin_count) { |
| 328 | if (lobj->wdomain) { | 332 | if (lobj->wdomain) { |
| 329 | bo->tbo.proposed_placement = | 333 | radeon_ttm_placement_from_domain(bo, |
| 330 | radeon_ttm_flags_from_domain(lobj->wdomain); | 334 | lobj->wdomain); |
| 331 | } else { | 335 | } else { |
| 332 | bo->tbo.proposed_placement = | 336 | radeon_ttm_placement_from_domain(bo, |
| 333 | radeon_ttm_flags_from_domain(lobj->rdomain); | 337 | lobj->rdomain); |
| 334 | } | 338 | } |
| 335 | retry: | ||
| 336 | r = ttm_buffer_object_validate(&bo->tbo, | 339 | r = ttm_buffer_object_validate(&bo->tbo, |
| 337 | bo->tbo.proposed_placement, | 340 | &bo->placement, |
| 338 | true, false); | 341 | true, false); |
| 339 | if (unlikely(r)) { | 342 | if (unlikely(r)) |
| 340 | if (r == -ERESTART) | ||
| 341 | goto retry; | ||
| 342 | return r; | 343 | return r; |
| 343 | } | ||
| 344 | } | 344 | } |
| 345 | lobj->gpu_offset = radeon_bo_gpu_offset(bo); | 345 | lobj->gpu_offset = radeon_bo_gpu_offset(bo); |
| 346 | lobj->tiling_flags = bo->tiling_flags; | 346 | lobj->tiling_flags = bo->tiling_flags; |
| @@ -378,7 +378,7 @@ int radeon_bo_fbdev_mmap(struct radeon_bo *bo, | |||
| 378 | return ttm_fbdev_mmap(vma, &bo->tbo); | 378 | return ttm_fbdev_mmap(vma, &bo->tbo); |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static int radeon_bo_get_surface_reg(struct radeon_bo *bo) | 381 | int radeon_bo_get_surface_reg(struct radeon_bo *bo) |
| 382 | { | 382 | { |
| 383 | struct radeon_device *rdev = bo->rdev; | 383 | struct radeon_device *rdev = bo->rdev; |
| 384 | struct radeon_surface_reg *reg; | 384 | struct radeon_surface_reg *reg; |
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index e9da13077e2f..f6b69c2c0d00 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h | |||
| @@ -175,5 +175,5 @@ extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, | |||
| 175 | extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, | 175 | extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, |
| 176 | struct ttm_mem_reg *mem); | 176 | struct ttm_mem_reg *mem); |
| 177 | extern void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); | 177 | extern void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); |
| 178 | 178 | extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); | |
| 179 | #endif | 179 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index bdb46c8cadd1..d2ed896cca01 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -197,16 +197,19 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
| 197 | return 0; | 197 | return 0; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | static uint32_t radeon_evict_flags(struct ttm_buffer_object *bo) | 200 | static void radeon_evict_flags(struct ttm_buffer_object *bo, |
| 201 | struct ttm_placement *placement) | ||
| 201 | { | 202 | { |
| 202 | uint32_t cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEMTYPE; | 203 | struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); |
| 203 | |||
| 204 | switch (bo->mem.mem_type) { | 204 | switch (bo->mem.mem_type) { |
| 205 | case TTM_PL_VRAM: | ||
| 206 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); | ||
| 207 | break; | ||
| 208 | case TTM_PL_TT: | ||
| 205 | default: | 209 | default: |
| 206 | return (cur_placement & ~TTM_PL_MASK_CACHING) | | 210 | radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); |
| 207 | TTM_PL_FLAG_SYSTEM | | ||
| 208 | TTM_PL_FLAG_CACHED; | ||
| 209 | } | 211 | } |
| 212 | *placement = rbo->placement; | ||
| 210 | } | 213 | } |
| 211 | 214 | ||
| 212 | static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) | 215 | static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) |
| @@ -283,14 +286,21 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, | |||
| 283 | struct radeon_device *rdev; | 286 | struct radeon_device *rdev; |
| 284 | struct ttm_mem_reg *old_mem = &bo->mem; | 287 | struct ttm_mem_reg *old_mem = &bo->mem; |
| 285 | struct ttm_mem_reg tmp_mem; | 288 | struct ttm_mem_reg tmp_mem; |
| 286 | uint32_t proposed_placement; | 289 | u32 placements; |
| 290 | struct ttm_placement placement; | ||
| 287 | int r; | 291 | int r; |
| 288 | 292 | ||
| 289 | rdev = radeon_get_rdev(bo->bdev); | 293 | rdev = radeon_get_rdev(bo->bdev); |
| 290 | tmp_mem = *new_mem; | 294 | tmp_mem = *new_mem; |
| 291 | tmp_mem.mm_node = NULL; | 295 | tmp_mem.mm_node = NULL; |
| 292 | proposed_placement = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; | 296 | placement.fpfn = 0; |
| 293 | r = ttm_bo_mem_space(bo, proposed_placement, &tmp_mem, | 297 | placement.lpfn = 0; |
| 298 | placement.num_placement = 1; | ||
| 299 | placement.placement = &placements; | ||
| 300 | placement.num_busy_placement = 1; | ||
| 301 | placement.busy_placement = &placements; | ||
| 302 | placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; | ||
| 303 | r = ttm_bo_mem_space(bo, &placement, &tmp_mem, | ||
| 294 | interruptible, no_wait); | 304 | interruptible, no_wait); |
| 295 | if (unlikely(r)) { | 305 | if (unlikely(r)) { |
| 296 | return r; | 306 | return r; |
| @@ -329,15 +339,21 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, | |||
| 329 | struct radeon_device *rdev; | 339 | struct radeon_device *rdev; |
| 330 | struct ttm_mem_reg *old_mem = &bo->mem; | 340 | struct ttm_mem_reg *old_mem = &bo->mem; |
| 331 | struct ttm_mem_reg tmp_mem; | 341 | struct ttm_mem_reg tmp_mem; |
| 332 | uint32_t proposed_flags; | 342 | struct ttm_placement placement; |
| 343 | u32 placements; | ||
| 333 | int r; | 344 | int r; |
| 334 | 345 | ||
| 335 | rdev = radeon_get_rdev(bo->bdev); | 346 | rdev = radeon_get_rdev(bo->bdev); |
| 336 | tmp_mem = *new_mem; | 347 | tmp_mem = *new_mem; |
| 337 | tmp_mem.mm_node = NULL; | 348 | tmp_mem.mm_node = NULL; |
| 338 | proposed_flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; | 349 | placement.fpfn = 0; |
| 339 | r = ttm_bo_mem_space(bo, proposed_flags, &tmp_mem, | 350 | placement.lpfn = 0; |
| 340 | interruptible, no_wait); | 351 | placement.num_placement = 1; |
| 352 | placement.placement = &placements; | ||
| 353 | placement.num_busy_placement = 1; | ||
| 354 | placement.busy_placement = &placements; | ||
| 355 | placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; | ||
| 356 | r = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, no_wait); | ||
| 341 | if (unlikely(r)) { | 357 | if (unlikely(r)) { |
| 342 | return r; | 358 | return r; |
| 343 | } | 359 | } |
| @@ -407,18 +423,6 @@ memcpy: | |||
| 407 | return r; | 423 | return r; |
| 408 | } | 424 | } |
| 409 | 425 | ||
| 410 | const uint32_t radeon_mem_prios[] = { | ||
| 411 | TTM_PL_VRAM, | ||
| 412 | TTM_PL_TT, | ||
| 413 | TTM_PL_SYSTEM, | ||
| 414 | }; | ||
| 415 | |||
| 416 | const uint32_t radeon_busy_prios[] = { | ||
| 417 | TTM_PL_TT, | ||
| 418 | TTM_PL_VRAM, | ||
| 419 | TTM_PL_SYSTEM, | ||
| 420 | }; | ||
| 421 | |||
| 422 | static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg, | 426 | static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg, |
| 423 | bool lazy, bool interruptible) | 427 | bool lazy, bool interruptible) |
| 424 | { | 428 | { |
| @@ -446,10 +450,6 @@ static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg) | |||
| 446 | } | 450 | } |
| 447 | 451 | ||
| 448 | static struct ttm_bo_driver radeon_bo_driver = { | 452 | static struct ttm_bo_driver radeon_bo_driver = { |
| 449 | .mem_type_prio = radeon_mem_prios, | ||
| 450 | .mem_busy_prio = radeon_busy_prios, | ||
| 451 | .num_mem_type_prio = ARRAY_SIZE(radeon_mem_prios), | ||
| 452 | .num_mem_busy_prio = ARRAY_SIZE(radeon_busy_prios), | ||
| 453 | .create_ttm_backend_entry = &radeon_create_ttm_backend_entry, | 453 | .create_ttm_backend_entry = &radeon_create_ttm_backend_entry, |
| 454 | .invalidate_caches = &radeon_invalidate_caches, | 454 | .invalidate_caches = &radeon_invalidate_caches, |
| 455 | .init_mem_type = &radeon_init_mem_type, | 455 | .init_mem_type = &radeon_init_mem_type, |
| @@ -483,7 +483,7 @@ int radeon_ttm_init(struct radeon_device *rdev) | |||
| 483 | return r; | 483 | return r; |
| 484 | } | 484 | } |
| 485 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, | 485 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, |
| 486 | 0, rdev->mc.real_vram_size >> PAGE_SHIFT); | 486 | rdev->mc.real_vram_size >> PAGE_SHIFT); |
| 487 | if (r) { | 487 | if (r) { |
| 488 | DRM_ERROR("Failed initializing VRAM heap.\n"); | 488 | DRM_ERROR("Failed initializing VRAM heap.\n"); |
| 489 | return r; | 489 | return r; |
| @@ -506,7 +506,7 @@ int radeon_ttm_init(struct radeon_device *rdev) | |||
| 506 | DRM_INFO("radeon: %uM of VRAM memory ready\n", | 506 | DRM_INFO("radeon: %uM of VRAM memory ready\n", |
| 507 | (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); | 507 | (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); |
| 508 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, | 508 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, |
| 509 | 0, rdev->mc.gtt_size >> PAGE_SHIFT); | 509 | rdev->mc.gtt_size >> PAGE_SHIFT); |
| 510 | if (r) { | 510 | if (r) { |
| 511 | DRM_ERROR("Failed initializing GTT heap.\n"); | 511 | DRM_ERROR("Failed initializing GTT heap.\n"); |
| 512 | return r; | 512 | return r; |
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index eda6d757b5c4..c1fcdddb6be6 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -430,6 +430,8 @@ int rs400_resume(struct radeon_device *rdev) | |||
| 430 | radeon_combios_asic_init(rdev->ddev); | 430 | radeon_combios_asic_init(rdev->ddev); |
| 431 | /* Resume clock after posting */ | 431 | /* Resume clock after posting */ |
| 432 | r300_clock_startup(rdev); | 432 | r300_clock_startup(rdev); |
| 433 | /* Initialize surface registers */ | ||
| 434 | radeon_surface_init(rdev); | ||
| 433 | return rs400_startup(rdev); | 435 | return rs400_startup(rdev); |
| 434 | } | 436 | } |
| 435 | 437 | ||
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index fd5ab01f6ad1..4f8ea4260572 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -586,6 +586,8 @@ int rs600_resume(struct radeon_device *rdev) | |||
| 586 | atom_asic_init(rdev->mode_info.atom_context); | 586 | atom_asic_init(rdev->mode_info.atom_context); |
| 587 | /* Resume clock after posting */ | 587 | /* Resume clock after posting */ |
| 588 | rv515_clock_startup(rdev); | 588 | rv515_clock_startup(rdev); |
| 589 | /* Initialize surface registers */ | ||
| 590 | radeon_surface_init(rdev); | ||
| 589 | return rs600_startup(rdev); | 591 | return rs600_startup(rdev); |
| 590 | } | 592 | } |
| 591 | 593 | ||
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index eb486ee7ea00..1e22f52d6039 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -260,8 +260,9 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, | |||
| 260 | 260 | ||
| 261 | b.full = rfixed_const(mode->crtc_hdisplay); | 261 | b.full = rfixed_const(mode->crtc_hdisplay); |
| 262 | c.full = rfixed_const(256); | 262 | c.full = rfixed_const(256); |
| 263 | a.full = rfixed_mul(wm->num_line_pair, b); | 263 | a.full = rfixed_div(b, c); |
| 264 | request_fifo_depth.full = rfixed_div(a, c); | 264 | request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair); |
| 265 | request_fifo_depth.full = rfixed_ceil(request_fifo_depth); | ||
| 265 | if (a.full < rfixed_const(4)) { | 266 | if (a.full < rfixed_const(4)) { |
| 266 | wm->lb_request_fifo_depth = 4; | 267 | wm->lb_request_fifo_depth = 4; |
| 267 | } else { | 268 | } else { |
| @@ -390,6 +391,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, | |||
| 390 | a.full = rfixed_const(16); | 391 | a.full = rfixed_const(16); |
| 391 | wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); | 392 | wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
| 392 | wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); | 393 | wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); |
| 394 | wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max); | ||
| 393 | 395 | ||
| 394 | /* Determine estimated width */ | 396 | /* Determine estimated width */ |
| 395 | estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; | 397 | estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; |
| @@ -399,6 +401,7 @@ void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, | |||
| 399 | } else { | 401 | } else { |
| 400 | a.full = rfixed_const(16); | 402 | a.full = rfixed_const(16); |
| 401 | wm->priority_mark.full = rfixed_div(estimated_width, a); | 403 | wm->priority_mark.full = rfixed_div(estimated_width, a); |
| 404 | wm->priority_mark.full = rfixed_ceil(wm->priority_mark); | ||
| 402 | wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; | 405 | wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; |
| 403 | } | 406 | } |
| 404 | } | 407 | } |
| @@ -655,6 +658,8 @@ int rs690_resume(struct radeon_device *rdev) | |||
| 655 | atom_asic_init(rdev->mode_info.atom_context); | 658 | atom_asic_init(rdev->mode_info.atom_context); |
| 656 | /* Resume clock after posting */ | 659 | /* Resume clock after posting */ |
| 657 | rv515_clock_startup(rdev); | 660 | rv515_clock_startup(rdev); |
| 661 | /* Initialize surface registers */ | ||
| 662 | radeon_surface_init(rdev); | ||
| 658 | return rs690_startup(rdev); | 663 | return rs690_startup(rdev); |
| 659 | } | 664 | } |
| 660 | 665 | ||
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 7793239e24b2..59632a506b46 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -513,6 +513,8 @@ int rv515_resume(struct radeon_device *rdev) | |||
| 513 | atom_asic_init(rdev->mode_info.atom_context); | 513 | atom_asic_init(rdev->mode_info.atom_context); |
| 514 | /* Resume clock after posting */ | 514 | /* Resume clock after posting */ |
| 515 | rv515_clock_startup(rdev); | 515 | rv515_clock_startup(rdev); |
| 516 | /* Initialize surface registers */ | ||
| 517 | radeon_surface_init(rdev); | ||
| 516 | return rv515_startup(rdev); | 518 | return rv515_startup(rdev); |
| 517 | } | 519 | } |
| 518 | 520 | ||
| @@ -889,8 +891,9 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, | |||
| 889 | 891 | ||
| 890 | b.full = rfixed_const(mode->crtc_hdisplay); | 892 | b.full = rfixed_const(mode->crtc_hdisplay); |
| 891 | c.full = rfixed_const(256); | 893 | c.full = rfixed_const(256); |
| 892 | a.full = rfixed_mul(wm->num_line_pair, b); | 894 | a.full = rfixed_div(b, c); |
| 893 | request_fifo_depth.full = rfixed_div(a, c); | 895 | request_fifo_depth.full = rfixed_mul(a, wm->num_line_pair); |
| 896 | request_fifo_depth.full = rfixed_ceil(request_fifo_depth); | ||
| 894 | if (a.full < rfixed_const(4)) { | 897 | if (a.full < rfixed_const(4)) { |
| 895 | wm->lb_request_fifo_depth = 4; | 898 | wm->lb_request_fifo_depth = 4; |
| 896 | } else { | 899 | } else { |
| @@ -992,15 +995,17 @@ void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, | |||
| 992 | a.full = rfixed_const(16); | 995 | a.full = rfixed_const(16); |
| 993 | wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); | 996 | wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
| 994 | wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); | 997 | wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); |
| 998 | wm->priority_mark_max.full = rfixed_ceil(wm->priority_mark_max); | ||
| 995 | 999 | ||
| 996 | /* Determine estimated width */ | 1000 | /* Determine estimated width */ |
| 997 | estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; | 1001 | estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; |
| 998 | estimated_width.full = rfixed_div(estimated_width, consumption_time); | 1002 | estimated_width.full = rfixed_div(estimated_width, consumption_time); |
| 999 | if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { | 1003 | if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { |
| 1000 | wm->priority_mark.full = rfixed_const(10); | 1004 | wm->priority_mark.full = wm->priority_mark_max.full; |
| 1001 | } else { | 1005 | } else { |
| 1002 | a.full = rfixed_const(16); | 1006 | a.full = rfixed_const(16); |
| 1003 | wm->priority_mark.full = rfixed_div(estimated_width, a); | 1007 | wm->priority_mark.full = rfixed_div(estimated_width, a); |
| 1008 | wm->priority_mark.full = rfixed_ceil(wm->priority_mark); | ||
| 1004 | wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; | 1009 | wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; |
| 1005 | } | 1010 | } |
| 1006 | } | 1011 | } |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index dd4f02096a80..2d124bb57762 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -874,6 +874,14 @@ static int rv770_startup(struct radeon_device *rdev) | |||
| 874 | { | 874 | { |
| 875 | int r; | 875 | int r; |
| 876 | 876 | ||
| 877 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
| 878 | r = r600_init_microcode(rdev); | ||
| 879 | if (r) { | ||
| 880 | DRM_ERROR("Failed to load firmware!\n"); | ||
| 881 | return r; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | |||
| 877 | rv770_mc_program(rdev); | 885 | rv770_mc_program(rdev); |
| 878 | if (rdev->flags & RADEON_IS_AGP) { | 886 | if (rdev->flags & RADEON_IS_AGP) { |
| 879 | rv770_agp_enable(rdev); | 887 | rv770_agp_enable(rdev); |
| @@ -1039,25 +1047,17 @@ int rv770_init(struct radeon_device *rdev) | |||
| 1039 | rdev->ih.ring_obj = NULL; | 1047 | rdev->ih.ring_obj = NULL; |
| 1040 | r600_ih_ring_init(rdev, 64 * 1024); | 1048 | r600_ih_ring_init(rdev, 64 * 1024); |
| 1041 | 1049 | ||
| 1042 | if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { | ||
| 1043 | r = r600_init_microcode(rdev); | ||
| 1044 | if (r) { | ||
| 1045 | DRM_ERROR("Failed to load firmware!\n"); | ||
| 1046 | return r; | ||
| 1047 | } | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | r = r600_pcie_gart_init(rdev); | 1050 | r = r600_pcie_gart_init(rdev); |
| 1051 | if (r) | 1051 | if (r) |
| 1052 | return r; | 1052 | return r; |
| 1053 | 1053 | ||
| 1054 | rdev->accel_working = true; | ||
| 1055 | r = r600_blit_init(rdev); | 1054 | r = r600_blit_init(rdev); |
| 1056 | if (r) { | 1055 | if (r) { |
| 1057 | DRM_ERROR("radeon: failled blitter (%d).\n", r); | 1056 | DRM_ERROR("radeon: failed blitter (%d).\n", r); |
| 1058 | rdev->accel_working = false; | 1057 | return r; |
| 1059 | } | 1058 | } |
| 1060 | 1059 | ||
| 1060 | rdev->accel_working = true; | ||
| 1061 | r = rv770_startup(rdev); | 1061 | r = rv770_startup(rdev); |
| 1062 | if (r) { | 1062 | if (r) { |
| 1063 | rv770_suspend(rdev); | 1063 | rv770_suspend(rdev); |
| @@ -1069,12 +1069,12 @@ int rv770_init(struct radeon_device *rdev) | |||
| 1069 | if (rdev->accel_working) { | 1069 | if (rdev->accel_working) { |
| 1070 | r = radeon_ib_pool_init(rdev); | 1070 | r = radeon_ib_pool_init(rdev); |
| 1071 | if (r) { | 1071 | if (r) { |
| 1072 | DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); | 1072 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); |
| 1073 | rdev->accel_working = false; | 1073 | rdev->accel_working = false; |
| 1074 | } | 1074 | } |
| 1075 | r = r600_ib_test(rdev); | 1075 | r = r600_ib_test(rdev); |
| 1076 | if (r) { | 1076 | if (r) { |
| 1077 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | 1077 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); |
| 1078 | rdev->accel_working = false; | 1078 | rdev->accel_working = false; |
| 1079 | } | 1079 | } |
| 1080 | } | 1080 | } |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e13fd23f3334..a835b6fe42a1 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -27,6 +27,14 @@ | |||
| 27 | /* | 27 | /* |
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
| 29 | */ | 29 | */ |
| 30 | /* Notes: | ||
| 31 | * | ||
| 32 | * We store bo pointer in drm_mm_node struct so we know which bo own a | ||
| 33 | * specific node. There is no protection on the pointer, thus to make | ||
| 34 | * sure things don't go berserk you have to access this pointer while | ||
| 35 | * holding the global lru lock and make sure anytime you free a node you | ||
| 36 | * reset the pointer to NULL. | ||
| 37 | */ | ||
| 30 | 38 | ||
| 31 | #include "ttm/ttm_module.h" | 39 | #include "ttm/ttm_module.h" |
| 32 | #include "ttm/ttm_bo_driver.h" | 40 | #include "ttm/ttm_bo_driver.h" |
| @@ -51,6 +59,60 @@ static struct attribute ttm_bo_count = { | |||
| 51 | .mode = S_IRUGO | 59 | .mode = S_IRUGO |
| 52 | }; | 60 | }; |
| 53 | 61 | ||
| 62 | static inline int ttm_mem_type_from_flags(uint32_t flags, uint32_t *mem_type) | ||
| 63 | { | ||
| 64 | int i; | ||
| 65 | |||
| 66 | for (i = 0; i <= TTM_PL_PRIV5; i++) | ||
| 67 | if (flags & (1 << i)) { | ||
| 68 | *mem_type = i; | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | return -EINVAL; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void ttm_mem_type_manager_debug(struct ttm_bo_global *glob, | ||
| 75 | struct ttm_mem_type_manager *man) | ||
| 76 | { | ||
| 77 | printk(KERN_ERR TTM_PFX " has_type: %d\n", man->has_type); | ||
| 78 | printk(KERN_ERR TTM_PFX " use_type: %d\n", man->use_type); | ||
| 79 | printk(KERN_ERR TTM_PFX " flags: 0x%08X\n", man->flags); | ||
| 80 | printk(KERN_ERR TTM_PFX " gpu_offset: 0x%08lX\n", man->gpu_offset); | ||
| 81 | printk(KERN_ERR TTM_PFX " io_offset: 0x%08lX\n", man->io_offset); | ||
| 82 | printk(KERN_ERR TTM_PFX " io_size: %ld\n", man->io_size); | ||
| 83 | printk(KERN_ERR TTM_PFX " size: %ld\n", (unsigned long)man->size); | ||
| 84 | printk(KERN_ERR TTM_PFX " available_caching: 0x%08X\n", | ||
| 85 | man->available_caching); | ||
| 86 | printk(KERN_ERR TTM_PFX " default_caching: 0x%08X\n", | ||
| 87 | man->default_caching); | ||
| 88 | spin_lock(&glob->lru_lock); | ||
| 89 | drm_mm_debug_table(&man->manager, TTM_PFX); | ||
| 90 | spin_unlock(&glob->lru_lock); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, | ||
| 94 | struct ttm_placement *placement) | ||
| 95 | { | ||
| 96 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 97 | struct ttm_bo_global *glob = bo->glob; | ||
| 98 | struct ttm_mem_type_manager *man; | ||
| 99 | int i, ret, mem_type; | ||
| 100 | |||
| 101 | printk(KERN_ERR TTM_PFX "No space for %p (%ld pages, %ldK, %ldM)\n", | ||
| 102 | bo, bo->mem.num_pages, bo->mem.size >> 10, | ||
| 103 | bo->mem.size >> 20); | ||
| 104 | for (i = 0; i < placement->num_placement; i++) { | ||
| 105 | ret = ttm_mem_type_from_flags(placement->placement[i], | ||
| 106 | &mem_type); | ||
| 107 | if (ret) | ||
| 108 | return; | ||
| 109 | man = &bdev->man[mem_type]; | ||
| 110 | printk(KERN_ERR TTM_PFX " placement[%d]=0x%08X (%d)\n", | ||
| 111 | i, placement->placement[i], mem_type); | ||
| 112 | ttm_mem_type_manager_debug(glob, man); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 54 | static ssize_t ttm_bo_global_show(struct kobject *kobj, | 116 | static ssize_t ttm_bo_global_show(struct kobject *kobj, |
| 55 | struct attribute *attr, | 117 | struct attribute *attr, |
| 56 | char *buffer) | 118 | char *buffer) |
| @@ -117,7 +179,7 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible) | |||
| 117 | ret = wait_event_interruptible(bo->event_queue, | 179 | ret = wait_event_interruptible(bo->event_queue, |
| 118 | atomic_read(&bo->reserved) == 0); | 180 | atomic_read(&bo->reserved) == 0); |
| 119 | if (unlikely(ret != 0)) | 181 | if (unlikely(ret != 0)) |
| 120 | return -ERESTART; | 182 | return ret; |
| 121 | } else { | 183 | } else { |
| 122 | wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0); | 184 | wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0); |
| 123 | } | 185 | } |
| @@ -247,7 +309,6 @@ EXPORT_SYMBOL(ttm_bo_unreserve); | |||
| 247 | /* | 309 | /* |
| 248 | * Call bo->mutex locked. | 310 | * Call bo->mutex locked. |
| 249 | */ | 311 | */ |
| 250 | |||
| 251 | static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) | 312 | static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) |
| 252 | { | 313 | { |
| 253 | struct ttm_bo_device *bdev = bo->bdev; | 314 | struct ttm_bo_device *bdev = bo->bdev; |
| @@ -329,14 +390,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
| 329 | } | 390 | } |
| 330 | 391 | ||
| 331 | if (bo->mem.mem_type == TTM_PL_SYSTEM) { | 392 | if (bo->mem.mem_type == TTM_PL_SYSTEM) { |
| 332 | 393 | bo->mem = *mem; | |
| 333 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 334 | uint32_t save_flags = old_mem->placement; | ||
| 335 | |||
| 336 | *old_mem = *mem; | ||
| 337 | mem->mm_node = NULL; | 394 | mem->mm_node = NULL; |
| 338 | ttm_flag_masked(&save_flags, mem->placement, | ||
| 339 | TTM_PL_MASK_MEMTYPE); | ||
| 340 | goto moved; | 395 | goto moved; |
| 341 | } | 396 | } |
| 342 | 397 | ||
| @@ -419,6 +474,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) | |||
| 419 | kref_put(&bo->list_kref, ttm_bo_ref_bug); | 474 | kref_put(&bo->list_kref, ttm_bo_ref_bug); |
| 420 | } | 475 | } |
| 421 | if (bo->mem.mm_node) { | 476 | if (bo->mem.mm_node) { |
| 477 | bo->mem.mm_node->private = NULL; | ||
| 422 | drm_mm_put_block(bo->mem.mm_node); | 478 | drm_mm_put_block(bo->mem.mm_node); |
| 423 | bo->mem.mm_node = NULL; | 479 | bo->mem.mm_node = NULL; |
| 424 | } | 480 | } |
| @@ -555,24 +611,21 @@ void ttm_bo_unref(struct ttm_buffer_object **p_bo) | |||
| 555 | } | 611 | } |
| 556 | EXPORT_SYMBOL(ttm_bo_unref); | 612 | EXPORT_SYMBOL(ttm_bo_unref); |
| 557 | 613 | ||
| 558 | static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, | 614 | static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible, |
| 559 | bool interruptible, bool no_wait) | 615 | bool no_wait) |
| 560 | { | 616 | { |
| 561 | int ret = 0; | ||
| 562 | struct ttm_bo_device *bdev = bo->bdev; | 617 | struct ttm_bo_device *bdev = bo->bdev; |
| 563 | struct ttm_bo_global *glob = bo->glob; | 618 | struct ttm_bo_global *glob = bo->glob; |
| 564 | struct ttm_mem_reg evict_mem; | 619 | struct ttm_mem_reg evict_mem; |
| 565 | uint32_t proposed_placement; | 620 | struct ttm_placement placement; |
| 566 | 621 | int ret = 0; | |
| 567 | if (bo->mem.mem_type != mem_type) | ||
| 568 | goto out; | ||
| 569 | 622 | ||
| 570 | spin_lock(&bo->lock); | 623 | spin_lock(&bo->lock); |
| 571 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); | 624 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); |
| 572 | spin_unlock(&bo->lock); | 625 | spin_unlock(&bo->lock); |
| 573 | 626 | ||
| 574 | if (unlikely(ret != 0)) { | 627 | if (unlikely(ret != 0)) { |
| 575 | if (ret != -ERESTART) { | 628 | if (ret != -ERESTARTSYS) { |
| 576 | printk(KERN_ERR TTM_PFX | 629 | printk(KERN_ERR TTM_PFX |
| 577 | "Failed to expire sync object before " | 630 | "Failed to expire sync object before " |
| 578 | "buffer eviction.\n"); | 631 | "buffer eviction.\n"); |
| @@ -585,116 +638,139 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, | |||
| 585 | evict_mem = bo->mem; | 638 | evict_mem = bo->mem; |
| 586 | evict_mem.mm_node = NULL; | 639 | evict_mem.mm_node = NULL; |
| 587 | 640 | ||
| 588 | proposed_placement = bdev->driver->evict_flags(bo); | 641 | placement.fpfn = 0; |
| 589 | 642 | placement.lpfn = 0; | |
| 590 | ret = ttm_bo_mem_space(bo, proposed_placement, | 643 | placement.num_placement = 0; |
| 591 | &evict_mem, interruptible, no_wait); | 644 | placement.num_busy_placement = 0; |
| 592 | if (unlikely(ret != 0 && ret != -ERESTART)) | 645 | bdev->driver->evict_flags(bo, &placement); |
| 593 | ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM, | 646 | ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible, |
| 594 | &evict_mem, interruptible, no_wait); | 647 | no_wait); |
| 595 | |||
| 596 | if (ret) { | 648 | if (ret) { |
| 597 | if (ret != -ERESTART) | 649 | if (ret != -ERESTARTSYS) { |
| 598 | printk(KERN_ERR TTM_PFX | 650 | printk(KERN_ERR TTM_PFX |
| 599 | "Failed to find memory space for " | 651 | "Failed to find memory space for " |
| 600 | "buffer 0x%p eviction.\n", bo); | 652 | "buffer 0x%p eviction.\n", bo); |
| 653 | ttm_bo_mem_space_debug(bo, &placement); | ||
| 654 | } | ||
| 601 | goto out; | 655 | goto out; |
| 602 | } | 656 | } |
| 603 | 657 | ||
| 604 | ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible, | 658 | ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible, |
| 605 | no_wait); | 659 | no_wait); |
| 606 | if (ret) { | 660 | if (ret) { |
| 607 | if (ret != -ERESTART) | 661 | if (ret != -ERESTARTSYS) |
| 608 | printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); | 662 | printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); |
| 663 | spin_lock(&glob->lru_lock); | ||
| 664 | if (evict_mem.mm_node) { | ||
| 665 | evict_mem.mm_node->private = NULL; | ||
| 666 | drm_mm_put_block(evict_mem.mm_node); | ||
| 667 | evict_mem.mm_node = NULL; | ||
| 668 | } | ||
| 669 | spin_unlock(&glob->lru_lock); | ||
| 609 | goto out; | 670 | goto out; |
| 610 | } | 671 | } |
| 672 | bo->evicted = true; | ||
| 673 | out: | ||
| 674 | return ret; | ||
| 675 | } | ||
| 676 | |||
| 677 | static int ttm_mem_evict_first(struct ttm_bo_device *bdev, | ||
| 678 | uint32_t mem_type, | ||
| 679 | bool interruptible, bool no_wait) | ||
| 680 | { | ||
| 681 | struct ttm_bo_global *glob = bdev->glob; | ||
| 682 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | ||
| 683 | struct ttm_buffer_object *bo; | ||
| 684 | int ret, put_count = 0; | ||
| 611 | 685 | ||
| 612 | spin_lock(&glob->lru_lock); | 686 | spin_lock(&glob->lru_lock); |
| 613 | if (evict_mem.mm_node) { | 687 | bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru); |
| 614 | drm_mm_put_block(evict_mem.mm_node); | 688 | kref_get(&bo->list_kref); |
| 615 | evict_mem.mm_node = NULL; | 689 | ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, false, 0); |
| 616 | } | 690 | if (likely(ret == 0)) |
| 691 | put_count = ttm_bo_del_from_lru(bo); | ||
| 617 | spin_unlock(&glob->lru_lock); | 692 | spin_unlock(&glob->lru_lock); |
| 618 | bo->evicted = true; | 693 | if (unlikely(ret != 0)) |
| 619 | out: | 694 | return ret; |
| 695 | while (put_count--) | ||
| 696 | kref_put(&bo->list_kref, ttm_bo_ref_bug); | ||
| 697 | ret = ttm_bo_evict(bo, interruptible, no_wait); | ||
| 698 | ttm_bo_unreserve(bo); | ||
| 699 | kref_put(&bo->list_kref, ttm_bo_release_list); | ||
| 620 | return ret; | 700 | return ret; |
| 621 | } | 701 | } |
| 622 | 702 | ||
| 703 | static int ttm_bo_man_get_node(struct ttm_buffer_object *bo, | ||
| 704 | struct ttm_mem_type_manager *man, | ||
| 705 | struct ttm_placement *placement, | ||
| 706 | struct ttm_mem_reg *mem, | ||
| 707 | struct drm_mm_node **node) | ||
| 708 | { | ||
| 709 | struct ttm_bo_global *glob = bo->glob; | ||
| 710 | unsigned long lpfn; | ||
| 711 | int ret; | ||
| 712 | |||
| 713 | lpfn = placement->lpfn; | ||
| 714 | if (!lpfn) | ||
| 715 | lpfn = man->size; | ||
| 716 | *node = NULL; | ||
| 717 | do { | ||
| 718 | ret = drm_mm_pre_get(&man->manager); | ||
| 719 | if (unlikely(ret)) | ||
| 720 | return ret; | ||
| 721 | |||
| 722 | spin_lock(&glob->lru_lock); | ||
| 723 | *node = drm_mm_search_free_in_range(&man->manager, | ||
| 724 | mem->num_pages, mem->page_alignment, | ||
| 725 | placement->fpfn, lpfn, 1); | ||
| 726 | if (unlikely(*node == NULL)) { | ||
| 727 | spin_unlock(&glob->lru_lock); | ||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | *node = drm_mm_get_block_atomic_range(*node, mem->num_pages, | ||
| 731 | mem->page_alignment, | ||
| 732 | placement->fpfn, | ||
| 733 | lpfn); | ||
| 734 | spin_unlock(&glob->lru_lock); | ||
| 735 | } while (*node == NULL); | ||
| 736 | return 0; | ||
| 737 | } | ||
| 738 | |||
| 623 | /** | 739 | /** |
| 624 | * Repeatedly evict memory from the LRU for @mem_type until we create enough | 740 | * Repeatedly evict memory from the LRU for @mem_type until we create enough |
| 625 | * space, or we've evicted everything and there isn't enough space. | 741 | * space, or we've evicted everything and there isn't enough space. |
| 626 | */ | 742 | */ |
| 627 | static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev, | 743 | static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, |
| 628 | struct ttm_mem_reg *mem, | 744 | uint32_t mem_type, |
| 629 | uint32_t mem_type, | 745 | struct ttm_placement *placement, |
| 630 | bool interruptible, bool no_wait) | 746 | struct ttm_mem_reg *mem, |
| 747 | bool interruptible, bool no_wait) | ||
| 631 | { | 748 | { |
| 749 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 632 | struct ttm_bo_global *glob = bdev->glob; | 750 | struct ttm_bo_global *glob = bdev->glob; |
| 633 | struct drm_mm_node *node; | ||
| 634 | struct ttm_buffer_object *entry; | ||
| 635 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | 751 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; |
| 636 | struct list_head *lru; | 752 | struct drm_mm_node *node; |
| 637 | unsigned long num_pages = mem->num_pages; | ||
| 638 | int put_count = 0; | ||
| 639 | int ret; | 753 | int ret; |
| 640 | 754 | ||
| 641 | retry_pre_get: | ||
| 642 | ret = drm_mm_pre_get(&man->manager); | ||
| 643 | if (unlikely(ret != 0)) | ||
| 644 | return ret; | ||
| 645 | |||
| 646 | spin_lock(&glob->lru_lock); | ||
| 647 | do { | 755 | do { |
| 648 | node = drm_mm_search_free(&man->manager, num_pages, | 756 | ret = ttm_bo_man_get_node(bo, man, placement, mem, &node); |
| 649 | mem->page_alignment, 1); | 757 | if (unlikely(ret != 0)) |
| 758 | return ret; | ||
| 650 | if (node) | 759 | if (node) |
| 651 | break; | 760 | break; |
| 652 | 761 | spin_lock(&glob->lru_lock); | |
| 653 | lru = &man->lru; | 762 | if (list_empty(&man->lru)) { |
| 654 | if (list_empty(lru)) | 763 | spin_unlock(&glob->lru_lock); |
| 655 | break; | 764 | break; |
| 656 | 765 | } | |
| 657 | entry = list_first_entry(lru, struct ttm_buffer_object, lru); | ||
| 658 | kref_get(&entry->list_kref); | ||
| 659 | |||
| 660 | ret = | ||
| 661 | ttm_bo_reserve_locked(entry, interruptible, no_wait, | ||
| 662 | false, 0); | ||
| 663 | |||
| 664 | if (likely(ret == 0)) | ||
| 665 | put_count = ttm_bo_del_from_lru(entry); | ||
| 666 | |||
| 667 | spin_unlock(&glob->lru_lock); | 766 | spin_unlock(&glob->lru_lock); |
| 668 | 767 | ret = ttm_mem_evict_first(bdev, mem_type, interruptible, | |
| 768 | no_wait); | ||
| 669 | if (unlikely(ret != 0)) | 769 | if (unlikely(ret != 0)) |
| 670 | return ret; | 770 | return ret; |
| 671 | |||
| 672 | while (put_count--) | ||
| 673 | kref_put(&entry->list_kref, ttm_bo_ref_bug); | ||
| 674 | |||
| 675 | ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait); | ||
| 676 | |||
| 677 | ttm_bo_unreserve(entry); | ||
| 678 | |||
| 679 | kref_put(&entry->list_kref, ttm_bo_release_list); | ||
| 680 | if (ret) | ||
| 681 | return ret; | ||
| 682 | |||
| 683 | spin_lock(&glob->lru_lock); | ||
| 684 | } while (1); | 771 | } while (1); |
| 685 | 772 | if (node == NULL) | |
| 686 | if (!node) { | ||
| 687 | spin_unlock(&glob->lru_lock); | ||
| 688 | return -ENOMEM; | 773 | return -ENOMEM; |
| 689 | } | ||
| 690 | |||
| 691 | node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment); | ||
| 692 | if (unlikely(!node)) { | ||
| 693 | spin_unlock(&glob->lru_lock); | ||
| 694 | goto retry_pre_get; | ||
| 695 | } | ||
| 696 | |||
| 697 | spin_unlock(&glob->lru_lock); | ||
| 698 | mem->mm_node = node; | 774 | mem->mm_node = node; |
| 699 | mem->mem_type = mem_type; | 775 | mem->mem_type = mem_type; |
| 700 | return 0; | 776 | return 0; |
| @@ -725,7 +801,6 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, | |||
| 725 | return result; | 801 | return result; |
| 726 | } | 802 | } |
| 727 | 803 | ||
| 728 | |||
| 729 | static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, | 804 | static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, |
| 730 | bool disallow_fixed, | 805 | bool disallow_fixed, |
| 731 | uint32_t mem_type, | 806 | uint32_t mem_type, |
| @@ -758,66 +833,55 @@ static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, | |||
| 758 | * space. | 833 | * space. |
| 759 | */ | 834 | */ |
| 760 | int ttm_bo_mem_space(struct ttm_buffer_object *bo, | 835 | int ttm_bo_mem_space(struct ttm_buffer_object *bo, |
| 761 | uint32_t proposed_placement, | 836 | struct ttm_placement *placement, |
| 762 | struct ttm_mem_reg *mem, | 837 | struct ttm_mem_reg *mem, |
| 763 | bool interruptible, bool no_wait) | 838 | bool interruptible, bool no_wait) |
| 764 | { | 839 | { |
| 765 | struct ttm_bo_device *bdev = bo->bdev; | 840 | struct ttm_bo_device *bdev = bo->bdev; |
| 766 | struct ttm_bo_global *glob = bo->glob; | ||
| 767 | struct ttm_mem_type_manager *man; | 841 | struct ttm_mem_type_manager *man; |
| 768 | |||
| 769 | uint32_t num_prios = bdev->driver->num_mem_type_prio; | ||
| 770 | const uint32_t *prios = bdev->driver->mem_type_prio; | ||
| 771 | uint32_t i; | ||
| 772 | uint32_t mem_type = TTM_PL_SYSTEM; | 842 | uint32_t mem_type = TTM_PL_SYSTEM; |
| 773 | uint32_t cur_flags = 0; | 843 | uint32_t cur_flags = 0; |
| 774 | bool type_found = false; | 844 | bool type_found = false; |
| 775 | bool type_ok = false; | 845 | bool type_ok = false; |
| 776 | bool has_eagain = false; | 846 | bool has_erestartsys = false; |
| 777 | struct drm_mm_node *node = NULL; | 847 | struct drm_mm_node *node = NULL; |
| 778 | int ret; | 848 | int i, ret; |
| 779 | 849 | ||
| 780 | mem->mm_node = NULL; | 850 | mem->mm_node = NULL; |
| 781 | for (i = 0; i < num_prios; ++i) { | 851 | for (i = 0; i <= placement->num_placement; ++i) { |
| 782 | mem_type = prios[i]; | 852 | ret = ttm_mem_type_from_flags(placement->placement[i], |
| 853 | &mem_type); | ||
| 854 | if (ret) | ||
| 855 | return ret; | ||
| 783 | man = &bdev->man[mem_type]; | 856 | man = &bdev->man[mem_type]; |
| 784 | 857 | ||
| 785 | type_ok = ttm_bo_mt_compatible(man, | 858 | type_ok = ttm_bo_mt_compatible(man, |
| 786 | bo->type == ttm_bo_type_user, | 859 | bo->type == ttm_bo_type_user, |
| 787 | mem_type, proposed_placement, | 860 | mem_type, |
| 788 | &cur_flags); | 861 | placement->placement[i], |
| 862 | &cur_flags); | ||
| 789 | 863 | ||
| 790 | if (!type_ok) | 864 | if (!type_ok) |
| 791 | continue; | 865 | continue; |
| 792 | 866 | ||
| 793 | cur_flags = ttm_bo_select_caching(man, bo->mem.placement, | 867 | cur_flags = ttm_bo_select_caching(man, bo->mem.placement, |
| 794 | cur_flags); | 868 | cur_flags); |
| 869 | /* | ||
| 870 | * Use the access and other non-mapping-related flag bits from | ||
| 871 | * the memory placement flags to the current flags | ||
| 872 | */ | ||
| 873 | ttm_flag_masked(&cur_flags, placement->placement[i], | ||
| 874 | ~TTM_PL_MASK_MEMTYPE); | ||
| 795 | 875 | ||
| 796 | if (mem_type == TTM_PL_SYSTEM) | 876 | if (mem_type == TTM_PL_SYSTEM) |
| 797 | break; | 877 | break; |
| 798 | 878 | ||
| 799 | if (man->has_type && man->use_type) { | 879 | if (man->has_type && man->use_type) { |
| 800 | type_found = true; | 880 | type_found = true; |
| 801 | do { | 881 | ret = ttm_bo_man_get_node(bo, man, placement, mem, |
| 802 | ret = drm_mm_pre_get(&man->manager); | 882 | &node); |
| 803 | if (unlikely(ret)) | 883 | if (unlikely(ret)) |
| 804 | return ret; | 884 | return ret; |
| 805 | |||
| 806 | spin_lock(&glob->lru_lock); | ||
| 807 | node = drm_mm_search_free(&man->manager, | ||
| 808 | mem->num_pages, | ||
| 809 | mem->page_alignment, | ||
| 810 | 1); | ||
| 811 | if (unlikely(!node)) { | ||
| 812 | spin_unlock(&glob->lru_lock); | ||
| 813 | break; | ||
| 814 | } | ||
| 815 | node = drm_mm_get_block_atomic(node, | ||
| 816 | mem->num_pages, | ||
| 817 | mem-> | ||
| 818 | page_alignment); | ||
| 819 | spin_unlock(&glob->lru_lock); | ||
| 820 | } while (!node); | ||
| 821 | } | 885 | } |
| 822 | if (node) | 886 | if (node) |
| 823 | break; | 887 | break; |
| @@ -827,67 +891,65 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, | |||
| 827 | mem->mm_node = node; | 891 | mem->mm_node = node; |
| 828 | mem->mem_type = mem_type; | 892 | mem->mem_type = mem_type; |
| 829 | mem->placement = cur_flags; | 893 | mem->placement = cur_flags; |
| 894 | if (node) | ||
| 895 | node->private = bo; | ||
| 830 | return 0; | 896 | return 0; |
| 831 | } | 897 | } |
| 832 | 898 | ||
| 833 | if (!type_found) | 899 | if (!type_found) |
| 834 | return -EINVAL; | 900 | return -EINVAL; |
| 835 | 901 | ||
| 836 | num_prios = bdev->driver->num_mem_busy_prio; | 902 | for (i = 0; i <= placement->num_busy_placement; ++i) { |
| 837 | prios = bdev->driver->mem_busy_prio; | 903 | ret = ttm_mem_type_from_flags(placement->placement[i], |
| 838 | 904 | &mem_type); | |
| 839 | for (i = 0; i < num_prios; ++i) { | 905 | if (ret) |
| 840 | mem_type = prios[i]; | 906 | return ret; |
| 841 | man = &bdev->man[mem_type]; | 907 | man = &bdev->man[mem_type]; |
| 842 | |||
| 843 | if (!man->has_type) | 908 | if (!man->has_type) |
| 844 | continue; | 909 | continue; |
| 845 | |||
| 846 | if (!ttm_bo_mt_compatible(man, | 910 | if (!ttm_bo_mt_compatible(man, |
| 847 | bo->type == ttm_bo_type_user, | 911 | bo->type == ttm_bo_type_user, |
| 848 | mem_type, | 912 | mem_type, |
| 849 | proposed_placement, &cur_flags)) | 913 | placement->placement[i], |
| 914 | &cur_flags)) | ||
| 850 | continue; | 915 | continue; |
| 851 | 916 | ||
| 852 | cur_flags = ttm_bo_select_caching(man, bo->mem.placement, | 917 | cur_flags = ttm_bo_select_caching(man, bo->mem.placement, |
| 853 | cur_flags); | 918 | cur_flags); |
| 919 | /* | ||
| 920 | * Use the access and other non-mapping-related flag bits from | ||
| 921 | * the memory placement flags to the current flags | ||
| 922 | */ | ||
| 923 | ttm_flag_masked(&cur_flags, placement->placement[i], | ||
| 924 | ~TTM_PL_MASK_MEMTYPE); | ||
| 854 | 925 | ||
| 855 | ret = ttm_bo_mem_force_space(bdev, mem, mem_type, | 926 | ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, |
| 856 | interruptible, no_wait); | 927 | interruptible, no_wait); |
| 857 | |||
| 858 | if (ret == 0 && mem->mm_node) { | 928 | if (ret == 0 && mem->mm_node) { |
| 859 | mem->placement = cur_flags; | 929 | mem->placement = cur_flags; |
| 930 | mem->mm_node->private = bo; | ||
| 860 | return 0; | 931 | return 0; |
| 861 | } | 932 | } |
| 862 | 933 | if (ret == -ERESTARTSYS) | |
| 863 | if (ret == -ERESTART) | 934 | has_erestartsys = true; |
| 864 | has_eagain = true; | ||
| 865 | } | 935 | } |
| 866 | 936 | ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM; | |
| 867 | ret = (has_eagain) ? -ERESTART : -ENOMEM; | ||
| 868 | return ret; | 937 | return ret; |
| 869 | } | 938 | } |
| 870 | EXPORT_SYMBOL(ttm_bo_mem_space); | 939 | EXPORT_SYMBOL(ttm_bo_mem_space); |
| 871 | 940 | ||
| 872 | int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait) | 941 | int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait) |
| 873 | { | 942 | { |
| 874 | int ret = 0; | ||
| 875 | |||
| 876 | if ((atomic_read(&bo->cpu_writers) > 0) && no_wait) | 943 | if ((atomic_read(&bo->cpu_writers) > 0) && no_wait) |
| 877 | return -EBUSY; | 944 | return -EBUSY; |
| 878 | 945 | ||
| 879 | ret = wait_event_interruptible(bo->event_queue, | 946 | return wait_event_interruptible(bo->event_queue, |
| 880 | atomic_read(&bo->cpu_writers) == 0); | 947 | atomic_read(&bo->cpu_writers) == 0); |
| 881 | |||
| 882 | if (ret == -ERESTARTSYS) | ||
| 883 | ret = -ERESTART; | ||
| 884 | |||
| 885 | return ret; | ||
| 886 | } | 948 | } |
| 887 | 949 | ||
| 888 | int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | 950 | int ttm_bo_move_buffer(struct ttm_buffer_object *bo, |
| 889 | uint32_t proposed_placement, | 951 | struct ttm_placement *placement, |
| 890 | bool interruptible, bool no_wait) | 952 | bool interruptible, bool no_wait) |
| 891 | { | 953 | { |
| 892 | struct ttm_bo_global *glob = bo->glob; | 954 | struct ttm_bo_global *glob = bo->glob; |
| 893 | int ret = 0; | 955 | int ret = 0; |
| @@ -900,101 +962,82 @@ int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | |||
| 900 | * Have the driver move function wait for idle when necessary, | 962 | * Have the driver move function wait for idle when necessary, |
| 901 | * instead of doing it here. | 963 | * instead of doing it here. |
| 902 | */ | 964 | */ |
| 903 | |||
| 904 | spin_lock(&bo->lock); | 965 | spin_lock(&bo->lock); |
| 905 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); | 966 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); |
| 906 | spin_unlock(&bo->lock); | 967 | spin_unlock(&bo->lock); |
| 907 | |||
| 908 | if (ret) | 968 | if (ret) |
| 909 | return ret; | 969 | return ret; |
| 910 | |||
| 911 | mem.num_pages = bo->num_pages; | 970 | mem.num_pages = bo->num_pages; |
| 912 | mem.size = mem.num_pages << PAGE_SHIFT; | 971 | mem.size = mem.num_pages << PAGE_SHIFT; |
| 913 | mem.page_alignment = bo->mem.page_alignment; | 972 | mem.page_alignment = bo->mem.page_alignment; |
| 914 | |||
| 915 | /* | 973 | /* |
| 916 | * Determine where to move the buffer. | 974 | * Determine where to move the buffer. |
| 917 | */ | 975 | */ |
| 918 | 976 | ret = ttm_bo_mem_space(bo, placement, &mem, interruptible, no_wait); | |
| 919 | ret = ttm_bo_mem_space(bo, proposed_placement, &mem, | ||
| 920 | interruptible, no_wait); | ||
| 921 | if (ret) | 977 | if (ret) |
| 922 | goto out_unlock; | 978 | goto out_unlock; |
| 923 | |||
| 924 | ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait); | 979 | ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait); |
| 925 | |||
| 926 | out_unlock: | 980 | out_unlock: |
| 927 | if (ret && mem.mm_node) { | 981 | if (ret && mem.mm_node) { |
| 928 | spin_lock(&glob->lru_lock); | 982 | spin_lock(&glob->lru_lock); |
| 983 | mem.mm_node->private = NULL; | ||
| 929 | drm_mm_put_block(mem.mm_node); | 984 | drm_mm_put_block(mem.mm_node); |
| 930 | spin_unlock(&glob->lru_lock); | 985 | spin_unlock(&glob->lru_lock); |
| 931 | } | 986 | } |
| 932 | return ret; | 987 | return ret; |
| 933 | } | 988 | } |
| 934 | 989 | ||
| 935 | static int ttm_bo_mem_compat(uint32_t proposed_placement, | 990 | static int ttm_bo_mem_compat(struct ttm_placement *placement, |
| 936 | struct ttm_mem_reg *mem) | 991 | struct ttm_mem_reg *mem) |
| 937 | { | 992 | { |
| 938 | if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0) | 993 | int i; |
| 939 | return 0; | 994 | |
| 940 | if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0) | 995 | for (i = 0; i < placement->num_placement; i++) { |
| 941 | return 0; | 996 | if ((placement->placement[i] & mem->placement & |
| 942 | 997 | TTM_PL_MASK_CACHING) && | |
| 943 | return 1; | 998 | (placement->placement[i] & mem->placement & |
| 999 | TTM_PL_MASK_MEM)) | ||
| 1000 | return i; | ||
| 1001 | } | ||
| 1002 | return -1; | ||
| 944 | } | 1003 | } |
| 945 | 1004 | ||
| 946 | int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | 1005 | int ttm_buffer_object_validate(struct ttm_buffer_object *bo, |
| 947 | uint32_t proposed_placement, | 1006 | struct ttm_placement *placement, |
| 948 | bool interruptible, bool no_wait) | 1007 | bool interruptible, bool no_wait) |
| 949 | { | 1008 | { |
| 950 | int ret; | 1009 | int ret; |
| 951 | 1010 | ||
| 952 | BUG_ON(!atomic_read(&bo->reserved)); | 1011 | BUG_ON(!atomic_read(&bo->reserved)); |
| 953 | bo->proposed_placement = proposed_placement; | 1012 | /* Check that range is valid */ |
| 954 | 1013 | if (placement->lpfn || placement->fpfn) | |
| 955 | TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n", | 1014 | if (placement->fpfn > placement->lpfn || |
| 956 | (unsigned long)proposed_placement, | 1015 | (placement->lpfn - placement->fpfn) < bo->num_pages) |
| 957 | (unsigned long)bo->mem.placement); | 1016 | return -EINVAL; |
| 958 | |||
| 959 | /* | 1017 | /* |
| 960 | * Check whether we need to move buffer. | 1018 | * Check whether we need to move buffer. |
| 961 | */ | 1019 | */ |
| 962 | 1020 | ret = ttm_bo_mem_compat(placement, &bo->mem); | |
| 963 | if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) { | 1021 | if (ret < 0) { |
| 964 | ret = ttm_bo_move_buffer(bo, bo->proposed_placement, | 1022 | ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait); |
| 965 | interruptible, no_wait); | 1023 | if (ret) |
| 966 | if (ret) { | ||
| 967 | if (ret != -ERESTART) | ||
| 968 | printk(KERN_ERR TTM_PFX | ||
| 969 | "Failed moving buffer. " | ||
| 970 | "Proposed placement 0x%08x\n", | ||
| 971 | bo->proposed_placement); | ||
| 972 | if (ret == -ENOMEM) | ||
| 973 | printk(KERN_ERR TTM_PFX | ||
| 974 | "Out of aperture space or " | ||
| 975 | "DRM memory quota.\n"); | ||
| 976 | return ret; | 1024 | return ret; |
| 977 | } | 1025 | } else { |
| 1026 | /* | ||
| 1027 | * Use the access and other non-mapping-related flag bits from | ||
| 1028 | * the compatible memory placement flags to the active flags | ||
| 1029 | */ | ||
| 1030 | ttm_flag_masked(&bo->mem.placement, placement->placement[ret], | ||
| 1031 | ~TTM_PL_MASK_MEMTYPE); | ||
| 978 | } | 1032 | } |
| 979 | |||
| 980 | /* | 1033 | /* |
| 981 | * We might need to add a TTM. | 1034 | * We might need to add a TTM. |
| 982 | */ | 1035 | */ |
| 983 | |||
| 984 | if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { | 1036 | if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { |
| 985 | ret = ttm_bo_add_ttm(bo, true); | 1037 | ret = ttm_bo_add_ttm(bo, true); |
| 986 | if (ret) | 1038 | if (ret) |
| 987 | return ret; | 1039 | return ret; |
| 988 | } | 1040 | } |
| 989 | /* | ||
| 990 | * Validation has succeeded, move the access and other | ||
| 991 | * non-mapping-related flag bits from the proposed flags to | ||
| 992 | * the active flags | ||
| 993 | */ | ||
| 994 | |||
| 995 | ttm_flag_masked(&bo->mem.placement, bo->proposed_placement, | ||
| 996 | ~TTM_PL_MASK_MEMTYPE); | ||
| 997 | |||
| 998 | return 0; | 1041 | return 0; |
| 999 | } | 1042 | } |
| 1000 | EXPORT_SYMBOL(ttm_buffer_object_validate); | 1043 | EXPORT_SYMBOL(ttm_buffer_object_validate); |
| @@ -1042,8 +1085,10 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev, | |||
| 1042 | size_t acc_size, | 1085 | size_t acc_size, |
| 1043 | void (*destroy) (struct ttm_buffer_object *)) | 1086 | void (*destroy) (struct ttm_buffer_object *)) |
| 1044 | { | 1087 | { |
| 1045 | int ret = 0; | 1088 | int i, c, ret = 0; |
| 1046 | unsigned long num_pages; | 1089 | unsigned long num_pages; |
| 1090 | uint32_t placements[8]; | ||
| 1091 | struct ttm_placement placement; | ||
| 1047 | 1092 | ||
| 1048 | size += buffer_start & ~PAGE_MASK; | 1093 | size += buffer_start & ~PAGE_MASK; |
| 1049 | num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 1094 | num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| @@ -1100,7 +1145,16 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev, | |||
| 1100 | goto out_err; | 1145 | goto out_err; |
| 1101 | } | 1146 | } |
| 1102 | 1147 | ||
| 1103 | ret = ttm_buffer_object_validate(bo, flags, interruptible, false); | 1148 | placement.fpfn = 0; |
| 1149 | placement.lpfn = 0; | ||
| 1150 | for (i = 0, c = 0; i <= TTM_PL_PRIV5; i++) | ||
| 1151 | if (flags & (1 << i)) | ||
| 1152 | placements[c++] = (flags & ~TTM_PL_MASK_MEM) | (1 << i); | ||
| 1153 | placement.placement = placements; | ||
| 1154 | placement.num_placement = c; | ||
| 1155 | placement.busy_placement = placements; | ||
| 1156 | placement.num_busy_placement = c; | ||
| 1157 | ret = ttm_buffer_object_validate(bo, &placement, interruptible, false); | ||
| 1104 | if (ret) | 1158 | if (ret) |
| 1105 | goto out_err; | 1159 | goto out_err; |
| 1106 | 1160 | ||
| @@ -1135,8 +1189,8 @@ int ttm_buffer_object_create(struct ttm_bo_device *bdev, | |||
| 1135 | struct ttm_buffer_object **p_bo) | 1189 | struct ttm_buffer_object **p_bo) |
| 1136 | { | 1190 | { |
| 1137 | struct ttm_buffer_object *bo; | 1191 | struct ttm_buffer_object *bo; |
| 1138 | int ret; | ||
| 1139 | struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; | 1192 | struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; |
| 1193 | int ret; | ||
| 1140 | 1194 | ||
| 1141 | size_t acc_size = | 1195 | size_t acc_size = |
| 1142 | ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); | 1196 | ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); |
| @@ -1161,66 +1215,32 @@ int ttm_buffer_object_create(struct ttm_bo_device *bdev, | |||
| 1161 | return ret; | 1215 | return ret; |
| 1162 | } | 1216 | } |
| 1163 | 1217 | ||
| 1164 | static int ttm_bo_leave_list(struct ttm_buffer_object *bo, | ||
| 1165 | uint32_t mem_type, bool allow_errors) | ||
| 1166 | { | ||
| 1167 | int ret; | ||
| 1168 | |||
| 1169 | spin_lock(&bo->lock); | ||
| 1170 | ret = ttm_bo_wait(bo, false, false, false); | ||
| 1171 | spin_unlock(&bo->lock); | ||
| 1172 | |||
| 1173 | if (ret && allow_errors) | ||
| 1174 | goto out; | ||
| 1175 | |||
| 1176 | if (bo->mem.mem_type == mem_type) | ||
| 1177 | ret = ttm_bo_evict(bo, mem_type, false, false); | ||
| 1178 | |||
| 1179 | if (ret) { | ||
| 1180 | if (allow_errors) { | ||
| 1181 | goto out; | ||
| 1182 | } else { | ||
| 1183 | ret = 0; | ||
| 1184 | printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n"); | ||
| 1185 | } | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | out: | ||
| 1189 | return ret; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, | 1218 | static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, |
| 1193 | struct list_head *head, | 1219 | unsigned mem_type, bool allow_errors) |
| 1194 | unsigned mem_type, bool allow_errors) | ||
| 1195 | { | 1220 | { |
| 1221 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | ||
| 1196 | struct ttm_bo_global *glob = bdev->glob; | 1222 | struct ttm_bo_global *glob = bdev->glob; |
| 1197 | struct ttm_buffer_object *entry; | ||
| 1198 | int ret; | 1223 | int ret; |
| 1199 | int put_count; | ||
| 1200 | 1224 | ||
| 1201 | /* | 1225 | /* |
| 1202 | * Can't use standard list traversal since we're unlocking. | 1226 | * Can't use standard list traversal since we're unlocking. |
| 1203 | */ | 1227 | */ |
| 1204 | 1228 | ||
| 1205 | spin_lock(&glob->lru_lock); | 1229 | spin_lock(&glob->lru_lock); |
| 1206 | 1230 | while (!list_empty(&man->lru)) { | |
| 1207 | while (!list_empty(head)) { | ||
| 1208 | entry = list_first_entry(head, struct ttm_buffer_object, lru); | ||
| 1209 | kref_get(&entry->list_kref); | ||
| 1210 | ret = ttm_bo_reserve_locked(entry, false, false, false, 0); | ||
| 1211 | put_count = ttm_bo_del_from_lru(entry); | ||
| 1212 | spin_unlock(&glob->lru_lock); | 1231 | spin_unlock(&glob->lru_lock); |
| 1213 | while (put_count--) | 1232 | ret = ttm_mem_evict_first(bdev, mem_type, false, false); |
| 1214 | kref_put(&entry->list_kref, ttm_bo_ref_bug); | 1233 | if (ret) { |
| 1215 | BUG_ON(ret); | 1234 | if (allow_errors) { |
| 1216 | ret = ttm_bo_leave_list(entry, mem_type, allow_errors); | 1235 | return ret; |
| 1217 | ttm_bo_unreserve(entry); | 1236 | } else { |
| 1218 | kref_put(&entry->list_kref, ttm_bo_release_list); | 1237 | printk(KERN_ERR TTM_PFX |
| 1238 | "Cleanup eviction failed\n"); | ||
| 1239 | } | ||
| 1240 | } | ||
| 1219 | spin_lock(&glob->lru_lock); | 1241 | spin_lock(&glob->lru_lock); |
| 1220 | } | 1242 | } |
| 1221 | |||
| 1222 | spin_unlock(&glob->lru_lock); | 1243 | spin_unlock(&glob->lru_lock); |
| 1223 | |||
| 1224 | return 0; | 1244 | return 0; |
| 1225 | } | 1245 | } |
| 1226 | 1246 | ||
| @@ -1247,7 +1267,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) | |||
| 1247 | 1267 | ||
| 1248 | ret = 0; | 1268 | ret = 0; |
| 1249 | if (mem_type > 0) { | 1269 | if (mem_type > 0) { |
| 1250 | ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false); | 1270 | ttm_bo_force_list_clean(bdev, mem_type, false); |
| 1251 | 1271 | ||
| 1252 | spin_lock(&glob->lru_lock); | 1272 | spin_lock(&glob->lru_lock); |
| 1253 | if (drm_mm_clean(&man->manager)) | 1273 | if (drm_mm_clean(&man->manager)) |
| @@ -1280,12 +1300,12 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) | |||
| 1280 | return 0; | 1300 | return 0; |
| 1281 | } | 1301 | } |
| 1282 | 1302 | ||
| 1283 | return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true); | 1303 | return ttm_bo_force_list_clean(bdev, mem_type, true); |
| 1284 | } | 1304 | } |
| 1285 | EXPORT_SYMBOL(ttm_bo_evict_mm); | 1305 | EXPORT_SYMBOL(ttm_bo_evict_mm); |
| 1286 | 1306 | ||
| 1287 | int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | 1307 | int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, |
| 1288 | unsigned long p_offset, unsigned long p_size) | 1308 | unsigned long p_size) |
| 1289 | { | 1309 | { |
| 1290 | int ret = -EINVAL; | 1310 | int ret = -EINVAL; |
| 1291 | struct ttm_mem_type_manager *man; | 1311 | struct ttm_mem_type_manager *man; |
| @@ -1315,7 +1335,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | |||
| 1315 | type); | 1335 | type); |
| 1316 | return ret; | 1336 | return ret; |
| 1317 | } | 1337 | } |
| 1318 | ret = drm_mm_init(&man->manager, p_offset, p_size); | 1338 | ret = drm_mm_init(&man->manager, 0, p_size); |
| 1319 | if (ret) | 1339 | if (ret) |
| 1320 | return ret; | 1340 | return ret; |
| 1321 | } | 1341 | } |
| @@ -1464,7 +1484,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, | |||
| 1464 | * Initialize the system memory buffer type. | 1484 | * Initialize the system memory buffer type. |
| 1465 | * Other types need to be driver / IOCTL initialized. | 1485 | * Other types need to be driver / IOCTL initialized. |
| 1466 | */ | 1486 | */ |
| 1467 | ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0); | 1487 | ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); |
| 1468 | if (unlikely(ret != 0)) | 1488 | if (unlikely(ret != 0)) |
| 1469 | goto out_no_sys; | 1489 | goto out_no_sys; |
| 1470 | 1490 | ||
| @@ -1694,7 +1714,7 @@ int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible, | |||
| 1694 | ret = wait_event_interruptible | 1714 | ret = wait_event_interruptible |
| 1695 | (bo->event_queue, atomic_read(&bo->reserved) == 0); | 1715 | (bo->event_queue, atomic_read(&bo->reserved) == 0); |
| 1696 | if (unlikely(ret != 0)) | 1716 | if (unlikely(ret != 0)) |
| 1697 | return -ERESTART; | 1717 | return ret; |
| 1698 | } else { | 1718 | } else { |
| 1699 | wait_event(bo->event_queue, | 1719 | wait_event(bo->event_queue, |
| 1700 | atomic_read(&bo->reserved) == 0); | 1720 | atomic_read(&bo->reserved) == 0); |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 1c040d040338..609a85a4d855 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
| @@ -114,7 +114,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 114 | ret = ttm_bo_wait(bo, false, true, false); | 114 | ret = ttm_bo_wait(bo, false, true, false); |
| 115 | spin_unlock(&bo->lock); | 115 | spin_unlock(&bo->lock); |
| 116 | if (unlikely(ret != 0)) { | 116 | if (unlikely(ret != 0)) { |
| 117 | retval = (ret != -ERESTART) ? | 117 | retval = (ret != -ERESTARTSYS) ? |
| 118 | VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; | 118 | VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; |
| 119 | goto out_unlock; | 119 | goto out_unlock; |
| 120 | } | 120 | } |
| @@ -349,9 +349,6 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, | |||
| 349 | switch (ret) { | 349 | switch (ret) { |
| 350 | case 0: | 350 | case 0: |
| 351 | break; | 351 | break; |
| 352 | case -ERESTART: | ||
| 353 | ret = -EINTR; | ||
| 354 | goto out_unref; | ||
| 355 | case -EBUSY: | 352 | case -EBUSY: |
| 356 | ret = -EAGAIN; | 353 | ret = -EAGAIN; |
| 357 | goto out_unref; | 354 | goto out_unref; |
| @@ -421,8 +418,6 @@ ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf, | |||
| 421 | switch (ret) { | 418 | switch (ret) { |
| 422 | case 0: | 419 | case 0: |
| 423 | break; | 420 | break; |
| 424 | case -ERESTART: | ||
| 425 | return -EINTR; | ||
| 426 | case -EBUSY: | 421 | case -EBUSY: |
| 427 | return -EAGAIN; | 422 | return -EAGAIN; |
| 428 | default: | 423 | default: |
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index 8bfde5f40841..f5245c02b8fd 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c | |||
| @@ -323,8 +323,10 @@ static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob, | |||
| 323 | * No special dma32 zone needed. | 323 | * No special dma32 zone needed. |
| 324 | */ | 324 | */ |
| 325 | 325 | ||
| 326 | if (mem <= ((uint64_t) 1ULL << 32)) | 326 | if (mem <= ((uint64_t) 1ULL << 32)) { |
| 327 | kfree(zone); | ||
| 327 | return 0; | 328 | return 0; |
| 329 | } | ||
| 328 | 330 | ||
| 329 | /* | 331 | /* |
| 330 | * Limit max dma32 memory to 4GB for now | 332 | * Limit max dma32 memory to 4GB for now |
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 62329f9a42cb..4c10be39a43b 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
| @@ -66,6 +66,13 @@ extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, | |||
| 66 | unsigned long size, | 66 | unsigned long size, |
| 67 | unsigned alignment, | 67 | unsigned alignment, |
| 68 | int atomic); | 68 | int atomic); |
| 69 | extern struct drm_mm_node *drm_mm_get_block_range_generic( | ||
| 70 | struct drm_mm_node *node, | ||
| 71 | unsigned long size, | ||
| 72 | unsigned alignment, | ||
| 73 | unsigned long start, | ||
| 74 | unsigned long end, | ||
| 75 | int atomic); | ||
| 69 | static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, | 76 | static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent, |
| 70 | unsigned long size, | 77 | unsigned long size, |
| 71 | unsigned alignment) | 78 | unsigned alignment) |
| @@ -78,11 +85,38 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *pa | |||
| 78 | { | 85 | { |
| 79 | return drm_mm_get_block_generic(parent, size, alignment, 1); | 86 | return drm_mm_get_block_generic(parent, size, alignment, 1); |
| 80 | } | 87 | } |
| 88 | static inline struct drm_mm_node *drm_mm_get_block_range( | ||
| 89 | struct drm_mm_node *parent, | ||
| 90 | unsigned long size, | ||
| 91 | unsigned alignment, | ||
| 92 | unsigned long start, | ||
| 93 | unsigned long end) | ||
| 94 | { | ||
| 95 | return drm_mm_get_block_range_generic(parent, size, alignment, | ||
| 96 | start, end, 0); | ||
| 97 | } | ||
| 98 | static inline struct drm_mm_node *drm_mm_get_block_atomic_range( | ||
| 99 | struct drm_mm_node *parent, | ||
| 100 | unsigned long size, | ||
| 101 | unsigned alignment, | ||
| 102 | unsigned long start, | ||
| 103 | unsigned long end) | ||
| 104 | { | ||
| 105 | return drm_mm_get_block_range_generic(parent, size, alignment, | ||
| 106 | start, end, 1); | ||
| 107 | } | ||
| 81 | extern void drm_mm_put_block(struct drm_mm_node *cur); | 108 | extern void drm_mm_put_block(struct drm_mm_node *cur); |
| 82 | extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, | 109 | extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, |
| 83 | unsigned long size, | 110 | unsigned long size, |
| 84 | unsigned alignment, | 111 | unsigned alignment, |
| 85 | int best_match); | 112 | int best_match); |
| 113 | extern struct drm_mm_node *drm_mm_search_free_in_range( | ||
| 114 | const struct drm_mm *mm, | ||
| 115 | unsigned long size, | ||
| 116 | unsigned alignment, | ||
| 117 | unsigned long start, | ||
| 118 | unsigned long end, | ||
| 119 | int best_match); | ||
| 86 | extern int drm_mm_init(struct drm_mm *mm, unsigned long start, | 120 | extern int drm_mm_init(struct drm_mm *mm, unsigned long start, |
| 87 | unsigned long size); | 121 | unsigned long size); |
| 88 | extern void drm_mm_takedown(struct drm_mm *mm); | 122 | extern void drm_mm_takedown(struct drm_mm *mm); |
| @@ -99,6 +133,7 @@ static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block) | |||
| 99 | return block->mm; | 133 | return block->mm; |
| 100 | } | 134 | } |
| 101 | 135 | ||
| 136 | extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); | ||
| 102 | #ifdef CONFIG_DEBUG_FS | 137 | #ifdef CONFIG_DEBUG_FS |
| 103 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm); | 138 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm); |
| 104 | #endif | 139 | #endif |
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 491146170522..4fd498523ce3 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h | |||
| @@ -44,6 +44,29 @@ struct ttm_bo_device; | |||
| 44 | 44 | ||
| 45 | struct drm_mm_node; | 45 | struct drm_mm_node; |
| 46 | 46 | ||
| 47 | |||
| 48 | /** | ||
| 49 | * struct ttm_placement | ||
| 50 | * | ||
| 51 | * @fpfn: first valid page frame number to put the object | ||
| 52 | * @lpfn: last valid page frame number to put the object | ||
| 53 | * @num_placement: number of prefered placements | ||
| 54 | * @placement: prefered placements | ||
| 55 | * @num_busy_placement: number of prefered placements when need to evict buffer | ||
| 56 | * @busy_placement: prefered placements when need to evict buffer | ||
| 57 | * | ||
| 58 | * Structure indicating the placement you request for an object. | ||
| 59 | */ | ||
| 60 | struct ttm_placement { | ||
| 61 | unsigned fpfn; | ||
| 62 | unsigned lpfn; | ||
| 63 | unsigned num_placement; | ||
| 64 | const uint32_t *placement; | ||
| 65 | unsigned num_busy_placement; | ||
| 66 | const uint32_t *busy_placement; | ||
| 67 | }; | ||
| 68 | |||
| 69 | |||
| 47 | /** | 70 | /** |
| 48 | * struct ttm_mem_reg | 71 | * struct ttm_mem_reg |
| 49 | * | 72 | * |
| @@ -109,10 +132,6 @@ struct ttm_tt; | |||
| 109 | * the object is destroyed. | 132 | * the object is destroyed. |
| 110 | * @event_queue: Queue for processes waiting on buffer object status change. | 133 | * @event_queue: Queue for processes waiting on buffer object status change. |
| 111 | * @lock: spinlock protecting mostly synchronization members. | 134 | * @lock: spinlock protecting mostly synchronization members. |
| 112 | * @proposed_placement: Proposed placement for the buffer. Changed only by the | ||
| 113 | * creator prior to validation as opposed to bo->mem.proposed_flags which is | ||
| 114 | * changed by the implementation prior to a buffer move if it wants to outsmart | ||
| 115 | * the buffer creator / user. This latter happens, for example, at eviction. | ||
| 116 | * @mem: structure describing current placement. | 135 | * @mem: structure describing current placement. |
| 117 | * @persistant_swap_storage: Usually the swap storage is deleted for buffers | 136 | * @persistant_swap_storage: Usually the swap storage is deleted for buffers |
| 118 | * pinned in physical memory. If this behaviour is not desired, this member | 137 | * pinned in physical memory. If this behaviour is not desired, this member |
| @@ -177,7 +196,6 @@ struct ttm_buffer_object { | |||
| 177 | * Members protected by the bo::reserved lock. | 196 | * Members protected by the bo::reserved lock. |
| 178 | */ | 197 | */ |
| 179 | 198 | ||
| 180 | uint32_t proposed_placement; | ||
| 181 | struct ttm_mem_reg mem; | 199 | struct ttm_mem_reg mem; |
| 182 | struct file *persistant_swap_storage; | 200 | struct file *persistant_swap_storage; |
| 183 | struct ttm_tt *ttm; | 201 | struct ttm_tt *ttm; |
| @@ -285,7 +303,7 @@ ttm_bo_reference(struct ttm_buffer_object *bo) | |||
| 285 | * Note: It might be necessary to block validations before the | 303 | * Note: It might be necessary to block validations before the |
| 286 | * wait by reserving the buffer. | 304 | * wait by reserving the buffer. |
| 287 | * Returns -EBUSY if no_wait is true and the buffer is busy. | 305 | * Returns -EBUSY if no_wait is true and the buffer is busy. |
| 288 | * Returns -ERESTART if interrupted by a signal. | 306 | * Returns -ERESTARTSYS if interrupted by a signal. |
| 289 | */ | 307 | */ |
| 290 | extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, | 308 | extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, |
| 291 | bool interruptible, bool no_wait); | 309 | bool interruptible, bool no_wait); |
| @@ -293,21 +311,22 @@ extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, | |||
| 293 | * ttm_buffer_object_validate | 311 | * ttm_buffer_object_validate |
| 294 | * | 312 | * |
| 295 | * @bo: The buffer object. | 313 | * @bo: The buffer object. |
| 296 | * @proposed_placement: Proposed_placement for the buffer object. | 314 | * @placement: Proposed placement for the buffer object. |
| 297 | * @interruptible: Sleep interruptible if sleeping. | 315 | * @interruptible: Sleep interruptible if sleeping. |
| 298 | * @no_wait: Return immediately if the buffer is busy. | 316 | * @no_wait: Return immediately if the buffer is busy. |
| 299 | * | 317 | * |
| 300 | * Changes placement and caching policy of the buffer object | 318 | * Changes placement and caching policy of the buffer object |
| 301 | * according to bo::proposed_flags. | 319 | * according proposed placement. |
| 302 | * Returns | 320 | * Returns |
| 303 | * -EINVAL on invalid proposed_flags. | 321 | * -EINVAL on invalid proposed placement. |
| 304 | * -ENOMEM on out-of-memory condition. | 322 | * -ENOMEM on out-of-memory condition. |
| 305 | * -EBUSY if no_wait is true and buffer busy. | 323 | * -EBUSY if no_wait is true and buffer busy. |
| 306 | * -ERESTART if interrupted by a signal. | 324 | * -ERESTARTSYS if interrupted by a signal. |
| 307 | */ | 325 | */ |
| 308 | extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | 326 | extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, |
| 309 | uint32_t proposed_placement, | 327 | struct ttm_placement *placement, |
| 310 | bool interruptible, bool no_wait); | 328 | bool interruptible, bool no_wait); |
| 329 | |||
| 311 | /** | 330 | /** |
| 312 | * ttm_bo_unref | 331 | * ttm_bo_unref |
| 313 | * | 332 | * |
| @@ -328,7 +347,7 @@ extern void ttm_bo_unref(struct ttm_buffer_object **bo); | |||
| 328 | * waiting for buffer idle. This lock is recursive. | 347 | * waiting for buffer idle. This lock is recursive. |
| 329 | * Returns | 348 | * Returns |
| 330 | * -EBUSY if the buffer is busy and no_wait is true. | 349 | * -EBUSY if the buffer is busy and no_wait is true. |
| 331 | * -ERESTART if interrupted by a signal. | 350 | * -ERESTARTSYS if interrupted by a signal. |
| 332 | */ | 351 | */ |
| 333 | 352 | ||
| 334 | extern int | 353 | extern int |
| @@ -371,7 +390,7 @@ extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); | |||
| 371 | * Returns | 390 | * Returns |
| 372 | * -ENOMEM: Out of memory. | 391 | * -ENOMEM: Out of memory. |
| 373 | * -EINVAL: Invalid placement flags. | 392 | * -EINVAL: Invalid placement flags. |
| 374 | * -ERESTART: Interrupted by signal while sleeping waiting for resources. | 393 | * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. |
| 375 | */ | 394 | */ |
| 376 | 395 | ||
| 377 | extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, | 396 | extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, |
| @@ -411,7 +430,7 @@ extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, | |||
| 411 | * Returns | 430 | * Returns |
| 412 | * -ENOMEM: Out of memory. | 431 | * -ENOMEM: Out of memory. |
| 413 | * -EINVAL: Invalid placement flags. | 432 | * -EINVAL: Invalid placement flags. |
| 414 | * -ERESTART: Interrupted by signal while waiting for resources. | 433 | * -ERESTARTSYS: Interrupted by signal while waiting for resources. |
| 415 | */ | 434 | */ |
| 416 | 435 | ||
| 417 | extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, | 436 | extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, |
| @@ -445,7 +464,6 @@ extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, | |||
| 445 | * | 464 | * |
| 446 | * @bdev: Pointer to a ttm_bo_device struct. | 465 | * @bdev: Pointer to a ttm_bo_device struct. |
| 447 | * @mem_type: The memory type. | 466 | * @mem_type: The memory type. |
| 448 | * @p_offset: offset for managed area in pages. | ||
| 449 | * @p_size: size managed area in pages. | 467 | * @p_size: size managed area in pages. |
| 450 | * | 468 | * |
| 451 | * Initialize a manager for a given memory type. | 469 | * Initialize a manager for a given memory type. |
| @@ -458,7 +476,7 @@ extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, | |||
| 458 | */ | 476 | */ |
| 459 | 477 | ||
| 460 | extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | 478 | extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, |
| 461 | unsigned long p_offset, unsigned long p_size); | 479 | unsigned long p_size); |
| 462 | /** | 480 | /** |
| 463 | * ttm_bo_clean_mm | 481 | * ttm_bo_clean_mm |
| 464 | * | 482 | * |
| @@ -503,7 +521,7 @@ extern int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type); | |||
| 503 | * | 521 | * |
| 504 | * Returns: | 522 | * Returns: |
| 505 | * -EINVAL: Invalid or uninitialized memory type. | 523 | * -EINVAL: Invalid or uninitialized memory type. |
| 506 | * -ERESTART: The call was interrupted by a signal while waiting to | 524 | * -ERESTARTSYS: The call was interrupted by a signal while waiting to |
| 507 | * evict a buffer. | 525 | * evict a buffer. |
| 508 | */ | 526 | */ |
| 509 | 527 | ||
| @@ -606,7 +624,7 @@ extern int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, | |||
| 606 | * be called from the fops::read and fops::write method. | 624 | * be called from the fops::read and fops::write method. |
| 607 | * Returns: | 625 | * Returns: |
| 608 | * See man (2) write, man(2) read. In particular, | 626 | * See man (2) write, man(2) read. In particular, |
| 609 | * the function may return -EINTR if | 627 | * the function may return -ERESTARTSYS if |
| 610 | * interrupted by a signal. | 628 | * interrupted by a signal. |
| 611 | */ | 629 | */ |
| 612 | 630 | ||
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 7a39ab9aa1d1..ff7664e0c3cd 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
| @@ -242,12 +242,6 @@ struct ttm_mem_type_manager { | |||
| 242 | /** | 242 | /** |
| 243 | * struct ttm_bo_driver | 243 | * struct ttm_bo_driver |
| 244 | * | 244 | * |
| 245 | * @mem_type_prio: Priority array of memory types to place a buffer object in | ||
| 246 | * if it fits without evicting buffers from any of these memory types. | ||
| 247 | * @mem_busy_prio: Priority array of memory types to place a buffer object in | ||
| 248 | * if it needs to evict buffers to make room. | ||
| 249 | * @num_mem_type_prio: Number of elements in the @mem_type_prio array. | ||
| 250 | * @num_mem_busy_prio: Number of elements in the @num_mem_busy_prio array. | ||
| 251 | * @create_ttm_backend_entry: Callback to create a struct ttm_backend. | 245 | * @create_ttm_backend_entry: Callback to create a struct ttm_backend. |
| 252 | * @invalidate_caches: Callback to invalidate read caches when a buffer object | 246 | * @invalidate_caches: Callback to invalidate read caches when a buffer object |
| 253 | * has been evicted. | 247 | * has been evicted. |
| @@ -265,11 +259,6 @@ struct ttm_mem_type_manager { | |||
| 265 | */ | 259 | */ |
| 266 | 260 | ||
| 267 | struct ttm_bo_driver { | 261 | struct ttm_bo_driver { |
| 268 | const uint32_t *mem_type_prio; | ||
| 269 | const uint32_t *mem_busy_prio; | ||
| 270 | uint32_t num_mem_type_prio; | ||
| 271 | uint32_t num_mem_busy_prio; | ||
| 272 | |||
| 273 | /** | 262 | /** |
| 274 | * struct ttm_bo_driver member create_ttm_backend_entry | 263 | * struct ttm_bo_driver member create_ttm_backend_entry |
| 275 | * | 264 | * |
| @@ -306,7 +295,8 @@ struct ttm_bo_driver { | |||
| 306 | * finished, they'll end up in bo->mem.flags | 295 | * finished, they'll end up in bo->mem.flags |
| 307 | */ | 296 | */ |
| 308 | 297 | ||
| 309 | uint32_t(*evict_flags) (struct ttm_buffer_object *bo); | 298 | void(*evict_flags) (struct ttm_buffer_object *bo, |
| 299 | struct ttm_placement *placement); | ||
| 310 | /** | 300 | /** |
| 311 | * struct ttm_bo_driver member move: | 301 | * struct ttm_bo_driver member move: |
| 312 | * | 302 | * |
| @@ -648,12 +638,12 @@ extern bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, | |||
| 648 | * -EBUSY: No space available (only if no_wait == 1). | 638 | * -EBUSY: No space available (only if no_wait == 1). |
| 649 | * -ENOMEM: Could not allocate memory for the buffer object, either due to | 639 | * -ENOMEM: Could not allocate memory for the buffer object, either due to |
| 650 | * fragmentation or concurrent allocators. | 640 | * fragmentation or concurrent allocators. |
| 651 | * -ERESTART: An interruptible sleep was interrupted by a signal. | 641 | * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. |
| 652 | */ | 642 | */ |
| 653 | extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, | 643 | extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, |
| 654 | uint32_t proposed_placement, | 644 | struct ttm_placement *placement, |
| 655 | struct ttm_mem_reg *mem, | 645 | struct ttm_mem_reg *mem, |
| 656 | bool interruptible, bool no_wait); | 646 | bool interruptible, bool no_wait); |
| 657 | /** | 647 | /** |
| 658 | * ttm_bo_wait_for_cpu | 648 | * ttm_bo_wait_for_cpu |
| 659 | * | 649 | * |
| @@ -663,7 +653,7 @@ extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, | |||
| 663 | * Wait until a buffer object is no longer sync'ed for CPU access. | 653 | * Wait until a buffer object is no longer sync'ed for CPU access. |
| 664 | * Returns: | 654 | * Returns: |
| 665 | * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1). | 655 | * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1). |
| 666 | * -ERESTART: An interruptible sleep was interrupted by a signal. | 656 | * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. |
| 667 | */ | 657 | */ |
| 668 | 658 | ||
| 669 | extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); | 659 | extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); |
| @@ -767,7 +757,7 @@ extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); | |||
| 767 | * -EAGAIN: The reservation may cause a deadlock. | 757 | * -EAGAIN: The reservation may cause a deadlock. |
| 768 | * Release all buffer reservations, wait for @bo to become unreserved and | 758 | * Release all buffer reservations, wait for @bo to become unreserved and |
| 769 | * try again. (only if use_sequence == 1). | 759 | * try again. (only if use_sequence == 1). |
| 770 | * -ERESTART: A wait for the buffer to become unreserved was interrupted by | 760 | * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by |
| 771 | * a signal. Release all buffer reservations and return to user-space. | 761 | * a signal. Release all buffer reservations and return to user-space. |
| 772 | */ | 762 | */ |
| 773 | extern int ttm_bo_reserve(struct ttm_buffer_object *bo, | 763 | extern int ttm_bo_reserve(struct ttm_buffer_object *bo, |
| @@ -808,7 +798,7 @@ extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, | |||
| 808 | * | 798 | * |
| 809 | * Returns: | 799 | * Returns: |
| 810 | * -EBUSY: If no_wait == 1 and the buffer is already reserved. | 800 | * -EBUSY: If no_wait == 1 and the buffer is already reserved. |
| 811 | * -ERESTART: If interruptible == 1 and the process received a signal | 801 | * -ERESTARTSYS: If interruptible == 1 and the process received a signal |
| 812 | * while sleeping. | 802 | * while sleeping. |
| 813 | */ | 803 | */ |
| 814 | extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo, | 804 | extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo, |
