From 9d248517d4bd807c7690d55d0b6f54618fc60942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 23 Jul 2018 16:01:39 +0200 Subject: [PATCH 01/41] drm/amdgpu: add support for inplace IB patching for MM engines v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to need that for the second UVD instance on Vega20. v2: rename to patch_cs_in_place Signed-off-by: Christian König Reviewed-and-tested-by: James Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 20 ++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0283e2b3c851..1f6345dda6ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1748,6 +1748,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_vm_write_pte(adev, ib, pe, value, count, incr) ((adev)->vm_manager.vm_pte_funcs->write_pte((ib), (pe), (value), (count), (incr))) #define amdgpu_vm_set_pte_pde(adev, ib, pe, addr, count, incr, flags) ((adev)->vm_manager.vm_pte_funcs->set_pte_pde((ib), (pe), (addr), (count), (incr), (flags))) #define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib))) +#define amdgpu_ring_patch_cs_in_place(r, p, ib) ((r)->funcs->patch_cs_in_place((p), (ib))) #define amdgpu_ring_test_ring(r) (r)->funcs->test_ring((r)) #define amdgpu_ring_test_ib(r, t) (r)->funcs->test_ib((r), (t)) #define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 178d9ce4eba1..533b2e7656c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -916,7 +916,7 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, int r; /* Only for UVD/VCE VM emulation */ - if (p->ring->funcs->parse_cs) { + if (p->ring->funcs->parse_cs || p->ring->funcs->patch_cs_in_place) { unsigned i, j; for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) { @@ -957,12 +957,20 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, offset = m->start * AMDGPU_GPU_PAGE_SIZE; kptr += va_start - offset; - memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); - amdgpu_bo_kunmap(aobj); + if (p->ring->funcs->parse_cs) { + memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); + amdgpu_bo_kunmap(aobj); - r = amdgpu_ring_parse_cs(ring, p, j); - if (r) - return r; + r = amdgpu_ring_parse_cs(ring, p, j); + if (r) + return r; + } else { + ib->ptr = (uint32_t *)kptr; + r = amdgpu_ring_patch_cs_in_place(ring, p, j); + amdgpu_bo_kunmap(aobj); + if (r) + return r; + } j++; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 5018c0b6bf1a..d242b9a51e90 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -123,6 +123,7 @@ struct amdgpu_ring_funcs { void (*set_wptr)(struct amdgpu_ring *ring); /* validating and patching of IBs */ int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx); + int (*patch_cs_in_place)(struct amdgpu_cs_parser *p, uint32_t ib_idx); /* constants to calculate how many DW are needed for an emit */ unsigned emit_frame_size; unsigned emit_ib_size; From 66c28d6df2d8292098839d365b82a1e30b567211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 18 Jul 2018 14:52:42 +0200 Subject: [PATCH 02/41] drm/amdgpu: patch the IBs for the second UVD instance v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch the IBs for the second UVD instance so that userspace don't need to care about the instance they submit to. v2: use direct IB patching Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-and-tested-by: James Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index db5f3d78ab12..d74c1b242667 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1205,6 +1205,34 @@ static int uvd_v7_0_ring_test_ring(struct amdgpu_ring *ring) return r; } +/** + * uvd_v7_0_ring_patch_cs_in_place - Patch the IB for command submission. + * + * @p: the CS parser with the IBs + * @ib_idx: which IB to patch + * + */ +static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, + uint32_t ib_idx) +{ + struct amdgpu_ib *ib = &p->job->ibs[ib_idx]; + unsigned i; + + /* No patching necessary for the first instance */ + if (!p->ring->me) + return 0; + + for (i = 0; i < ib->length_dw; i += 2) { + uint32_t reg = amdgpu_get_ib_value(p, ib_idx, i); + + reg -= p->adev->reg_offset[UVD_HWIP][0][1]; + reg += p->adev->reg_offset[UVD_HWIP][1][1]; + + amdgpu_set_ib_value(p, ib_idx, i, reg); + } + return 0; +} + /** * uvd_v7_0_ring_emit_ib - execute indirect buffer * @@ -1697,6 +1725,7 @@ static const struct amdgpu_ring_funcs uvd_v7_0_ring_vm_funcs = { .get_rptr = uvd_v7_0_ring_get_rptr, .get_wptr = uvd_v7_0_ring_get_wptr, .set_wptr = uvd_v7_0_ring_set_wptr, + .patch_cs_in_place = uvd_v7_0_ring_patch_cs_in_place, .emit_frame_size = 6 + /* hdp invalidate */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 + From 824474ba38e27ccacc9d2dd066f780e9b3c2ad78 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 13 Jul 2018 18:00:06 -0400 Subject: [PATCH 03/41] drm/amd/display: Retry link training again [Why] Some receivers seem to fail the first link training but are good on subsequent tries. We want to retry link training again. This fixes HTC vive pro not lighting up after being disabled. [How] Check if the link training passed without fall back if this is not the case then we retry link training. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 20 +++++++++++++++++-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 5 ++++- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 3 ++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 388a0635c38d..966d2f9c8c99 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -60,7 +60,14 @@ enum { LINK_RATE_REF_FREQ_IN_MHZ = 27, - PEAK_FACTOR_X1000 = 1006 + PEAK_FACTOR_X1000 = 1006, + /* + * Some receivers fail to train on first try and are good + * on subsequent tries. 2 retries should be plenty. If we + * don't have a successful training then we don't expect to + * ever get one. + */ + LINK_TRAINING_MAX_VERIFY_RETRY = 2 }; /******************************************************************************* @@ -760,7 +767,16 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) */ /* deal with non-mst cases */ - dp_verify_link_cap(link, &link->reported_link_cap); + for (i = 0; i < LINK_TRAINING_MAX_VERIFY_RETRY; i++) { + int fail_count = 0; + + dp_verify_link_cap(link, + &link->reported_link_cap, + &fail_count); + + if (fail_count == 0) + break; + } } /* HDMI-DVI Dongle */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9d901ca70588..58ee9aad13fb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1088,7 +1088,8 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) bool dp_verify_link_cap( struct dc_link *link, - struct dc_link_settings *known_limit_link_setting) + struct dc_link_settings *known_limit_link_setting, + int *fail_count) { struct dc_link_settings max_link_cap = {0}; struct dc_link_settings cur_link_setting = {0}; @@ -1160,6 +1161,8 @@ bool dp_verify_link_cap( skip_video_pattern); if (status == LINK_TRAINING_SUCCESS) success = true; + else + (*fail_count)++; } if (success) diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 697b5ee73845..a37255c757e0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -35,7 +35,8 @@ struct dc_link_settings; bool dp_verify_link_cap( struct dc_link *link, - struct dc_link_settings *known_limit_link_setting); + struct dc_link_settings *known_limit_link_setting, + int *fail_count); bool dp_validate_mode_timing( struct dc_link *link, From 65c78961b30005447a0d9b285de93354d8308f34 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 28 Jun 2018 17:50:05 -0400 Subject: [PATCH 04/41] drm/amd/display: flatten aux_engine and engine [Why] engine and aux_engine are unnecessary layers we want to remove this layer. [How] flatten engine and aux engine structs into one struct called aux_engine and remove all references to the engine struct. Signed-off-by: Bhawanpreet Lakha Reviewed-by: Harry Wentland Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_ddc.c | 8 +- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 55 ++++---- drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 4 +- .../amd/display/dc/dce100/dce100_resource.c | 4 +- .../amd/display/dc/dce110/dce110_resource.c | 4 +- .../amd/display/dc/dce112/dce112_resource.c | 4 +- .../amd/display/dc/dce120/dce120_resource.c | 4 +- .../drm/amd/display/dc/dce80/dce80_resource.c | 4 +- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 4 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- .../drm/amd/display/dc/inc/hw/aux_engine.h | 127 +++++++++++++----- .../gpu/drm/amd/display/dc/inc/hw/engine.h | 106 --------------- 12 files changed, 140 insertions(+), 186 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/engine.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 4019fe07d291..8def0d9fa0ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -33,7 +33,6 @@ #include "include/vector.h" #include "core_types.h" #include "dc_link_ddc.h" -#include "engine.h" #include "aux_engine.h" #define AUX_POWER_UP_WA_DELAY 500 @@ -640,7 +639,6 @@ int dc_link_aux_transfer(struct ddc_service *ddc, enum i2caux_transaction_action action) { struct ddc *ddc_pin = ddc->ddc_pin; - struct engine *engine; struct aux_engine *aux_engine; enum aux_channel_operation_result operation_result; struct aux_request_transaction_data aux_req; @@ -652,8 +650,8 @@ int dc_link_aux_transfer(struct ddc_service *ddc, memset(&aux_req, 0, sizeof(aux_req)); memset(&aux_rep, 0, sizeof(aux_rep)); - engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; - aux_engine = engine->funcs->acquire(engine, ddc_pin); + aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; + aux_engine->funcs->acquire(aux_engine, ddc_pin); aux_req.type = type; aux_req.action = action; @@ -685,7 +683,7 @@ int dc_link_aux_transfer(struct ddc_service *ddc, res = -1; break; } - aux_engine->base.funcs->release_engine(&aux_engine->base); + aux_engine->funcs->release_engine(aux_engine); return res; } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index b28e2120767e..3f5b2e6f7553 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -28,12 +28,12 @@ #include "dce/dce_11_0_sh_mask.h" #define CTX \ - aux110->base.base.ctx + aux110->base.ctx #define REG(reg_name)\ (aux110->regs->reg_name) #define DC_LOGGER \ - engine->base.ctx->logger + engine->ctx->logger #include "reg_helper.h" @@ -51,9 +51,9 @@ enum { AUX_DEFER_RETRY_COUNTER = 6 }; static void release_engine( - struct engine *engine) + struct aux_engine *engine) { - struct aux_engine_dce110 *aux110 = FROM_ENGINE(engine); + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); dal_ddc_close(engine->ddc); @@ -827,22 +827,21 @@ static bool end_of_transaction_command( /* according Syed, it does not need now DoDummyMOT */ } -bool submit_request( - struct engine *engine, +static bool submit_request( + struct aux_engine *engine, struct i2caux_transaction_request *request, bool middle_of_transaction) { - struct aux_engine *aux_engine = FROM_AUX_ENGINE_ENGINE(engine); bool result; bool mot_used = true; switch (request->operation) { case I2CAUX_TRANSACTION_READ: - result = read_command(aux_engine, request, mot_used); + result = read_command(engine, request, mot_used); break; case I2CAUX_TRANSACTION_WRITE: - result = write_command(aux_engine, request, mot_used); + result = write_command(engine, request, mot_used); break; default: result = false; @@ -854,45 +853,45 @@ bool submit_request( */ if (!middle_of_transaction || !result) - end_of_transaction_command(aux_engine, request); + end_of_transaction_command(engine, request); /* mask AUX interrupt */ return result; } enum i2caux_engine_type get_engine_type( - const struct engine *engine) + const struct aux_engine *engine) { return I2CAUX_ENGINE_TYPE_AUX; } -static struct aux_engine *acquire( - struct engine *engine, +static bool acquire( + struct aux_engine *engine, struct ddc *ddc) { - struct aux_engine *aux_engine = FROM_AUX_ENGINE_ENGINE(engine); + enum gpio_result result; - if (aux_engine->funcs->is_engine_available) { + if (engine->funcs->is_engine_available) { /*check whether SW could use the engine*/ - if (!aux_engine->funcs->is_engine_available(aux_engine)) - return NULL; + if (!engine->funcs->is_engine_available(engine)) + return false; } result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, GPIO_DDC_CONFIG_TYPE_MODE_AUX); if (result != GPIO_RESULT_OK) - return NULL; + return false; - if (!aux_engine->funcs->acquire_engine(aux_engine)) { + if (!engine->funcs->acquire_engine(engine)) { dal_ddc_close(ddc); - return NULL; + return false; } engine->ddc = ddc; - return aux_engine; + return true; } static const struct aux_engine_funcs aux_engine_funcs = { @@ -902,9 +901,6 @@ static const struct aux_engine_funcs aux_engine_funcs = { .read_channel_reply = read_channel_reply, .get_channel_status = get_channel_status, .is_engine_available = is_engine_available, -}; - -static const struct engine_funcs engine_funcs = { .release_engine = release_engine, .destroy_engine = dce110_engine_destroy, .submit_request = submit_request, @@ -912,10 +908,10 @@ static const struct engine_funcs engine_funcs = { .acquire = acquire, }; -void dce110_engine_destroy(struct engine **engine) +void dce110_engine_destroy(struct aux_engine **engine) { - struct aux_engine_dce110 *engine110 = FROM_ENGINE(*engine); + struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); kfree(engine110); *engine = NULL; @@ -927,13 +923,12 @@ struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_eng uint32_t timeout_period, const struct dce110_aux_registers *regs) { - aux_engine110->base.base.ddc = NULL; - aux_engine110->base.base.ctx = ctx; + aux_engine110->base.ddc = NULL; + aux_engine110->base.ctx = ctx; aux_engine110->base.delay = 0; aux_engine110->base.max_defer_write_retry = 0; - aux_engine110->base.base.funcs = &engine_funcs; aux_engine110->base.funcs = &aux_engine_funcs; - aux_engine110->base.base.inst = inst; + aux_engine110->base.inst = inst; aux_engine110->timeout_period = timeout_period; aux_engine110->regs = regs; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index c6b2aec2e367..f7caab85dc80 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -103,9 +103,9 @@ struct aux_engine *dce110_aux_engine_construct( uint32_t timeout_period, const struct dce110_aux_registers *regs); -void dce110_engine_destroy(struct engine **engine); +void dce110_engine_destroy(struct aux_engine **engine); bool dce110_aux_engine_acquire( - struct engine *aux_engine, + struct aux_engine *aux_engine, struct ddc *ddc); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index c34c9531915e..fd2bdae4dcec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c @@ -586,7 +586,7 @@ struct output_pixel_processor *dce100_opp_create( return &opp->base; } -struct engine *dce100_aux_engine_create( +struct aux_engine *dce100_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -600,7 +600,7 @@ struct engine *dce100_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } struct clock_source *dce100_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 4a665a29191b..e5e9e92521e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -604,7 +604,7 @@ static struct output_pixel_processor *dce110_opp_create( return &opp->base; } -struct engine *dce110_aux_engine_create( +struct aux_engine *dce110_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -618,7 +618,7 @@ struct engine *dce110_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } struct clock_source *dce110_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index caf90ae2cbb0..84a05ff2d674 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -604,7 +604,7 @@ struct output_pixel_processor *dce112_opp_create( return &opp->base; } -struct engine *dce112_aux_engine_create( +struct aux_engine *dce112_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -618,7 +618,7 @@ struct engine *dce112_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } struct clock_source *dce112_clock_source_create( diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f7d02f2190d3..61d8e22d23c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -376,7 +376,7 @@ struct output_pixel_processor *dce120_opp_create( ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); return &opp->base; } -struct engine *dce120_aux_engine_create( +struct aux_engine *dce120_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -390,7 +390,7 @@ struct engine *dce120_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } static const struct bios_registers bios_regs = { diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 6fb33ad2d3c8..dc9f3e9afc33 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -464,7 +464,7 @@ static struct output_pixel_processor *dce80_opp_create( return &opp->base; } -struct engine *dce80_aux_engine_create( +struct aux_engine *dce80_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -478,7 +478,7 @@ struct engine *dce80_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } static struct stream_encoder *dce80_stream_encoder_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index cd8c22839227..5d169f07d745 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -594,7 +594,7 @@ static struct output_pixel_processor *dcn10_opp_create( return &opp->base; } -struct engine *dcn10_aux_engine_create( +struct aux_engine *dcn10_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -608,7 +608,7 @@ struct engine *dcn10_aux_engine_create( SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, &aux_engine_regs[inst]); - return &aux_engine->base.base; + return &aux_engine->base; } static struct mpc *dcn10_mpc_create(struct dc_context *ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 0fa385872ed3..9f33306f9014 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -138,7 +138,7 @@ struct resource_pool { struct output_pixel_processor *opps[MAX_PIPES]; struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; - struct engine *engines[MAX_PIPES]; + struct aux_engine *engines[MAX_PIPES]; struct hubbub *hubbub; struct mpc *mpc; struct pp_smu_funcs_rv *pp_smu; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h b/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h index 06d7e5d4cf21..e79cd4e92919 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/aux_engine.h @@ -26,46 +26,72 @@ #ifndef __DAL_AUX_ENGINE_H__ #define __DAL_AUX_ENGINE_H__ -#include "engine.h" +#include "dc_ddc_types.h" #include "include/i2caux_interface.h" -struct aux_engine; -union aux_config; -struct aux_engine_funcs { - void (*destroy)( - struct aux_engine **ptr); - bool (*acquire_engine)( - struct aux_engine *engine); - void (*configure)( - struct aux_engine *engine, - union aux_config cfg); - void (*submit_channel_request)( - struct aux_engine *engine, - struct aux_request_transaction_data *request); - void (*process_channel_reply)( - struct aux_engine *engine, - struct aux_reply_transaction_data *reply); - int (*read_channel_reply)( - struct aux_engine *engine, - uint32_t size, - uint8_t *buffer, - uint8_t *reply_result, - uint32_t *sw_status); - enum aux_channel_operation_result (*get_channel_status)( - struct aux_engine *engine, - uint8_t *returned_bytes); - bool (*is_engine_available)(struct aux_engine *engine); +enum i2caux_transaction_operation { + I2CAUX_TRANSACTION_READ, + I2CAUX_TRANSACTION_WRITE }; -struct engine; + +enum i2caux_transaction_address_space { + I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, + I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD +}; + +struct i2caux_transaction_payload { + enum i2caux_transaction_address_space address_space; + uint32_t address; + uint32_t length; + uint8_t *data; +}; + +enum i2caux_transaction_status { + I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), + I2CAUX_TRANSACTION_STATUS_SUCCEEDED, + I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, + I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, + I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, + I2CAUX_TRANSACTION_STATUS_FAILED_NACK, + I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, + I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, + I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW, + I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON +}; + +struct i2caux_transaction_request { + enum i2caux_transaction_operation operation; + struct i2caux_transaction_payload payload; + enum i2caux_transaction_status status; +}; + +enum i2caux_engine_type { + I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), + I2CAUX_ENGINE_TYPE_AUX, + I2CAUX_ENGINE_TYPE_I2C_DDC_HW, + I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, + I2CAUX_ENGINE_TYPE_I2C_SW +}; + +enum i2c_default_speed { + I2CAUX_DEFAULT_I2C_HW_SPEED = 50, + I2CAUX_DEFAULT_I2C_SW_SPEED = 50 +}; + +union aux_config; + struct aux_engine { - struct engine base; + uint32_t inst; + struct ddc *ddc; + struct dc_context *ctx; const struct aux_engine_funcs *funcs; /* following values are expressed in milliseconds */ uint32_t delay; uint32_t max_defer_write_retry; - bool acquire_reset; }; + struct read_command_context { uint8_t *buffer; uint32_t current_read_length; @@ -86,6 +112,7 @@ struct read_command_context { bool transaction_complete; bool operation_succeeded; }; + struct write_command_context { bool mot; @@ -110,4 +137,44 @@ struct write_command_context { bool transaction_complete; bool operation_succeeded; }; + + +struct aux_engine_funcs { + void (*destroy)( + struct aux_engine **ptr); + bool (*acquire_engine)( + struct aux_engine *engine); + void (*configure)( + struct aux_engine *engine, + union aux_config cfg); + void (*submit_channel_request)( + struct aux_engine *engine, + struct aux_request_transaction_data *request); + void (*process_channel_reply)( + struct aux_engine *engine, + struct aux_reply_transaction_data *reply); + int (*read_channel_reply)( + struct aux_engine *engine, + uint32_t size, + uint8_t *buffer, + uint8_t *reply_result, + uint32_t *sw_status); + enum aux_channel_operation_result (*get_channel_status)( + struct aux_engine *engine, + uint8_t *returned_bytes); + bool (*is_engine_available)(struct aux_engine *engine); + enum i2caux_engine_type (*get_engine_type)( + const struct aux_engine *engine); + bool (*acquire)( + struct aux_engine *engine, + struct ddc *ddc); + bool (*submit_request)( + struct aux_engine *engine, + struct i2caux_transaction_request *request, + bool middle_of_transaction); + void (*release_engine)( + struct aux_engine *engine); + void (*destroy_engine)( + struct aux_engine **engine); +}; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h b/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h deleted file mode 100644 index 1f5476f41236..000000000000 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/engine.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012-15 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: AMD - * - */ - -#ifndef __DAL_ENGINE_H__ -#define __DAL_ENGINE_H__ - -#include "dc_ddc_types.h" - -enum i2caux_transaction_operation { - I2CAUX_TRANSACTION_READ, - I2CAUX_TRANSACTION_WRITE -}; - -enum i2caux_transaction_address_space { - I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C = 1, - I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD -}; - -struct i2caux_transaction_payload { - enum i2caux_transaction_address_space address_space; - uint32_t address; - uint32_t length; - uint8_t *data; -}; - -enum i2caux_transaction_status { - I2CAUX_TRANSACTION_STATUS_UNKNOWN = (-1L), - I2CAUX_TRANSACTION_STATUS_SUCCEEDED, - I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY, - I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT, - I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR, - I2CAUX_TRANSACTION_STATUS_FAILED_NACK, - I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE, - I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION, - I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION, - I2CAUX_TRANSACTION_STATUS_FAILED_BUFFER_OVERFLOW, - I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON -}; - -struct i2caux_transaction_request { - enum i2caux_transaction_operation operation; - struct i2caux_transaction_payload payload; - enum i2caux_transaction_status status; -}; - -enum i2caux_engine_type { - I2CAUX_ENGINE_TYPE_UNKNOWN = (-1L), - I2CAUX_ENGINE_TYPE_AUX, - I2CAUX_ENGINE_TYPE_I2C_DDC_HW, - I2CAUX_ENGINE_TYPE_I2C_GENERIC_HW, - I2CAUX_ENGINE_TYPE_I2C_SW -}; - -enum i2c_default_speed { - I2CAUX_DEFAULT_I2C_HW_SPEED = 50, - I2CAUX_DEFAULT_I2C_SW_SPEED = 50 -}; - -struct engine; - -struct engine_funcs { - enum i2caux_engine_type (*get_engine_type)( - const struct engine *engine); - struct aux_engine* (*acquire)( - struct engine *engine, - struct ddc *ddc); - bool (*submit_request)( - struct engine *engine, - struct i2caux_transaction_request *request, - bool middle_of_transaction); - void (*release_engine)( - struct engine *engine); - void (*destroy_engine)( - struct engine **engine); -}; - -struct engine { - const struct engine_funcs *funcs; - uint32_t inst; - struct ddc *ddc; - struct dc_context *ctx; -}; - -#endif From f358b39d187500717b4bc8633cef45d87eff0a3e Mon Sep 17 00:00:00 2001 From: "Jerry (Fangzhi) Zuo" Date: Tue, 17 Jul 2018 11:53:54 -0400 Subject: [PATCH 05/41] drm/amd/display: Fix Vega10 black screen after mode change [Why] The sequence is slightly changed when bring .set_bandwidth out from the end of programming backend to the end of programming surface. Vega10 doesn't like to get clocks updated if stream_count is zero in the current context (Atomic Reset). [How] Do not update clocks if no stream is showing up in the context. Fixes 1b2b130192 "dc: Remove 300Mhz minimum disp clk limit." Signed-off-by: Jerry (Fangzhi) Zuo Reviewed-by: Tony Cheng Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../drm/amd/display/dc/dce110/dce110_hw_sequencer.h | 5 +++++ .../drm/amd/display/dc/dce120/dce120_hw_sequencer.c | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 33a14e163f88..1149c413f6d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2552,7 +2552,7 @@ static void pplib_apply_display_requirements( dc->prev_display_config = *pp_display_cfg; } -static void dce110_set_bandwidth( +void dce110_set_bandwidth( struct dc *dc, struct dc_state *context, bool decrease_allowed) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index d6db3dbd9015..e4c5db75c4c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -68,6 +68,11 @@ void dce110_fill_display_configs( const struct dc_state *context, struct dm_pp_display_configuration *pp_display_cfg); +void dce110_set_bandwidth( + struct dc *dc, + struct dc_state *context, + bool decrease_allowed); + uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); void dp_receiver_power_ctrl(struct dc_link *link, bool on); diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c index e96ff86d2fc3..5853522a6182 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c @@ -244,7 +244,16 @@ static void dce120_update_dchub( dh_data->dchub_info_valid = false; } +static void dce120_set_bandwidth( + struct dc *dc, + struct dc_state *context, + bool decrease_allowed) +{ + if (context->stream_count <= 0) + return; + dce110_set_bandwidth(dc, context, decrease_allowed); +} void dce120_hw_sequencer_construct(struct dc *dc) { @@ -254,5 +263,6 @@ void dce120_hw_sequencer_construct(struct dc *dc) dce110_hw_sequencer_construct(dc); dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; dc->hwss.update_dchub = dce120_update_dchub; + dc->hwss.set_bandwidth = dce120_set_bandwidth; } From 9907704174e0ad4ed02766fac4049971e583323d Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Tue, 17 Jul 2018 09:43:44 -0400 Subject: [PATCH 06/41] drm/amd/display: Prevent PSR from being enabled if initialization fails [Why] PSR_SET command is sent to the microcontroller in order to initialize parameters needed for PSR feature, such as telling the microcontroller which pipe is driving the PSR supported panel. When this command is skipped or fails, the microcontroller may program the wrong thing if driver tries to enable PSR. [How] If PSR_SET fails, do not set psr_enable flag to indicate the feature is not yet initialized. Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 38 +++++++++++-------- drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 062a46543887..ca7989e4932b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -150,7 +150,7 @@ static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) } } -static void dce_dmcu_setup_psr(struct dmcu *dmcu, +static bool dce_dmcu_setup_psr(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context) { @@ -261,6 +261,8 @@ static void dce_dmcu_setup_psr(struct dmcu *dmcu, /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + return true; } static bool dce_is_dmcu_initialized(struct dmcu *dmcu) @@ -545,24 +547,25 @@ static void dcn10_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable, bool wait) * least a few frames. Should never hit the max retry assert below. */ if (wait == true) { - for (retryCount = 0; retryCount <= 1000; retryCount++) { - dcn10_get_dmcu_psr_state(dmcu, &psr_state); - if (enable) { - if (psr_state != 0) - break; - } else { - if (psr_state == 0) - break; + for (retryCount = 0; retryCount <= 1000; retryCount++) { + dcn10_get_dmcu_psr_state(dmcu, &psr_state); + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + udelay(500); } - udelay(500); - } - /* assert if max retry hit */ - ASSERT(retryCount <= 1000); + /* assert if max retry hit */ + if (retryCount >= 1000) + ASSERT(0); } } -static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, +static bool dcn10_dmcu_setup_psr(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context) { @@ -577,7 +580,7 @@ static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, /* If microcontroller is not running, do nothing */ if (dmcu->dmcu_state != DMCU_RUNNING) - return; + return false; link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc, psr_context->psrExitLinkTrainingRequired); @@ -677,6 +680,11 @@ static void dcn10_dmcu_setup_psr(struct dmcu *dmcu, /* notifyDMCUMsg */ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + + /* waitDMCUReadyForCmd */ + REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 1, 10000); + + return true; } static void dcn10_psr_wait_loop( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h index de60f940030d..4550747fb61c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h @@ -48,7 +48,7 @@ struct dmcu_funcs { const char *src, unsigned int bytes); void (*set_psr_enable)(struct dmcu *dmcu, bool enable, bool wait); - void (*setup_psr)(struct dmcu *dmcu, + bool (*setup_psr)(struct dmcu *dmcu, struct dc_link *link, struct psr_context *psr_context); void (*get_psr_state)(struct dmcu *dmcu, uint32_t *psr_state); From 116f451c90a94de6203757c117278b99a837d3b5 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 9 Jul 2018 17:26:34 -0400 Subject: [PATCH 07/41] drm/amd/display: DC 3.1.59 Signed-off-by: Harry Wentland Reviewed-by: Aric Cyr Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7515c0dcbdd2..c2d390fba0bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -38,7 +38,7 @@ #include "inc/compressor.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.1.58" +#define DC_VER "3.1.59" #define MAX_SURFACES 3 #define MAX_STREAMS 6 From d04cc604a66b07eff8fce824fb6c0fdc0875d2e3 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 25 Jul 2018 09:45:47 -0400 Subject: [PATCH 08/41] drm/amd: Add missing fields in atom_integrated_system_info_v1_11 This structure needs to align with structure in atomfirmware table. Update it. Signed-off-by: Harry Wentland Acked-by: Alex Deucher Reviewed-by: Dmytro Laktyushkin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/atomfirmware.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index 33b4de4ad66e..4bc118df3bc4 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -1074,7 +1074,7 @@ struct atom_integrated_system_info_v1_11 uint16_t dpphy_override; // bit vector, enum of atom_sysinfo_dpphy_override_def uint16_t lvds_misc; // enum of atom_sys_info_lvds_misc_def uint16_t backlight_pwm_hz; // pwm frequency in hz - uint8_t memorytype; // enum of atom_sys_mem_type + uint8_t memorytype; // enum of atom_dmi_t17_mem_type_def, APU memory type indication. uint8_t umachannelnumber; // number of memory channels uint8_t pwr_on_digon_to_de; /* all pwr sequence numbers below are in uint of 4ms */ uint8_t pwr_on_de_to_vary_bl; @@ -1084,18 +1084,25 @@ struct atom_integrated_system_info_v1_11 uint8_t pwr_on_vary_bl_to_blon; uint8_t pwr_down_bloff_to_vary_bloff; uint8_t min_allowed_bl_level; + uint8_t htc_hyst_limit; + uint8_t htc_tmp_limit; + uint8_t reserved1; + uint8_t reserved2; struct atom_external_display_connection_info extdispconninfo; struct atom_14nm_dpphy_dvihdmi_tuningset dvi_tuningset; struct atom_14nm_dpphy_dvihdmi_tuningset hdmi_tuningset; struct atom_14nm_dpphy_dvihdmi_tuningset hdmi6g_tuningset; - struct atom_14nm_dpphy_dp_tuningset dp_tuningset; - struct atom_14nm_dpphy_dp_tuningset dp_hbr3_tuningset; + struct atom_14nm_dpphy_dp_tuningset dp_tuningset; // rbr 1.62G dp tuning set + struct atom_14nm_dpphy_dp_tuningset dp_hbr3_tuningset; // HBR3 dp tuning set struct atom_camera_data camera_info; struct atom_hdmi_retimer_redriver_set dp0_retimer_set; //for DP0 struct atom_hdmi_retimer_redriver_set dp1_retimer_set; //for DP1 struct atom_hdmi_retimer_redriver_set dp2_retimer_set; //for DP2 struct atom_hdmi_retimer_redriver_set dp3_retimer_set; //for DP3 - uint32_t reserved[108]; + struct atom_14nm_dpphy_dp_tuningset dp_hbr_tuningset; //hbr 2.7G dp tuning set + struct atom_14nm_dpphy_dp_tuningset dp_hbr2_tuningset; //hbr2 5.4G dp turnig set + struct atom_14nm_dpphy_dp_tuningset edp_tuningset; //edp tuning set + uint32_t reserved[66]; }; From f1e582ebfd703ea01dc4caf4d339b7c84ec3ff29 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 25 Jul 2018 15:11:34 -0500 Subject: [PATCH 09/41] drm/amdgpu: implement harvesting support for UVD 7.2 (v3) Properly handle cases where one or more instance of the IP block may be harvested. v2: make sure ip_num_rings is initialized amdgpu_queue_mgr.c v3: rebase on Christian's UVD changes, drop unused var Reviewed-by: James Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 17 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c | 13 ++++- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 11 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 4 ++ drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 56 ++++++++++++++++++- 5 files changed, 89 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c7dce14fd47d..dd2132fa2b89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -286,7 +286,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file struct drm_crtc *crtc; uint32_t ui32 = 0; uint64_t ui64 = 0; - int i, found; + int i, j, found; int ui32_size = sizeof(ui32); if (!info->return_size || !info->return_pointer) @@ -348,7 +348,11 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file break; case AMDGPU_HW_IP_UVD: type = AMD_IP_BLOCK_TYPE_UVD; - ring_mask |= adev->uvd.inst[0].ring.ready; + for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (adev->uvd.harvest_config & (1 << i)) + continue; + ring_mask |= adev->uvd.inst[i].ring.ready; + } ib_start_alignment = 64; ib_size_alignment = 64; break; @@ -361,9 +365,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file break; case AMDGPU_HW_IP_UVD_ENC: type = AMD_IP_BLOCK_TYPE_UVD; - for (i = 0; i < adev->uvd.num_enc_rings; i++) - ring_mask |= - adev->uvd.inst[0].ring_enc[i].ready << i; + for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (adev->uvd.harvest_config & (1 << i)) + continue; + for (j = 0; j < adev->uvd.num_enc_rings; j++) + ring_mask |= adev->uvd.inst[i].ring_enc[j].ready << j; + } ib_start_alignment = 64; ib_size_alignment = 64; break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c index d8357290ad09..a172bba32b45 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c @@ -214,7 +214,7 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev, u32 hw_ip, u32 instance, u32 ring, struct amdgpu_ring **out_ring) { - int r, ip_num_rings; + int i, r, ip_num_rings = 0; struct amdgpu_queue_mapper *mapper = &mgr->mapper[hw_ip]; if (!adev || !mgr || !out_ring) @@ -243,14 +243,21 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev, ip_num_rings = adev->sdma.num_instances; break; case AMDGPU_HW_IP_UVD: - ip_num_rings = adev->uvd.num_uvd_inst; + for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (!(adev->uvd.harvest_config & (1 << i))) + ip_num_rings++; + } break; case AMDGPU_HW_IP_VCE: ip_num_rings = adev->vce.num_rings; break; case AMDGPU_HW_IP_UVD_ENC: + for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (!(adev->uvd.harvest_config & (1 << i))) + ip_num_rings++; + } ip_num_rings = - adev->uvd.num_enc_rings * adev->uvd.num_uvd_inst; + adev->uvd.num_enc_rings * ip_num_rings; break; case AMDGPU_HW_IP_VCN_DEC: ip_num_rings = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index fca86d71fafc..632fa5980ff4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -255,7 +255,8 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); for (j = 0; j < adev->uvd.num_uvd_inst; j++) { - + if (adev->uvd.harvest_config & (1 << j)) + continue; r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &adev->uvd.inst[j].vcpu_bo, &adev->uvd.inst[j].gpu_addr, &adev->uvd.inst[j].cpu_addr); @@ -308,6 +309,8 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) drm_sched_entity_destroy(&adev->uvd.entity); for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { + if (adev->uvd.harvest_config & (1 << j)) + continue; kfree(adev->uvd.inst[j].saved_bo); amdgpu_bo_free_kernel(&adev->uvd.inst[j].vcpu_bo, @@ -343,6 +346,8 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) } for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { + if (adev->uvd.harvest_config & (1 << j)) + continue; if (adev->uvd.inst[j].vcpu_bo == NULL) continue; @@ -365,6 +370,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev) int i; for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (adev->uvd.harvest_config & (1 << i)) + continue; if (adev->uvd.inst[i].vcpu_bo == NULL) return -EINVAL; @@ -1159,6 +1166,8 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) unsigned fences = 0, i, j; for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring); for (j = 0; j < adev->uvd.num_enc_rings; ++j) { fences += amdgpu_fence_count_emitted(&adev->uvd.inst[i].ring_enc[j]); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h index 66872286ab12..33c5f806f925 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h @@ -48,6 +48,9 @@ struct amdgpu_uvd_inst { uint32_t srbm_soft_reset; }; +#define AMDGPU_UVD_HARVEST_UVD0 (1 << 0) +#define AMDGPU_UVD_HARVEST_UVD1 (1 << 1) + struct amdgpu_uvd { const struct firmware *fw; /* UVD firmware */ unsigned fw_version; @@ -61,6 +64,7 @@ struct amdgpu_uvd { atomic_t handles[AMDGPU_MAX_UVD_HANDLES]; struct drm_sched_entity entity; struct delayed_work idle_work; + unsigned harvest_config; }; int amdgpu_uvd_sw_init(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index d74c1b242667..5fab3560a71d 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -41,6 +41,12 @@ #include "mmhub/mmhub_1_0_sh_mask.h" #include "ivsrcid/uvd/irqsrcs_uvd_7_0.h" +#define mmUVD_PG0_CC_UVD_HARVESTING 0x00c7 +#define mmUVD_PG0_CC_UVD_HARVESTING_BASE_IDX 1 +//UVD_PG0_CC_UVD_HARVESTING +#define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE__SHIFT 0x1 +#define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK 0x00000002L + #define UVD7_MAX_HW_INSTANCES_VEGA20 2 static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev); @@ -370,10 +376,25 @@ error: static int uvd_v7_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_VEGA20) + + if (adev->asic_type == CHIP_VEGA20) { + u32 harvest; + int i; + adev->uvd.num_uvd_inst = UVD7_MAX_HW_INSTANCES_VEGA20; - else + for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + harvest = RREG32_SOC15(UVD, i, mmUVD_PG0_CC_UVD_HARVESTING); + if (harvest & UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK) { + adev->uvd.harvest_config |= 1 << i; + } + } + if (adev->uvd.harvest_config == (AMDGPU_UVD_HARVEST_UVD0 | + AMDGPU_UVD_HARVEST_UVD1)) + /* both instances are harvested, disable the block */ + return -ENOENT; + } else { adev->uvd.num_uvd_inst = 1; + } if (amdgpu_sriov_vf(adev)) adev->uvd.num_enc_rings = 1; @@ -393,6 +414,8 @@ static int uvd_v7_0_sw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; for (j = 0; j < adev->uvd.num_uvd_inst; j++) { + if (adev->uvd.harvest_config & (1 << j)) + continue; /* UVD TRAP */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], UVD_7_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->uvd.inst[j].irq); if (r) @@ -425,6 +448,8 @@ static int uvd_v7_0_sw_init(void *handle) return r; for (j = 0; j < adev->uvd.num_uvd_inst; j++) { + if (adev->uvd.harvest_config & (1 << j)) + continue; if (!amdgpu_sriov_vf(adev)) { ring = &adev->uvd.inst[j].ring; sprintf(ring->name, "uvd<%d>", j); @@ -472,6 +497,8 @@ static int uvd_v7_0_sw_fini(void *handle) return r; for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { + if (adev->uvd.harvest_config & (1 << j)) + continue; for (i = 0; i < adev->uvd.num_enc_rings; ++i) amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]); } @@ -500,6 +527,8 @@ static int uvd_v7_0_hw_init(void *handle) goto done; for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { + if (adev->uvd.harvest_config & (1 << j)) + continue; ring = &adev->uvd.inst[j].ring; if (!amdgpu_sriov_vf(adev)) { @@ -579,8 +608,11 @@ static int uvd_v7_0_hw_fini(void *handle) DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); } - for (i = 0; i < adev->uvd.num_uvd_inst; ++i) + for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; adev->uvd.inst[i].ring.ready = false; + } return 0; } @@ -623,6 +655,8 @@ static void uvd_v7_0_mc_resume(struct amdgpu_device *adev) int i; for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { WREG32_SOC15(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr)); @@ -695,6 +729,8 @@ static int uvd_v7_0_mmsch_start(struct amdgpu_device *adev, WREG32_SOC15(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP, 0); for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; WDOORBELL32(adev->uvd.inst[i].ring_enc[0].doorbell_index, 0); adev->wb.wb[adev->uvd.inst[i].ring_enc[0].wptr_offs] = 0; adev->uvd.inst[i].ring_enc[0].wptr = 0; @@ -751,6 +787,8 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev) init_table += header->uvd_table_offset; for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; ring = &adev->uvd.inst[i].ring; ring->wptr = 0; size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4); @@ -890,6 +928,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev) int i, j, k, r; for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { + if (adev->uvd.harvest_config & (1 << k)) + continue; /* disable DPG */ WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_POWER_STATUS), 0, ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); @@ -902,6 +942,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev) uvd_v7_0_mc_resume(adev); for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { + if (adev->uvd.harvest_config & (1 << k)) + continue; ring = &adev->uvd.inst[k].ring; /* disable clock gating */ WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_CGC_CTRL), 0, @@ -1069,6 +1111,8 @@ static void uvd_v7_0_stop(struct amdgpu_device *adev) uint8_t i = 0; for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { + if (adev->uvd.harvest_config & (1 << i)) + continue; /* force RBC into idle state */ WREG32_SOC15(UVD, i, mmUVD_RBC_RB_CNTL, 0x11010101); @@ -1785,6 +1829,8 @@ static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev) int i; for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (adev->uvd.harvest_config & (1 << i)) + continue; adev->uvd.inst[i].ring.funcs = &uvd_v7_0_ring_vm_funcs; adev->uvd.inst[i].ring.me = i; DRM_INFO("UVD(%d) is enabled in VM mode\n", i); @@ -1796,6 +1842,8 @@ static void uvd_v7_0_set_enc_ring_funcs(struct amdgpu_device *adev) int i, j; for (j = 0; j < adev->uvd.num_uvd_inst; j++) { + if (adev->uvd.harvest_config & (1 << j)) + continue; for (i = 0; i < adev->uvd.num_enc_rings; ++i) { adev->uvd.inst[j].ring_enc[i].funcs = &uvd_v7_0_enc_ring_vm_funcs; adev->uvd.inst[j].ring_enc[i].me = j; @@ -1815,6 +1863,8 @@ static void uvd_v7_0_set_irq_funcs(struct amdgpu_device *adev) int i; for (i = 0; i < adev->uvd.num_uvd_inst; i++) { + if (adev->uvd.harvest_config & (1 << i)) + continue; adev->uvd.inst[i].irq.num_types = adev->uvd.num_enc_rings + 1; adev->uvd.inst[i].irq.funcs = &uvd_v7_0_irq_funcs; } From 2ac305b7c8d7f93a6ef0018391e9865ea4ac0d65 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 26 Jul 2018 16:32:08 +0800 Subject: [PATCH 10/41] drm/ttm: add ttm_set_memory header (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch moves all non-x86 abstraction to the ttm_set_memory header. It is to make function calling more clearly. (v2): add ttm_ prefix. Suggested-by: Christian König Signed-off-by: Huang Rui Reviewed-by: Bas Nieuwenhuizen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- include/drm/ttm/ttm_set_memory.h | 128 +++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 include/drm/ttm/ttm_set_memory.h diff --git a/include/drm/ttm/ttm_set_memory.h b/include/drm/ttm/ttm_set_memory.h new file mode 100644 index 000000000000..a70723cf208b --- /dev/null +++ b/include/drm/ttm/ttm_set_memory.h @@ -0,0 +1,128 @@ +/************************************************************************** + * + * Copyright (c) 2018 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Huang Rui + */ + +#ifndef TTM_SET_MEMORY +#define TTM_SET_MEMORY + +#include + +#ifdef CONFIG_X86 + +#include + +static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray) +{ + return set_pages_array_wb(pages, addrinarray); +} + +static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray) +{ + return set_pages_array_wc(pages, addrinarray); +} + +static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray) +{ + return set_pages_array_uc(pages, addrinarray); +} + +static inline int ttm_set_pages_wb(struct page *page, int numpages) +{ + return set_pages_wb(page, numpages); +} + +#else /* for CONFIG_X86 */ + +#if IS_ENABLED(CONFIG_AGP) + +#include + +static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + unmap_page_from_agp(pages[i]); + return 0; +} + +static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + map_page_into_agp(pages[i]); + return 0; +} + +static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray) +{ + int i; + + for (i = 0; i < addrinarray; i++) + map_page_into_agp(pages[i]); + return 0; +} + +static inline int ttm_set_pages_wb(struct page *page, int numpages) +{ + int i; + + for (i = 0; i < numpages; i++) + unmap_page_from_agp(page++); + return 0; +} + +#else /* for CONFIG_AGP */ + +static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray) +{ + return 0; +} + +static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray) +{ + return 0; +} + +static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray) +{ + return 0; +} + +static inline int ttm_set_pages_wb(struct page *page, int numpages) +{ + return 0; +} + +#endif /* for CONFIG_AGP */ + +#endif /* for CONFIG_X86 */ + +#endif From c7bb1e57e20a7f43b52df183d1a5a1aa936acc2d Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 26 Jul 2018 16:48:54 +0800 Subject: [PATCH 11/41] drm/ttm: clean up non-x86 definitions on ttm_page_alloc_dma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All non-x86 definitions are moved to ttm_set_memory header, so remove it from ttm_page_alloc_dma.c. Suggested-by: Christian König Signed-off-by: Huang Rui Reviewed-by: Bas Nieuwenhuizen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 48 ++---------------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 3f14c1cc0789..f31148ad981c 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -50,12 +50,7 @@ #include #include #include -#if IS_ENABLED(CONFIG_AGP) -#include -#endif -#ifdef CONFIG_X86 -#include -#endif +#include #define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) #define SMALL_ALLOCATION 4 @@ -268,41 +263,6 @@ static struct kobj_type ttm_pool_kobj_type = { .default_attrs = ttm_pool_attrs, }; -#ifndef CONFIG_X86 -static int set_pages_array_wb(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - unmap_page_from_agp(pages[i]); -#endif - return 0; -} - -static int set_pages_array_wc(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - map_page_into_agp(pages[i]); -#endif - return 0; -} - -static int set_pages_array_uc(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - map_page_into_agp(pages[i]); -#endif - return 0; -} -#endif /* for !CONFIG_X86 */ - static int ttm_set_pages_caching(struct dma_pool *pool, struct page **pages, unsigned cpages) { @@ -315,7 +275,7 @@ static int ttm_set_pages_caching(struct dma_pool *pool, pool->dev_name, cpages); } if (pool->type & IS_WC) { - r = set_pages_array_wc(pages, cpages); + r = ttm_set_pages_array_wc(pages, cpages); if (r) pr_err("%s: Failed to set %d pages to wc!\n", pool->dev_name, cpages); @@ -395,7 +355,7 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) if (!(pool->type & IS_CACHED)) { num_pages = pool->size / PAGE_SIZE; for (i = 0; i < num_pages; ++i, ++page) { - if (set_pages_array_wb(&page, 1)) { + if (ttm_set_pages_array_wb(&page, 1)) { pr_err("%s: Failed to set %d pages to wb!\n", pool->dev_name, 1); } @@ -420,7 +380,7 @@ static void ttm_dma_pages_put(struct dma_pool *pool, struct list_head *d_pages, /* Don't set WB on WB page pool. */ if (npages && !(pool->type & IS_CACHED) && - set_pages_array_wb(pages, npages)) + ttm_set_pages_array_wb(pages, npages)) pr_err("%s: Failed to set %d pages to wb!\n", pool->dev_name, npages); From d55f9b87428f4732472ec7e9ccb7b4135751996c Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 26 Jul 2018 16:49:36 +0800 Subject: [PATCH 12/41] drm/ttm: clean up non-x86 definitions on ttm_page_alloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All non-x86 definitions are moved to ttm_set_memory header, so remove it from ttm_page_alloc.c. Suggested-by: Christian König Signed-off-by: Huang Rui Reviewed-by: Bas Nieuwenhuizen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_page_alloc.c | 62 +++------------------------- 1 file changed, 5 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 6e2d1300b457..f841accc2c00 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -47,13 +47,7 @@ #include #include - -#if IS_ENABLED(CONFIG_AGP) -#include -#endif -#ifdef CONFIG_X86 -#include -#endif +#include #define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) #define SMALL_ALLOCATION 16 @@ -222,52 +216,6 @@ static struct kobj_type ttm_pool_kobj_type = { static struct ttm_pool_manager *_manager; -#ifndef CONFIG_X86 -static int set_pages_wb(struct page *page, int numpages) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < numpages; i++) - unmap_page_from_agp(page++); -#endif - return 0; -} - -static int set_pages_array_wb(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - unmap_page_from_agp(pages[i]); -#endif - return 0; -} - -static int set_pages_array_wc(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - map_page_into_agp(pages[i]); -#endif - return 0; -} - -static int set_pages_array_uc(struct page **pages, int addrinarray) -{ -#if IS_ENABLED(CONFIG_AGP) - int i; - - for (i = 0; i < addrinarray; i++) - map_page_into_agp(pages[i]); -#endif - return 0; -} -#endif - /** * Select the right pool or requested caching state and ttm flags. */ static struct ttm_page_pool *ttm_get_pool(int flags, bool huge, @@ -302,13 +250,13 @@ static void ttm_pages_put(struct page *pages[], unsigned npages, unsigned int i, pages_nr = (1 << order); if (order == 0) { - if (set_pages_array_wb(pages, npages)) + if (ttm_set_pages_array_wb(pages, npages)) pr_err("Failed to set %d pages to wb!\n", npages); } for (i = 0; i < npages; ++i) { if (order > 0) { - if (set_pages_wb(pages[i], pages_nr)) + if (ttm_set_pages_wb(pages[i], pages_nr)) pr_err("Failed to set %d pages to wb!\n", pages_nr); } __free_pages(pages[i], order); @@ -498,12 +446,12 @@ static int ttm_set_pages_caching(struct page **pages, /* Set page caching */ switch (cstate) { case tt_uncached: - r = set_pages_array_uc(pages, cpages); + r = ttm_set_pages_array_uc(pages, cpages); if (r) pr_err("Failed to set %d pages to uc!\n", cpages); break; case tt_wc: - r = set_pages_array_wc(pages, cpages); + r = ttm_set_pages_array_wc(pages, cpages); if (r) pr_err("Failed to set %d pages to wc!\n", cpages); break; From 610b399f1ff269e4b9ec85cfdffb06f9befd0c41 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Wed, 25 Jul 2018 22:29:50 +0200 Subject: [PATCH 13/41] drm/ttm: Merge hugepage attr changes in ttm_dma_page_put. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every set_pages_array_wb call resulted in cross-core interrupts and TLB flushes. Merge more of them for less overhead. This reduces the time needed to free a 1.6 GiB GTT WC buffer as part of Vulkan CTS from ~2 sec to < 0.25 sec. (Allocation still takes more than 2 sec though) (v2): use set_pages_wb instead of set_memory_wb. Signed-off-by: Bas Nieuwenhuizen Signed-off-by: Huang Rui Reviewed-by: Christian König Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index f31148ad981c..8304917294a2 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -349,17 +349,14 @@ static void ttm_pool_update_free_locked(struct dma_pool *pool, static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) { struct page *page = d_page->p; - unsigned i, num_pages; + unsigned num_pages; /* Don't set WB on WB page pool. */ if (!(pool->type & IS_CACHED)) { num_pages = pool->size / PAGE_SIZE; - for (i = 0; i < num_pages; ++i, ++page) { - if (ttm_set_pages_array_wb(&page, 1)) { - pr_err("%s: Failed to set %d pages to wb!\n", - pool->dev_name, 1); - } - } + if (ttm_set_pages_wb(page, num_pages)) + pr_err("%s: Failed to set %d pages to wb!\n", + pool->dev_name, num_pages); } list_del(&d_page->page_list); From 204029e1979959ea6150c2a5c3e961800f52d0d4 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 26 Jul 2018 18:00:13 +0800 Subject: [PATCH 14/41] drm/amdgpu: correct evict flag for bo move MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pass the evict flag instead of hard code Signed-off-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8c4358e36c87..c1ae528c7b0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -580,7 +580,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, } /* blit VRAM to GTT */ - r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, &tmp_mem, old_mem); + r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, &tmp_mem, old_mem); if (unlikely(r)) { goto out_cleanup; } @@ -632,7 +632,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, } /* copy to VRAM */ - r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, new_mem, old_mem); + r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, new_mem, old_mem); if (unlikely(r)) { goto out_cleanup; } From 2e603d0429a4e7cba93a4bc4fcdbdf830adaa472 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 26 Jul 2018 14:08:03 +0800 Subject: [PATCH 15/41] drm/amdgpu: clean up the superfluous space and align the comment text for amdgpu_ttm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch cleans up spaces and align the text to refine the comment for amdgpu_ttm. Signed-off-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 107 +++++++++++------------- 1 file changed, 51 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c1ae528c7b0e..fcf421263fd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -92,11 +92,9 @@ static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref) } /** - * amdgpu_ttm_global_init - Initialize global TTM memory reference - * structures. + * amdgpu_ttm_global_init - Initialize global TTM memory reference structures. * - * @adev: AMDGPU device for which the global structures need to be - * registered. + * @adev: AMDGPU device for which the global structures need to be registered. * * This is called as part of the AMDGPU ttm init from amdgpu_ttm_init() * during bring up. @@ -162,13 +160,12 @@ static int amdgpu_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) } /** - * amdgpu_init_mem_type - Initialize a memory manager for a specific - * type of memory request. + * amdgpu_init_mem_type - Initialize a memory manager for a specific type of + * memory request. * - * @bdev: The TTM BO device object (contains a reference to - * amdgpu_device) - * @type: The type of memory requested - * @man: + * @bdev: The TTM BO device object (contains a reference to amdgpu_device) + * @type: The type of memory requested + * @man: The memory type manager for each domain * * This is called by ttm_bo_init_mm() when a buffer object is being * initialized. @@ -292,8 +289,8 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, /** * amdgpu_verify_access - Verify access for a mmap call * - * @bo: The buffer object to map - * @filp: The file pointer from the process performing the mmap + * @bo: The buffer object to map + * @filp: The file pointer from the process performing the mmap * * This is called by ttm_bo_mmap() to verify whether a process * has the right to mmap a BO to their process space. @@ -318,11 +315,10 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) /** * amdgpu_move_null - Register memory for a buffer object * - * @bo: The bo to assign the memory to - * @new_mem: The memory to be assigned. + * @bo: The bo to assign the memory to + * @new_mem: The memory to be assigned. * - * Assign the memory from new_mem to the memory of the buffer object - * bo. + * Assign the memory from new_mem to the memory of the buffer object bo. */ static void amdgpu_move_null(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) @@ -335,8 +331,12 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, } /** - * amdgpu_mm_node_addr - Compute the GPU relative offset of a GTT - * buffer. + * amdgpu_mm_node_addr - Compute the GPU relative offset of a GTT buffer. + * + * @bo: The bo to assign the memory to. + * @mm_node: Memory manager node for drm allocator. + * @mem: The region where the bo resides. + * */ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, struct drm_mm_node *mm_node, @@ -352,10 +352,12 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, } /** - * amdgpu_find_mm_node - Helper function finds the drm_mm_node - * corresponding to @offset. It also modifies - * the offset to be within the drm_mm_node - * returned + * amdgpu_find_mm_node - Helper function finds the drm_mm_node corresponding to + * @offset. It also modifies the offset to be within the drm_mm_node returned + * + * @mem: The region where the bo resides. + * @offset: The offset that drm_mm_node is used for finding. + * */ static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, unsigned long *offset) @@ -497,8 +499,8 @@ error: /** * amdgpu_move_blit - Copy an entire buffer to another buffer * - * This is a helper called by amdgpu_bo_move() and - * amdgpu_move_vram_ram() to help move buffers to and from VRAM. + * This is a helper called by amdgpu_bo_move() and amdgpu_move_vram_ram() to + * help move buffers to and from VRAM. */ static int amdgpu_move_blit(struct ttm_buffer_object *bo, bool evict, bool no_wait_gpu, @@ -794,8 +796,8 @@ struct amdgpu_ttm_tt { }; /** - * amdgpu_ttm_tt_get_user_pages - Pin pages of memory pointed to - * by a USERPTR pointer to memory + * amdgpu_ttm_tt_get_user_pages - Pin pages of memory pointed to by a USERPTR + * pointer to memory * * Called by amdgpu_gem_userptr_ioctl() and amdgpu_cs_parser_bos(). * This provides a wrapper around the get_user_pages() call to provide @@ -818,8 +820,10 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) down_read(&mm->mmap_sem); if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { - /* check that we only use anonymous memory - to prevent problems with writeback */ + /* + * check that we only use anonymous memory to prevent problems + * with writeback + */ unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE; struct vm_area_struct *vma; @@ -870,10 +874,9 @@ release_pages: } /** - * amdgpu_ttm_tt_set_user_pages - Copy pages in, putting old pages - * as necessary. + * amdgpu_ttm_tt_set_user_pages - Copy pages in, putting old pages as necessary. * - * Called by amdgpu_cs_list_validate(). This creates the page list + * Called by amdgpu_cs_list_validate(). This creates the page list * that backs user memory and will ultimately be mapped into the device * address space. */ @@ -915,8 +918,7 @@ void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) } /** - * amdgpu_ttm_tt_pin_userptr - prepare the sg table with the - * user pages + * amdgpu_ttm_tt_pin_userptr - prepare the sg table with the user pages * * Called by amdgpu_ttm_backend_bind() **/ @@ -1295,8 +1297,8 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) } /** - * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt - * for the current task + * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt for the current + * task * * @ttm: The ttm_tt object to bind this userptr object to * @addr: The address in the current tasks VM space to use @@ -1346,9 +1348,8 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) } /** - * amdgpu_ttm_tt_affect_userptr - Determine if a ttm_tt object lays - * inside an address range for the - * current task. + * amdgpu_ttm_tt_affect_userptr - Determine if a ttm_tt object lays inside an + * address range for the current task. * */ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, @@ -1386,8 +1387,7 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, } /** - * amdgpu_ttm_tt_userptr_invalidated - Has the ttm_tt object been - * invalidated? + * amdgpu_ttm_tt_userptr_invalidated - Has the ttm_tt object been invalidated? */ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, int *last_invalidated) @@ -1400,10 +1400,8 @@ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, } /** - * amdgpu_ttm_tt_userptr_needs_pages - Have the pages backing this - * ttm_tt object been invalidated - * since the last time they've - * been set? + * amdgpu_ttm_tt_userptr_needs_pages - Have the pages backing this ttm_tt object + * been invalidated since the last time they've been set? */ bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) { @@ -1459,13 +1457,12 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, } /** - * amdgpu_ttm_bo_eviction_valuable - Check to see if we can evict - * a buffer object. + * amdgpu_ttm_bo_eviction_valuable - Check to see if we can evict a buffer + * object. * - * Return true if eviction is sensible. Called by - * ttm_mem_evict_first() on behalf of ttm_bo_mem_force_space() - * which tries to evict buffer objects until it can find space - * for a new object and by ttm_bo_force_list_clean() which is + * Return true if eviction is sensible. Called by ttm_mem_evict_first() on + * behalf of ttm_bo_mem_force_space() which tries to evict buffer objects until + * it can find space for a new object and by ttm_bo_force_list_clean() which is * used to clean out a memory space. */ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, @@ -1515,8 +1512,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, } /** - * amdgpu_ttm_access_memory - Read or Write memory that backs a - * buffer object. + * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object. * * @bo: The buffer object to read/write * @offset: Offset into buffer object @@ -1704,8 +1700,8 @@ error_create: return r; } /** - * amdgpu_ttm_init - Init the memory management (ttm) as well as - * various gtt/vram related fields. + * amdgpu_ttm_init - Init the memory management (ttm) as well as various + * gtt/vram related fields. * * This initializes all of the memory space pools that the TTM layer * will need such as the GTT space (system memory mapped to the device), @@ -1856,8 +1852,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) } /** - * amdgpu_ttm_late_init - Handle any late initialization for - * amdgpu_ttm + * amdgpu_ttm_late_init - Handle any late initialization for amdgpu_ttm */ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { From 2d227ec2c11c568910299e8f913bac2dda47397c Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 20 Jul 2018 16:26:46 +0800 Subject: [PATCH 16/41] drm/amd/pp/Polaris12: Fix a chunk of registers missed to program DIDTConfig_Polaris12[] table missed a big chunk of data. Pointed by aidan.fabius Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- .../drm/amd/powerplay/hwmgr/smu7_powertune.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c index c952845833d7..5e19f5977eb1 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c @@ -403,6 +403,49 @@ static const struct gpu_pt_config_reg DIDTConfig_Polaris12[] = { { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, From 90983631a6486f68c1e95bf30713a179ac0a083f Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 20 Jul 2018 18:19:00 +0800 Subject: [PATCH 17/41] drm/amd/pp: Delete unused temp variables Only delete the dead temp variables in Polaris. Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../amd/powerplay/smumgr/polaris10_smumgr.c | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index a4ce199af475..1276f168ff68 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -1204,7 +1204,6 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, (struct phm_ppt_v1_information *)(hwmgr->pptable); SMIO_Pattern vol_level; uint32_t mvdd; - uint16_t us_mvdd; table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; @@ -1255,16 +1254,11 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, "in Clock Dependency Table", ); - us_mvdd = 0; - if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || - (data->mclk_dpm_key_disabled)) - us_mvdd = data->vbios_boot_state.mvdd_bootup_value; - else { - if (!polaris10_populate_mvdd_value(hwmgr, + if (!((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled))) + polaris10_populate_mvdd_value(hwmgr, data->dpm_table.mclk_table.dpm_levels[0].value, - &vol_level)) - us_mvdd = vol_level.Voltage; - } + &vol_level); if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level)) table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); @@ -1517,7 +1511,7 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0; + uint8_t i, stretch_amount, volt_offset = 0; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = @@ -1568,11 +1562,7 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { + if (stretch_amount == 0 || stretch_amount > 5) { phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ClockStretcher); PP_ASSERT_WITH_CODE(false, From 8a50bb47a863c3cb8950a2e810448c9a82a9d446 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 25 Jul 2018 11:45:03 +0800 Subject: [PATCH 18/41] drm/amd/pp: Convert voltage unit in mV*4 to mV on CZ/ST the voltage showed in debugfs and hwmon should be in mV Reviewed-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c index 288802f209dd..0adfc5392cd3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c @@ -244,6 +244,7 @@ static int smu8_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) return 0; } +/* convert form 8bit vid to real voltage in mV*4 */ static uint32_t smu8_convert_8Bit_index_to_voltage( struct pp_hwmgr *hwmgr, uint16_t voltage) { @@ -1702,13 +1703,13 @@ static int smu8_read_sensor(struct pp_hwmgr *hwmgr, int idx, case AMDGPU_PP_SENSOR_VDDNB: tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; - vddnb = smu8_convert_8Bit_index_to_voltage(hwmgr, tmp); + vddnb = smu8_convert_8Bit_index_to_voltage(hwmgr, tmp) / 4; *((uint32_t *)value) = vddnb; return 0; case AMDGPU_PP_SENSOR_VDDGFX: tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; - vddgfx = smu8_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp); + vddgfx = smu8_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp) / 4; *((uint32_t *)value) = vddgfx; return 0; case AMDGPU_PP_SENSOR_UVD_VCLK: From ccf9ef0b0d10434dec5046bcfc4e834a7b1830fd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 25 Jul 2018 11:51:46 +0800 Subject: [PATCH 19/41] drm/amdgpu: fix a reversed condition This test was reversed so it would end up leading to vddnb value can't be read via hwmon on APU. Reviewed-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 15a1192c1ec5..23fc1d32b937 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1185,7 +1185,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, int r, size = sizeof(vddnb); /* only APUs have vddnb */ - if (adev->flags & AMD_IS_APU) + if (!(adev->flags & AMD_IS_APU)) return -EINVAL; /* Can't get voltage when the card is off */ From 52c054caf83012fe9fe858ee86d90b4ea2cc3cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 27 Jul 2018 15:32:04 +0200 Subject: [PATCH 20/41] drm/amdgpu: add proper error handling to amdgpu_bo_list_get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we silently don't use a BO list when the handle is invalid. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Huang Rui Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 28 ++++++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 11 +++++--- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 1f6345dda6ea..4d4d6697fbce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -713,8 +713,8 @@ struct amdgpu_bo_list { struct amdgpu_bo_list_entry *array; }; -struct amdgpu_bo_list * -amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id); +int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, + struct amdgpu_bo_list **result); void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, struct list_head *validated); void amdgpu_bo_list_put(struct amdgpu_bo_list *list); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 7679c068c89a..944868e47119 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -180,27 +180,20 @@ error_free: return r; } -struct amdgpu_bo_list * -amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id) +int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, + struct amdgpu_bo_list **result) { - struct amdgpu_bo_list *result; - rcu_read_lock(); - result = idr_find(&fpriv->bo_list_handles, id); + *result = idr_find(&fpriv->bo_list_handles, id); - if (result) { - if (kref_get_unless_zero(&result->refcount)) { - rcu_read_unlock(); - mutex_lock(&result->lock); - } else { - rcu_read_unlock(); - result = NULL; - } - } else { + if (*result && kref_get_unless_zero(&(*result)->refcount)) { rcu_read_unlock(); + mutex_lock(&(*result)->lock); + return 0; } - return result; + rcu_read_unlock(); + return -ENOENT; } void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, @@ -335,9 +328,8 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, break; case AMDGPU_BO_LIST_OP_UPDATE: - r = -ENOENT; - list = amdgpu_bo_list_get(fpriv, handle); - if (!list) + r = amdgpu_bo_list_get(fpriv, handle, &list); + if (r) goto error_free; r = amdgpu_bo_list_set(adev, filp, list, info, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 533b2e7656c0..8a49c3b97bd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -572,11 +572,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, INIT_LIST_HEAD(&p->validated); /* p->bo_list could already be assigned if AMDGPU_CHUNK_ID_BO_HANDLES is present */ - if (!p->bo_list) - p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle); - else + if (p->bo_list) { mutex_lock(&p->bo_list->lock); + } else if (cs->in.bo_list_handle) { + r = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle, + &p->bo_list); + if (r) + return r; + } + if (p->bo_list) { amdgpu_bo_list_get_list(p->bo_list, &p->validated); if (p->bo_list->first_userptr != p->bo_list->num_entries) From ba7f47831ebdad141791be53a51049d6771156cd Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 6 Jul 2018 14:12:11 +0900 Subject: [PATCH 21/41] drm/sched: remove unneeded -Iinclude/drm compiler flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I refactored the include directives under include/drm/ some time ago. This flag is unneeded. Signed-off-by: Masahiro Yamada Reviewed-by: Christian König Acked-by: Nayan Deshmukh Signed-off-by: Alex Deucher --- drivers/gpu/drm/scheduler/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/Makefile b/drivers/gpu/drm/scheduler/Makefile index bd0377c0d2ee..7665883f81d4 100644 --- a/drivers/gpu/drm/scheduler/Makefile +++ b/drivers/gpu/drm/scheduler/Makefile @@ -20,7 +20,6 @@ # OTHER DEALINGS IN THE SOFTWARE. # # -ccflags-y := -Iinclude/drm gpu-sched-y := gpu_scheduler.o sched_fence.o obj-$(CONFIG_DRM_SCHED) += gpu-sched.o From 275105ce7be37a2cc80eb1b60e6526355f54df94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 15:33:34 +0200 Subject: [PATCH 22/41] drm/amdgpu: fix total size calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit long might only be 32bit in size and we can easily use more than 4GB here. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 944868e47119..6728448167ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -105,9 +105,9 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, struct amdgpu_bo *oa_obj = adev->gds.oa_gfx_bo; unsigned last_entry = 0, first_userptr = num_entries; + uint64_t total_size = 0; unsigned i; int r; - unsigned long total_size = 0; array = kvmalloc_array(num_entries, sizeof(struct amdgpu_bo_list_entry), GFP_KERNEL); if (!array) From 0cb7c1f03bfb3991120313c5927c1749041ef800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 16:18:54 +0200 Subject: [PATCH 23/41] drm/amdgpu: return error if both BOs and bo_list handle is given MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return -EINVAL when both the BOs as well as a list handle is provided in the IOCTL. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 8a49c3b97bd4..d41cea78e4aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -572,14 +572,17 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, INIT_LIST_HEAD(&p->validated); /* p->bo_list could already be assigned if AMDGPU_CHUNK_ID_BO_HANDLES is present */ - if (p->bo_list) { - mutex_lock(&p->bo_list->lock); + if (cs->in.bo_list_handle) { + if (p->bo_list) + return -EINVAL; - } else if (cs->in.bo_list_handle) { r = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle, &p->bo_list); if (r) return r; + + } else if (p->bo_list) { + mutex_lock(&p->bo_list->lock); } if (p->bo_list) { From 8ab19ea619aeed8ca4a36c124e8edfd9b9491aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 27 Jul 2018 16:56:34 +0200 Subject: [PATCH 24/41] drm/amdgpu: add new amdgpu_vm_bo_trace_cs() function v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to trace all VM ranges which should be valid inside a CS. v2: dump mappings without BO as well Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-and-tested-by: Andrey Grodzovsky (v1) Reviewed-by: Huang Rui (v1) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 5 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 29 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 1 + 4 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d41cea78e4aa..0295666968da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1223,6 +1223,7 @@ static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p) static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, union drm_amdgpu_cs *cs) { + struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_ring *ring = p->ring; struct drm_sched_entity *entity = &p->ctx->rings[ring->idx].entity; enum drm_sched_priority priority; @@ -1275,6 +1276,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, amdgpu_job_free_resources(job); trace_amdgpu_cs_ioctl(job); + amdgpu_vm_bo_trace_cs(&fpriv->vm, &p->ticket); priority = job->base.s_priority; drm_sched_entity_push_job(&job->base, entity); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 11f262f15200..7206a0025b17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -314,6 +314,11 @@ DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_mapping, TP_ARGS(mapping) ); +DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_cs, + TP_PROTO(struct amdgpu_bo_va_mapping *mapping), + TP_ARGS(mapping) +); + TRACE_EVENT(amdgpu_vm_set_ptes, TP_PROTO(uint64_t pe, uint64_t addr, unsigned count, uint32_t incr, uint64_t flags), diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 5d7d7900ccab..015613b4f98b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2343,6 +2343,35 @@ struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, return amdgpu_vm_it_iter_first(&vm->va, addr, addr); } +/** + * amdgpu_vm_bo_trace_cs - trace all reserved mappings + * + * @vm: the requested vm + * @ticket: CS ticket + * + * Trace all mappings of BOs reserved during a command submission. + */ +void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket) +{ + struct amdgpu_bo_va_mapping *mapping; + + if (!trace_amdgpu_vm_bo_cs_enabled()) + return; + + for (mapping = amdgpu_vm_it_iter_first(&vm->va, 0, U64_MAX); mapping; + mapping = amdgpu_vm_it_iter_next(mapping, 0, U64_MAX)) { + if (mapping->bo_va && mapping->bo_va->base.bo) { + struct amdgpu_bo *bo; + + bo = mapping->bo_va->base.bo; + if (READ_ONCE(bo->tbo.resv->lock.ctx) != ticket) + continue; + } + + trace_amdgpu_vm_bo_cs(mapping); + } +} + /** * amdgpu_vm_bo_rmv - remove a bo to a specific vm * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index d416f895233d..67a15d439ac0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -318,6 +318,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, uint64_t saddr, uint64_t size); struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, uint64_t addr); +void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket); void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va); void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t vm_size, From 4a8c21a1e9b3c35b21c5a4a4c16a009a193389bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 13:27:09 +0200 Subject: [PATCH 25/41] drm/amdgpu: move bo_list defines to amdgpu_bo_list.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further demangle amdgpu.h Signed-off-by: Christian König Reviewed-by: Chunming Zhou Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 40 +----------- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 70 +++++++++++++++++++++ 2 files changed, 71 insertions(+), 39 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4d4d6697fbce..447c4c7a36d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -74,6 +74,7 @@ #include "amdgpu_gart.h" #include "amdgpu_debugfs.h" #include "amdgpu_job.h" +#include "amdgpu_bo_list.h" /* * Modules parameters. @@ -689,45 +690,6 @@ struct amdgpu_fpriv { struct amdgpu_ctx_mgr ctx_mgr; }; -/* - * residency list - */ -struct amdgpu_bo_list_entry { - struct amdgpu_bo *robj; - struct ttm_validate_buffer tv; - struct amdgpu_bo_va *bo_va; - uint32_t priority; - struct page **user_pages; - int user_invalidated; -}; - -struct amdgpu_bo_list { - struct mutex lock; - struct rcu_head rhead; - struct kref refcount; - struct amdgpu_bo *gds_obj; - struct amdgpu_bo *gws_obj; - struct amdgpu_bo *oa_obj; - unsigned first_userptr; - unsigned num_entries; - struct amdgpu_bo_list_entry *array; -}; - -int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, - struct amdgpu_bo_list **result); -void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, - struct list_head *validated); -void amdgpu_bo_list_put(struct amdgpu_bo_list *list); -void amdgpu_bo_list_free(struct amdgpu_bo_list *list); -int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, - struct drm_amdgpu_bo_list_entry **info_param); - -int amdgpu_bo_list_create(struct amdgpu_device *adev, - struct drm_file *filp, - struct drm_amdgpu_bo_list_entry *info, - unsigned num_entries, - struct amdgpu_bo_list **list); - /* * GFX stuff */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h new file mode 100644 index 000000000000..833f846bfdad --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -0,0 +1,70 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_BO_LIST_H__ +#define __AMDGPU_BO_LIST_H__ + +#include +#include + +struct amdgpu_device; +struct amdgpu_bo; +struct amdgpu_bo_va; +struct amdgpu_fpriv; + +struct amdgpu_bo_list_entry { + struct amdgpu_bo *robj; + struct ttm_validate_buffer tv; + struct amdgpu_bo_va *bo_va; + uint32_t priority; + struct page **user_pages; + int user_invalidated; +}; + +struct amdgpu_bo_list { + struct mutex lock; + struct rcu_head rhead; + struct kref refcount; + struct amdgpu_bo *gds_obj; + struct amdgpu_bo *gws_obj; + struct amdgpu_bo *oa_obj; + unsigned first_userptr; + unsigned num_entries; + struct amdgpu_bo_list_entry *array; +}; + +int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, + struct amdgpu_bo_list **result); +void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, + struct list_head *validated); +void amdgpu_bo_list_put(struct amdgpu_bo_list *list); +void amdgpu_bo_list_free(struct amdgpu_bo_list *list); +int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, + struct drm_amdgpu_bo_list_entry **info_param); + +int amdgpu_bo_list_create(struct amdgpu_device *adev, + struct drm_file *filp, + struct drm_amdgpu_bo_list_entry *info, + unsigned num_entries, + struct amdgpu_bo_list **list); + +#endif From 81c6dabcc990c341793368db985ee8aca5713b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 13:46:04 +0200 Subject: [PATCH 26/41] drm/amdgpu: always recreate bo_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bo_list handle is allocated by OP_CREATE, so in OP_UPDATE here we just re-create the bo_list object and replace the handle. This way we don't need locking to protect the bo_list because it's always re-created when changed. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 25 +++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 --- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 6728448167ba..556040e45931 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -50,7 +50,6 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref) for (i = 0; i < list->num_entries; ++i) amdgpu_bo_unref(&list->array[i].robj); - mutex_destroy(&list->lock); kvfree(list->array); kfree_rcu(list, rhead); } @@ -70,7 +69,6 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, return -ENOMEM; /* initialize bo list*/ - mutex_init(&list->lock); kref_init(&list->refcount); r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); if (r) { @@ -188,7 +186,6 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, if (*result && kref_get_unless_zero(&(*result)->refcount)) { rcu_read_unlock(); - mutex_lock(&(*result)->lock); return 0; } @@ -231,7 +228,6 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, void amdgpu_bo_list_put(struct amdgpu_bo_list *list) { - mutex_unlock(&list->lock); kref_put(&list->refcount, amdgpu_bo_list_release_rcu); } @@ -242,7 +238,6 @@ void amdgpu_bo_list_free(struct amdgpu_bo_list *list) for (i = 0; i < list->num_entries; ++i) amdgpu_bo_unref(&list->array[i].robj); - mutex_destroy(&list->lock); kvfree(list->array); kfree(list); } @@ -297,7 +292,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, union drm_amdgpu_bo_list *args = data; uint32_t handle = args->in.list_handle; struct drm_amdgpu_bo_list_entry *info = NULL; - struct amdgpu_bo_list *list; + struct amdgpu_bo_list *list, *old; int r; r = amdgpu_bo_create_list_entry_array(&args->in, &info); @@ -328,16 +323,22 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, break; case AMDGPU_BO_LIST_OP_UPDATE: - r = amdgpu_bo_list_get(fpriv, handle, &list); + r = amdgpu_bo_list_create(adev, filp, info, args->in.bo_number, + &list); if (r) goto error_free; - r = amdgpu_bo_list_set(adev, filp, list, info, - args->in.bo_number); - amdgpu_bo_list_put(list); - if (r) - goto error_free; + mutex_lock(&fpriv->bo_list_lock); + old = idr_replace(&fpriv->bo_list_handles, list, handle); + mutex_unlock(&fpriv->bo_list_lock); + if (IS_ERR(old)) { + amdgpu_bo_list_put(list); + r = PTR_ERR(old); + goto error_free; + } + + amdgpu_bo_list_put(old); break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index 833f846bfdad..89195fdcb1ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -41,7 +41,6 @@ struct amdgpu_bo_list_entry { }; struct amdgpu_bo_list { - struct mutex lock; struct rcu_head rhead; struct kref refcount; struct amdgpu_bo *gds_obj; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 0295666968da..f7154f3ed807 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -580,9 +580,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, &p->bo_list); if (r) return r; - - } else if (p->bo_list) { - mutex_lock(&p->bo_list->lock); } if (p->bo_list) { From a0f208453b97565dab8c334ff013aa5ab3c66d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 14:17:41 +0200 Subject: [PATCH 27/41] drm/amdgpu: nuke amdgpu_bo_list_free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The RCU grace period is harmless and avoiding it is not worth the effort of doubling the implementation. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 13 +------------ drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 556040e45931..5335f1b5459f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -231,17 +231,6 @@ void amdgpu_bo_list_put(struct amdgpu_bo_list *list) kref_put(&list->refcount, amdgpu_bo_list_release_rcu); } -void amdgpu_bo_list_free(struct amdgpu_bo_list *list) -{ - unsigned i; - - for (i = 0; i < list->num_entries; ++i) - amdgpu_bo_unref(&list->array[i].robj); - - kvfree(list->array); - kfree(list); -} - int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, struct drm_amdgpu_bo_list_entry **info_param) { @@ -310,7 +299,7 @@ int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, r = idr_alloc(&fpriv->bo_list_handles, list, 1, 0, GFP_KERNEL); mutex_unlock(&fpriv->bo_list_lock); if (r < 0) { - amdgpu_bo_list_free(list); + amdgpu_bo_list_put(list); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index 89195fdcb1ef..0ce540203db1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -56,7 +56,6 @@ int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, struct list_head *validated); void amdgpu_bo_list_put(struct amdgpu_bo_list *list); -void amdgpu_bo_list_free(struct amdgpu_bo_list *list); int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, struct drm_amdgpu_bo_list_entry **info_param); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index dd2132fa2b89..bd98cc5fb97b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -967,7 +967,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, amdgpu_bo_unref(&pd); idr_for_each_entry(&fpriv->bo_list_handles, list, handle) - amdgpu_bo_list_free(list); + amdgpu_bo_list_put(list); idr_destroy(&fpriv->bo_list_handles); mutex_destroy(&fpriv->bo_list_lock); From 39f7f69a6054bb9777b47b6afdb5ce2fae30dbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 15:37:46 +0200 Subject: [PATCH 28/41] drm/amdgpu: add bo_list iterators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to iterate over all entries in a bo_list. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 21 +++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 10 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 51 +++++++++------------ 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 5335f1b5459f..096bcf4a6334 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -43,12 +43,12 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, static void amdgpu_bo_list_release_rcu(struct kref *ref) { - unsigned i; struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list, refcount); + struct amdgpu_bo_list_entry *e; - for (i = 0; i < list->num_entries; ++i) - amdgpu_bo_unref(&list->array[i].robj); + amdgpu_bo_list_for_each_entry(e, list) + amdgpu_bo_unref(&e->robj); kvfree(list->array); kfree_rcu(list, rhead); @@ -103,6 +103,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, struct amdgpu_bo *oa_obj = adev->gds.oa_gfx_bo; unsigned last_entry = 0, first_userptr = num_entries; + struct amdgpu_bo_list_entry *e; uint64_t total_size = 0; unsigned i; int r; @@ -156,7 +157,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, trace_amdgpu_bo_list_set(list, entry->robj); } - for (i = 0; i < list->num_entries; ++i) + amdgpu_bo_list_for_each_entry(e, list) amdgpu_bo_unref(&list->array[i].robj); kvfree(list->array); @@ -201,6 +202,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, * concatenated in descending order. */ struct list_head bucket[AMDGPU_BO_LIST_NUM_BUCKETS]; + struct amdgpu_bo_list_entry *e; unsigned i; for (i = 0; i < AMDGPU_BO_LIST_NUM_BUCKETS; i++) @@ -211,14 +213,13 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, * in the list, the sort mustn't change the ordering of buffers * with the same priority, i.e. it must be stable. */ - for (i = 0; i < list->num_entries; i++) { - unsigned priority = list->array[i].priority; + amdgpu_bo_list_for_each_entry(e, list) { + unsigned priority = e->priority; - if (!list->array[i].robj->parent) - list_add_tail(&list->array[i].tv.head, - &bucket[priority]); + if (!e->robj->parent) + list_add_tail(&e->tv.head, &bucket[priority]); - list->array[i].user_pages = NULL; + e->user_pages = NULL; } /* Connect the sorted buckets in the output list. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index 0ce540203db1..3d77abfcd4a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -65,4 +65,14 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, unsigned num_entries, struct amdgpu_bo_list **list); +#define amdgpu_bo_list_for_each_entry(e, list) \ + for (e = &(list)->array[0]; \ + e != &(list)->array[(list)->num_entries]; \ + ++e) + +#define amdgpu_bo_list_for_each_userptr_entry(e, list) \ + for (e = &(list)->array[(list)->first_userptr]; \ + e != &(list)->array[(list)->num_entries]; \ + ++e) + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index f7154f3ed807..1d7292ab2b62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -563,10 +563,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_bo_list_entry *e; struct list_head duplicates; - unsigned i, tries = 10; struct amdgpu_bo *gds; struct amdgpu_bo *gws; struct amdgpu_bo *oa; + unsigned tries = 10; int r; INIT_LIST_HEAD(&p->validated); @@ -596,7 +596,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, while (1) { struct list_head need_pages; - unsigned i; r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates); @@ -611,12 +610,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, break; INIT_LIST_HEAD(&need_pages); - for (i = p->bo_list->first_userptr; - i < p->bo_list->num_entries; ++i) { - struct amdgpu_bo *bo; - - e = &p->bo_list->array[i]; - bo = e->robj; + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { + struct amdgpu_bo *bo = e->robj; if (amdgpu_ttm_tt_userptr_invalidated(bo->tbo.ttm, &e->user_invalidated) && e->user_pages) { @@ -710,16 +705,14 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, if (p->bo_list) { struct amdgpu_vm *vm = &fpriv->vm; - unsigned i; + struct amdgpu_bo_list_entry *e; gds = p->bo_list->gds_obj; gws = p->bo_list->gws_obj; oa = p->bo_list->oa_obj; - for (i = 0; i < p->bo_list->num_entries; i++) { - struct amdgpu_bo *bo = p->bo_list->array[i].robj; - p->bo_list->array[i].bo_va = amdgpu_vm_bo_find(vm, bo); - } + amdgpu_bo_list_for_each_entry(e, p->bo_list) + e->bo_va = amdgpu_vm_bo_find(vm, e->robj); } else { gds = p->adev->gds.gds_gfx_bo; gws = p->adev->gds.gws_gfx_bo; @@ -753,10 +746,7 @@ error_validate: error_free_pages: if (p->bo_list) { - for (i = p->bo_list->first_userptr; - i < p->bo_list->num_entries; ++i) { - e = &p->bo_list->array[i]; - + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { if (!e->user_pages) continue; @@ -830,7 +820,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; struct amdgpu_bo *bo; - int i, r; + int r; r = amdgpu_vm_clear_freed(adev, vm, NULL); if (r) @@ -861,15 +851,17 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) } if (p->bo_list) { - for (i = 0; i < p->bo_list->num_entries; i++) { + struct amdgpu_bo_list_entry *e; + + amdgpu_bo_list_for_each_entry(e, p->bo_list) { struct dma_fence *f; /* ignore duplicates */ - bo = p->bo_list->array[i].robj; + bo = e->robj; if (!bo) continue; - bo_va = p->bo_list->array[i].bo_va; + bo_va = e->bo_va; if (bo_va == NULL) continue; @@ -898,14 +890,15 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) return r; if (amdgpu_vm_debug && p->bo_list) { + struct amdgpu_bo_list_entry *e; + /* Invalidate all BOs to test for userspace bugs */ - for (i = 0; i < p->bo_list->num_entries; i++) { + amdgpu_bo_list_for_each_entry(e, p->bo_list) { /* ignore duplicates */ - bo = p->bo_list->array[i].robj; - if (!bo) + if (!e->robj) continue; - amdgpu_vm_bo_invalidate(adev, bo, false); + amdgpu_vm_bo_invalidate(adev, e->robj, false); } } @@ -1225,16 +1218,16 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, struct drm_sched_entity *entity = &p->ctx->rings[ring->idx].entity; enum drm_sched_priority priority; struct amdgpu_job *job; - unsigned i; uint64_t seq; int r; amdgpu_mn_lock(p->mn); if (p->bo_list) { - for (i = p->bo_list->first_userptr; - i < p->bo_list->num_entries; ++i) { - struct amdgpu_bo *bo = p->bo_list->array[i].robj; + struct amdgpu_bo_list_entry *e; + + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { + struct amdgpu_bo *bo = e->robj; if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { amdgpu_mn_unlock(p->mn); From 920990cb080a44203bf6c8eb706e79ad23241ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 16:16:01 +0200 Subject: [PATCH 29/41] drm/amdgpu: allocate the bo_list array after the list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids multiple allocations for the head and the array. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 120 ++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 17 ++- 2 files changed, 60 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 096bcf4a6334..d472a2c8399f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -35,13 +35,15 @@ #define AMDGPU_BO_LIST_MAX_PRIORITY 32u #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) -static int amdgpu_bo_list_set(struct amdgpu_device *adev, - struct drm_file *filp, - struct amdgpu_bo_list *list, - struct drm_amdgpu_bo_list_entry *info, - unsigned num_entries); +static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu) +{ + struct amdgpu_bo_list *list = container_of(rcu, struct amdgpu_bo_list, + rhead); -static void amdgpu_bo_list_release_rcu(struct kref *ref) + kvfree(list); +} + +static void amdgpu_bo_list_free(struct kref *ref) { struct amdgpu_bo_list *list = container_of(ref, struct amdgpu_bo_list, refcount); @@ -50,67 +52,36 @@ static void amdgpu_bo_list_release_rcu(struct kref *ref) amdgpu_bo_list_for_each_entry(e, list) amdgpu_bo_unref(&e->robj); - kvfree(list->array); - kfree_rcu(list, rhead); + call_rcu(&list->rhead, amdgpu_bo_list_free_rcu); } -int amdgpu_bo_list_create(struct amdgpu_device *adev, - struct drm_file *filp, - struct drm_amdgpu_bo_list_entry *info, - unsigned num_entries, - struct amdgpu_bo_list **list_out) +int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp, + struct drm_amdgpu_bo_list_entry *info, + unsigned num_entries, struct amdgpu_bo_list **result) { - struct amdgpu_bo_list *list; - int r; - - - list = kzalloc(sizeof(struct amdgpu_bo_list), GFP_KERNEL); - if (!list) - return -ENOMEM; - - /* initialize bo list*/ - kref_init(&list->refcount); - r = amdgpu_bo_list_set(adev, filp, list, info, num_entries); - if (r) { - kfree(list); - return r; - } - - *list_out = list; - return 0; -} - -static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) -{ - struct amdgpu_bo_list *list; - - mutex_lock(&fpriv->bo_list_lock); - list = idr_remove(&fpriv->bo_list_handles, id); - mutex_unlock(&fpriv->bo_list_lock); - if (list) - kref_put(&list->refcount, amdgpu_bo_list_release_rcu); -} - -static int amdgpu_bo_list_set(struct amdgpu_device *adev, - struct drm_file *filp, - struct amdgpu_bo_list *list, - struct drm_amdgpu_bo_list_entry *info, - unsigned num_entries) -{ - struct amdgpu_bo_list_entry *array; - struct amdgpu_bo *gds_obj = adev->gds.gds_gfx_bo; - struct amdgpu_bo *gws_obj = adev->gds.gws_gfx_bo; - struct amdgpu_bo *oa_obj = adev->gds.oa_gfx_bo; - unsigned last_entry = 0, first_userptr = num_entries; - struct amdgpu_bo_list_entry *e; + struct amdgpu_bo_list_entry *array; + struct amdgpu_bo_list *list; uint64_t total_size = 0; + size_t size; unsigned i; int r; - array = kvmalloc_array(num_entries, sizeof(struct amdgpu_bo_list_entry), GFP_KERNEL); - if (!array) + if (num_entries > SIZE_MAX / sizeof(struct amdgpu_bo_list_entry)) + return -EINVAL; + + size = sizeof(struct amdgpu_bo_list); + size += num_entries * sizeof(struct amdgpu_bo_list_entry); + list = kvmalloc(size, GFP_KERNEL); + if (!list) return -ENOMEM; + + kref_init(&list->refcount); + list->gds_obj = adev->gds.gds_gfx_bo; + list->gws_obj = adev->gds.gws_gfx_bo; + list->oa_obj = adev->gds.oa_gfx_bo; + + array = amdgpu_bo_list_array_entry(list, 0); memset(array, 0, num_entries * sizeof(struct amdgpu_bo_list_entry)); for (i = 0; i < num_entries; ++i) { @@ -147,36 +118,41 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev, entry->tv.shared = !entry->robj->prime_shared_count; if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GDS) - gds_obj = entry->robj; + list->gds_obj = entry->robj; if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_GWS) - gws_obj = entry->robj; + list->gws_obj = entry->robj; if (entry->robj->preferred_domains == AMDGPU_GEM_DOMAIN_OA) - oa_obj = entry->robj; + list->oa_obj = entry->robj; total_size += amdgpu_bo_size(entry->robj); trace_amdgpu_bo_list_set(list, entry->robj); } - amdgpu_bo_list_for_each_entry(e, list) - amdgpu_bo_unref(&list->array[i].robj); - - kvfree(list->array); - - list->gds_obj = gds_obj; - list->gws_obj = gws_obj; - list->oa_obj = oa_obj; list->first_userptr = first_userptr; - list->array = array; list->num_entries = num_entries; trace_amdgpu_cs_bo_status(list->num_entries, total_size); + + *result = list; return 0; error_free: while (i--) amdgpu_bo_unref(&array[i].robj); - kvfree(array); + kvfree(list); return r; + +} + +static void amdgpu_bo_list_destroy(struct amdgpu_fpriv *fpriv, int id) +{ + struct amdgpu_bo_list *list; + + mutex_lock(&fpriv->bo_list_lock); + list = idr_remove(&fpriv->bo_list_handles, id); + mutex_unlock(&fpriv->bo_list_lock); + if (list) + kref_put(&list->refcount, amdgpu_bo_list_free); } int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, @@ -229,7 +205,7 @@ void amdgpu_bo_list_get_list(struct amdgpu_bo_list *list, void amdgpu_bo_list_put(struct amdgpu_bo_list *list) { - kref_put(&list->refcount, amdgpu_bo_list_release_rcu); + kref_put(&list->refcount, amdgpu_bo_list_free); } int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index 3d77abfcd4a6..61b089768e1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -48,7 +48,6 @@ struct amdgpu_bo_list { struct amdgpu_bo *oa_obj; unsigned first_userptr; unsigned num_entries; - struct amdgpu_bo_list_entry *array; }; int amdgpu_bo_list_get(struct amdgpu_fpriv *fpriv, int id, @@ -65,14 +64,22 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, unsigned num_entries, struct amdgpu_bo_list **list); +static inline struct amdgpu_bo_list_entry * +amdgpu_bo_list_array_entry(struct amdgpu_bo_list *list, unsigned index) +{ + struct amdgpu_bo_list_entry *array = (void *)&list[1]; + + return &array[index]; +} + #define amdgpu_bo_list_for_each_entry(e, list) \ - for (e = &(list)->array[0]; \ - e != &(list)->array[(list)->num_entries]; \ + for (e = amdgpu_bo_list_array_entry(list, 0); \ + e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ ++e) #define amdgpu_bo_list_for_each_userptr_entry(e, list) \ - for (e = &(list)->array[(list)->first_userptr]; \ - e != &(list)->array[(list)->num_entries]; \ + for (e = amdgpu_bo_list_array_entry(list, (list)->first_userptr); \ + e != amdgpu_bo_list_array_entry(list, (list)->num_entries); \ ++e) #endif From 4a102ad4ba0daf886dcf0927ce2a7f6c3b3a615c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 16:44:14 +0200 Subject: [PATCH 30/41] drm/amdgpu: create an empty bo_list if no handle is provided MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having extra handling just create an empty bo_list when no handle is provided. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 111 ++++++++++--------------- 1 file changed, 46 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1d7292ab2b62..502b94fb116a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -561,6 +561,7 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, union drm_amdgpu_cs *cs) { struct amdgpu_fpriv *fpriv = p->filp->driver_priv; + struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_list_entry *e; struct list_head duplicates; struct amdgpu_bo *gds; @@ -580,13 +581,17 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, &p->bo_list); if (r) return r; + } else if (!p->bo_list) { + /* Create a empty bo_list when no handle is provided */ + r = amdgpu_bo_list_create(p->adev, p->filp, NULL, 0, + &p->bo_list); + if (r) + return r; } - if (p->bo_list) { - amdgpu_bo_list_get_list(p->bo_list, &p->validated); - if (p->bo_list->first_userptr != p->bo_list->num_entries) - p->mn = amdgpu_mn_get(p->adev, AMDGPU_MN_TYPE_GFX); - } + amdgpu_bo_list_get_list(p->bo_list, &p->validated); + if (p->bo_list->first_userptr != p->bo_list->num_entries) + p->mn = amdgpu_mn_get(p->adev, AMDGPU_MN_TYPE_GFX); INIT_LIST_HEAD(&duplicates); amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd); @@ -605,10 +610,6 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, goto error_free_pages; } - /* Without a BO list we don't have userptr BOs */ - if (!p->bo_list) - break; - INIT_LIST_HEAD(&need_pages); amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { struct amdgpu_bo *bo = e->robj; @@ -703,21 +704,12 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved, p->bytes_moved_vis); - if (p->bo_list) { - struct amdgpu_vm *vm = &fpriv->vm; - struct amdgpu_bo_list_entry *e; + gds = p->bo_list->gds_obj; + gws = p->bo_list->gws_obj; + oa = p->bo_list->oa_obj; - gds = p->bo_list->gds_obj; - gws = p->bo_list->gws_obj; - oa = p->bo_list->oa_obj; - - amdgpu_bo_list_for_each_entry(e, p->bo_list) - e->bo_va = amdgpu_vm_bo_find(vm, e->robj); - } else { - gds = p->adev->gds.gds_gfx_bo; - gws = p->adev->gds.gws_gfx_bo; - oa = p->adev->gds.oa_gfx_bo; - } + amdgpu_bo_list_for_each_entry(e, p->bo_list) + e->bo_va = amdgpu_vm_bo_find(vm, e->robj); if (gds) { p->job->gds_base = amdgpu_bo_gpu_offset(gds); @@ -745,15 +737,13 @@ error_validate: error_free_pages: - if (p->bo_list) { - amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { - if (!e->user_pages) - continue; + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { + if (!e->user_pages) + continue; - release_pages(e->user_pages, - e->robj->tbo.ttm->num_pages); - kvfree(e->user_pages); - } + release_pages(e->user_pages, + e->robj->tbo.ttm->num_pages); + kvfree(e->user_pages); } return r; @@ -815,9 +805,10 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) { - struct amdgpu_device *adev = p->adev; struct amdgpu_fpriv *fpriv = p->filp->driver_priv; + struct amdgpu_device *adev = p->adev; struct amdgpu_vm *vm = &fpriv->vm; + struct amdgpu_bo_list_entry *e; struct amdgpu_bo_va *bo_va; struct amdgpu_bo *bo; int r; @@ -850,31 +841,26 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) return r; } - if (p->bo_list) { - struct amdgpu_bo_list_entry *e; + amdgpu_bo_list_for_each_entry(e, p->bo_list) { + struct dma_fence *f; - amdgpu_bo_list_for_each_entry(e, p->bo_list) { - struct dma_fence *f; + /* ignore duplicates */ + bo = e->robj; + if (!bo) + continue; - /* ignore duplicates */ - bo = e->robj; - if (!bo) - continue; + bo_va = e->bo_va; + if (bo_va == NULL) + continue; - bo_va = e->bo_va; - if (bo_va == NULL) - continue; - - r = amdgpu_vm_bo_update(adev, bo_va, false); - if (r) - return r; - - f = bo_va->last_pt_update; - r = amdgpu_sync_fence(adev, &p->job->sync, f, false); - if (r) - return r; - } + r = amdgpu_vm_bo_update(adev, bo_va, false); + if (r) + return r; + f = bo_va->last_pt_update; + r = amdgpu_sync_fence(adev, &p->job->sync, f, false); + if (r) + return r; } r = amdgpu_vm_handle_moved(adev, vm); @@ -889,9 +875,7 @@ static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p) if (r) return r; - if (amdgpu_vm_debug && p->bo_list) { - struct amdgpu_bo_list_entry *e; - + if (amdgpu_vm_debug) { /* Invalidate all BOs to test for userspace bugs */ amdgpu_bo_list_for_each_entry(e, p->bo_list) { /* ignore duplicates */ @@ -1217,22 +1201,19 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, struct amdgpu_ring *ring = p->ring; struct drm_sched_entity *entity = &p->ctx->rings[ring->idx].entity; enum drm_sched_priority priority; + struct amdgpu_bo_list_entry *e; struct amdgpu_job *job; uint64_t seq; int r; amdgpu_mn_lock(p->mn); - if (p->bo_list) { - struct amdgpu_bo_list_entry *e; + amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { + struct amdgpu_bo *bo = e->robj; - amdgpu_bo_list_for_each_userptr_entry(e, p->bo_list) { - struct amdgpu_bo *bo = e->robj; - - if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { - amdgpu_mn_unlock(p->mn); - return -ERESTARTSYS; - } + if (amdgpu_ttm_tt_userptr_needs_pages(bo->tbo.ttm)) { + amdgpu_mn_unlock(p->mn); + return -ERESTARTSYS; } } From 43bce41cf48eb51eab5ad9e0d40ed382a7bb61d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 26 Jul 2018 13:43:49 +0200 Subject: [PATCH 31/41] drm/scheduler: only kill entity if last user is killed v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note which task is using the entity and only kill it if the last user of the entity is killed. This should prevent problems when entities are leaked to child processes. v2: add missing kernel doc Signed-off-by: Christian König Reviewed-by: Andrey Grodzovsky Acked-by: Nayan Deshmukh Signed-off-by: Alex Deucher --- drivers/gpu/drm/scheduler/gpu_scheduler.c | 6 +++++- include/drm/gpu_scheduler.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler.c b/drivers/gpu/drm/scheduler/gpu_scheduler.c index 3f2fc5e8242a..f563e4fbb4b6 100644 --- a/drivers/gpu/drm/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/scheduler/gpu_scheduler.c @@ -275,6 +275,7 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) { struct drm_gpu_scheduler *sched; + struct task_struct *last_user; long ret = timeout; sched = entity->rq->sched; @@ -295,7 +296,9 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) /* For killed process disable any more IBs enqueue right now */ - if ((current->flags & PF_EXITING) && (current->exit_code == SIGKILL)) + last_user = cmpxchg(&entity->last_user, current->group_leader, NULL); + if ((!last_user || last_user == current->group_leader) && + (current->flags & PF_EXITING) && (current->exit_code == SIGKILL)) drm_sched_entity_set_rq(entity, NULL); return ret; @@ -541,6 +544,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job, trace_drm_sched_job(sched_job, entity); + WRITE_ONCE(entity->last_user, current->group_leader); first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node); /* first job wakes up scheduler */ diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 091b9afcd184..21c648b0b2a1 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -66,6 +66,7 @@ enum drm_sched_priority { * @guilty: points to ctx's guilty. * @fini_status: contains the exit status in case the process was signalled. * @last_scheduled: points to the finished fence of the last scheduled job. + * @last_user: last group leader pushing a job into the entity. * * Entities will emit jobs in order to their corresponding hardware * ring, and the scheduler will alternate between entities based on @@ -85,6 +86,7 @@ struct drm_sched_entity { struct dma_fence_cb cb; atomic_t *guilty; struct dma_fence *last_scheduled; + struct task_struct *last_user; }; /** From a875f58e237a0009c337dd140e4f92a7cffab7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 30 Jul 2018 11:40:06 +0200 Subject: [PATCH 32/41] drm/scheduler: stop setting rq to NULL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We removed the redundancy of having an extra scheduler field, so we can't set the rq to NULL any more or otherwise won't know which scheduler to use for the cleanup. Just remove the entity from the scheduling list instead. Signed-off-by: Christian König Acked-by: Nayan Deshmukh Bug: https://bugs.freedesktop.org/show_bug.cgi?id=107367 Signed-off-by: Alex Deucher --- drivers/gpu/drm/scheduler/gpu_scheduler.c | 35 ++++++----------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler.c b/drivers/gpu/drm/scheduler/gpu_scheduler.c index f563e4fbb4b6..1b733229201e 100644 --- a/drivers/gpu/drm/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/scheduler/gpu_scheduler.c @@ -198,21 +198,6 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, } EXPORT_SYMBOL(drm_sched_entity_init); -/** - * drm_sched_entity_is_initialized - Query if entity is initialized - * - * @sched: Pointer to scheduler instance - * @entity: The pointer to a valid scheduler entity - * - * return true if entity is initialized, false otherwise -*/ -static bool drm_sched_entity_is_initialized(struct drm_gpu_scheduler *sched, - struct drm_sched_entity *entity) -{ - return entity->rq != NULL && - entity->rq->sched == sched; -} - /** * drm_sched_entity_is_idle - Check if entity is idle * @@ -224,7 +209,8 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) { rmb(); - if (!entity->rq || spsc_queue_peek(&entity->job_queue) == NULL) + if (list_empty(&entity->list) || + spsc_queue_peek(&entity->job_queue) == NULL) return true; return false; @@ -279,8 +265,6 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) long ret = timeout; sched = entity->rq->sched; - if (!drm_sched_entity_is_initialized(sched, entity)) - return ret; /** * The client will not queue more IBs during this fini, consume existing * queued IBs or discard them on SIGKILL @@ -299,7 +283,7 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout) last_user = cmpxchg(&entity->last_user, current->group_leader, NULL); if ((!last_user || last_user == current->group_leader) && (current->flags & PF_EXITING) && (current->exit_code == SIGKILL)) - drm_sched_entity_set_rq(entity, NULL); + drm_sched_rq_remove_entity(entity->rq, entity); return ret; } @@ -320,7 +304,7 @@ void drm_sched_entity_fini(struct drm_sched_entity *entity) struct drm_gpu_scheduler *sched; sched = entity->rq->sched; - drm_sched_entity_set_rq(entity, NULL); + drm_sched_rq_remove_entity(entity->rq, entity); /* Consumption of existing IBs wasn't completed. Forcefully * remove them here. @@ -416,15 +400,12 @@ void drm_sched_entity_set_rq(struct drm_sched_entity *entity, if (entity->rq == rq) return; + BUG_ON(!rq); + spin_lock(&entity->rq_lock); - - if (entity->rq) - drm_sched_rq_remove_entity(entity->rq, entity); - + drm_sched_rq_remove_entity(entity->rq, entity); entity->rq = rq; - if (rq) - drm_sched_rq_add_entity(rq, entity); - + drm_sched_rq_add_entity(rq, entity); spin_unlock(&entity->rq_lock); } EXPORT_SYMBOL(drm_sched_entity_set_rq); From 71d5ef11273b3dbdb57be7d2940dcee70007ae84 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 31 Jul 2018 09:12:35 +0200 Subject: [PATCH 33/41] drm/amdgpu: Replace ttm_bo_reference with ttm_bo_get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function ttm_bo_get acquires a reference on a TTM buffer object. The function's name is more aligned to the Linux kernel convention of naming ref-counting function _get and _put. v2: * changed prefix to drm/amdgpu Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 21bfa2d8039e..f7ac9abf9cc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -825,7 +825,7 @@ struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo) if (bo == NULL) return NULL; - ttm_bo_reference(&bo->tbo); + ttm_bo_get(&bo->tbo); return bo; } From fea872b279c8cd9433a3c9bb91949643cf645e07 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 31 Jul 2018 09:12:36 +0200 Subject: [PATCH 34/41] drm/amdgpu: Replace ttm_bo_unref with ttm_bo_put MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function ttm_bo_put releases a reference to a TTM buffer object. The function's name is more aligned to the Linux kernel convention of naming ref-counting function _get and _put. A call to ttm_bo_unref takes the address of the TTM BO object's pointer and clears the pointer's value to NULL. This is not necessary in most cases and sometimes even worked around by the calling code. A call to ttm_bo_put only releases the reference without clearing the pointer. The current behaviour of cleaning the pointer is kept in the calling code, but should be removed if not required in a later patch. v2: * set prefix to drm/amdgpu Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index f7ac9abf9cc1..b0e14a3d54ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -843,9 +843,8 @@ void amdgpu_bo_unref(struct amdgpu_bo **bo) return; tbo = &((*bo)->tbo); - ttm_bo_unref(&tbo); - if (tbo == NULL) - *bo = NULL; + ttm_bo_put(tbo); + *bo = NULL; } /** From 269a8b6e342501fa221a398dd2730b7af7e94a5d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 31 Jul 2018 08:16:58 +0200 Subject: [PATCH 35/41] drm/radeon: Replace ttm_bo_reference with ttm_bo_get MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function ttm_bo_get acquires a reference on a TTM buffer object. The function's name is more aligned to the Linux kernel convention of naming ref-counting function _get and _put. Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index edbb4cd519fd..1a9d4f547024 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -307,7 +307,7 @@ struct radeon_bo *radeon_bo_ref(struct radeon_bo *bo) if (bo == NULL) return NULL; - ttm_bo_reference(&bo->tbo); + ttm_bo_get(&bo->tbo); return bo; } From 77605e43701578892e98a39383071f1a8503ff8f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 31 Jul 2018 08:16:59 +0200 Subject: [PATCH 36/41] drm/radeon: Replace ttm_bo_unref with ttm_bo_put MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function ttm_bo_put releases a reference to a TTM buffer object. The function's name is more aligned to the Linux kernel convention of naming ref-counting function _get and _put. A call to ttm_bo_unref takes the address of the TTM BO object's pointer and clears the pointer's value to NULL. This is not necessary in most cases and sometimes even worked around by the calling code. A call to ttm_bo_put only releases the reference without clearing the pointer. The current behaviour of cleaning the pointer is kept in the calling code, but should be removed if not required in a later patch. Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1a9d4f547024..ba2fd295697f 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -320,9 +320,8 @@ void radeon_bo_unref(struct radeon_bo **bo) return; rdev = (*bo)->rdev; tbo = &((*bo)->tbo); - ttm_bo_unref(&tbo); - if (tbo == NULL) - *bo = NULL; + ttm_bo_put(tbo); + *bo = NULL; } int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, From 7ac7aebe85d3b3b57a58efefcdde2bd5d398550d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 31 Jul 2018 11:42:54 +0100 Subject: [PATCH 37/41] drm/amd/display: add missing void parameter to dc_create_transfer_func Add a missing void parameter to function dc_create_transfer_func, fixes sparse warning: warning: non-ANSI function declaration of function 'dc_create_transfer_func' Signed-off-by: Colin Ian King Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 815dfb50089b..8fb3aefd195c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -192,7 +192,7 @@ void dc_transfer_func_release(struct dc_transfer_func *tf) kref_put(&tf->refcount, dc_transfer_func_free); } -struct dc_transfer_func *dc_create_transfer_func() +struct dc_transfer_func *dc_create_transfer_func(void) { struct dc_transfer_func *tf = kvzalloc(sizeof(*tf), GFP_KERNEL); From ddf74e79a54070f277ae520722d3bab7f7a6c67a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 23 Jul 2018 11:32:32 -0500 Subject: [PATCH 38/41] drm/amdgpu/pm: Fix potential Spectre v1 idx can be indirectly controlled by user-space, hence leading to a potential exploitation of the Spectre variant 1 vulnerability. This issue was detected with the help of Smatch: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:408 amdgpu_set_pp_force_state() warn: potential spectre issue 'data.states' Fix this by sanitizing idx before using it to index data.states Notice that given that speculation windows are large, the policy is to kill the speculation on the first load and not worry if it can be completed with a dependent load/store [1]. [1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 23fc1d32b937..8f98629fbe59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -31,7 +31,7 @@ #include #include #include - +#include static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); @@ -403,6 +403,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, count = -EINVAL; goto fail; } + idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); amdgpu_dpm_get_pp_num_states(adev, &data); state = data.states[idx]; From fe710322b81343601ca1759a9f3d4b694ed72fca Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 1 Aug 2018 13:49:31 +0800 Subject: [PATCH 39/41] drm/ttm: fix missed conversion of set_pages_array_uc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixed the error when do not configure CONFIG_X86, otherwise, below error will be encountered. All errors (new ones prefixed by >>): drivers/gpu/drm/ttm/ttm_page_alloc_dma.c: In function 'ttm_set_pages_caching': >> drivers/gpu/drm/ttm/ttm_page_alloc_dma.c:272:7: error: implicit declaration of function 'set_pages_array_uc'; did you mean +'ttm_set_pages_array_uc'? [-Werror=implicit-function-declaration] r = set_pages_array_uc(pages, cpages); ^~~~~~~~~~~~~~~~~~ ttm_set_pages_array_uc cc1: some warnings being treated as errors Reported-by: kbuild test robot Reviewed-by: Christian König Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 8304917294a2..507be7ac1165 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -269,7 +269,7 @@ static int ttm_set_pages_caching(struct dma_pool *pool, int r = 0; /* Set page caching */ if (pool->type & IS_UC) { - r = set_pages_array_uc(pages, cpages); + r = ttm_set_pages_array_uc(pages, cpages); if (r) pr_err("%s: Failed to set %d pages to uc!\n", pool->dev_name, cpages); From dceb219fc60766006bfe8e53afa62816b94fcb11 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 1 Aug 2018 13:49:32 +0800 Subject: [PATCH 40/41] drm/ttm: Add ttm_set_pages_wc and ttm_set_pages_uc helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These two helpers will be used on set page caching. Reviewed-by: Christian König Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- include/drm/ttm/ttm_set_memory.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/drm/ttm/ttm_set_memory.h b/include/drm/ttm/ttm_set_memory.h index a70723cf208b..7c492b49e38c 100644 --- a/include/drm/ttm/ttm_set_memory.h +++ b/include/drm/ttm/ttm_set_memory.h @@ -57,6 +57,18 @@ static inline int ttm_set_pages_wb(struct page *page, int numpages) return set_pages_wb(page, numpages); } +static inline int ttm_set_pages_wc(struct page *page, int numpages) +{ + unsigned long addr = (unsigned long)page_address(page); + + return set_memory_wc(addr, numpages); +} + +static inline int ttm_set_pages_uc(struct page *page, int numpages) +{ + return set_pages_uc(page, numpages); +} + #else /* for CONFIG_X86 */ #if IS_ENABLED(CONFIG_AGP) @@ -123,6 +135,16 @@ static inline int ttm_set_pages_wb(struct page *page, int numpages) #endif /* for CONFIG_AGP */ +static inline int ttm_set_pages_wc(struct page *page, int numpages) +{ + return 0; +} + +static inline int ttm_set_pages_uc(struct page *page, int numpages) +{ + return 0; +} + #endif /* for CONFIG_X86 */ #endif From df36b2fb8390d98453fff1aae3927095fe9ff36c Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 1 Aug 2018 13:49:33 +0800 Subject: [PATCH 41/41] drm/ttm: clean up non-x86 definitions on ttm_tt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All non-x86 definitions are moved to ttm_set_memory header, so remove it from ttm_tt.c. Reviewed-by: Christian König Signed-off-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_tt.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index a1e543972ca7..e3a0691582ff 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -38,9 +38,7 @@ #include #include #include -#ifdef CONFIG_X86 -#include -#endif +#include /** * Allocates a ttm structure for the given BO. @@ -115,10 +113,9 @@ static int ttm_sg_tt_alloc_page_directory(struct ttm_dma_tt *ttm) return 0; } -#ifdef CONFIG_X86 -static inline int ttm_tt_set_page_caching(struct page *p, - enum ttm_caching_state c_old, - enum ttm_caching_state c_new) +static int ttm_tt_set_page_caching(struct page *p, + enum ttm_caching_state c_old, + enum ttm_caching_state c_new) { int ret = 0; @@ -129,26 +126,18 @@ static inline int ttm_tt_set_page_caching(struct page *p, /* p isn't in the default caching state, set it to * writeback first to free its current memtype. */ - ret = set_pages_wb(p, 1); + ret = ttm_set_pages_wb(p, 1); if (ret) return ret; } if (c_new == tt_wc) - ret = set_memory_wc((unsigned long) page_address(p), 1); + ret = ttm_set_pages_wc(p, 1); else if (c_new == tt_uncached) - ret = set_pages_uc(p, 1); + ret = ttm_set_pages_uc(p, 1); return ret; } -#else /* CONFIG_X86 */ -static inline int ttm_tt_set_page_caching(struct page *p, - enum ttm_caching_state c_old, - enum ttm_caching_state c_new) -{ - return 0; -} -#endif /* CONFIG_X86 */ /* * Change caching policy for the linear kernel map