diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
40 files changed, 1464 insertions, 1152 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 121a034fe27d..f53e52f4d672 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -92,13 +92,13 @@ extern int amdgpu_vm_debug; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_powerplay; -extern int amdgpu_powercontainment; +extern int amdgpu_no_evict; +extern int amdgpu_direct_gma_size; extern unsigned amdgpu_pcie_gen_cap; extern unsigned amdgpu_pcie_lane_cap; extern unsigned amdgpu_cg_mask; extern unsigned amdgpu_pg_mask; extern char *amdgpu_disable_cu; -extern int amdgpu_sclk_deep_sleep_en; extern char *amdgpu_virtual_display; extern unsigned amdgpu_pp_feature_mask; extern int amdgpu_vram_page_split; @@ -1633,7 +1633,6 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_display_set_vga_render_state(adev, r) (adev)->mode_info.funcs->set_vga_render_state((adev), (r)) #define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc)) #define amdgpu_display_vblank_wait(adev, crtc) (adev)->mode_info.funcs->vblank_wait((adev), (crtc)) -#define amdgpu_display_is_display_hung(adev) (adev)->mode_info.funcs->is_display_hung((adev)) #define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l)) #define amdgpu_display_backlight_get_level(adev, e) (adev)->mode_info.funcs->backlight_get_level((e)) #define amdgpu_display_hpd_sense(adev, h) (adev)->mode_info.funcs->hpd_sense((adev), (h)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 2b6afe123f3d..b7e2762fcdd2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -70,7 +70,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev) return false; } adev->bios = kmalloc(size, GFP_KERNEL); - if (adev->bios == NULL) { + if (!adev->bios) { iounmap(bios); return false; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 78da52f90099..5a277495d6a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -841,16 +841,6 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, return amdgpu_cs_sync_rings(p); } -static int amdgpu_cs_handle_lockup(struct amdgpu_device *adev, int r) -{ - if (r == -EDEADLK) { - r = amdgpu_gpu_reset(adev); - if (!r) - r = -EAGAIN; - } - return r; -} - static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, struct amdgpu_cs_parser *parser) { @@ -1054,29 +1044,29 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) r = amdgpu_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser !\n"); - amdgpu_cs_parser_fini(&parser, r, false); - r = amdgpu_cs_handle_lockup(adev, r); - return r; - } - r = amdgpu_cs_parser_bos(&parser, data); - if (r == -ENOMEM) - DRM_ERROR("Not enough memory for command submission!\n"); - else if (r && r != -ERESTARTSYS) - DRM_ERROR("Failed to process the buffer list %d!\n", r); - else if (!r) { - reserved_buffers = true; - r = amdgpu_cs_ib_fill(adev, &parser); + goto out; } - if (!r) { - r = amdgpu_cs_dependencies(adev, &parser); - if (r) - DRM_ERROR("Failed in the dependencies handling %d!\n", r); + r = amdgpu_cs_parser_bos(&parser, data); + if (r) { + if (r == -ENOMEM) + DRM_ERROR("Not enough memory for command submission!\n"); + else if (r != -ERESTARTSYS) + DRM_ERROR("Failed to process the buffer list %d!\n", r); + goto out; } + reserved_buffers = true; + r = amdgpu_cs_ib_fill(adev, &parser); if (r) goto out; + r = amdgpu_cs_dependencies(adev, &parser); + if (r) { + DRM_ERROR("Failed in the dependencies handling %d!\n", r); + goto out; + } + for (i = 0; i < parser.job->num_ibs; i++) trace_amdgpu_cs(&parser, i); @@ -1088,7 +1078,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); - r = amdgpu_cs_handle_lockup(adev, r); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index deee2db36fce..fc790e5c46fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1017,8 +1017,8 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) amdgpu_vm_block_size = 9; } - if ((amdgpu_vram_page_split != -1 && amdgpu_vram_page_split < 16) || - !amdgpu_check_pot_argument(amdgpu_vram_page_split)) { + if (amdgpu_vram_page_split != -1 && (amdgpu_vram_page_split < 16 || + !amdgpu_check_pot_argument(amdgpu_vram_page_split))) { dev_warn(adev->dev, "invalid VRAM page split (%d)\n", amdgpu_vram_page_split); amdgpu_vram_page_split = 1024; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index bd85e35998e7..955d6f21e2b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -52,6 +52,8 @@ enum amdgpu_dpm_event_src { AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 }; +#define SCLK_DEEP_SLEEP_MASK 0x8 + struct amdgpu_ps { u32 caps; /* vbios flags */ u32 class; /* vbios flags */ @@ -317,6 +319,11 @@ struct amdgpu_dpm_funcs { (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ (adev)->pm.funcs->get_fan_speed_percent((adev), (s))) +#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \ + ((adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_speed_rpm((adev)->powerplay.pp_handle, (s)) : \ + -EINVAL) + #define amdgpu_dpm_get_sclk(adev, l) \ ((adev)->pp_enabled ? \ (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 42da6163b893..7914f999b1bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -91,8 +91,8 @@ int amdgpu_exp_hw_support = 0; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_powerplay = -1; -int amdgpu_powercontainment = 1; -int amdgpu_sclk_deep_sleep_en = 1; +int amdgpu_no_evict = 0; +int amdgpu_direct_gma_size = 0; unsigned amdgpu_pcie_gen_cap = 0; unsigned amdgpu_pcie_lane_cap = 0; unsigned amdgpu_cg_mask = 0xffffffff; @@ -182,14 +182,14 @@ module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))"); module_param_named(powerplay, amdgpu_powerplay, int, 0444); -MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 = disable)"); -module_param_named(powercontainment, amdgpu_powercontainment, int, 0444); - MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444); -MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)"); -module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444); +MODULE_PARM_DESC(no_evict, "Support pinning request from user space (1 = enable, 0 = disable (default))"); +module_param_named(no_evict, amdgpu_no_evict, int, 0444); + +MODULE_PARM_DESC(direct_gma_size, "Direct GMA size in megabytes (max 96MB)"); +module_param_named(direct_gma_size, amdgpu_direct_gma_size, int, 0444); MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))"); module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 97928d7281f6..7b60fb79c3a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -382,24 +382,27 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring, if (!ring->fence_drv.fences) return -ENOMEM; - timeout = msecs_to_jiffies(amdgpu_lockup_timeout); - if (timeout == 0) { - /* - * FIXME: - * Delayed workqueue cannot use it directly, - * so the scheduler will not use delayed workqueue if - * MAX_SCHEDULE_TIMEOUT is set. - * Currently keep it simple and silly. - */ - timeout = MAX_SCHEDULE_TIMEOUT; - } - r = amd_sched_init(&ring->sched, &amdgpu_sched_ops, - num_hw_submission, - timeout, ring->name); - if (r) { - DRM_ERROR("Failed to create scheduler on ring %s.\n", - ring->name); - return r; + /* No need to setup the GPU scheduler for KIQ ring */ + if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) { + timeout = msecs_to_jiffies(amdgpu_lockup_timeout); + if (timeout == 0) { + /* + * FIXME: + * Delayed workqueue cannot use it directly, + * so the scheduler will not use delayed workqueue if + * MAX_SCHEDULE_TIMEOUT is set. + * Currently keep it simple and silly. + */ + timeout = MAX_SCHEDULE_TIMEOUT; + } + r = amd_sched_init(&ring->sched, &amdgpu_sched_ops, + num_hw_submission, + timeout, ring->name); + if (r) { + DRM_ERROR("Failed to create scheduler on ring %s.\n", + ring->name); + return r; + } } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 9fa809876339..fb902932f571 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -424,15 +424,6 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, return 0; } -bool amdgpu_irq_get_delayed(struct amdgpu_device *adev, - struct amdgpu_irq_src *src, - unsigned type) -{ - if ((type >= src->num_types) || !src->enabled_types) - return false; - return atomic_inc_return(&src->enabled_types[type]) == 1; -} - /** * amdgpu_irq_put - disable interrupt * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h index f016464035b8..1642f4108297 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h @@ -88,9 +88,6 @@ int amdgpu_irq_update(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type); int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type); -bool amdgpu_irq_get_delayed(struct amdgpu_device *adev, - struct amdgpu_irq_src *src, - unsigned type); int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type); bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 1e23334b07fb..202b4176b74e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -271,8 +271,6 @@ struct amdgpu_display_funcs { u32 (*vblank_get_counter)(struct amdgpu_device *adev, int crtc); /* wait for vblank */ void (*vblank_wait)(struct amdgpu_device *adev, int crtc); - /* is dce hung */ - bool (*is_display_hung)(struct amdgpu_device *adev); /* set backlight level */ void (*backlight_set_level)(struct amdgpu_encoder *amdgpu_encoder, u8 level); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 1479d09bd4dd..bf79b73e1538 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -128,17 +128,6 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) lpfn = adev->mc.real_vram_size >> PAGE_SHIFT; - if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS && - !(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && - adev->mc.visible_vram_size < adev->mc.real_vram_size) { - places[c].fpfn = visible_pfn; - places[c].lpfn = lpfn; - places[c].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM | - TTM_PL_FLAG_TOPDOWN; - c++; - } - places[c].fpfn = 0; places[c].lpfn = lpfn; places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | @@ -382,39 +371,36 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, amdgpu_fill_placement_to_bo(bo, placement); /* Kernel allocation are uninterruptible */ + + if (!resv) { + bool locked; + + reservation_object_init(&bo->tbo.ttm_resv); + locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock); + WARN_ON(!locked); + } r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, !kernel, NULL, - acc_size, sg, resv, &amdgpu_ttm_bo_destroy); - if (unlikely(r != 0)) { + acc_size, sg, resv ? resv : &bo->tbo.ttm_resv, + &amdgpu_ttm_bo_destroy); + if (unlikely(r != 0)) return r; - } if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED && bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) { struct dma_fence *fence; - if (adev->mman.buffer_funcs_ring == NULL || - !adev->mman.buffer_funcs_ring->ready) { - r = -EBUSY; - goto fail_free; - } - - r = amdgpu_bo_reserve(bo, false); - if (unlikely(r != 0)) - goto fail_free; - - amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); - r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); - if (unlikely(r != 0)) + r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence); + if (unlikely(r)) goto fail_unreserve; - amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence); amdgpu_bo_fence(bo, fence, false); - amdgpu_bo_unreserve(bo); dma_fence_put(bo->tbo.moving); bo->tbo.moving = dma_fence_get(fence); dma_fence_put(fence); } + if (!resv) + ww_mutex_unlock(&bo->tbo.resv->lock); *bo_ptr = bo; trace_amdgpu_bo_create(bo); @@ -422,8 +408,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, return 0; fail_unreserve: - amdgpu_bo_unreserve(bo); -fail_free: + ww_mutex_unlock(&bo->tbo.resv->lock); amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 274f3309aec9..723ae682bf25 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -737,6 +737,21 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return sprintf(buf, "%i\n", speed); } +static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 speed; + + err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); + if (err) + return err; + + return sprintf(buf, "%i\n", speed); +} + static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1); @@ -744,6 +759,7 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, amdgpu static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0); static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0); static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0); static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -753,6 +769,7 @@ static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1_min.dev_attr.attr, &sensor_dev_attr_pwm1_max.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, NULL }; @@ -804,6 +821,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; + /* requires powerplay */ + if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr) + return 0; + return effective_mode; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index fa6baf31a35d..fc592c2b0e16 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -155,9 +155,6 @@ static int amdgpu_pp_sw_init(void *handle) ret = adev->powerplay.ip_funcs->sw_init( adev->powerplay.pp_handle); - if (adev->pp_enabled) - adev->pm.dpm_enabled = true; - return ret; } @@ -187,6 +184,9 @@ static int amdgpu_pp_hw_init(void *handle) ret = adev->powerplay.ip_funcs->hw_init( adev->powerplay.pp_handle); + if ((amdgpu_dpm != 0) && !amdgpu_sriov_vf(adev)) + adev->pm.dpm_enabled = true; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index f2ad49c8e85b..574f0b79c690 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -44,7 +44,8 @@ enum amdgpu_ring_type { AMDGPU_RING_TYPE_COMPUTE, AMDGPU_RING_TYPE_SDMA, AMDGPU_RING_TYPE_UVD, - AMDGPU_RING_TYPE_VCE + AMDGPU_RING_TYPE_VCE, + AMDGPU_RING_TYPE_KIQ }; struct amdgpu_device; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index 34a795463988..de9f919ae336 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c @@ -327,9 +327,8 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_manager *sa_manager, return -EINVAL; *sa_bo = kmalloc(sizeof(struct amdgpu_sa_bo), GFP_KERNEL); - if ((*sa_bo) == NULL) { + if (!(*sa_bo)) return -ENOMEM; - } (*sa_bo)->manager = sa_manager; (*sa_bo)->fence = NULL; INIT_LIST_HEAD(&(*sa_bo)->olist); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1821c05484d0..8f18b8ed2b3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1382,28 +1382,40 @@ error_free: } int amdgpu_fill_buffer(struct amdgpu_bo *bo, - uint32_t src_data, - struct reservation_object *resv, - struct dma_fence **fence) + uint32_t src_data, + struct reservation_object *resv, + struct dma_fence **fence) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct amdgpu_job *job; + uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes; struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; - uint32_t max_bytes, byte_count; - uint64_t dst_offset; + struct drm_mm_node *mm_node; + unsigned long num_pages; unsigned int num_loops, num_dw; - unsigned int i; + + struct amdgpu_job *job; int r; - byte_count = bo->tbo.num_pages << PAGE_SHIFT; - max_bytes = adev->mman.buffer_funcs->fill_max_bytes; - num_loops = DIV_ROUND_UP(byte_count, max_bytes); + if (!ring->ready) { + DRM_ERROR("Trying to clear memory with ring turned off.\n"); + return -EINVAL; + } + + num_pages = bo->tbo.num_pages; + mm_node = bo->tbo.mem.mm_node; + num_loops = 0; + while (num_pages) { + uint32_t byte_count = mm_node->size << PAGE_SHIFT; + + num_loops += DIV_ROUND_UP(byte_count, max_bytes); + num_pages -= mm_node->size; + ++mm_node; + } num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw; /* for IB padding */ - while (num_dw & 0x7) - num_dw++; + num_dw += 64; r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job); if (r) @@ -1411,28 +1423,43 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, if (resv) { r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_FENCE_OWNER_UNDEFINED); + AMDGPU_FENCE_OWNER_UNDEFINED); if (r) { DRM_ERROR("sync failed (%d).\n", r); goto error_free; } } - dst_offset = bo->tbo.mem.start << PAGE_SHIFT; - for (i = 0; i < num_loops; i++) { - uint32_t cur_size_in_bytes = min(byte_count, max_bytes); + num_pages = bo->tbo.num_pages; + mm_node = bo->tbo.mem.mm_node; - amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, - dst_offset, cur_size_in_bytes); + while (num_pages) { + uint32_t byte_count = mm_node->size << PAGE_SHIFT; + uint64_t dst_addr; - dst_offset += cur_size_in_bytes; - byte_count -= cur_size_in_bytes; + r = amdgpu_mm_node_addr(&bo->tbo, mm_node, + &bo->tbo.mem, &dst_addr); + if (r) + return r; + + while (byte_count) { + uint32_t cur_size_in_bytes = min(byte_count, max_bytes); + + amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, + dst_addr, cur_size_in_bytes); + + dst_addr += cur_size_in_bytes; + byte_count -= cur_size_in_bytes; + } + + num_pages -= mm_node->size; + ++mm_node; } amdgpu_ring_pad_ib(ring, &job->ibs[0]); WARN_ON(job->ibs[0].length_dw > num_dw); r = amdgpu_job_submit(job, ring, &adev->mman.entity, - AMDGPU_FENCE_OWNER_UNDEFINED, fence); + AMDGPU_FENCE_OWNER_UNDEFINED, fence); if (r) goto error_free; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index fb270c7e7171..a81dfaeeb8c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -360,6 +360,18 @@ static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo) } } +static u64 amdgpu_uvd_get_addr_from_ctx(struct amdgpu_uvd_cs_ctx *ctx) +{ + uint32_t lo, hi; + uint64_t addr; + + lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0); + hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1); + addr = ((uint64_t)lo) | (((uint64_t)hi) << 32); + + return addr; +} + /** * amdgpu_uvd_cs_pass1 - first parsing round * @@ -372,14 +384,10 @@ static int amdgpu_uvd_cs_pass1(struct amdgpu_uvd_cs_ctx *ctx) { struct amdgpu_bo_va_mapping *mapping; struct amdgpu_bo *bo; - uint32_t cmd, lo, hi; - uint64_t addr; + uint32_t cmd; + uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx); int r = 0; - lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0); - hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1); - addr = ((uint64_t)lo) | (((uint64_t)hi) << 32); - mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo); if (mapping == NULL) { DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr); @@ -698,18 +706,16 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx) { struct amdgpu_bo_va_mapping *mapping; struct amdgpu_bo *bo; - uint32_t cmd, lo, hi; + uint32_t cmd; uint64_t start, end; - uint64_t addr; + uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx); int r; - lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0); - hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1); - addr = ((uint64_t)lo) | (((uint64_t)hi) << 32); - mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo); - if (mapping == NULL) + if (mapping == NULL) { + DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr); return -EINVAL; + } start = amdgpu_bo_gpu_offset(bo); @@ -893,10 +899,13 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) ctx.buf_sizes = buf_sizes; ctx.ib_idx = ib_idx; - /* first round, make sure the buffers are actually in the UVD segment */ - r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1); - if (r) - return r; + /* first round only required on chips without UVD 64 bit address support */ + if (!parser->adev->uvd.address_64_bit) { + /* first round, make sure the buffers are actually in the UVD segment */ + r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1); + if (r) + return r; + } /* second round, patch buffe |