From dc48529fb14ee8450705c00d91f4dcc155e1c2cb Mon Sep 17 00:00:00 2001 From: David Francis Date: Wed, 21 Aug 2019 10:33:26 -0400 Subject: drm/dp_mst: Add PBN calculation for DSC modes With DSC, bpp can be fractional in multiples of 1/16. Change drm_dp_calc_pbn_mode to reflect this, adding a new parameter bool dsc. When this parameter is true, treat the bpp parameter as having units not of bits per pixel, but 1/16 of a bit per pixel v2: Don't add separate function for this v3: In the equation divide bpp by 16 as it is expected not to leave any remainder v4: Added DSC test parameters for selftest Reviewed-by: Manasi Navare Reviewed-by: Lyude Paul Reviewed-by: Harry Wentland Signed-off-by: David Francis Signed-off-by: Mikita Lipski Signed-off-by: Alex Deucher --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 63425e246018..d0b8ebb3dfe2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -806,7 +806,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, * topology */ asyh->or.bpc = min(connector->display_info.bpc, 8U); - asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3); + asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3, false); } slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, -- cgit v1.2.3 From 1c6c1cb5afc77cc8afbe563937c3bd1a41172459 Mon Sep 17 00:00:00 2001 From: Mikita Lipski Date: Thu, 14 Nov 2019 16:24:29 -0500 Subject: drm/dp_mst: Manually overwrite PBN divider for calculating timeslots [why] For DSC case we cannot use topology manager's PBN divider variable. The default divider does not take FEC into account. Therefore the driver has to calculate its own divider based on the link rate and lane count its handling, as it is hw specific. [how] Pass pbn_div as an argument, which is used if its more than zero, otherwise default topology manager's pbn_div will be used. Reviewed-by: Lyude Paul Signed-off-by: Mikita Lipski Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- drivers/gpu/drm/drm_dp_mst_topology.c | 9 +++++++-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- include/drm/drm_dp_mst_helper.h | 3 ++- 5 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index abc359a20a18..ec8f6fc88925 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4938,7 +4938,8 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state, mst_mgr, mst_port, - dm_new_connector_state->pbn); + dm_new_connector_state->pbn, + 0); if (dm_new_connector_state->vcpi_slots < 0) { DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 480c71a00cf2..90201827781d 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4093,6 +4093,7 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, * @mgr: MST topology manager for the port * @port: port to find vcpi slots for * @pbn: bandwidth required for the mode in PBN + * @pbn_div: divider for DSC mode that takes FEC into account * * Allocates VCPI slots to @port, replacing any previous VCPI allocations it * may have had. Any atomic drivers which support MST must call this function @@ -4119,7 +4120,8 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, */ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn) + struct drm_dp_mst_port *port, int pbn, + int pbn_div) { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_vcpi_allocation *pos, *vcpi = NULL; @@ -4152,7 +4154,10 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, if (!vcpi) prev_slots = 0; - req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); + if (pbn_div <= 0) + pbn_div = mgr->pbn_div; + + req_slots = DIV_ROUND_UP(pbn, pbn_div); DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n", port->connector->base.id, port->connector->name, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 92be17711287..a068f54a6793 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -65,7 +65,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, false); slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, - port, crtc_state->pbn); + port, crtc_state->pbn, 0); if (slots == -EDEADLK) return slots; if (slots >= 0) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index d0b8ebb3dfe2..fd31bff0c920 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -810,7 +810,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, } slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, - asyh->dp.pbn); + asyh->dp.pbn, 0); if (slots < 0) return slots; diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index c217b2aaaafa..82ab6776ad5b 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -779,7 +779,8 @@ struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_a int __must_check drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn); + struct drm_dp_mst_port *port, int pbn, + int pbn_div); int __must_check drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, -- cgit v1.2.3 From 11a8630917b681ff2f5320938b8d76b354c89d34 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 20 Aug 2019 13:32:00 +1000 Subject: drm/nouveau/gr/gk208-gm10x: regenerate built-in firmware Commit 5fde30a2684041f9820aa9dc4fbd0009a45076a9 in envytools modified some of the Falcon V5 encodings, regenerate the relevant FW with this. Also modify build rules to include SPDX header in generated files. Tested on GM107, with no issues noted. Signed-off-by: Ben Skeggs --- .../drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h | 786 ++++++++++----------- .../drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h | 786 ++++++++++----------- 2 files changed, 786 insertions(+), 786 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h index c24f35ad56a6..ae2d5b6891cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h @@ -441,7 +441,7 @@ static uint32_t gk208_grhub_code[] = { 0x020014fe, 0x12004002, 0xbd0002f6, - 0x05c94104, + 0x05ca4104, 0xbd0010fe, 0x07004024, 0xbd0002f6, @@ -460,423 +460,423 @@ static uint32_t gk208_grhub_code[] = { 0x01039204, 0x03090080, 0xbd0003f6, - 0x87044204, - 0xf6040040, - 0x04bd0002, - 0x00400402, - 0x0002f603, - 0x31f404bd, - 0x96048e10, - 0x00657e40, - 0xc7feb200, - 0x01b590f1, - 0x1ff4f003, - 0x01020fb5, - 0x041fbb01, - 0x800112b6, - 0xf6010300, - 0x04bd0001, - 0x01040080, + 0x87048204, + 0x04004000, + 0xbd0002f6, + 0x40040204, + 0x02f60300, + 0xf404bd00, + 0x048e1031, + 0x657e4096, + 0xfeb20000, + 0xb590f1c7, + 0xf4f00301, + 0x020fb51f, + 0x1fbb0101, + 0x0112b604, + 0x01030080, 0xbd0001f6, - 0x01004104, - 0xac7e020f, - 0xbb7e0006, - 0x100f0006, - 0x0006fd7e, - 0x98000e98, - 0x207e010f, - 0x14950001, - 0xc0008008, - 0x0004f601, - 0x008004bd, - 0x04f601c1, - 0xb704bd00, - 0xbb130030, - 0xf5b6001f, - 0xd3008002, - 0x000ff601, - 0x15b604bd, - 0x0110b608, - 0xb20814b6, - 0x02687e1f, - 0x001fbb00, - 0x84020398, -/* 0x041f: init_gpc */ - 0xb8502000, - 0x0008044e, - 0x8f7e1fb2, + 0x04008004, + 0x0001f601, + 0x004104bd, + 0x7e020f01, + 0x7e0006ad, + 0x0f0006bc, + 0x06fe7e10, + 0x000e9800, + 0x7e010f98, + 0x95000120, + 0x00800814, + 0x04f601c0, + 0x8004bd00, + 0xf601c100, + 0x04bd0004, + 0x130030b7, + 0xb6001fbb, + 0x008002f5, + 0x0ff601d3, + 0xb604bd00, + 0x10b60815, + 0x0814b601, + 0x687e1fb2, + 0x1fbb0002, + 0x02039800, + 0x50200084, +/* 0x0420: init_gpc */ + 0x08044eb8, + 0x7e1fb200, + 0xb800008f, + 0x00010c4e, + 0x8f7ef4bd, 0x4eb80000, - 0xbd00010c, - 0x008f7ef4, - 0x044eb800, - 0x8f7e0001, + 0x7e000104, + 0xb800008f, + 0x0001004e, + 0x8f7e020f, 0x4eb80000, - 0x0f000100, - 0x008f7e02, - 0x004eb800, -/* 0x044e: init_gpc_wait */ +/* 0x044f: init_gpc_wait */ + 0x7e000800, + 0xc8000065, + 0x0bf41fff, + 0x044eb8f9, 0x657e0008, - 0xffc80000, - 0xf90bf41f, - 0x08044eb8, - 0x00657e00, - 0x001fbb00, - 0x800040b7, - 0xf40132b6, - 0x000fb41b, - 0x0006fd7e, - 0xac7e000f, - 0x00800006, - 0x01f60201, - 0xbd04bd00, - 0x1f19f014, - 0x02300080, - 0xbd0001f6, -/* 0x0491: wait */ - 0x0028f404, -/* 0x0497: main */ - 0x0d0031f4, - 0x00377e10, - 0xf401f400, - 0x4001e4b1, - 0x00c71bf5, - 0x99f094bd, - 0x37008004, - 0x0009f602, - 0x008104bd, - 0x11cf02c0, - 0xc1008200, - 0x0022cf02, - 0xf41f13c8, - 0x23c8770b, - 0x550bf41f, - 0x12b220f9, - 0x99f094bd, - 0x37008007, - 0x0009f602, - 0x32f404bd, - 0x0231f401, - 0x0008807e, - 0x99f094bd, - 0x17008007, - 0x0009f602, - 0x20fc04bd, - 0x99f094bd, - 0x37008006, - 0x0009f602, - 0x31f404bd, - 0x08807e01, + 0x1fbb0000, + 0x0040b700, + 0x0132b680, + 0x0fb41bf4, + 0x06fe7e00, + 0x7e000f00, + 0x800006ad, + 0xf6020100, + 0x04bd0001, + 0x19f014bd, + 0x3000801f, + 0x0001f602, +/* 0x0492: wait */ + 0x28f404bd, + 0x0031f400, +/* 0x0498: main */ + 0x377e100d, + 0x01f40000, + 0x01e4b1f4, + 0xc71bf540, 0xf094bd00, - 0x00800699, + 0x00800499, + 0x09f60237, + 0x8104bd00, + 0xcf02c000, + 0x00820011, + 0x22cf02c1, + 0x1f13c800, + 0xc8770bf4, + 0x0bf41f23, + 0xb220f955, + 0xf094bd12, + 0x00800799, + 0x09f60237, + 0xf404bd00, + 0x31f40132, + 0x08817e02, + 0xf094bd00, + 0x00800799, 0x09f60217, + 0xfc04bd00, + 0xf094bd20, + 0x00800699, + 0x09f60237, 0xf404bd00, -/* 0x0522: chsw_prev_no_next */ - 0x20f92f0e, - 0x32f412b2, - 0x0232f401, - 0x0008807e, - 0x008020fc, - 0x02f602c0, + 0x817e0131, + 0x94bd0008, + 0x800699f0, + 0xf6021700, + 0x04bd0009, +/* 0x0523: chsw_prev_no_next */ + 0xf92f0ef4, + 0xf412b220, + 0x32f40132, + 0x08817e02, + 0x8020fc00, + 0xf602c000, + 0x04bd0002, +/* 0x053f: chsw_no_prev */ + 0xc8130ef4, + 0x0bf41f23, + 0x0131f40d, + 0x7e0232f4, +/* 0x054f: chsw_done */ + 0x02000881, + 0xc3008001, + 0x0002f602, + 0x94bd04bd, + 0x800499f0, + 0xf6021700, + 0x04bd0009, + 0xff300ef5, +/* 0x056c: main_not_ctx_switch */ + 0xf401e4b0, + 0xf2b20c1b, + 0x0008217e, +/* 0x057b: main_not_ctx_chan */ + 0xb0400ef4, + 0x1bf402e4, + 0xf094bd2c, + 0x00800799, + 0x09f60237, 0xf404bd00, -/* 0x053e: chsw_no_prev */ - 0x23c8130e, - 0x0d0bf41f, - 0xf40131f4, - 0x807e0232, -/* 0x054e: chsw_done */ - 0x01020008, - 0x02c30080, - 0xbd0002f6, - 0xf094bd04, - 0x00800499, + 0x32f40132, + 0x08817e02, + 0xf094bd00, + 0x00800799, 0x09f60217, - 0xf504bd00, -/* 0x056b: main_not_ctx_switch */ - 0xb0ff300e, - 0x1bf401e4, - 0x7ef2b20c, - 0xf4000820, -/* 0x057a: main_not_ctx_chan */ - 0xe4b0400e, - 0x2c1bf402, - 0x99f094bd, - 0x37008007, - 0x0009f602, - 0x32f404bd, - 0x0232f401, - 0x0008807e, - 0x99f094bd, - 0x17008007, - 0x0009f602, - 0x0ef404bd, -/* 0x05a9: main_not_ctx_save */ - 0x10ef9411, - 0x7e01f5f0, - 0xf50002f8, -/* 0x05b7: main_done */ - 0xbdfee40e, - 0x1f29f024, - 0x02300080, - 0xbd0002f6, - 0xd20ef504, -/* 0x05c9: ih */ - 0xf900f9fe, - 0x0188fe80, - 0x90f980f9, - 0xb0f9a0f9, - 0xe0f9d0f9, - 0x04bdf0f9, - 0xcf02004a, - 0xabc400aa, - 0x230bf404, - 0x004e100d, - 0x00eecf1a, - 0xcf19004f, - 0x047e00ff, - 0xb0b70000, - 0x010e0400, - 0xf61d0040, - 0x04bd000e, -/* 0x060c: ih_no_fifo */ - 0x0100abe4, - 0x0d0c0bf4, - 0x40014e10, - 0x0000047e, -/* 0x061c: ih_no_ctxsw */ - 0x0400abe4, - 0x8e560bf4, - 0x7e400708, + 0xf404bd00, +/* 0x05aa: main_not_ctx_save */ + 0xef94110e, + 0x01f5f010, + 0x0002f87e, + 0xfee40ef5, +/* 0x05b8: main_done */ + 0x29f024bd, + 0x3000801f, + 0x0002f602, + 0x0ef504bd, +/* 0x05ca: ih */ + 0x00f9fed2, + 0x88fe80f9, + 0xf980f901, + 0xf9a0f990, + 0xf9d0f9b0, + 0xbdf0f9e0, + 0x02004a04, + 0xc400aacf, + 0x0bf404ab, + 0x4e100d23, + 0xeecf1a00, + 0x19004f00, + 0x7e00ffcf, + 0xb7000004, + 0x0e0400b0, + 0x1d004001, + 0xbd000ef6, +/* 0x060d: ih_no_fifo */ + 0x00abe404, + 0x0c0bf401, + 0x014e100d, + 0x00047e40, +/* 0x061d: ih_no_ctxsw */ + 0x00abe400, + 0x560bf404, + 0x4007088e, + 0x0000657e, + 0x0080ffb2, + 0x0ff60204, + 0x8e04bd00, + 0x7e400704, 0xb2000065, - 0x040080ff, + 0x030080ff, 0x000ff602, - 0x048e04bd, - 0x657e4007, - 0xffb20000, - 0x02030080, - 0xbd000ff6, - 0x50fec704, - 0x8f02ee94, - 0xbb400700, - 0x657e00ef, - 0x00800000, - 0x0ff60202, + 0xfec704bd, + 0x02ee9450, + 0x4007008f, + 0x7e00efbb, + 0x80000065, + 0xf6020200, + 0x04bd000f, + 0xf87e030f, + 0x004b0002, + 0x8ebfb201, + 0x7e400144, +/* 0x0677: ih_no_fwmthd */ + 0x4b00008f, + 0xb0bd0504, + 0xf4b4abff, + 0x00800c0b, + 0x0bf60307, +/* 0x068b: ih_no_other */ + 0x4004bd00, + 0x0af60100, + 0xfc04bd00, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x00fc80fc, + 0xf80032f4, +/* 0x06ad: ctx_4170s */ + 0x10f5f001, + 0x708effb2, + 0x8f7e4041, + 0x00f80000, +/* 0x06bc: ctx_4170w */ + 0x4041708e, + 0x0000657e, + 0xf4f0ffb2, + 0xf31bf410, +/* 0x06ce: ctx_redswitch */ + 0x004e00f8, + 0x40e5f002, + 0xf020e5f0, + 0x008010e5, + 0x0ef60185, 0x0f04bd00, - 0x02f87e03, - 0x01004b00, - 0x448ebfb2, - 0x8f7e4001, -/* 0x0676: ih_no_fwmthd */ - 0x044b0000, - 0xffb0bd05, - 0x0bf4b4ab, - 0x0700800c, - 0x000bf603, -/* 0x068a: ih_no_other */ - 0x004004bd, - 0x000af601, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0xf400fc80, - 0x01f80032, -/* 0x06ac: ctx_4170s */ - 0xb210f5f0, - 0x41708eff, +/* 0x06e5: ctx_redswitch_delay */ + 0x01f2b608, + 0xf1fd1bf4, + 0xf10400e5, + 0x800100e5, + 0xf6018500, + 0x04bd000e, +/* 0x06fe: ctx_86c */ + 0x008000f8, + 0x0ff60223, + 0xb204bd00, + 0x8a148eff, 0x008f7e40, -/* 0x06bb: ctx_4170w */ - 0x8e00f800, - 0x7e404170, - 0xb2000065, - 0x10f4f0ff, - 0xf8f31bf4, -/* 0x06cd: ctx_redswitch */ - 0x02004e00, - 0xf040e5f0, - 0xe5f020e5, - 0x85008010, - 0x000ef601, - 0x080f04bd, -/* 0x06e4: ctx_redswitch_delay */ - 0xf401f2b6, - 0xe5f1fd1b, - 0xe5f10400, - 0x00800100, - 0x0ef60185, - 0xf804bd00, -/* 0x06fd: ctx_86c */ - 0x23008000, + 0x8effb200, + 0x7e41a88c, + 0xf800008f, +/* 0x071d: ctx_mem */ + 0x84008000, 0x000ff602, - 0xffb204bd, - 0x408a148e, - 0x00008f7e, - 0x8c8effb2, - 0x8f7e41a8, - 0x00f80000, -/* 0x071c: ctx_mem */ - 0x02840080, - 0xbd000ff6, -/* 0x0725: ctx_mem_wait */ - 0x84008f04, - 0x00ffcf02, - 0xf405fffd, - 0x00f8f61b, -/* 0x0734: ctx_load */ - 0x99f094bd, - 0x37008005, - 0x0009f602, - 0x0c0a04bd, - 0x0000b87e, - 0x0080f4bd, - 0x0ff60289, - 0x8004bd00, - 0xf602c100, - 0x04bd0002, - 0x02830080, +/* 0x0726: ctx_mem_wait */ + 0x008f04bd, + 0xffcf0284, + 0x05fffd00, + 0xf8f61bf4, +/* 0x0735: ctx_load */ + 0xf094bd00, + 0x00800599, + 0x09f60237, + 0x0a04bd00, + 0x00b87e0c, + 0x80f4bd00, + 0xf6028900, + 0x04bd000f, + 0x02c10080, 0xbd0002f6, - 0x7e070f04, - 0x8000071c, - 0xf602c000, - 0x04bd0002, - 0xf0000bfe, - 0x24b61f2a, - 0x0220b604, - 0x99f094bd, - 0x37008008, - 0x0009f602, - 0x008004bd, - 0x02f60281, - 0xd204bd00, - 0x80000000, - 0x800225f0, - 0xf6028800, - 0x04bd0002, - 0x00421001, - 0x0223f002, - 0xf80512fa, - 0xf094bd03, + 0x83008004, + 0x0002f602, + 0x070f04bd, + 0x00071d7e, + 0x02c00080, + 0xbd0002f6, + 0x000bfe04, + 0xb61f2af0, + 0x20b60424, + 0xf094bd02, 0x00800899, - 0x09f60217, - 0x9804bd00, - 0x14b68101, - 0x80029818, - 0xfd0825b6, - 0x01b50512, - 0xf094bd16, - 0x00800999, 0x09f60237, 0x8004bd00, 0xf6028100, - 0x04bd0001, - 0x00800102, - 0x02f60288, - 0x4104bd00, - 0x13f00100, - 0x0501fa06, + 0x04bd0002, + 0x000000d2, + 0x0225f080, + 0x02880080, + 0xbd0002f6, + 0x42100104, + 0x23f00200, + 0x0512fa02, 0x94bd03f8, - 0x800999f0, + 0x800899f0, 0xf6021700, 0x04bd0009, - 0x99f094bd, - 0x17008005, - 0x0009f602, - 0x00f804bd, -/* 0x0820: ctx_chan */ - 0x0007347e, - 0xb87e0c0a, - 0x050f0000, - 0x00071c7e, -/* 0x0832: ctx_mmio_exec */ - 0x039800f8, - 0x81008041, - 0x0003f602, - 0x34bd04bd, -/* 0x0840: ctx_mmio_loop */ - 0xf4ff34c4, - 0x00450e1b, - 0x0653f002, - 0xf80535fa, -/* 0x0851: ctx_mmio_pull */ - 0x804e9803, - 0x7e814f98, - 0xb600008f, - 0x12b60830, - 0xdf1bf401, -/* 0x0864: ctx_mmio_done */ - 0x80160398, - 0xf6028100, - 0x04bd0003, - 0x414000b5, - 0x13f00100, - 0x0601fa06, - 0x00f803f8, -/* 0x0880: ctx_xfer */ - 0x0080040e, - 0x0ef60302, -/* 0x088b: ctx_xfer_idle */ - 0x8e04bd00, - 0xcf030000, - 0xe4f100ee, - 0x1bf42000, - 0x0611f4f5, -/* 0x089f: ctx_xfer_pre */ - 0x0f0c02f4, - 0x06fd7e10, - 0x1b11f400, -/* 0x08a8: ctx_xfer_pre_load */ - 0xac7e020f, - 0xbb7e0006, - 0xcd7e0006, - 0xf4bd0006, - 0x0006ac7e, - 0x0007347e, -/* 0x08c0: ctx_xfer_exec */ - 0xbd160198, - 0x05008024, - 0x0002f601, - 0x1fb204bd, - 0x41a5008e, - 0x00008f7e, - 0xf001fcf0, - 0x24b6022c, - 0x05f2fd01, - 0x048effb2, - 0x8f7e41a5, - 0x167e0000, - 0x24bd0002, - 0x0247fc80, - 0xbd0002f6, - 0x012cf004, - 0x800320b6, - 0xf6024afc, + 0xb6810198, + 0x02981814, + 0x0825b680, + 0xb50512fd, + 0x94bd1601, + 0x800999f0, + 0xf6023700, + 0x04bd0009, + 0x02810080, + 0xbd0001f6, + 0x80010204, + 0xf6028800, 0x04bd0002, - 0xf001acf0, - 0x000b06a5, - 0x98000c98, - 0x000e010d, - 0x00013d7e, - 0xec7e080a, - 0x0a7e0000, - 0x01f40002, - 0x7e0c0a12, + 0xf0010041, + 0x01fa0613, + 0xbd03f805, + 0x0999f094, + 0x02170080, + 0xbd0009f6, + 0xf094bd04, + 0x00800599, + 0x09f60217, + 0xf804bd00, +/* 0x0821: ctx_chan */ + 0x07357e00, + 0x7e0c0a00, 0x0f0000b8, - 0x071c7e05, - 0x2d02f400, -/* 0x093c: ctx_xfer_post */ - 0xac7e020f, - 0xf4bd0006, - 0x0006fd7e, - 0x0002277e, - 0x0006bb7e, - 0xac7ef4bd, + 0x071d7e05, +/* 0x0833: ctx_mmio_exec */ + 0x9800f800, + 0x00804103, + 0x03f60281, + 0xbd04bd00, +/* 0x0841: ctx_mmio_loop */ + 0xff34c434, + 0x450e1bf4, + 0x53f00200, + 0x0535fa06, +/* 0x0852: ctx_mmio_pull */ + 0x4e9803f8, + 0x814f9880, + 0x00008f7e, + 0xb60830b6, + 0x1bf40112, +/* 0x0865: ctx_mmio_done */ + 0x160398df, + 0x02810080, + 0xbd0003f6, + 0x4000b504, + 0xf0010041, + 0x01fa0613, + 0xf803f806, +/* 0x0881: ctx_xfer */ + 0x80040e00, + 0xf6030200, + 0x04bd000e, +/* 0x088c: ctx_xfer_idle */ + 0x0300008e, + 0xf100eecf, + 0xf42000e4, + 0x11f4f51b, + 0x0c02f406, +/* 0x08a0: ctx_xfer_pre */ + 0xfe7e100f, 0x11f40006, - 0x40019810, - 0xf40511fd, - 0x327e070b, -/* 0x0966: ctx_xfer_no_post_mmio */ -/* 0x0966: ctx_xfer_done */ - 0x00f80008, +/* 0x08a9: ctx_xfer_pre_load */ + 0x7e020f1b, + 0x7e0006ad, + 0x7e0006bc, + 0xbd0006ce, + 0x06ad7ef4, + 0x07357e00, +/* 0x08c1: ctx_xfer_exec */ + 0x16019800, + 0x008024bd, + 0x02f60105, + 0xb204bd00, + 0xa5008e1f, + 0x008f7e41, + 0x01fcf000, + 0xb6022cf0, + 0xf2fd0124, + 0x8effb205, + 0x7e41a504, + 0x7e00008f, + 0xbd000216, + 0x47fc8024, + 0x0002f602, + 0x2cf004bd, + 0x0320b601, + 0x024afc80, + 0xbd0002f6, + 0x01acf004, + 0x0b06a5f0, + 0x000c9800, + 0x0e010d98, + 0x013d7e00, + 0x7e080a00, + 0x7e0000ec, + 0xf400020a, + 0x0c0a1201, + 0x0000b87e, + 0x1d7e050f, + 0x02f40007, +/* 0x093d: ctx_xfer_post */ + 0x7e020f2d, + 0xbd0006ad, + 0x06fe7ef4, + 0x02277e00, + 0x06bc7e00, + 0x7ef4bd00, + 0xf40006ad, + 0x01981011, + 0x0511fd40, + 0x7e070bf4, +/* 0x0967: ctx_xfer_no_post_mmio */ +/* 0x0967: ctx_xfer_done */ + 0xf8000833, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h index 649a442b4390..449dae753203 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h @@ -441,7 +441,7 @@ static uint32_t gm107_grhub_code[] = { 0x020014fe, 0x12004002, 0xbd0002f6, - 0x05c94104, + 0x05ca4104, 0xbd0010fe, 0x07004024, 0xbd0002f6, @@ -460,423 +460,423 @@ static uint32_t gm107_grhub_code[] = { 0x01039204, 0x03090080, 0xbd0003f6, - 0x87044204, - 0xf6040040, - 0x04bd0002, - 0x00400402, - 0x0002f603, - 0x31f404bd, - 0x96048e10, - 0x00657e40, - 0xc7feb200, - 0x01b590f1, - 0x1ff4f003, - 0x01020fb5, - 0x041fbb01, - 0x800112b6, - 0xf6010300, - 0x04bd0001, - 0x01040080, + 0x87048204, + 0x04004000, + 0xbd0002f6, + 0x40040204, + 0x02f60300, + 0xf404bd00, + 0x048e1031, + 0x657e4096, + 0xfeb20000, + 0xb590f1c7, + 0xf4f00301, + 0x020fb51f, + 0x1fbb0101, + 0x0112b604, + 0x01030080, 0xbd0001f6, - 0x01004104, - 0xac7e020f, - 0xbb7e0006, - 0x100f0006, - 0x0006fd7e, - 0x98000e98, - 0x207e010f, - 0x14950001, - 0xc0008008, - 0x0004f601, - 0x008004bd, - 0x04f601c1, - 0xb704bd00, - 0xbb130030, - 0xf5b6001f, - 0xd3008002, - 0x000ff601, - 0x15b604bd, - 0x0110b608, - 0xb20814b6, - 0x02687e1f, - 0x001fbb00, - 0x84020398, -/* 0x041f: init_gpc */ - 0xb8502000, - 0x0008044e, - 0x8f7e1fb2, + 0x04008004, + 0x0001f601, + 0x004104bd, + 0x7e020f01, + 0x7e0006ad, + 0x0f0006bc, + 0x06fe7e10, + 0x000e9800, + 0x7e010f98, + 0x95000120, + 0x00800814, + 0x04f601c0, + 0x8004bd00, + 0xf601c100, + 0x04bd0004, + 0x130030b7, + 0xb6001fbb, + 0x008002f5, + 0x0ff601d3, + 0xb604bd00, + 0x10b60815, + 0x0814b601, + 0x687e1fb2, + 0x1fbb0002, + 0x02039800, + 0x50200084, +/* 0x0420: init_gpc */ + 0x08044eb8, + 0x7e1fb200, + 0xb800008f, + 0x00010c4e, + 0x8f7ef4bd, 0x4eb80000, - 0xbd00010c, - 0x008f7ef4, - 0x044eb800, - 0x8f7e0001, + 0x7e000104, + 0xb800008f, + 0x0001004e, + 0x8f7e020f, 0x4eb80000, - 0x0f000100, - 0x008f7e02, - 0x004eb800, -/* 0x044e: init_gpc_wait */ +/* 0x044f: init_gpc_wait */ + 0x7e000800, + 0xc8000065, + 0x0bf41fff, + 0x044eb8f9, 0x657e0008, - 0xffc80000, - 0xf90bf41f, - 0x08044eb8, - 0x00657e00, - 0x001fbb00, - 0x800040b7, - 0xf40132b6, - 0x000fb41b, - 0x0006fd7e, - 0xac7e000f, - 0x00800006, - 0x01f60201, - 0xbd04bd00, - 0x1f19f014, - 0x02300080, - 0xbd0001f6, -/* 0x0491: wait */ - 0x0028f404, -/* 0x0497: main */ - 0x0d0031f4, - 0x00377e10, - 0xf401f400, - 0x4001e4b1, - 0x00c71bf5, - 0x99f094bd, - 0x37008004, - 0x0009f602, - 0x008104bd, - 0x11cf02c0, - 0xc1008200, - 0x0022cf02, - 0xf41f13c8, - 0x23c8770b, - 0x550bf41f, - 0x12b220f9, - 0x99f094bd, - 0x37008007, - 0x0009f602, - 0x32f404bd, - 0x0231f401, - 0x0008807e, - 0x99f094bd, - 0x17008007, - 0x0009f602, - 0x20fc04bd, - 0x99f094bd, - 0x37008006, - 0x0009f602, - 0x31f404bd, - 0x08807e01, + 0x1fbb0000, + 0x0040b700, + 0x0132b680, + 0x0fb41bf4, + 0x06fe7e00, + 0x7e000f00, + 0x800006ad, + 0xf6020100, + 0x04bd0001, + 0x19f014bd, + 0x3000801f, + 0x0001f602, +/* 0x0492: wait */ + 0x28f404bd, + 0x0031f400, +/* 0x0498: main */ + 0x377e100d, + 0x01f40000, + 0x01e4b1f4, + 0xc71bf540, 0xf094bd00, - 0x00800699, + 0x00800499, + 0x09f60237, + 0x8104bd00, + 0xcf02c000, + 0x00820011, + 0x22cf02c1, + 0x1f13c800, + 0xc8770bf4, + 0x0bf41f23, + 0xb220f955, + 0xf094bd12, + 0x00800799, + 0x09f60237, + 0xf404bd00, + 0x31f40132, + 0x08817e02, + 0xf094bd00, + 0x00800799, 0x09f60217, + 0xfc04bd00, + 0xf094bd20, + 0x00800699, + 0x09f60237, 0xf404bd00, -/* 0x0522: chsw_prev_no_next */ - 0x20f92f0e, - 0x32f412b2, - 0x0232f401, - 0x0008807e, - 0x008020fc, - 0x02f602c0, + 0x817e0131, + 0x94bd0008, + 0x800699f0, + 0xf6021700, + 0x04bd0009, +/* 0x0523: chsw_prev_no_next */ + 0xf92f0ef4, + 0xf412b220, + 0x32f40132, + 0x08817e02, + 0x8020fc00, + 0xf602c000, + 0x04bd0002, +/* 0x053f: chsw_no_prev */ + 0xc8130ef4, + 0x0bf41f23, + 0x0131f40d, + 0x7e0232f4, +/* 0x054f: chsw_done */ + 0x02000881, + 0xc3008001, + 0x0002f602, + 0x94bd04bd, + 0x800499f0, + 0xf6021700, + 0x04bd0009, + 0xff300ef5, +/* 0x056c: main_not_ctx_switch */ + 0xf401e4b0, + 0xf2b20c1b, + 0x0008217e, +/* 0x057b: main_not_ctx_chan */ + 0xb0400ef4, + 0x1bf402e4, + 0xf094bd2c, + 0x00800799, + 0x09f60237, 0xf404bd00, -/* 0x053e: chsw_no_prev */ - 0x23c8130e, - 0x0d0bf41f, - 0xf40131f4, - 0x807e0232, -/* 0x054e: chsw_done */ - 0x01020008, - 0x02c30080, - 0xbd0002f6, - 0xf094bd04, - 0x00800499, + 0x32f40132, + 0x08817e02, + 0xf094bd00, + 0x00800799, 0x09f60217, - 0xf504bd00, -/* 0x056b: main_not_ctx_switch */ - 0xb0ff300e, - 0x1bf401e4, - 0x7ef2b20c, - 0xf4000820, -/* 0x057a: main_not_ctx_chan */ - 0xe4b0400e, - 0x2c1bf402, - 0x99f094bd, - 0x37008007, - 0x0009f602, - 0x32f404bd, - 0x0232f401, - 0x0008807e, - 0x99f094bd, - 0x17008007, - 0x0009f602, - 0x0ef404bd, -/* 0x05a9: main_not_ctx_save */ - 0x10ef9411, - 0x7e01f5f0, - 0xf50002f8, -/* 0x05b7: main_done */ - 0xbdfee40e, - 0x1f29f024, - 0x02300080, - 0xbd0002f6, - 0xd20ef504, -/* 0x05c9: ih */ - 0xf900f9fe, - 0x0188fe80, - 0x90f980f9, - 0xb0f9a0f9, - 0xe0f9d0f9, - 0x04bdf0f9, - 0xcf02004a, - 0xabc400aa, - 0x230bf404, - 0x004e100d, - 0x00eecf1a, - 0xcf19004f, - 0x047e00ff, - 0xb0b70000, - 0x010e0400, - 0xf61d0040, - 0x04bd000e, -/* 0x060c: ih_no_fifo */ - 0x0100abe4, - 0x0d0c0bf4, - 0x40014e10, - 0x0000047e, -/* 0x061c: ih_no_ctxsw */ - 0x0400abe4, - 0x8e560bf4, - 0x7e400708, + 0xf404bd00, +/* 0x05aa: main_not_ctx_save */ + 0xef94110e, + 0x01f5f010, + 0x0002f87e, + 0xfee40ef5, +/* 0x05b8: main_done */ + 0x29f024bd, + 0x3000801f, + 0x0002f602, + 0x0ef504bd, +/* 0x05ca: ih */ + 0x00f9fed2, + 0x88fe80f9, + 0xf980f901, + 0xf9a0f990, + 0xf9d0f9b0, + 0xbdf0f9e0, + 0x02004a04, + 0xc400aacf, + 0x0bf404ab, + 0x4e100d23, + 0xeecf1a00, + 0x19004f00, + 0x7e00ffcf, + 0xb7000004, + 0x0e0400b0, + 0x1d004001, + 0xbd000ef6, +/* 0x060d: ih_no_fifo */ + 0x00abe404, + 0x0c0bf401, + 0x014e100d, + 0x00047e40, +/* 0x061d: ih_no_ctxsw */ + 0x00abe400, + 0x560bf404, + 0x4007088e, + 0x0000657e, + 0x0080ffb2, + 0x0ff60204, + 0x8e04bd00, + 0x7e400704, 0xb2000065, - 0x040080ff, + 0x030080ff, 0x000ff602, - 0x048e04bd, - 0x657e4007, - 0xffb20000, - 0x02030080, - 0xbd000ff6, - 0x50fec704, - 0x8f02ee94, - 0xbb400700, - 0x657e00ef, - 0x00800000, - 0x0ff60202, + 0xfec704bd, + 0x02ee9450, + 0x4007008f, + 0x7e00efbb, + 0x80000065, + 0xf6020200, + 0x04bd000f, + 0xf87e030f, + 0x004b0002, + 0x8ebfb201, + 0x7e400144, +/* 0x0677: ih_no_fwmthd */ + 0x4b00008f, + 0xb0bd0504, + 0xf4b4abff, + 0x00800c0b, + 0x0bf60307, +/* 0x068b: ih_no_other */ + 0x4004bd00, + 0x0af60100, + 0xfc04bd00, + 0xfce0fcf0, + 0xfcb0fcd0, + 0xfc90fca0, + 0x0088fe80, + 0x00fc80fc, + 0xf80032f4, +/* 0x06ad: ctx_4170s */ + 0x10f5f001, + 0x708effb2, + 0x8f7e4041, + 0x00f80000, +/* 0x06bc: ctx_4170w */ + 0x4041708e, + 0x0000657e, + 0xf4f0ffb2, + 0xf31bf410, +/* 0x06ce: ctx_redswitch */ + 0x004e00f8, + 0x40e5f002, + 0xf020e5f0, + 0x008010e5, + 0x0ef60185, 0x0f04bd00, - 0x02f87e03, - 0x01004b00, - 0x448ebfb2, - 0x8f7e4001, -/* 0x0676: ih_no_fwmthd */ - 0x044b0000, - 0xffb0bd05, - 0x0bf4b4ab, - 0x0700800c, - 0x000bf603, -/* 0x068a: ih_no_other */ - 0x004004bd, - 0x000af601, - 0xf0fc04bd, - 0xd0fce0fc, - 0xa0fcb0fc, - 0x80fc90fc, - 0xfc0088fe, - 0xf400fc80, - 0x01f80032, -/* 0x06ac: ctx_4170s */ - 0xb210f5f0, - 0x41708eff, +/* 0x06e5: ctx_redswitch_delay */ + 0x01f2b608, + 0xf1fd1bf4, + 0xf10400e5, + 0x800100e5, + 0xf6018500, + 0x04bd000e, +/* 0x06fe: ctx_86c */ + 0x008000f8, + 0x0ff60223, + 0xb204bd00, + 0x8a148eff, 0x008f7e40, -/* 0x06bb: ctx_4170w */ - 0x8e00f800, - 0x7e404170, - 0xb2000065, - 0x10f4f0ff, - 0xf8f31bf4, -/* 0x06cd: ctx_redswitch */ - 0x02004e00, - 0xf040e5f0, - 0xe5f020e5, - 0x85008010, - 0x000ef601, - 0x080f04bd, -/* 0x06e4: ctx_redswitch_delay */ - 0xf401f2b6, - 0xe5f1fd1b, - 0xe5f10400, - 0x00800100, - 0x0ef60185, - 0xf804bd00, -/* 0x06fd: ctx_86c */ - 0x23008000, + 0x8effb200, + 0x7e41a88c, + 0xf800008f, +/* 0x071d: ctx_mem */ + 0x84008000, 0x000ff602, - 0xffb204bd, - 0x408a148e, - 0x00008f7e, - 0x8c8effb2, - 0x8f7e41a8, - 0x00f80000, -/* 0x071c: ctx_mem */ - 0x02840080, - 0xbd000ff6, -/* 0x0725: ctx_mem_wait */ - 0x84008f04, - 0x00ffcf02, - 0xf405fffd, - 0x00f8f61b, -/* 0x0734: ctx_load */ - 0x99f094bd, - 0x37008005, - 0x0009f602, - 0x0c0a04bd, - 0x0000b87e, - 0x0080f4bd, - 0x0ff60289, - 0x8004bd00, - 0xf602c100, - 0x04bd0002, - 0x02830080, +/* 0x0726: ctx_mem_wait */ + 0x008f04bd, + 0xffcf0284, + 0x05fffd00, + 0xf8f61bf4, +/* 0x0735: ctx_load */ + 0xf094bd00, + 0x00800599, + 0x09f60237, + 0x0a04bd00, + 0x00b87e0c, + 0x80f4bd00, + 0xf6028900, + 0x04bd000f, + 0x02c10080, 0xbd0002f6, - 0x7e070f04, - 0x8000071c, - 0xf602c000, - 0x04bd0002, - 0xf0000bfe, - 0x24b61f2a, - 0x0220b604, - 0x99f094bd, - 0x37008008, - 0x0009f602, - 0x008004bd, - 0x02f60281, - 0xd204bd00, - 0x80000000, - 0x800225f0, - 0xf6028800, - 0x04bd0002, - 0x00421001, - 0x0223f002, - 0xf80512fa, - 0xf094bd03, + 0x83008004, + 0x0002f602, + 0x070f04bd, + 0x00071d7e, + 0x02c00080, + 0xbd0002f6, + 0x000bfe04, + 0xb61f2af0, + 0x20b60424, + 0xf094bd02, 0x00800899, - 0x09f60217, - 0x9804bd00, - 0x14b68101, - 0x80029818, - 0xfd0825b6, - 0x01b50512, - 0xf094bd16, - 0x00800999, 0x09f60237, 0x8004bd00, 0xf6028100, - 0x04bd0001, - 0x00800102, - 0x02f60288, - 0x4104bd00, - 0x13f00100, - 0x0501fa06, + 0x04bd0002, + 0x000000d2, + 0x0225f080, + 0x02880080, + 0xbd0002f6, + 0x42100104, + 0x23f00200, + 0x0512fa02, 0x94bd03f8, - 0x800999f0, + 0x800899f0, 0xf6021700, 0x04bd0009, - 0x99f094bd, - 0x17008005, - 0x0009f602, - 0x00f804bd, -/* 0x0820: ctx_chan */ - 0x0007347e, - 0xb87e0c0a, - 0x050f0000, - 0x00071c7e, -/* 0x0832: ctx_mmio_exec */ - 0x039800f8, - 0x81008041, - 0x0003f602, - 0x34bd04bd, -/* 0x0840: ctx_mmio_loop */ - 0xf4ff34c4, - 0x00450e1b, - 0x0653f002, - 0xf80535fa, -/* 0x0851: ctx_mmio_pull */ - 0x804e9803, - 0x7e814f98, - 0xb600008f, - 0x12b60830, - 0xdf1bf401, -/* 0x0864: ctx_mmio_done */ - 0x80160398, - 0xf6028100, - 0x04bd0003, - 0x414000b5, - 0x13f00100, - 0x0601fa06, - 0x00f803f8, -/* 0x0880: ctx_xfer */ - 0x0080040e, - 0x0ef60302, -/* 0x088b: ctx_xfer_idle */ - 0x8e04bd00, - 0xcf030000, - 0xe4f100ee, - 0x1bf42000, - 0x0611f4f5, -/* 0x089f: ctx_xfer_pre */ - 0x0f0c02f4, - 0x06fd7e10, - 0x1b11f400, -/* 0x08a8: ctx_xfer_pre_load */ - 0xac7e020f, - 0xbb7e0006, - 0xcd7e0006, - 0xf4bd0006, - 0x0006ac7e, - 0x0007347e, -/* 0x08c0: ctx_xfer_exec */ - 0xbd160198, - 0x05008024, - 0x0002f601, - 0x1fb204bd, - 0x41a5008e, - 0x00008f7e, - 0xf001fcf0, - 0x24b6022c, - 0x05f2fd01, - 0x048effb2, - 0x8f7e41a5, - 0x167e0000, - 0x24bd0002, - 0x0247fc80, - 0xbd0002f6, - 0x012cf004, - 0x800320b6, - 0xf6024afc, + 0xb6810198, + 0x02981814, + 0x0825b680, + 0xb50512fd, + 0x94bd1601, + 0x800999f0, + 0xf6023700, + 0x04bd0009, + 0x02810080, + 0xbd0001f6, + 0x80010204, + 0xf6028800, 0x04bd0002, - 0xf001acf0, - 0x000b06a5, - 0x98000c98, - 0x000e010d, - 0x00013d7e, - 0xec7e080a, - 0x0a7e0000, - 0x01f40002, - 0x7e0c0a12, + 0xf0010041, + 0x01fa0613, + 0xbd03f805, + 0x0999f094, + 0x02170080, + 0xbd0009f6, + 0xf094bd04, + 0x00800599, + 0x09f60217, + 0xf804bd00, +/* 0x0821: ctx_chan */ + 0x07357e00, + 0x7e0c0a00, 0x0f0000b8, - 0x071c7e05, - 0x2d02f400, -/* 0x093c: ctx_xfer_post */ - 0xac7e020f, - 0xf4bd0006, - 0x0006fd7e, - 0x0002277e, - 0x0006bb7e, - 0xac7ef4bd, + 0x071d7e05, +/* 0x0833: ctx_mmio_exec */ + 0x9800f800, + 0x00804103, + 0x03f60281, + 0xbd04bd00, +/* 0x0841: ctx_mmio_loop */ + 0xff34c434, + 0x450e1bf4, + 0x53f00200, + 0x0535fa06, +/* 0x0852: ctx_mmio_pull */ + 0x4e9803f8, + 0x814f9880, + 0x00008f7e, + 0xb60830b6, + 0x1bf40112, +/* 0x0865: ctx_mmio_done */ + 0x160398df, + 0x02810080, + 0xbd0003f6, + 0x4000b504, + 0xf0010041, + 0x01fa0613, + 0xf803f806, +/* 0x0881: ctx_xfer */ + 0x80040e00, + 0xf6030200, + 0x04bd000e, +/* 0x088c: ctx_xfer_idle */ + 0x0300008e, + 0xf100eecf, + 0xf42000e4, + 0x11f4f51b, + 0x0c02f406, +/* 0x08a0: ctx_xfer_pre */ + 0xfe7e100f, 0x11f40006, - 0x40019810, - 0xf40511fd, - 0x327e070b, -/* 0x0966: ctx_xfer_no_post_mmio */ -/* 0x0966: ctx_xfer_done */ - 0x00f80008, +/* 0x08a9: ctx_xfer_pre_load */ + 0x7e020f1b, + 0x7e0006ad, + 0x7e0006bc, + 0xbd0006ce, + 0x06ad7ef4, + 0x07357e00, +/* 0x08c1: ctx_xfer_exec */ + 0x16019800, + 0x008024bd, + 0x02f60105, + 0xb204bd00, + 0xa5008e1f, + 0x008f7e41, + 0x01fcf000, + 0xb6022cf0, + 0xf2fd0124, + 0x8effb205, + 0x7e41a504, + 0x7e00008f, + 0xbd000216, + 0x47fc8024, + 0x0002f602, + 0x2cf004bd, + 0x0320b601, + 0x024afc80, + 0xbd0002f6, + 0x01acf004, + 0x0b06a5f0, + 0x000c9800, + 0x0e010d98, + 0x013d7e00, + 0x7e080a00, + 0x7e0000ec, + 0xf400020a, + 0x0c0a1201, + 0x0000b87e, + 0x1d7e050f, + 0x02f40007, +/* 0x093d: ctx_xfer_post */ + 0x7e020f2d, + 0xbd0006ad, + 0x06fe7ef4, + 0x02277e00, + 0x06bc7e00, + 0x7ef4bd00, + 0xf40006ad, + 0x01981011, + 0x0511fd40, + 0x7e070bf4, +/* 0x0967: ctx_xfer_no_post_mmio */ +/* 0x0967: ctx_xfer_done */ + 0xf8000833, 0x00000000, 0x00000000, 0x00000000, -- cgit v1.2.3 From 131992709dc4c6140cec3b352f820cb873f7dd50 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Fri, 6 Sep 2019 00:13:59 -0400 Subject: drm/nouveau/kms/gf119-: allow both 256- and 1024-sized LUTs to be used The hardware supports either size. Also add checks to ensure that only these two sizes may be used for supplying a LUT. Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/base907c.c | 11 ++++++++--- drivers/gpu/drm/nouveau/dispnv50/head.c | 26 ++++++++++++++++++-------- drivers/gpu/drm/nouveau/dispnv50/head.h | 7 ++++--- drivers/gpu/drm/nouveau/dispnv50/head507d.c | 9 +++++++-- drivers/gpu/drm/nouveau/dispnv50/head827d.c | 1 + drivers/gpu/drm/nouveau/dispnv50/head907d.c | 11 ++++++++--- drivers/gpu/drm/nouveau/dispnv50/head917d.c | 1 + drivers/gpu/drm/nouveau/dispnv50/headc37d.c | 11 ++++++++--- drivers/gpu/drm/nouveau/dispnv50/headc57d.c | 12 ++++++++---- drivers/gpu/drm/nouveau/dispnv50/lut.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 17 ++++++++++++----- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 3 ++- drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c | 11 ++++++++--- drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c | 11 +++++++---- 14 files changed, 93 insertions(+), 40 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/base907c.c b/drivers/gpu/drm/nouveau/dispnv50/base907c.c index 5f2de77e0f32..224a34c340fe 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base907c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base907c.c @@ -75,12 +75,16 @@ base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } } -static void -base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +static bool +base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { - asyw->xlut.i.mode = 7; + if (size != 256 && size != 1024) + return false; + + asyw->xlut.i.mode = size == 1024 ? 4 : 7; asyw->xlut.i.enable = 2; asyw->xlut.i.load = head907d_olut_load; + return true; } static inline u32 @@ -160,6 +164,7 @@ base907c = { .csc_set = base907c_csc_set, .csc_clr = base907c_csc_clr, .olut_core = true, + .ilut_size = 1024, .xlut_set = base907c_xlut_set, .xlut_clr = base907c_xlut_clr, .image_set = base907c_image_set, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index c9692df2b76c..f64c87dfc1d0 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -213,6 +213,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head, { struct nv50_disp *disp = nv50_disp(head->base.base.dev); struct drm_property_blob *olut = asyh->state.gamma_lut; + int size; /* Determine whether core output LUT should be enabled. */ if (olut) { @@ -229,14 +230,23 @@ nv50_head_atomic_check_lut(struct nv50_head *head, } } - if (!olut && !head->func->olut_identity) { - asyh->olut.handle = 0; - return 0; + if (!olut) { + if (!head->func->olut_identity) { + asyh->olut.handle = 0; + return 0; + } + size = 0; + } else { + size = drm_color_lut_size(olut); } + if (!head->func->olut(head, asyh, size)) { + DRM_DEBUG_KMS("Invalid olut\n"); + return -EINVAL; + } asyh->olut.handle = disp->core->chan.vram.handle; asyh->olut.buffer = !asyh->olut.buffer; - head->func->olut(head, asyh); + return 0; } @@ -510,11 +520,11 @@ nv50_head_create(struct drm_device *dev, int index) drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane, &nv50_head_func, "head-%d", head->base.index); drm_crtc_helper_add(crtc, &nv50_head_help); + /* Keep the legacy gamma size at 256 to avoid compatibility issues */ drm_mode_crtc_set_gamma_size(crtc, 256); - if (disp->disp->object.oclass >= GF110_DISP) - drm_crtc_enable_color_mgmt(crtc, 256, true, 256); - else - drm_crtc_enable_color_mgmt(crtc, 0, false, 256); + drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size, + disp->disp->object.oclass >= GF110_DISP, + head->func->olut_size); if (head->func->olut_set) { ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut); diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h index d1c002f534d4..5c2cda2f32a8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.h +++ b/drivers/gpu/drm/nouveau/dispnv50/head.h @@ -20,8 +20,9 @@ void nv50_head_flush_clr(struct nv50_head *, struct nv50_head_atom *, bool y); struct nv50_head_func { void (*view)(struct nv50_head *, struct nv50_head_atom *); void (*mode)(struct nv50_head *, struct nv50_head_atom *); - void (*olut)(struct nv50_head *, struct nv50_head_atom *); + bool (*olut)(struct nv50_head *, struct nv50_head_atom *, int); bool olut_identity; + int olut_size; void (*olut_set)(struct nv50_head *, struct nv50_head_atom *); void (*olut_clr)(struct nv50_head *); void (*core_calc)(struct nv50_head *, struct nv50_head_atom *); @@ -43,7 +44,7 @@ struct nv50_head_func { extern const struct nv50_head_func head507d; void head507d_view(struct nv50_head *, struct nv50_head_atom *); void head507d_mode(struct nv50_head *, struct nv50_head_atom *); -void head507d_olut(struct nv50_head *, struct nv50_head_atom *); +bool head507d_olut(struct nv50_head *, struct nv50_head_atom *, int); void head507d_core_calc(struct nv50_head *, struct nv50_head_atom *); void head507d_core_clr(struct nv50_head *); int head507d_curs_layout(struct nv50_head *, struct nv50_wndw_atom *, @@ -60,7 +61,7 @@ extern const struct nv50_head_func head827d; extern const struct nv50_head_func head907d; void head907d_view(struct nv50_head *, struct nv50_head_atom *); void head907d_mode(struct nv50_head *, struct nv50_head_atom *); -void head907d_olut(struct nv50_head *, struct nv50_head_atom *); +bool head907d_olut(struct nv50_head *, struct nv50_head_atom *, int); void head907d_olut_set(struct nv50_head *, struct nv50_head_atom *); void head907d_olut_clr(struct nv50_head *); void head907d_core_set(struct nv50_head *, struct nv50_head_atom *); diff --git a/drivers/gpu/drm/nouveau/dispnv50/head507d.c b/drivers/gpu/drm/nouveau/dispnv50/head507d.c index 7561be5ca707..66ccf36b56a2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head507d.c @@ -271,15 +271,19 @@ head507d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -void -head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) +bool +head507d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) { + if (size != 256) + return false; + if (asyh->base.cpp == 1) asyh->olut.mode = 0; else asyh->olut.mode = 1; asyh->olut.load = head507d_olut_load; + return true; } void @@ -328,6 +332,7 @@ head507d = { .view = head507d_view, .mode = head507d_mode, .olut = head507d_olut, + .olut_size = 256, .olut_set = head507d_olut_set, .olut_clr = head507d_olut_clr, .core_calc = head507d_core_calc, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head827d.c b/drivers/gpu/drm/nouveau/dispnv50/head827d.c index af5e7bd5978b..11877119eea4 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head827d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head827d.c @@ -108,6 +108,7 @@ head827d = { .view = head507d_view, .mode = head507d_mode, .olut = head507d_olut, + .olut_size = 256, .olut_set = head827d_olut_set, .olut_clr = head827d_olut_clr, .core_calc = head507d_core_calc, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head907d.c b/drivers/gpu/drm/nouveau/dispnv50/head907d.c index c2d09dd97b1f..3002ec23d7a6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head907d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head907d.c @@ -230,11 +230,15 @@ head907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -void -head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) +bool +head907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) { - asyh->olut.mode = 7; + if (size != 256 && size != 1024) + return false; + + asyh->olut.mode = size == 1024 ? 4 : 7; asyh->olut.load = head907d_olut_load; + return true; } void @@ -285,6 +289,7 @@ head907d = { .view = head907d_view, .mode = head907d_mode, .olut = head907d_olut, + .olut_size = 1024, .olut_set = head907d_olut_set, .olut_clr = head907d_olut_clr, .core_calc = head507d_core_calc, diff --git a/drivers/gpu/drm/nouveau/dispnv50/head917d.c b/drivers/gpu/drm/nouveau/dispnv50/head917d.c index 303df8459ca8..76958cedd51f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head917d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head917d.c @@ -83,6 +83,7 @@ head917d = { .view = head907d_view, .mode = head907d_mode, .olut = head907d_olut, + .olut_size = 1024, .olut_set = head907d_olut_set, .olut_clr = head907d_olut_clr, .core_calc = head507d_core_calc, diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c index ef6a99d95a9c..00011ce109a6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc37d.c @@ -148,14 +148,18 @@ headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) } } -static void -headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) +static bool +headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) { + if (size != 256 && size != 1024) + return false; + asyh->olut.mode = 2; - asyh->olut.size = 0; + asyh->olut.size = size == 1024 ? 2 : 0; asyh->olut.range = 0; asyh->olut.output_mode = 1; asyh->olut.load = head907d_olut_load; + return true; } static void @@ -201,6 +205,7 @@ headc37d = { .view = headc37d_view, .mode = headc37d_mode, .olut = headc37d_olut, + .olut_size = 1024, .olut_set = headc37d_olut_set, .olut_clr = headc37d_olut_clr, .curs_layout = head917d_curs_layout, diff --git a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c index 32a7f9e85fb0..938d910a1b1e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/headc57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/headc57d.c @@ -151,17 +151,20 @@ headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -void -headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) +bool +headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) { + if (size != 0 && size != 256 && size != 1024) + return false; + asyh->olut.mode = 2; /* DIRECT10 */ asyh->olut.size = 4 /* VSS header. */ + 1024 + 1 /* Entries. */; asyh->olut.output_mode = 1; /* INTERPOLATE_ENABLE. */ - if (asyh->state.gamma_lut && - asyh->state.gamma_lut->length / sizeof(struct drm_color_lut) == 256) + if (size == 256) asyh->olut.load = headc57d_olut_load_8; else asyh->olut.load = headc57d_olut_load; + return true; } static void @@ -194,6 +197,7 @@ headc57d = { .mode = headc57d_mode, .olut = headc57d_olut, .olut_identity = true, + .olut_size = 1024, .olut_set = headc57d_olut_set, .olut_clr = headc57d_olut_clr, .curs_layout = head917d_curs_layout, diff --git a/drivers/gpu/drm/nouveau/dispnv50/lut.c b/drivers/gpu/drm/nouveau/dispnv50/lut.c index 994def4fd51a..4e95ca5604ab 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/lut.c +++ b/drivers/gpu/drm/nouveau/dispnv50/lut.c @@ -49,7 +49,7 @@ nv50_lut_load(struct nv50_lut *lut, int buffer, struct drm_property_blob *blob, kvfree(in); } } else { - load(in, blob->length / sizeof(*in), mem); + load(in, drm_color_lut_size(blob), mem); } return addr; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 5193b6257061..890315291b01 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -318,7 +318,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, bool modeset, return wndw->func->acquire(wndw, asyw, asyh); } -static void +static int nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, struct nv50_wndw_atom *armw, struct nv50_wndw_atom *asyw, @@ -340,7 +340,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, */ if (!(ilut = asyh->state.gamma_lut)) { asyw->visible = false; - return; + return 0; } if (wndw->func->ilut) @@ -359,7 +359,10 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, /* Recalculate LUT state. */ memset(&asyw->xlut, 0x00, sizeof(asyw->xlut)); if ((asyw->ilut = wndw->func->ilut ? ilut : NULL)) { - wndw->func->ilut(wndw, asyw); + if (!wndw->func->ilut(wndw, asyw, drm_color_lut_size(ilut))) { + DRM_DEBUG_KMS("Invalid ilut\n"); + return -EINVAL; + } asyw->xlut.handle = wndw->wndw.vram.handle; asyw->xlut.i.buffer = !asyw->xlut.i.buffer; asyw->set.xlut = true; @@ -384,6 +387,7 @@ nv50_wndw_atomic_check_lut(struct nv50_wndw *wndw, /* Can't do an immediate flip while changing the LUT. */ asyh->state.async_flip = false; + return 0; } static int @@ -424,8 +428,11 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) (!armw->visible || asyh->state.color_mgmt_changed || asyw->state.fb->format->format != - armw->state.fb->format->format)) - nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh); + armw->state.fb->format->format)) { + ret = nv50_wndw_atomic_check_lut(wndw, armw, asyw, asyh); + if (ret) + return ret; + } /* Calculate new window state. */ if (asyw->visible) { diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index c63bd3bdaf06..caf397475918 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -64,12 +64,13 @@ struct nv50_wndw_func { void (*ntfy_clr)(struct nv50_wndw *); int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, struct nvif_device *); - void (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *); + bool (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *, int); void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *, const struct drm_color_ctm *); void (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*csc_clr)(struct nv50_wndw *); bool ilut_identity; + int ilut_size; bool olut_core; void (*xlut_set)(struct nv50_wndw *, struct nv50_wndw_atom *); void (*xlut_clr)(struct nv50_wndw *); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index 0f9402162bde..b92dc3461bbd 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -71,14 +71,18 @@ wndwc37e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) } } -static void -wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +static bool +wndwc37e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { + if (size != 256 && size != 1024) + return false; + asyw->xlut.i.mode = 2; - asyw->xlut.i.size = 0; + asyw->xlut.i.size = size == 1024 ? 2 : 0; asyw->xlut.i.range = 0; asyw->xlut.i.output_mode = 1; asyw->xlut.i.load = head907d_olut_load; + return true; } void @@ -261,6 +265,7 @@ wndwc37e = { .ntfy_reset = corec37d_ntfy_init, .ntfy_wait_begun = base507c_ntfy_wait_begun, .ilut = wndwc37e_ilut, + .ilut_size = 1024, .xlut_set = wndwc37e_ilut_set, .xlut_clr = wndwc37e_ilut_clr, .csc = base907c_csc, diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index a311c79e5295..35c9c52fab26 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -156,19 +156,21 @@ wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem) writew(readw(mem - 4), mem + 4); } -static void -wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw) +static bool +wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size) { - u16 size = asyw->ilut->length / sizeof(struct drm_color_lut); + if (size = size ? size : 1024, size != 256 && size != 1024) + return false; + if (size == 256) { asyw->xlut.i.mode = 1; /* DIRECT8. */ } else { asyw->xlut.i.mode = 2; /* DIRECT10. */ - size = 1024; } asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */; asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */ asyw->xlut.i.load = wndwc57e_ilut_load; + return true; } static const struct nv50_wndw_func @@ -183,6 +185,7 @@ wndwc57e = { .ntfy_wait_begun = base507c_ntfy_wait_begun, .ilut = wndwc57e_ilut, .ilut_identity = true, + .ilut_size = 1024, .xlut_set = wndwc57e_ilut_set, .xlut_clr = wndwc57e_ilut_clr, .csc = base907c_csc, -- cgit v1.2.3 From 122c1639185fbb0e8fd33a9e23444de64df44684 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Fri, 13 Sep 2019 18:37:20 -0400 Subject: drm/nouveau/kms/nv50-: Remove nv50_mstc_best_encoder() When drm_connector_helper_funcs->atomic_best_encoder is defined, ->best_encoder is ignored by the atomic modesetting helpers. That being said, this hook is completely broken anyway - it always returns the first msto for a given mstc, despite the fact it might already be in use. So, just get rid of it. We'll need this in a moment anyway, when we make mstos per-head as opposed to per-connector. Changes since v1: * Fix typo in documentation - imirkin Signed-off-by: Lyude Paul Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index fd31bff0c920..a3d07a1e404e 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -946,14 +946,6 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector, return &mstc->mstm->msto[head->base.index]->encoder; } -static struct drm_encoder * -nv50_mstc_best_encoder(struct drm_connector *connector) -{ - struct nv50_mstc *mstc = nv50_mstc(connector); - - return &mstc->mstm->msto[0]->encoder; -} - static enum drm_mode_status nv50_mstc_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -1038,7 +1030,6 @@ static const struct drm_connector_helper_funcs nv50_mstc_help = { .get_modes = nv50_mstc_get_modes, .mode_valid = nv50_mstc_mode_valid, - .best_encoder = nv50_mstc_best_encoder, .atomic_best_encoder = nv50_mstc_atomic_best_encoder, .atomic_check = nv50_mstc_atomic_check, .detect_ctx = nv50_mstc_detect, -- cgit v1.2.3 From 5ff0cb1ce2536321045b5bc33ab8fb2467750f33 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Fri, 13 Sep 2019 18:03:52 -0400 Subject: drm/nouveau/kms/nv50-: Use less encoders by making mstos per-head Currently, for every single MST capable DRM connector we create a set of fake encoders, one for each possible head. Unfortunately this ends up being a huge waste of encoders. While this currently isn't causing us any problems, it's extremely close to doing so. The ThinkPad P71 is a good example of this. Originally when trying to figure out why nouveau was failing to load on this laptop, I discovered it was because nouveau was creating too many encoders. This ended up being because we were mistakenly creating MST encoders for the eDP port, however we are still extremely close to hitting the encoder limit on this machine as it exposes 1 eDP port and 5 DP ports, resulting in 31 encoders. So while this fix didn't end up being necessary to fix the P71, we still need to implement this so that we avoid hitting the encoder limit for valid display configurations in the event that some machine with more connectors then this becomes available. Plus, we don't want to let good code go to waste :) So, use less encoders by only creating one MSTO per head. Then, attach each new MSTC to each MSTO which corresponds to a head that it's parent DP port is capable of using. This brings the number of encoders we register on the ThinkPad P71 from 31, down to just 15. Yay! Signed-off-by: Lyude Paul Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 92 ++++++++++++++++++++------------- drivers/gpu/drm/nouveau/dispnv50/disp.h | 2 + drivers/gpu/drm/nouveau/dispnv50/head.c | 17 +++--- drivers/gpu/drm/nouveau/dispnv50/head.h | 3 +- 4 files changed, 68 insertions(+), 46 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index a3d07a1e404e..eba520508e4f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -660,7 +660,6 @@ struct nv50_mstm { struct nouveau_encoder *outp; struct drm_dp_mst_topology_mgr mgr; - struct nv50_msto *msto[4]; bool modified; bool disabled; @@ -726,7 +725,6 @@ nv50_msto_cleanup(struct nv50_msto *msto) drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port); msto->mstc = NULL; - msto->head = NULL; msto->disabled = false; } @@ -872,7 +870,6 @@ nv50_msto_enable(struct drm_encoder *encoder) mstm->outp->update(mstm->outp, head->base.index, armh, proto, nv50_dp_bpc_to_depth(armh->or.bpc)); - msto->head = head; msto->mstc = mstc; mstm->modified = true; } @@ -913,37 +910,40 @@ nv50_msto = { .destroy = nv50_msto_destroy, }; -static int -nv50_msto_new(struct drm_device *dev, u32 heads, const char *name, int id, - struct nv50_msto **pmsto) +static struct nv50_msto * +nv50_msto_new(struct drm_device *dev, struct nv50_head *head, int id) { struct nv50_msto *msto; int ret; - if (!(msto = *pmsto = kzalloc(sizeof(*msto), GFP_KERNEL))) - return -ENOMEM; + msto = kzalloc(sizeof(*msto), GFP_KERNEL); + if (!msto) + return ERR_PTR(-ENOMEM); ret = drm_encoder_init(dev, &msto->encoder, &nv50_msto, - DRM_MODE_ENCODER_DPMST, "%s-mst-%d", name, id); + DRM_MODE_ENCODER_DPMST, "mst-%d", id); if (ret) { - kfree(*pmsto); - *pmsto = NULL; - return ret; + kfree(msto); + return ERR_PTR(ret); } drm_encoder_helper_add(&msto->encoder, &nv50_msto_help); - msto->encoder.possible_crtcs = heads; - return 0; + msto->encoder.possible_crtcs = drm_crtc_mask(&head->base.base); + msto->head = head; + return msto; } static struct drm_encoder * nv50_mstc_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *connector_state) { - struct nv50_head *head = nv50_head(connector_state->crtc); struct nv50_mstc *mstc = nv50_mstc(connector); + struct drm_crtc *crtc = connector_state->crtc; - return &mstc->mstm->msto[head->base.index]->encoder; + if (!(mstc->mstm->outp->dcb->heads & drm_crtc_mask(crtc))) + return NULL; + + return &nv50_head(crtc)->msto->encoder; } static enum drm_mode_status @@ -1062,8 +1062,9 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, const char *path, struct nv50_mstc **pmstc) { struct drm_device *dev = mstm->outp->base.base.dev; + struct drm_crtc *crtc; struct nv50_mstc *mstc; - int ret, i; + int ret; if (!(mstc = *pmstc = kzalloc(sizeof(*mstc), GFP_KERNEL))) return -ENOMEM; @@ -1083,8 +1084,13 @@ nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port, mstc->connector.funcs->reset(&mstc->connector); nouveau_conn_attach_properties(&mstc->connector); - for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto[i]; i++) - drm_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder); + drm_for_each_crtc(crtc, dev) { + if (!(mstm->outp->dcb->heads & drm_crtc_mask(crtc))) + continue; + + drm_connector_attach_encoder(&mstc->connector, + &nv50_head(crtc)->msto->encoder); + } drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0); drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0); @@ -1358,7 +1364,7 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, const int max_payloads = hweight8(outp->dcb->heads); struct drm_device *dev = outp->base.base.dev; struct nv50_mstm *mstm; - int ret, i; + int ret; u8 dpcd; /* This is a workaround for some monitors not functioning @@ -1381,13 +1387,6 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, if (ret) return ret; - for (i = 0; i < max_payloads; i++) { - ret = nv50_msto_new(dev, outp->dcb->heads, outp->base.base.name, - i, &mstm->msto[i]); - if (ret) - return ret; - } - return 0; } @@ -1560,17 +1559,24 @@ nv50_sor_func = { .destroy = nv50_sor_destroy, }; +static bool nv50_has_mst(struct nouveau_drm *drm) +{ + struct nvkm_bios *bios = nvxx_bios(&drm->client.device); + u32 data; + u8 ver, hdr, cnt, len; + + data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len); + return data && ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04); +} + static int nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nvkm_bios *bios = nvxx_bios(&drm->client.device); struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; - u8 ver, hdr, cnt, len; - u32 data; int type, ret; switch (dcbe->type) { @@ -1615,10 +1621,9 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) } if (nv_connector->type != DCB_CONNECTOR_eDP && - (data = nvbios_dp_table(bios, &ver, &hdr, &cnt, &len)) && - ver >= 0x40 && (nvbios_rd08(bios, data + 0x08) & 0x04)) { - ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16, - nv_connector->base.base.id, + nv50_has_mst(drm)) { + ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, + 16, nv_connector->base.base.id, &nv_encoder->dp.mstm); if (ret) return ret; @@ -2314,6 +2319,7 @@ nv50_display_create(struct drm_device *dev) struct nv50_disp *disp; struct dcb_output *dcbe; int crtcs, ret, i; + bool has_mst = nv50_has_mst(drm); disp = kzalloc(sizeof(*disp), GFP_KERNEL); if (!disp) @@ -2362,11 +2368,25 @@ nv50_display_create(struct drm_device *dev) crtcs = 0x3; for (i = 0; i < fls(crtcs); i++) { + struct nv50_head *head; + if (!(crtcs & (1 << i))) continue; - ret = nv50_head_create(dev, i); - if (ret) + + head = nv50_head_create(dev, i); + if (IS_ERR(head)) { + ret = PTR_ERR(head); goto out; + } + + if (has_mst) { + head->msto = nv50_msto_new(dev, head, i); + if (IS_ERR(head->msto)) { + ret = PTR_ERR(head->msto); + head->msto = NULL; + goto out; + } + } } /* create encoder/connector objects based on VBIOS DCB table */ diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index c0a79531b087..d54fe00ac3a3 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -4,6 +4,8 @@ #include "nouveau_display.h" +struct nv50_msto; + struct nv50_disp { struct nvif_disp *disp; struct nv50_core *core; diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c index f64c87dfc1d0..d9d64602947d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.c +++ b/drivers/gpu/drm/nouveau/dispnv50/head.c @@ -483,7 +483,7 @@ nv50_head_func = { .atomic_destroy_state = nv50_head_atomic_destroy_state, }; -int +struct nv50_head * nv50_head_create(struct drm_device *dev, int index) { struct nouveau_drm *drm = nouveau_drm(dev); @@ -495,7 +495,7 @@ nv50_head_create(struct drm_device *dev, int index) head = kzalloc(sizeof(*head), GFP_KERNEL); if (!head) - return -ENOMEM; + return ERR_PTR(-ENOMEM); head->func = disp->core->func->head; head->base.index = index; @@ -513,7 +513,7 @@ nv50_head_create(struct drm_device *dev, int index) ret = nv50_curs_new(drm, head->base.index, &curs); if (ret) { kfree(head); - return ret; + return ERR_PTR(ret); } crtc = &head->base.base; @@ -528,12 +528,11 @@ nv50_head_create(struct drm_device *dev, int index) if (head->func->olut_set) { ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut); - if (ret) - goto out; + if (ret) { + nv50_head_destroy(crtc); + return ERR_PTR(ret); + } } -out: - if (ret) - nv50_head_destroy(crtc); - return ret; + return head; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.h b/drivers/gpu/drm/nouveau/dispnv50/head.h index 5c2cda2f32a8..c32b27cdaefc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/head.h +++ b/drivers/gpu/drm/nouveau/dispnv50/head.h @@ -11,9 +11,10 @@ struct nv50_head { const struct nv50_head_func *func; struct nouveau_crtc base; struct nv50_lut olut; + struct nv50_msto *msto; }; -int nv50_head_create(struct drm_device *, int index); +struct nv50_head *nv50_head_create(struct drm_device *, int index); void nv50_head_flush_set(struct nv50_head *, struct nv50_head_atom *); void nv50_head_flush_clr(struct nv50_head *, struct nv50_head_atom *, bool y); -- cgit v1.2.3 From 481404957a14f9c46576913ba12985e6798b7d32 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Fri, 13 Sep 2019 18:03:53 -0400 Subject: drm/nouveau/kms/nv50-: Report possible_crtcs incorrectly on mstos, for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is seperate from the previous one to make it easier to revert in the future. Basically, while working on making MSTOs per-head as opposed to per-head-per-connector I discovered these lovely issues: https://gitlab.freedesktop.org/xorg/xserver/merge_requests/277 https://gitlab.gnome.org/GNOME/mutter/issues/759 Note as well that Intel already has a temporary workaround for this in their kernel driver. So, unfortunately we need to follow suit to avoid causing a regression in userspace. Once these issues get fixed, this commit should be reverted. Signed-off-by: Lyude Paul Cc: Ville Syrjälä Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index eba520508e4f..5fabe2b88eca 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -2386,6 +2386,18 @@ nv50_display_create(struct drm_device *dev) head->msto = NULL; goto out; } + + /* + * FIXME: This is a hack to workaround the following + * issues: + * + * https://gitlab.gnome.org/GNOME/mutter/issues/759 + * https://gitlab.freedesktop.org/xorg/xserver/merge_requests/277 + * + * Once these issues are closed, this should be + * removed + */ + head->msto->encoder.possible_crtcs = crtcs; } } -- cgit v1.2.3 From f42e4b337b327b1336c978c4b5174990a25f68a0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 29 Nov 2019 16:28:28 +0000 Subject: drm/nouveau/nouveau: fix incorrect sizeof on args.src an args.dst The sizeof is currently on args.src and args.dst and should be on *args.src and *args.dst. Fortunately these sizes just so happen to be the same size so it worked, however, this should be fixed and it also cleans up static analysis warnings Addresses-Coverity: ("sizeof not portable") Fixes: f268307ec7c7 ("nouveau: simplify nouveau_dmem_migrate_vma") Signed-off-by: Colin Ian King Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index fa1439941596..0ad5d87b5a8e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -635,10 +635,10 @@ nouveau_dmem_migrate_vma(struct nouveau_drm *drm, unsigned long c, i; int ret = -ENOMEM; - args.src = kcalloc(max, sizeof(args.src), GFP_KERNEL); + args.src = kcalloc(max, sizeof(*args.src), GFP_KERNEL); if (!args.src) goto out; - args.dst = kcalloc(max, sizeof(args.dst), GFP_KERNEL); + args.dst = kcalloc(max, sizeof(*args.dst), GFP_KERNEL); if (!args.dst) goto out_free_src; -- cgit v1.2.3 From 0ac7facb7071836154687a228eaead3fc82297c1 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 12:59:59 +0100 Subject: drm/nouveau/fault: Add support for GP10B There is no BAR2 on GP10B and there is no need to map through BAR2 because all memory is shared between the GPU and the CPU. Add a custom implementation of the fault sub-device that uses nvkm_memory_addr() instead of nvkm_memory_bar2() to return the address of a pinned fault buffer. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/subdev/fault.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c | 17 +++++-- drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.c | 53 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h | 10 ++++ 8 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h index 97322f95b3ee..a513c16ab105 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h @@ -31,6 +31,7 @@ struct nvkm_fault_data { }; int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); +int gp10b_fault_new(struct nvkm_device *, int, struct nvkm_fault **); int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); int tu102_fault_new(struct nvkm_device *, int, struct nvkm_fault **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index c3c7159f3411..b061df138142 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2375,7 +2375,7 @@ nv13b_chipset = { .name = "GP10B", .bar = gm20b_bar_new, .bus = gf100_bus_new, - .fault = gp100_fault_new, + .fault = gp10b_fault_new, .fb = gp10b_fb_new, .fuse = gm107_fuse_new, .ibus = gp10b_ibus_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild index 53b9d638f2c8..d65ec719f153 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild @@ -2,5 +2,6 @@ nvkm-y += nvkm/subdev/fault/base.o nvkm-y += nvkm/subdev/fault/user.o nvkm-y += nvkm/subdev/fault/gp100.o +nvkm-y += nvkm/subdev/fault/gp10b.o nvkm-y += nvkm/subdev/fault/gv100.o nvkm-y += nvkm/subdev/fault/tu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c index ca251560d3e0..1c4b852b26c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c @@ -108,7 +108,7 @@ nvkm_fault_oneinit_buffer(struct nvkm_fault *fault, int id) return ret; /* Pin fault buffer in BAR2. */ - buffer->addr = nvkm_memory_bar2(buffer->mem); + buffer->addr = fault->func->buffer.pin(buffer); if (buffer->addr == ~0ULL) return -EFAULT; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c index 4f3c4e091117..f6b189cc4330 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c @@ -21,25 +21,26 @@ */ #include "priv.h" +#include #include #include -static void +void gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) { struct nvkm_device *device = buffer->fault->subdev.device; nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, enable); } -static void +void gp100_fault_buffer_fini(struct nvkm_fault_buffer *buffer) { struct nvkm_device *device = buffer->fault->subdev.device; nvkm_mask(device, 0x002a70, 0x00000001, 0x00000000); } -static void +void gp100_fault_buffer_init(struct nvkm_fault_buffer *buffer) { struct nvkm_device *device = buffer->fault->subdev.device; @@ -48,7 +49,12 @@ gp100_fault_buffer_init(struct nvkm_fault_buffer *buffer) nvkm_mask(device, 0x002a70, 0x00000001, 0x00000001); } -static void +u64 gp100_fault_buffer_pin(struct nvkm_fault_buffer *buffer) +{ + return nvkm_memory_bar2(buffer->mem); +} + +void gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer) { buffer->entries = nvkm_rd32(buffer->fault->subdev.device, 0x002a78); @@ -56,7 +62,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer) buffer->put = 0x002a80; } -static void +void gp100_fault_intr(struct nvkm_fault *fault) { nvkm_event_send(&fault->event, 1, 0, NULL, 0); @@ -68,6 +74,7 @@ gp100_fault = { .buffer.nr = 1, .buffer.entry_size = 32, .buffer.info = gp100_fault_buffer_info, + .buffer.pin = gp100_fault_buffer_pin, .buffer.init = gp100_fault_buffer_init, .buffer.fini = gp100_fault_buffer_fini, .buffer.intr = gp100_fault_buffer_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.c new file mode 100644 index 000000000000..9e66d1f7654d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp10b.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 NVIDIA Corporation. + * + * 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. + */ + +#include "priv.h" + +#include + +#include + +u64 +gp10b_fault_buffer_pin(struct nvkm_fault_buffer *buffer) +{ + return nvkm_memory_addr(buffer->mem); +} + +static const struct nvkm_fault_func +gp10b_fault = { + .intr = gp100_fault_intr, + .buffer.nr = 1, + .buffer.entry_size = 32, + .buffer.info = gp100_fault_buffer_info, + .buffer.pin = gp10b_fault_buffer_pin, + .buffer.init = gp100_fault_buffer_init, + .buffer.fini = gp100_fault_buffer_fini, + .buffer.intr = gp100_fault_buffer_intr, + .user = { { 0, 0, MAXWELL_FAULT_BUFFER_A }, 0 }, +}; + +int +gp10b_fault_new(struct nvkm_device *device, int index, + struct nvkm_fault **pfault) +{ + return nvkm_fault_new_(&gp10b_fault, device, index, pfault); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c index 6747f09c2dc3..2707be4ffabc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c @@ -214,6 +214,7 @@ gv100_fault = { .buffer.nr = 2, .buffer.entry_size = 32, .buffer.info = gv100_fault_buffer_info, + .buffer.pin = gp100_fault_buffer_pin, .buffer.init = gv100_fault_buffer_init, .buffer.fini = gv100_fault_buffer_fini, .buffer.intr = gv100_fault_buffer_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h index 975e66ac6344..f6f1dd7eee1f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h @@ -30,6 +30,7 @@ struct nvkm_fault_func { int nr; u32 entry_size; void (*info)(struct nvkm_fault_buffer *); + u64 (*pin)(struct nvkm_fault_buffer *); void (*init)(struct nvkm_fault_buffer *); void (*fini)(struct nvkm_fault_buffer *); void (*intr)(struct nvkm_fault_buffer *, bool enable); @@ -40,6 +41,15 @@ struct nvkm_fault_func { } user; }; +void gp100_fault_buffer_intr(struct nvkm_fault_buffer *, bool enable); +void gp100_fault_buffer_fini(struct nvkm_fault_buffer *); +void gp100_fault_buffer_init(struct nvkm_fault_buffer *); +u64 gp100_fault_buffer_pin(struct nvkm_fault_buffer *); +void gp100_fault_buffer_info(struct nvkm_fault_buffer *); +void gp100_fault_intr(struct nvkm_fault *); + +u64 gp10b_fault_buffer_pin(struct nvkm_fault_buffer *); + int gv100_fault_oneinit(struct nvkm_fault *); int nvkm_ufault_new(struct nvkm_device *, const struct nvkm_oclass *, -- cgit v1.2.3 From f1331ea8ee0a7fe9a832a403587528adddd03561 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:00 +0100 Subject: drm/nouveau: Do not try to disable PCI device on Tegra When Nouveau is instantiated on top of a platform device, the dev->pdev field will be NULL and calling pci_disable_device() will crash. Move the PCI disabling code to the PCI specific driver removal code. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2cd83849600f..b65ae817eabf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -715,7 +715,6 @@ fail_nvkm: void nouveau_drm_device_remove(struct drm_device *dev) { - struct pci_dev *pdev = dev->pdev; struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_client *client; struct nvkm_device *device; @@ -727,7 +726,6 @@ nouveau_drm_device_remove(struct drm_device *dev) device = nvkm_device_find(client->device); nouveau_drm_device_fini(dev); - pci_disable_device(pdev); drm_dev_put(dev); nvkm_device_del(&device); } @@ -738,6 +736,7 @@ nouveau_drm_remove(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev); nouveau_drm_device_remove(dev); + pci_disable_device(pdev); } static int -- cgit v1.2.3 From b0b651aedb101785f91f8d13a4c1e6363f3fa178 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:01 +0100 Subject: drm/nouveau/tegra: Avoid pulsing reset twice When the GPU powergate is controlled by a generic power domain provider, the reset will automatically be asserted and deasserted as part of the power-ungating procedure. On some Jetson TX2 boards, doing an additional assert and deassert of the GPU outside of the power-ungate procedure can cause the GPU to go into a bad state where the memory interface can no longer access system memory. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 0e372a190d3f..747a775121cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -52,18 +52,18 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) clk_set_rate(tdev->clk_pwr, 204000000); udelay(10); - reset_control_assert(tdev->rst); - udelay(10); - if (!tdev->pdev->dev.pm_domain) { + reset_control_assert(tdev->rst); + udelay(10); + ret = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D); if (ret) goto err_clamp; udelay(10); - } - reset_control_deassert(tdev->rst); - udelay(10); + reset_control_deassert(tdev->rst); + udelay(10); + } return 0; -- cgit v1.2.3 From fc12262b96833ce131063c7081cd7fb3c4a048f3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:02 +0100 Subject: drm/nouveau/tegra: Set clock rate if not set If the GPU clock has not had a rate set, initialize it to the maximum clock rate to make sure it does run. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 747a775121cf..d0d52c1d4aee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -279,6 +279,7 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, struct nvkm_device **pdevice) { struct nvkm_device_tegra *tdev; + unsigned long rate; int ret; if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) @@ -307,6 +308,17 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, goto free; } + rate = clk_get_rate(tdev->clk); + if (rate == 0) { + ret = clk_set_rate(tdev->clk, ULONG_MAX); + if (ret < 0) + goto free; + + rate = clk_get_rate(tdev->clk); + + dev_dbg(&pdev->dev, "GPU clock set to %lu\n", rate); + } + if (func->require_ref_clk) tdev->clk_ref = devm_clk_get(&pdev->dev, "ref"); if (IS_ERR(tdev->clk_ref)) { -- cgit v1.2.3 From 6992ceb8c0f6f8e2f4374a1ab4dd84cd76cc4b64 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:03 +0100 Subject: drm/nouveau/secboot/gm20b,gp10b: Read WPR configuration from GPU registers The GPUs found on Tegra SoCs have registers that can be used to read the WPR configuration. Use these registers instead of reaching into the memory controller's register space to read the same information. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h | 2 +- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 83 ++++++++++++++-------- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c | 4 +- 3 files changed, 54 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h index 62c5e162099a..280b1448df88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h @@ -41,6 +41,6 @@ int gm200_secboot_run_blob(struct nvkm_secboot *, struct nvkm_gpuobj *, struct nvkm_falcon *); /* Tegra-only */ -int gm20b_secboot_tegra_read_wpr(struct gm200_secboot *, u32); +int gm20b_secboot_tegra_read_wpr(struct gm200_secboot *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index df8b919dcf09..72690d80f0ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -23,39 +23,65 @@ #include "acr.h" #include "gm200.h" -#define TEGRA210_MC_BASE 0x70019000 - #ifdef CONFIG_ARCH_TEGRA -#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 -#define MC_SECURITY_CARVEOUT2_BOM_0 0xc5c -#define MC_SECURITY_CARVEOUT2_BOM_HI_0 0xc60 -#define MC_SECURITY_CARVEOUT2_SIZE_128K 0xc64 -#define TEGRA_MC_SECURITY_CARVEOUT_CFG_LOCKED (1 << 1) /** * gm20b_secboot_tegra_read_wpr() - read the WPR registers on Tegra * - * On dGPU, we can manage the WPR region ourselves, but on Tegra the WPR region - * is reserved from system memory by the bootloader and irreversibly locked. - * This function reads the address and size of the pre-configured WPR region. + * On dGPU, we can manage the WPR region ourselves, but on Tegra this region + * is allocated from system memory by the secure firmware. The region is then + * marked as a "secure carveout" and irreversibly locked. Furthermore, the WPR + * secure carveout is also configured to be sent to the GPU via a dedicated + * serial bus between the memory controller and the GPU. The GPU requests this + * information upon leaving reset and exposes it through a FIFO register at + * offset 0x100cd4. + * + * The FIFO register's lower 4 bits can be used to set the read index into the + * FIFO. After each read of the FIFO register, the read index is incremented. + * + * Indices 2 and 3 contain the lower and upper addresses of the WPR. These are + * stored in units of 256 B. The WPR is inclusive of both addresses. + * + * Unfortunately, for some reason the WPR info register doesn't contain the + * correct values for the secure carveout. It seems like the upper address is + * always too small by 128 KiB - 1. Given that the secure carvout size in the + * memory controller configuration is specified in units of 128 KiB, it's + * possible that the computation of the upper address of the WPR is wrong and + * causes this difference. */ int -gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb, u32 mc_base) +gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb) { + struct nvkm_device *device = gsb->base.subdev.device; struct nvkm_secboot *sb = &gsb->base; - void __iomem *mc; - u32 cfg; + u64 base, limit; + u32 value; - mc = ioremap(mc_base, 0xd00); - if (!mc) { - nvkm_error(&sb->subdev, "Cannot map Tegra MC registers\n"); - return -ENOMEM; - } - sb->wpr_addr = ioread32_native(mc + MC_SECURITY_CARVEOUT2_BOM_0) | - ((u64)ioread32_native(mc + MC_SECURITY_CARVEOUT2_BOM_HI_0) << 32); - sb->wpr_size = ioread32_native(mc + MC_SECURITY_CARVEOUT2_SIZE_128K) - << 17; - cfg = ioread32_native(mc + MC_SECURITY_CARVEOUT2_CFG0); - iounmap(mc); + /* set WPR info register to point at WPR base address register */ + value = nvkm_rd32(device, 0x100cd4); + value &= ~0xf; + value |= 0x2; + nvkm_wr32(device, 0x100cd4, value); + + /* read base address */ + value = nvkm_rd32(device, 0x100cd4); + base = (u64)(value >> 4) << 12; + + /* read limit */ + value = nvkm_rd32(device, 0x100cd4); + limit = (u64)(value >> 4) << 12; + + /* + * The upper address of the WPR seems to be computed wrongly and is + * actually SZ_128K - 1 bytes lower than it should be. Adjust the + * value accordingly. + */ + limit += SZ_128K - 1; + + sb->wpr_size = limit - base + 1; + sb->wpr_addr = base; + + nvkm_info(&sb->subdev, "WPR: %016llx-%016llx\n", sb->wpr_addr, + sb->wpr_addr + sb->wpr_size - 1); /* Check that WPR settings are valid */ if (sb->wpr_size == 0) { @@ -63,16 +89,11 @@ gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb, u32 mc_base) return -EINVAL; } - if (!(cfg & TEGRA_MC_SECURITY_CARVEOUT_CFG_LOCKED)) { - nvkm_error(&sb->subdev, "WPR region not locked\n"); - return -EINVAL; - } - return 0; } #else int -gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb, u32 mc_base) +gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb) { nvkm_error(&gsb->base.subdev, "Tegra support not compiled in\n"); return -EINVAL; @@ -85,7 +106,7 @@ gm20b_secboot_oneinit(struct nvkm_secboot *sb) struct gm200_secboot *gsb = gm200_secboot(sb); int ret; - ret = gm20b_secboot_tegra_read_wpr(gsb, TEGRA210_MC_BASE); + ret = gm20b_secboot_tegra_read_wpr(gsb); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c index 28ca29d0eeee..d84e85825995 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c @@ -23,15 +23,13 @@ #include "acr.h" #include "gm200.h" -#define TEGRA186_MC_BASE 0x02c10000 - static int gp10b_secboot_oneinit(struct nvkm_secboot *sb) { struct gm200_secboot *gsb = gm200_secboot(sb); int ret; - ret = gm20b_secboot_tegra_read_wpr(gsb, TEGRA186_MC_BASE); + ret = gm20b_secboot_tegra_read_wpr(gsb); if (ret) return ret; -- cgit v1.2.3 From 0d0d498265e7cb3329d2a7185b1d7cfb3be95d65 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:04 +0100 Subject: drm/nouveau/ltc/gp10b: Add custom L2 cache implementation There are extra registers that need to be programmed to make the level 2 cache work on GP10B, such as the stream ID register that is used when an SMMU is used to translate memory addresses. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c | 65 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h | 2 + 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index 644d527c3b96..d76f60d7d29a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h @@ -40,4 +40,5 @@ int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); int gm200_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); int gp100_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); int gp102_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); +int gp10b_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index b061df138142..231ec0073af3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2380,7 +2380,7 @@ nv13b_chipset = { .fuse = gm107_fuse_new, .ibus = gp10b_ibus_new, .imem = gk20a_instmem_new, - .ltc = gp102_ltc_new, + .ltc = gp10b_ltc_new, .mc = gp10b_mc_new, .mmu = gp10b_mmu_new, .secboot = gp10b_secboot_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild index 2b6d36ea7067..728d75010847 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild @@ -6,3 +6,4 @@ nvkm-y += nvkm/subdev/ltc/gm107.o nvkm-y += nvkm/subdev/ltc/gm200.o nvkm-y += nvkm/subdev/ltc/gp100.o nvkm-y += nvkm/subdev/ltc/gp102.o +nvkm-y += nvkm/subdev/ltc/gp10b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c new file mode 100644 index 000000000000..c0063c7caa50 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019 NVIDIA Corporation. + * + * 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: Thierry Reding + */ + +#include "priv.h" + +static void +gp10b_ltc_init(struct nvkm_ltc *ltc) +{ + struct nvkm_device *device = ltc->subdev.device; + struct iommu_fwspec *spec; + + nvkm_wr32(device, 0x17e27c, ltc->ltc_nr); + nvkm_wr32(device, 0x17e000, ltc->ltc_nr); + nvkm_wr32(device, 0x100800, ltc->ltc_nr); + + spec = dev_iommu_fwspec_get(device->dev); + if (spec) { + u32 sid = spec->ids[0] & 0xffff; + + /* stream ID */ + nvkm_wr32(device, 0x160000, sid << 2); + } +} + +static const struct nvkm_ltc_func +gp10b_ltc = { + .oneinit = gp100_ltc_oneinit, + .init = gp10b_ltc_init, + .intr = gp100_ltc_intr, + .cbc_clear = gm107_ltc_cbc_clear, + .cbc_wait = gm107_ltc_cbc_wait, + .zbc = 16, + .zbc_clear_color = gm107_ltc_zbc_clear_color, + .zbc_clear_depth = gm107_ltc_zbc_clear_depth, + .zbc_clear_stencil = gp102_ltc_zbc_clear_stencil, + .invalidate = gf100_ltc_invalidate, + .flush = gf100_ltc_flush, +}; + +int +gp10b_ltc_new(struct nvkm_device *device, int index, struct nvkm_ltc **pltc) +{ + return nvkm_ltc_new_(&gp10b_ltc, device, index, pltc); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h index 2fcf18e46ce3..eca5a711b1b8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h @@ -46,4 +46,6 @@ void gm107_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32); int gp100_ltc_oneinit(struct nvkm_ltc *); void gp100_ltc_init(struct nvkm_ltc *); void gp100_ltc_intr(struct nvkm_ltc *); + +void gp102_ltc_zbc_clear_stencil(struct nvkm_ltc *, int, const u32); #endif -- cgit v1.2.3 From d7ca5ddf585e20e879e3ebe3e5be0a0477b700b8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 9 Dec 2019 13:00:05 +0100 Subject: drm/nouveau/ce/gp10b: Use correct copy engine gp10b uses the new engine enumeration mechanism introduced in the Pascal architecture. As a result, the copy engine, which used to be at index 2 for prior Tegra GPU instantiations, has now moved to index 0. Fix up the index and also use the gp100 variant of the copy engine class because on gp10b the PASCAL_DMA_COPY_B class is not supported. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 231ec0073af3..eba450e689b2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2387,7 +2387,7 @@ nv13b_chipset = { .pmu = gm20b_pmu_new, .timer = gk20a_timer_new, .top = gk104_top_new, - .ce[2] = gp102_ce_new, + .ce[0] = gp100_ce_new, .dma = gf119_dma_new, .fifo = gp10b_fifo_new, .gr = gp10b_gr_new, -- cgit v1.2.3 From 2574c809d7c0f07f11fdefd9894e51e126ee1d66 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 30 Dec 2019 10:46:28 +0800 Subject: drm/nouveau/kms/nv04-nv4x: Use match_string() helper to simplify the code match_string() returns the array index of a matching string. Use it instead of the open-coded implementation. Signed-off-by: YueHaibing Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 03466f04c741..3a9489ed6544 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -644,16 +644,13 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, int i; if (nouveau_tv_norm) { - for (i = 0; i < num_tv_norms; i++) { - if (!strcmp(nv17_tv_norm_names[i], nouveau_tv_norm)) { - tv_enc->tv_norm = i; - break; - } - } - - if (i == num_tv_norms) + i = match_string(nv17_tv_norm_names, num_tv_norms, + nouveau_tv_norm); + if (i < 0) NV_WARN(drm, "Invalid TV norm setting \"%s\"\n", nouveau_tv_norm); + else + tv_enc->tv_norm = i; } drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names); -- cgit v1.2.3 From 2cf3c8bc47d4f6718acc0b863ff3aa7c9d80d60c Mon Sep 17 00:00:00 2001 From: Wambui Karuga Date: Thu, 2 Jan 2020 15:25:48 +0300 Subject: drm/nouveau/fb/gf100-: declare constants as unsigned long long. Explicitly declare constants as unsigned long long to address the following sparse warnings: warning: constant is so big it is long v2: convert to unsigned long long for compatibility with 32-bit architectures. Signed-off-by: Wambui Karuga Suggested by: lia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index ac87a3b6b7c9..ba43fe158b22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -655,7 +655,7 @@ gf100_ram_new_(const struct nvkm_ram_func *func, static const struct nvkm_ram_func gf100_ram = { - .upper = 0x0200000000, + .upper = 0x0200000000ULL, .probe_fbp = gf100_ram_probe_fbp, .probe_fbp_amount = gf100_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c index 70a06e3cd55a..d97fa43efb91 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c @@ -43,7 +43,7 @@ gf108_ram_probe_fbp_amount(const struct nvkm_ram_func *func, u32 fbpao, static const struct nvkm_ram_func gf108_ram = { - .upper = 0x0200000000, + .upper = 0x0200000000ULL, .probe_fbp = gf100_ram_probe_fbp, .probe_fbp_amount = gf108_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 456aed1f2a02..d350d92852d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -1698,7 +1698,7 @@ gk104_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, static const struct nvkm_ram_func gk104_ram = { - .upper = 0x0200000000, + .upper = 0x0200000000ULL, .probe_fbp = gf100_ram_probe_fbp, .probe_fbp_amount = gf108_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c index 27c68e3f9772..be91da854dca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c @@ -33,7 +33,7 @@ gm107_ram_probe_fbp(const struct nvkm_ram_func *func, static const struct nvkm_ram_func gm107_ram = { - .upper = 0x1000000000, + .upper = 0x1000000000ULL, .probe_fbp = gm107_ram_probe_fbp, .probe_fbp_amount = gf108_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c index 6b0cac1fe7b4..8f91ea91ee25 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c @@ -48,7 +48,7 @@ gm200_ram_probe_fbp_amount(const struct nvkm_ram_func *func, u32 fbpao, static const struct nvkm_ram_func gm200_ram = { - .upper = 0x1000000000, + .upper = 0x1000000000ULL, .probe_fbp = gm107_ram_probe_fbp, .probe_fbp_amount = gm200_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c index adb62a6beb63..378f6fb70990 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c @@ -79,7 +79,7 @@ gp100_ram_probe_fbpa(struct nvkm_device *device, int fbpa) static const struct nvkm_ram_func gp100_ram = { - .upper = 0x1000000000, + .upper = 0x1000000000ULL, .probe_fbp = gm107_ram_probe_fbp, .probe_fbp_amount = gm200_ram_probe_fbp_amount, .probe_fbpa_amount = gp100_ram_probe_fbpa, -- cgit v1.2.3 From cd04e4ffd5c4d05d2a3eb0827fe481274dc4a8ef Mon Sep 17 00:00:00 2001 From: Wambui Karuga Date: Tue, 31 Dec 2019 23:56:07 +0300 Subject: drm/nouveau/kms/nv04: remove set but unused variable. The local variable `pclks` is defined and set but not used and can therefore be removed. Issue found by coccinelle. Signed-off-by: Wambui Karuga Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv04/arb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c index 362495535e69..f607a04d262d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/arb.c +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -54,7 +54,7 @@ static void nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) { int pagemiss, cas, width, bpp; - int nvclks, mclks, pclks, crtpagemiss; + int nvclks, mclks, crtpagemiss; int found, mclk_extra, mclk_loop, cbs, m1, p1; int mclk_freq, pclk_freq, nvclk_freq; int us_m, us_n, us_p, crtc_drain_rate; @@ -69,7 +69,6 @@ nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) bpp = arb->bpp; cbs = 128; - pclks = 2; nvclks = 10; mclks = 13 + cas; mclk_extra = 3; -- cgit v1.2.3 From b4229fc67d9b9d8910ad32c508fd94518bd01194 Mon Sep 17 00:00:00 2001 From: Wambui Karuga Date: Tue, 31 Dec 2019 23:57:34 +0300 Subject: drm/nouveau: use NULL for pointer assignment. Replace the use of 0 in the pointer assignment with NULL to address the following sparse warning: drivers/gpu/drm/nouveau/nouveau_hwmon.c:744:29: warning: Using plain integer as NULL pointer Signed-off-by: Wambui Karuga Reviewed-by: Daniel Vetter Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_hwmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c index d445c6f3fece..1c3104d20571 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hwmon.c +++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c @@ -741,7 +741,7 @@ nouveau_hwmon_init(struct drm_device *dev) special_groups[i++] = &pwm_fan_sensor_group; } - special_groups[i] = 0; + special_groups[i] = NULL; hwmon_dev = hwmon_device_register_with_info(dev->dev, "nouveau", dev, &nouveau_chip_info, special_groups); -- cgit v1.2.3 From 72ecb0a6ce89dd7f9d0f8171a45b0ed814b0f9a8 Mon Sep 17 00:00:00 2001 From: James Jones Date: Mon, 16 Dec 2019 16:56:12 -0800 Subject: drm/nouveau: Fix ttm move init with multiple GPUs The pointer used to walk the table of move ops and pick the right one for the current GPU was declared static, meaning its state was carried over between invocations of the function, and also made the function non-rentrant and thread-unsafe. Since the table is ordered such that newer GPU methods are listed first, the result of this was that initializing newer GPUs after older GPUs would result in no suitable ttm move acceleration operations being found, and ttm would fall back to CPU blits on the older GPUs. This change declares the walking pointer separately from the table and makes it non-static to fix the logic. Signed-off-by: James Jones Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index f8015e0318d7..1b62ccc57aef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1162,7 +1162,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, void nouveau_bo_move_init(struct nouveau_drm *drm) { - static const struct { + static const struct _method_table { const char *name; int engine; s32 oclass; @@ -1192,7 +1192,8 @@ nouveau_bo_move_init(struct nouveau_drm *drm) { "M2MF", 0, 0x0039, nv04_bo_move_m2mf, nv04_bo_move_init }, {}, { "CRYPT", 0, 0x88b4, nv98_bo_move_exec, nv50_bo_move_init }, - }, *mthd = _methods; + }; + const struct _method_table *mthd = _methods; const char *name = "CPU"; int ret; -- cgit v1.2.3 From 176ada03e3c2cc0e0d725ea4626dfebec681578f Mon Sep 17 00:00:00 2001 From: James Jones Date: Mon, 16 Dec 2019 16:58:05 -0800 Subject: drm/nouveau/mmu: Add correct turing page kinds Turing introduced a new simplified page kind scheme, reducing the number of possible page kinds from 256 to 16. It also is the first NVIDIA GPU in which the highest possible page kind value is not reserved as an "invalid" page kind. To address this, the invalid page kind is made an explicit property of the MMU HAL, and a new table of page kinds is added to the tu102 MMU HAL. One hardware change not addressed here is that 0x00 is technically no longer a supported page kind, and pitch surfaces are instead intended to share the block-linear generic page kind 0x06. However, because that will be a rather invasive change to nouveau and 0x00 still works fine in practice on Turing hardware, addressing this new behavior is deferred. Signed-off-by: James Jones Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/if0008.h | 2 +- drivers/gpu/drm/nouveau/include/nvif/mmu.h | 4 ++-- drivers/gpu/drm/nouveau/nvif/mmu.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h | 8 ++++---- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c | 16 +++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c | 7 +++++-- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c | 6 +++--- 12 files changed, 43 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0008.h b/drivers/gpu/drm/nouveau/include/nvif/if0008.h index 8450127420f5..c21d09f04f1d 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/if0008.h +++ b/drivers/gpu/drm/nouveau/include/nvif/if0008.h @@ -35,7 +35,7 @@ struct nvif_mmu_type_v0 { struct nvif_mmu_kind_v0 { __u8 version; - __u8 pad01[1]; + __u8 kind_inv; __u16 count; __u8 data[]; }; diff --git a/drivers/gpu/drm/nouveau/include/nvif/mmu.h b/drivers/gpu/drm/nouveau/include/nvif/mmu.h index 747ecf67e403..cec1e88a0a05 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/mmu.h +++ b/drivers/gpu/drm/nouveau/include/nvif/mmu.h @@ -7,6 +7,7 @@ struct nvif_mmu { u8 dmabits; u8 heap_nr; u8 type_nr; + u8 kind_inv; u16 kind_nr; s32 mem; @@ -36,9 +37,8 @@ void nvif_mmu_fini(struct nvif_mmu *); static inline bool nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind) { - const u8 invalid = mmu->kind_nr - 1; if (kind) { - if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid) + if (kind >= mmu->kind_nr || mmu->kind[kind] == mmu->kind_inv) return false; } return true; diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c b/drivers/gpu/drm/nouveau/nvif/mmu.c index 5641bda2046d..47efc408efa6 100644 --- a/drivers/gpu/drm/nouveau/nvif/mmu.c +++ b/drivers/gpu/drm/nouveau/nvif/mmu.c @@ -121,6 +121,7 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu) kind, argc); if (ret == 0) memcpy(mmu->kind, kind->data, kind->count); + mmu->kind_inv = kind->kind_inv; kfree(kind); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c index 2d075246dc46..2cd5ec81c0d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c @@ -30,7 +30,7 @@ * The value 0xff represents an invalid storage type. */ const u8 * -gf100_mmu_kind(struct nvkm_mmu *mmu, int *count) +gf100_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid) { static const u8 kind[256] = { @@ -69,6 +69,7 @@ gf100_mmu_kind(struct nvkm_mmu *mmu, int *count) }; *count = ARRAY_SIZE(kind); + *invalid = 0xff; return kind; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c index dbf644ebac97..83990c83f9f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c @@ -27,7 +27,7 @@ #include const u8 * -gm200_mmu_kind(struct nvkm_mmu *mmu, int *count) +gm200_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid) { static const u8 kind[256] = { @@ -65,6 +65,7 @@ gm200_mmu_kind(struct nvkm_mmu *mmu, int *count) 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff }; *count = ARRAY_SIZE(kind); + *invalid = 0xff; return kind; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c index db3dfbbb2aa0..c0083ddda65a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c @@ -27,7 +27,7 @@ #include const u8 * -nv50_mmu_kind(struct nvkm_mmu *base, int *count) +nv50_mmu_kind(struct nvkm_mmu *base, int *count, u8 *invalid) { /* 0x01: no bank swizzle * 0x02: bank swizzled @@ -57,6 +57,7 @@ nv50_mmu_kind(struct nvkm_mmu *base, int *count) 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x7f, 0x7f }; *count = ARRAY_SIZE(kind); + *invalid = 0x7f; return kind; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h index 07f2fcd18f3d..479b02344271 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h @@ -35,17 +35,17 @@ struct nvkm_mmu_func { u32 pd_offset; } vmm; - const u8 *(*kind)(struct nvkm_mmu *, int *count); + const u8 *(*kind)(struct nvkm_mmu *, int *count, u8 *invalid); bool kind_sys; }; extern const struct nvkm_mmu_func nv04_mmu; -const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count); +const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid); -const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count); +const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid); -const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *); +const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *, u8 *); struct nvkm_mmu_pt { union { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c index c0db0ce10cba..b21e82eb0916 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c @@ -1,5 +1,6 @@ /* * Copyright 2018 Red Hat Inc. + * Copyright 2019 NVIDIA Corporation. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,13 +27,26 @@ #include +const u8 * +tu102_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid) +{ + static const u8 + kind[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 */ + 0x06, 0x06, 0x02, 0x01, 0x03, 0x04, 0x05, 0x07, + }; + *count = ARRAY_SIZE(kind); + *invalid = 0x07; + return kind; +} + static const struct nvkm_mmu_func tu102_mmu = { .dma_bits = 47, .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, .vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, tu102_vmm_new }, - .kind = gm200_mmu_kind, + .kind = tu102_mmu_kind, .kind_sys = true, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c index 353f10f92b77..0e4b8941da37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c @@ -111,15 +111,17 @@ nvkm_ummu_kind(struct nvkm_ummu *ummu, void *argv, u32 argc) } *args = argv; const u8 *kind = NULL; int ret = -ENOSYS, count = 0; + u8 kind_inv = 0; if (mmu->func->kind) - kind = mmu->func->kind(mmu, &count); + kind = mmu->func->kind(mmu, &count, &kind_inv); if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { if (argc != args->v0.count * sizeof(*args->v0.data)) return -EINVAL; if (args->v0.count > count) return -EINVAL; + args->v0.kind_inv = kind_inv; memcpy(args->v0.data, kind, args->v0.count); } else return ret; @@ -157,9 +159,10 @@ nvkm_ummu_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, struct nvkm_mmu *mmu = device->mmu; struct nvkm_ummu *ummu; int ret = -ENOSYS, kinds = 0; + u8 unused = 0; if (mmu->func->kind) - mmu->func->kind(mmu, &kinds); + mmu->func->kind(mmu, &kinds, &unused); if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { args->v0.dmabits = mmu->dma_bits; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c index ab6424faf84c..6a2d9eb8e1ea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c @@ -247,7 +247,7 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, } *args = argv; struct nvkm_device *device = vmm->mmu->subdev.device; struct nvkm_memory *memory = map->memory; - u8 kind, priv, ro, vol; + u8 kind, kind_inv, priv, ro, vol; int kindn, aper, ret = -ENOSYS; const u8 *kindm; @@ -274,8 +274,8 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, if (WARN_ON(aper < 0)) return aper; - kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); - if (kind >= kindn || kindm[kind] == 0xff) { + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv); + if (kind >= kindn || kindm[kind] == kind_inv) { VMM_DEBUG(vmm, "kind %02x", kind); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c index b4f519768d5e..d86287565542 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c @@ -320,7 +320,7 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, } *args = argv; struct nvkm_device *device = vmm->mmu->subdev.device; struct nvkm_memory *memory = map->memory; - u8 kind, priv, ro, vol; + u8 kind, kind_inv, priv, ro, vol; int kindn, aper, ret = -ENOSYS; const u8 *kindm; @@ -347,8 +347,8 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, if (WARN_ON(aper < 0)) return aper; - kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); - if (kind >= kindn || kindm[kind] == 0xff) { + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv); + if (kind >= kindn || kindm[kind] == kind_inv) { VMM_DEBUG(vmm, "kind %02x", kind); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c index c98afe3134ee..2d89e27e8e9e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c @@ -235,7 +235,7 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, struct nvkm_device *device = vmm->mmu->subdev.device; struct nvkm_ram *ram = device->fb->ram; struct nvkm_memory *memory = map->memory; - u8 aper, kind, comp, priv, ro; + u8 aper, kind, kind_inv, comp, priv, ro; int kindn, ret = -ENOSYS; const u8 *kindm; @@ -278,8 +278,8 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, return -EINVAL; } - kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); - if (kind >= kindn || kindm[kind] == 0x7f) { + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv); + if (kind >= kindn || kindm[kind] == kind_inv) { VMM_DEBUG(vmm, "kind %02x", kind); return -EINVAL; } -- cgit v1.2.3 From 3613a9bea95a1470dd42e4ed1cc7d86ebe0a2dc0 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 8 Jan 2020 08:46:01 +0300 Subject: drm/nouveau/secboot/gm20b: initialize pointer in gm20b_secboot_new() We accidentally set "psb" which is a no-op instead of "*psb" so it generates a static checker warning. We should probably set it before the first error return so that it's always initialized. Fixes: 923f1bd27bf1 ("drm/nouveau/secboot/gm20b: add secure boot support") Signed-off-by: Dan Carpenter Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index 72690d80f0ad..32a584c4757f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -129,6 +129,7 @@ gm20b_secboot_new(struct nvkm_device *device, int index, struct gm200_secboot *gsb; struct nvkm_acr *acr; + *psb = NULL; acr = acr_r352_new(BIT(NVKM_SECBOOT_FALCON_FECS) | BIT(NVKM_SECBOOT_FALCON_PMU)); if (IS_ERR(acr)) @@ -137,10 +138,8 @@ gm20b_secboot_new(struct nvkm_device *device, int index, acr->optional_falcons = BIT(NVKM_SECBOOT_FALCON_PMU); gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); - if (!gsb) { - psb = NULL; + if (!gsb) return -ENOMEM; - } *psb = &gsb->base; ret = nvkm_secboot_ctor(&gm20b_secboot, acr, device, index, &gsb->base); -- cgit v1.2.3 From 4886c740c9bcc33da82f33367f19f7da23028190 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 7 Jan 2020 16:19:05 +1000 Subject: drm/nouveau/core: fix missing newline in fw loader error message Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index 092acdec2c39..8127eb345212 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -64,7 +64,7 @@ nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname, nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f); } - nvkm_error(subdev, "failed to load firmware \"%s\"", fwname); + nvkm_error(subdev, "failed to load firmware \"%s\"\n", fwname); return -ENOENT; } -- cgit v1.2.3 From 0514a6b7d9c838244d5b0970523dff4b87993a64 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 9 Jan 2020 15:46:29 +1000 Subject: drm/nouveau/fault/tu102: define nvkm_fault_func.pin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c index fa1dfe5692b0..45a6a68b9f48 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c @@ -154,6 +154,7 @@ tu102_fault = { .buffer.nr = 2, .buffer.entry_size = 32, .buffer.info = tu102_fault_buffer_info, + .buffer.pin = gp100_fault_buffer_pin, .buffer.init = tu102_fault_buffer_init, .buffer.fini = tu102_fault_buffer_fini, .buffer.intr = tu102_fault_buffer_intr, -- cgit v1.2.3 From fef1c0ef7074477974c893535b90c7ac97012b95 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 31 Oct 2019 15:49:48 +1000 Subject: drm/nouveau/gr/gf100-: remove dtor Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 2 -- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index c578deb5867a..0ce7e9cc847a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2031,8 +2031,6 @@ gf100_gr_dtor(struct nvkm_gr *base) { struct gf100_gr *gr = gf100_gr(base); - if (gr->func->dtor) - gr->func->dtor(gr); kfree(gr->data); nvkm_falcon_del(&gr->gpccs.falcon); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index fafdd0bbea9b..5c6a855acae5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -157,7 +157,6 @@ struct gf100_gr_func_zbc { }; struct gf100_gr_func { - void (*dtor)(struct gf100_gr *); void (*oneinit_tiles)(struct gf100_gr *); void (*oneinit_sm_id)(struct gf100_gr *); int (*init)(struct gf100_gr *); -- cgit v1.2.3 From 7adc77aa0e11f25b0e762859219c70852cd8d56f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 9 Jan 2020 11:46:15 +1000 Subject: drm/nouveau/gr/gk20a,gm200-: add terminators to method lists read from fw Method init is typically ordered by class in the FW image as ThreeD, TwoD, Compute. Due to a bug in parsing the FW into our internal format, we've been accidentally sending Twod + Compute methods to the ThreeD class, as well as Compute methods to the TwoD class - oops. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 500cb08dd608..b57ab5cea9a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -143,23 +143,24 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, nent = (fuc.size / sizeof(struct gk20a_fw_av)); - pack = vzalloc((sizeof(*pack) * max_classes) + - (sizeof(*init) * (nent + 1))); + pack = vzalloc((sizeof(*pack) * (max_classes + 1)) + + (sizeof(*init) * (nent + max_classes + 1))); if (!pack) { ret = -ENOMEM; goto end; } - init = (void *)(pack + max_classes); + init = (void *)(pack + max_classes + 1); - for (i = 0; i < nent; i++) { - struct gf100_gr_init *ent = &init[i]; + for (i = 0; i < nent; i++, init++) { struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; u32 class = av->addr & 0xffff; u32 addr = (av->addr & 0xffff0000) >> 14; if (prevclass != class) { - pack[classidx].init = ent; + if (prevclass) /* Add terminator to the method list. */ + init++; + pack[classidx].init = init; pack[classidx].type = class; prevclass = class; if (++classidx >= max_classes) { @@ -169,10 +170,10 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, } } - ent->addr = addr; - ent->data = av->data; - ent->count = 1; - ent->pitch = 1; + init->addr = addr; + init->data = av->data; + init->count = 1; + init->pitch = 1; } *ppack = pack; -- cgit v1.2.3 From 3c47e381d6514ed8043ef0e3ed69ce287d05b3a4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 1 Aug 2019 11:59:12 +1000 Subject: drm/nouveau/gr/gv100-: modify gr init to match newer version of RM Will be used as a basis for implementing changes needed for Turing. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 12 +++--------- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 11 +++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 19 ++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 85f2d1e950e8..284d7e022213 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1324,10 +1324,8 @@ gf100_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) void gf100_grctx_generate_floorsweep(struct gf100_gr *gr) { - struct nvkm_device *device = gr->base.engine.subdev.device; const struct gf100_grctx_func *func = gr->func->grctx; - int gpc, sm, i, j; - u32 data; + int sm; for (sm = 0; sm < gr->sm_nr; sm++) { func->sm_id(gr, gr->sm[sm].gpc, gr->sm[sm].tpc, sm); @@ -1335,12 +1333,8 @@ gf100_grctx_generate_floorsweep(struct gf100_gr *gr) func->tpc_nr(gr, gr->sm[sm].gpc); } - for (gpc = 0, i = 0; i < 4; i++) { - for (data = 0, j = 0; j < 8 && gpc < gr->gpc_nr; j++, gpc++) - data |= gr->tpc_nr[gpc] << (j * 4); - nvkm_wr32(device, 0x406028 + (i * 4), data); - nvkm_wr32(device, 0x405870 + (i * 4), data); - } + gf100_gr_init_num_tpc_per_gpc(gr, false, true); + gf100_gr_init_num_tpc_per_gpc(gr, true, false); if (func->r4060a8) func->r4060a8(gr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 0990765ef191..313f0080bbdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -67,14 +67,14 @@ gv100_grctx_generate_attrib(struct gf100_grctx *info) const u32 attrib = grctx->attrib_nr; const u32 gfxp = grctx->gfxp_nr; const int s = 12; - const int max_batches = 0xffff; u32 size = grctx->alpha_nr_max * gr->tpc_total; u32 ao = 0; u32 bo = ao + size; int gpc, ppc, b, n = 0; - size += grctx->gfxp_nr * gr->tpc_total; - size = ((size * 0x20) + 128) & ~127; + for (gpc = 0; gpc < gr->gpc_nr; gpc++) + size += grctx->gfxp_nr * gr->ppc_nr[gpc] * gr->ppc_tpc_max; + size = ((size * 0x20) + 127) & ~127; b = mmio_vram(info, size, (1 << s), false); mmio_refn(info, 0x418810, 0x80000000, s, b); @@ -84,13 +84,12 @@ gv100_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, 0x419e04, 0x80000000 | size >> 7); mmio_wr32(info, 0x405830, attrib); mmio_wr32(info, 0x40585c, alpha); - mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches); for (gpc = 0; gpc < gr->gpc_nr; gpc++) { for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) { const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc]; - const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc]; - const u32 gs = gfxp * gr->ppc_tpc_nr[gpc][ppc]; + const u32 bs = attrib * gr->ppc_tpc_max; + const u32 gs = gfxp * gr->ppc_tpc_max; const u32 u = 0x418ea0 + (n * 0x04); const u32 o = PPC_UNIT(gpc, ppc, 0); if (!(gr->ppc_mask[gpc] & (1 << ppc))) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 0ce7e9cc847a..6aefb2bb6e06 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2169,6 +2169,23 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return 0; } +void +gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *gr, bool pd, bool ds) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + int gpc, i, j; + u32 data; + + for (gpc = 0, i = 0; i < 4; i++) { + for (data = 0, j = 0; j < 8 && gpc < gr->gpc_nr; j++, gpc++) + data |= gr->tpc_nr[gpc] << (j * 4); + if (pd) + nvkm_wr32(device, 0x406028 + (i * 4), data); + if (ds) + nvkm_wr32(device, 0x405870 + (i * 4), data); + } +} + void gf100_gr_init_400054(struct gf100_gr *gr) { @@ -2336,8 +2353,8 @@ gf100_gr_init(struct gf100_gr *gr) if (gr->func->init_40601c) gr->func->init_40601c(gr); - nvkm_wr32(device, 0x404490, 0xc0000000); nvkm_wr32(device, 0x406018, 0xc0000000); + nvkm_wr32(device, 0x404490, 0xc0000000); if (gr->func->init_sked_hww_esr) gr->func->init_sked_hww_esr(gr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 5c6a855acae5..5cd5ab76926f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -216,6 +216,7 @@ void gf100_gr_init_419eb4(struct gf100_gr *); void gf100_gr_init_tex_hww_esr(struct gf100_gr *, int, int); void gf100_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gf100_gr_init_400054(struct gf100_gr *); +void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *, bool, bool); extern const struct gf100_gr_func_zbc gf100_gr_zbc; void gf117_gr_init_zcull(struct gf100_gr *); -- cgit v1.2.3 From 1eb013473bff5f95b6fe1ca4dd7deda47257b9c2 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 10 Jan 2020 14:32:01 +0800 Subject: drm/nouveau: Fix copy-paste error in nouveau_fence_wait_uevent_handler Like other cases, it should use rcu protected 'chan' rather than 'fence->channel' in nouveau_fence_wait_uevent_handler. Fixes: 0ec5f02f0e2c ("drm/nouveau: prevent stale fence->channel pointers, and protect with rcu") Signed-off-by: YueHaibing Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 9118df035b28..70bb6bb97af8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -156,7 +156,7 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify) fence = list_entry(fctx->pending.next, typeof(*fence), head); chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); - if (nouveau_fence_update(fence->channel, fctx)) + if (nouveau_fence_update(chan, fctx)) ret = NVIF_NOTIFY_DROP; } spin_unlock_irqrestore(&fctx->lock, flags); -- cgit v1.2.3 From 2e4534a22794746b11a794b2229b8d58797eccce Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 10 Jan 2020 15:28:37 +0800 Subject: drm/nouveau/drm/ttm: Remove set but not used variable 'mem' drivers/gpu/drm/nouveau/nouveau_ttm.c: In function nouveau_vram_manager_new: drivers/gpu/drm/nouveau/nouveau_ttm.c:66:22: warning: variable mem set but not used [-Wunused-but-set-variable] drivers/gpu/drm/nouveau/nouveau_ttm.c: In function nouveau_gart_manager_new: drivers/gpu/drm/nouveau/nouveau_ttm.c:106:22: warning: variable mem set but not used [-Wunused-but-set-variable] They are not used any more, so remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 77a0c6ad3cef..7ca0a2498532 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -63,14 +63,12 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_drm *drm = nouveau_bdev(bo->bdev); - struct nouveau_mem *mem; int ret; if (drm->client.device.info.ram_size == 0) return -ENOMEM; ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg); - mem = nouveau_mem(reg); if (ret) return ret; @@ -103,11 +101,9 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_drm *drm = nouveau_bdev(bo->bdev); - struct nouveau_mem *mem; int ret; ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg); - mem = nouveau_mem(reg); if (ret) return ret; -- cgit v1.2.3 From 409d659fe11d778a8f505f909815bc867a27ecbf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 14 Jan 2020 11:31:01 +1000 Subject: drm/nouveau/disp/dp: fix typo when determining failsafe link configuration Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 818d21bd28d3..3800aeb507d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -365,7 +365,7 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) * and it's better to have a failed modeset than that. */ for (cfg = nvkm_dp_rates; cfg->rate; cfg++) { - if (cfg->nr <= outp_nr && cfg->nr <= outp_bw) { + if (cfg->nr <= outp_nr && cfg->bw <= outp_bw) { /* Try to respect sink limits too when selecting * lowest link configuration. */ -- cgit v1.2.3 From 633cc9beeb6f9b5fa2f17a2a9d0e2790cb6c3de7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/fault/gv100-: fix memory leak on module unload Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c index 1c4b852b26c3..f6dca97140d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c @@ -146,6 +146,7 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev) struct nvkm_fault *fault = nvkm_fault(subdev); int i; + nvkm_notify_fini(&fault->nrpfb); nvkm_event_fini(&fault->event); for (i = 0; i < fault->buffer_nr; i++) { -- cgit v1.2.3 From 5a4b98cde434da25ff25171974036a492c023bce Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: move fetching of configuration until first use We want to be able to register falcons with ACR during the constructor for the subdev it belongs to, however, we may not have access to the falcon's registers prior to DEVINIT. Delay touching registers until the first time the falcon is acquired. This may temporarily break secboot on non-production boards due to not being able to determine whether the falcon is in debug or production mode, the new ACR subdev will not have this issue, and it's not a use-case that's terribly important for bisectability. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 2 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 95 ++++++++++++---------- 2 files changed, 55 insertions(+), 42 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 23b582d696c6..087ef96fc123 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -23,6 +23,8 @@ struct nvkm_falcon { struct mutex mutex; struct mutex dmem_mutex; + bool oneinit; + const struct nvkm_subdev *user; u8 version; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 366c87de6e72..3ed421058b08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -134,52 +134,13 @@ nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) return falcon->func->clear_interrupt(falcon, mask); } -void -nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) -{ - if (unlikely(!falcon)) - return; - - mutex_lock(&falcon->mutex); - if (falcon->user == user) { - nvkm_debug(falcon->user, "released %s falcon\n", falcon->name); - falcon->user = NULL; - } - mutex_unlock(&falcon->mutex); -} - -int -nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) -{ - mutex_lock(&falcon->mutex); - if (falcon->user) { - nvkm_error(user, "%s falcon already acquired by %s!\n", - falcon->name, nvkm_subdev_name[falcon->user->index]); - mutex_unlock(&falcon->mutex); - return -EBUSY; - } - - nvkm_debug(user, "acquired %s falcon\n", falcon->name); - falcon->user = user; - mutex_unlock(&falcon->mutex); - return 0; -} - -void -nvkm_falcon_ctor(const struct nvkm_falcon_func *func, - struct nvkm_subdev *subdev, const char *name, u32 addr, - struct nvkm_falcon *falcon) +static int +nvkm_falcon_oneinit(struct nvkm_falcon *falcon) { + const struct nvkm_subdev *subdev = falcon->owner; u32 debug_reg; u32 reg; - falcon->func = func; - falcon->owner = subdev; - falcon->name = name; - falcon->addr = addr; - mutex_init(&falcon->mutex); - mutex_init(&falcon->dmem_mutex); - reg = nvkm_falcon_rd32(falcon, 0x12c); falcon->version = reg & 0xf; falcon->secret = (reg >> 4) & 0x3; @@ -218,6 +179,56 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func, u32 val = nvkm_falcon_rd32(falcon, debug_reg); falcon->debug = (val >> 20) & 0x1; } + + return 0; +} + +void +nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) +{ + if (unlikely(!falcon)) + return; + + mutex_lock(&falcon->mutex); + if (falcon->user == user) { + nvkm_debug(falcon->user, "released %s falcon\n", falcon->name); + falcon->user = NULL; + } + mutex_unlock(&falcon->mutex); +} + +int +nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) +{ + int ret = 0; + + mutex_lock(&falcon->mutex); + if (falcon->user) { + nvkm_error(user, "%s falcon already acquired by %s!\n", + falcon->name, nvkm_subdev_name[falcon->user->index]); + mutex_unlock(&falcon->mutex); + return -EBUSY; + } + + nvkm_debug(user, "acquired %s falcon\n", falcon->name); + if (!falcon->oneinit) + ret = nvkm_falcon_oneinit(falcon); + falcon->user = user; + mutex_unlock(&falcon->mutex); + return ret; +} + +void +nvkm_falcon_ctor(const struct nvkm_falcon_func *func, + struct nvkm_subdev *subdev, const char *name, u32 addr, + struct nvkm_falcon *falcon) +{ + falcon->func = func; + falcon->owner = subdev; + falcon->name = name; + falcon->addr = addr; + mutex_init(&falcon->mutex); + mutex_init(&falcon->dmem_mutex); } void -- cgit v1.2.3 From de048192130db2c02e3f16d49ed4cc1f20e6ba90 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: fetch PRI address from TOP if not provided by constructor Shortcut to avoid each subdev having to do this itself. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 3ed421058b08..8f4c3aca2233 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -22,6 +22,7 @@ #include "priv.h" #include +#include void nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, @@ -141,6 +142,12 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon) u32 debug_reg; u32 reg; + if (!falcon->addr) { + falcon->addr = nvkm_top_addr(subdev->device, subdev->index); + if (WARN_ON(!falcon->addr)) + return -ENODEV; + } + reg = nvkm_falcon_rd32(falcon, 0x12c); falcon->version = reg & 0xf; falcon->secret = (reg >> 4) & 0x3; -- cgit v1.2.3 From a128bbfacc065bca59426afae9cad91b9d77f6aa Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: export existing funcs These will be used in upcoming commits which will provide more customisation. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 20 ++++++++++++++++++++ .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 5 ++--- drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 7 +++++++ drivers/gpu/drm/nouveau/nvkm/falcon/priv.h | 6 +----- drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 22 +++++++++++----------- 5 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h new file mode 100644 index 000000000000..0fa6e09b57ee --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -0,0 +1,20 @@ +#ifndef __NVKM_FALCON_H__ +#define __NVKM_FALCON_H__ +#include + +int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner, + const char *name, u32 addr, struct nvkm_falcon *); +void nvkm_falcon_dtor(struct nvkm_falcon *); + +void nvkm_falcon_v1_load_imem(struct nvkm_falcon *, + void *, u32, u32, u16, u8, bool); +void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); +void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); +void nvkm_falcon_v1_bind_context(struct nvkm_falcon *, struct nvkm_memory *); +int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32); +int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32); +void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr); +void nvkm_falcon_v1_start(struct nvkm_falcon *); +int nvkm_falcon_v1_enable(struct nvkm_falcon *); +void nvkm_falcon_v1_disable(struct nvkm_falcon *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 087ef96fc123..b7733694faed 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ -#ifndef __NVKM_FALCON_H__ -#define __NVKM_FALCON_H__ +#ifndef __NVKM_FLCNEN_H__ +#define __NVKM_FLCNEN_H__ #define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine) #include struct nvkm_fifo_chan; @@ -124,5 +124,4 @@ int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32); int nvkm_falcon_enable(struct nvkm_falcon *); void nvkm_falcon_disable(struct nvkm_falcon *); int nvkm_falcon_reset(struct nvkm_falcon *); - #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 8f4c3aca2233..fc66cdb82572 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -226,6 +226,11 @@ nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) } void +nvkm_falcon_dtor(struct nvkm_falcon *falcon) +{ +} + +int nvkm_falcon_ctor(const struct nvkm_falcon_func *func, struct nvkm_subdev *subdev, const char *name, u32 addr, struct nvkm_falcon *falcon) @@ -236,12 +241,14 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func, falcon->addr = addr; mutex_init(&falcon->mutex); mutex_init(&falcon->dmem_mutex); + return 0; } void nvkm_falcon_del(struct nvkm_falcon **pfalcon) { if (*pfalcon) { + nvkm_falcon_dtor(*pfalcon); kfree(*pfalcon); *pfalcon = NULL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h index 900fe1d37b4d..466188752eb0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h @@ -1,9 +1,5 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_FALCON_PRIV_H__ #define __NVKM_FALCON_PRIV_H__ -#include - -void -nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *, - const char *, u32, struct nvkm_falcon *); +#include #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 6d978feebbd7..49ea8a54061f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -25,7 +25,7 @@ #include #include -static void +void nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, u32 size, u16 tag, u8 port, bool secure) { @@ -91,9 +91,9 @@ nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start, static const u32 EMEM_START_ADDR = 0x1000000; -static void +void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, - u32 size, u8 port) + u32 size, u8 port) { u8 rem = size % 4; int i; @@ -148,7 +148,7 @@ nvkm_falcon_v1_read_emem(struct nvkm_falcon *falcon, u32 start, u32 size, } } -static void +void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, void *data) { @@ -179,7 +179,7 @@ nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, } } -static void +void nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) { struct nvkm_device *device = falcon->owner->device; @@ -271,13 +271,13 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) } } -static void +void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) { nvkm_falcon_wr32(falcon, 0x104, start_addr); } -static void +void nvkm_falcon_v1_start(struct nvkm_falcon *falcon) { u32 reg = nvkm_falcon_rd32(falcon, 0x100); @@ -288,7 +288,7 @@ nvkm_falcon_v1_start(struct nvkm_falcon *falcon) nvkm_falcon_wr32(falcon, 0x100, 0x2); } -static int +int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) { struct nvkm_device *device = falcon->owner->device; @@ -301,7 +301,7 @@ nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) return 0; } -static int +int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) { struct nvkm_device *device = falcon->owner->device; @@ -330,7 +330,7 @@ falcon_v1_wait_idle(struct nvkm_falcon *falcon) return 0; } -static int +int nvkm_falcon_v1_enable(struct nvkm_falcon *falcon) { struct nvkm_device *device = falcon->owner->device; @@ -352,7 +352,7 @@ nvkm_falcon_v1_enable(struct nvkm_falcon *falcon) return 0; } -static void +void nvkm_falcon_v1_disable(struct nvkm_falcon *falcon) { /* disable IRQs and wait for any previous code to complete */ -- cgit v1.2.3 From 5ff41544fc810df95ae585959334cc56c2270ccb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/core: output fw size in debug messages Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index 8127eb345212..50f2c3449afd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -57,7 +57,8 @@ nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname, snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); if (!firmware_request_nowarn(fw, f, device->dev)) { - nvkm_debug(subdev, "firmware \"%s\" loaded\n", f); + nvkm_debug(subdev, "firmware \"%s\" loaded - " + "%zu byte(s)\n", f, (*fw)->size); return i; } -- cgit v1.2.3 From 47c8f8e1a225b227805045c997ffdda8c78e57b6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/core: add a macro to better handle multiple firmware versions Will be used in upcoming commits to allow subdevs to better customise themselves based on which (if any) firmware is available. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/core/firmware.h | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h index 383370c32428..55ea2b39a8a8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_FIRMWARE_H__ #define __NVKM_FIRMWARE_H__ +#include #include int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname, @@ -9,4 +10,43 @@ int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname, int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, const struct firmware **); void nvkm_firmware_put(const struct firmware *); + +#define nvkm_firmware_load(s,l,o,p...) ({ \ + struct nvkm_subdev *_s = (s); \ + const char *_opts = (o); \ + char _option[32]; \ + typeof(l[0]) *_list = (l), *_next, *_fwif = NULL; \ + int _ver, _fwv, _ret = 0; \ + \ + snprintf(_option, sizeof(_option), "Nv%sFw", _opts); \ + _ver = nvkm_longopt(_s->device->cfgopt, _option, -2); \ + if (_ver >= -1) { \ + for (_next = _list; !_fwif && _next->load; _next++) { \ + if (_next->version == _ver) \ + _fwif = _next; \ + } \ + _ret = _fwif ? 0 : -EINVAL; \ + } \ + \ + if (_ret == 0) { \ + snprintf(_option, sizeof(_option), "Nv%sFwVer", _opts); \ + _fwv = _fwif ? _fwif->version : -1; \ + _ver = nvkm_longopt(_s->device->cfgopt, _option, _fwv); \ + for (_next = _fwif ? _fwif : _list; _next->load; _next++) { \ + _fwv = (_ver >= 0) ? _ver : _next->version; \ + _ret = _next->load(p, _fwv, _next); \ + if (_ret == 0 || _ver >= 0) { \ + _fwif = _next; \ + break; \ + } \ + } \ + } \ + \ + if (_ret) { \ + nvkm_error(_s, "failed to load firmware\n"); \ + _fwif = ERR_PTR(_ret); \ + } \ + \ + _fwif; \ +}) #endif -- cgit v1.2.3 From f25709f9aeb3c5183167b57df278cdecce3c9740 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/core: add representation of generic binary objects Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/os.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index 029a416197db..d7ba3205207f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -21,4 +21,17 @@ iowrite32_native(lower_32_bits(_v), &_p[0]); \ iowrite32_native(upper_32_bits(_v), &_p[1]); \ } while(0) + +struct nvkm_blob { + void *data; + u32 size; +}; + +static inline void +nvkm_blob_dtor(struct nvkm_blob *blob) +{ + kfree(blob->data); + blob->data = NULL; + blob->size = 0; +} #endif -- cgit v1.2.3 From 31bef57f6ce37a7382d89ab117b9e33bf92a0e8b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/core: define ACR subdev This will replace the current SECBOOT subdev for handling firmware on secure falcons. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 3 +++ drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 10 ++++++++++ drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 1 + 7 files changed, 19 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 6d55cd0476aa..3d42139c3f37 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -23,6 +23,7 @@ enum nvkm_devidx { NVKM_SUBDEV_MMU, NVKM_SUBDEV_BAR, NVKM_SUBDEV_FAULT, + NVKM_SUBDEV_ACR, NVKM_SUBDEV_PMU, NVKM_SUBDEV_VOLT, NVKM_SUBDEV_ICCSENSE, @@ -129,6 +130,7 @@ struct nvkm_device { struct notifier_block nb; } acpi; + struct nvkm_acr *acr; struct nvkm_bar *bar; struct nvkm_bios *bios; struct nvkm_bus *bus; @@ -202,6 +204,7 @@ struct nvkm_device_quirk { struct nvkm_device_chip { const char *name; + int (*acr )(struct nvkm_device *, int idx, struct nvkm_acr **); int (*bar )(struct nvkm_device *, int idx, struct nvkm_bar **); int (*bios )(struct nvkm_device *, int idx, struct nvkm_bios **); int (*bus )(struct nvkm_device *, int idx, struct nvkm_bus **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h new file mode 100644 index 000000000000..e2932395ab26 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_ACR_H__ +#define __NVKM_ACR_H__ +#define nvkm_acr(p) container_of((p), struct nvkm_acr, subdev) +#include + +struct nvkm_acr { + struct nvkm_subdev subdev; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c index 245990de1e90..aecb48434947 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c @@ -30,6 +30,7 @@ static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR]; const char * nvkm_subdev_name[NVKM_SUBDEV_NR] = { + [NVKM_SUBDEV_ACR ] = "acr", [NVKM_SUBDEV_BAR ] = "bar", [NVKM_SUBDEV_VBIOS ] = "bios", [NVKM_SUBDEV_BUS ] = "bus", diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index eba450e689b2..401323dc4a85 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2638,6 +2638,7 @@ nvkm_device_subdev(struct nvkm_device *device, int index) switch (index) { #define _(n,p,m) case NVKM_SUBDEV_##n: if (p) return (m); break + _(ACR , device->acr , &device->acr->subdev); _(BAR , device->bar , &device->bar->subdev); _(VBIOS , device->bios , &device->bios->subdev); _(BUS , device->bus , &device->bus->subdev); @@ -3144,6 +3145,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, } \ break switch (i) { + _(NVKM_SUBDEV_ACR , acr); _(NVKM_SUBDEV_BAR , bar); _(NVKM_SUBDEV_VBIOS , bios); _(NVKM_SUBDEV_BUS , bus); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index d8be2f77ac66..0f83ca3166af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -3,6 +3,7 @@ #define __NVKM_DEVICE_PRIV_H__ #include +#include #include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild index 4e136f3d7c28..bb3e53f891c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild @@ -1,4 +1,5 @@ # SPDX-License-Identifier: MIT +include $(src)/nvkm/subdev/acr/Kbuild include $(src)/nvkm/subdev/bar/Kbuild include $(src)/nvkm/subdev/bios/Kbuild include $(src)/nvkm/subdev/bus/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild new file mode 100644 index 000000000000..548d2d447de6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -0,0 +1 @@ +# SPDX-License-Identifier: MIT -- cgit v1.2.3 From 67e7c6cf8f521463ca8c6f37098dcaf9e391b080 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/acr: add stub implementation for all GPUs currently supported by SECBOOT PMU, SEC2 and GR will be modified to register their falcons with ACR before the main commit switching everything over. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 8 +++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 12 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 6 ++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 54 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 61 +++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c | 49 ++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 68 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c | 50 ++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c | 43 ++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 20 +++++++ .../gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c | 12 ---- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 2 - .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 16 ----- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c | 8 --- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c | 2 - 15 files changed, 371 insertions(+), 40 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index e2932395ab26..52fb5241f5f6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -3,8 +3,16 @@ #define __NVKM_ACR_H__ #define nvkm_acr(p) container_of((p), struct nvkm_acr, subdev) #include +struct nvkm_falcon; struct nvkm_acr { + const struct nvkm_acr_func *func; struct nvkm_subdev subdev; }; + +int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **); +int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); +int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **); +int gp108_acr_new(struct nvkm_device *, int, struct nvkm_acr **); +int gp10b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 401323dc4a85..859bf0c4a0da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2027,6 +2027,7 @@ nv118_chipset = { static const struct nvkm_device_chip nv120_chipset = { .name = "GM200", + .acr = gm200_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2062,6 +2063,7 @@ nv120_chipset = { static const struct nvkm_device_chip nv124_chipset = { .name = "GM204", + .acr = gm200_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2097,6 +2099,7 @@ nv124_chipset = { static const struct nvkm_device_chip nv126_chipset = { .name = "GM206", + .acr = gm200_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2132,6 +2135,7 @@ nv126_chipset = { static const struct nvkm_device_chip nv12b_chipset = { .name = "GM20B", + .acr = gm20b_acr_new, .bar = gm20b_bar_new, .bus = gf100_bus_new, .clk = gm20b_clk_new, @@ -2157,6 +2161,7 @@ nv12b_chipset = { static const struct nvkm_device_chip nv130_chipset = { .name = "GP100", + .acr = gm200_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2193,6 +2198,7 @@ nv130_chipset = { static const struct nvkm_device_chip nv132_chipset = { .name = "GP102", + .acr = gp102_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2229,6 +2235,7 @@ nv132_chipset = { static const struct nvkm_device_chip nv134_chipset = { .name = "GP104", + .acr = gp102_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2265,6 +2272,7 @@ nv134_chipset = { static const struct nvkm_device_chip nv136_chipset = { .name = "GP106", + .acr = gp102_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2301,6 +2309,7 @@ nv136_chipset = { static const struct nvkm_device_chip nv137_chipset = { .name = "GP107", + .acr = gp102_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2337,6 +2346,7 @@ nv137_chipset = { static const struct nvkm_device_chip nv138_chipset = { .name = "GP108", + .acr = gp108_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2373,6 +2383,7 @@ nv138_chipset = { static const struct nvkm_device_chip nv13b_chipset = { .name = "GP10B", + .acr = gp10b_acr_new, .bar = gm20b_bar_new, .bus = gf100_bus_new, .fault = gp10b_fault_new, @@ -2397,6 +2408,7 @@ nv13b_chipset = { static const struct nvkm_device_chip nv140_chipset = { .name = "GV100", + .acr = gp108_acr_new, .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index 548d2d447de6..6a2c08cac414 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -1 +1,7 @@ # SPDX-License-Identifier: MIT +nvkm-y += nvkm/subdev/acr/base.o +nvkm-y += nvkm/subdev/acr/gm200.o +nvkm-y += nvkm/subdev/acr/gm20b.o +nvkm-y += nvkm/subdev/acr/gp102.o +nvkm-y += nvkm/subdev/acr/gp108.o +nvkm-y += nvkm/subdev/acr/gp10b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c new file mode 100644 index 000000000000..417688a5094a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#include + +static void * +nvkm_acr_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_acr *acr = nvkm_acr(subdev); + return acr; +} + +static const struct nvkm_subdev_func +nvkm_acr = { + .dtor = nvkm_acr_dtor, +}; + +int +nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, + int index, struct nvkm_acr **pacr) +{ + struct nvkm_acr *acr; + + if (!(acr = *pacr = kzalloc(sizeof(*acr), GFP_KERNEL))) + return -ENOMEM; + nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev); + + fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + acr->func = fwif->func; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c new file mode 100644 index 000000000000..d04472de3e64 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/gm204/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/gm206/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gm200/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gm204/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gm204/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gm206/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gm206/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gp100/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin"); + +static const struct nvkm_acr_func +gm200_acr = { +}; + +static int +gm200_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_acr_fwif +gm200_acr_fwif[] = { + { 0, gm200_acr_load, &gm200_acr }, + {} +}; + +int +gm200_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gm200_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c new file mode 100644 index 000000000000..2e56b90c25da --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +MODULE_FIRMWARE("nvidia/gm20b/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin"); +#endif + +static const struct nvkm_acr_func +gm20b_acr = { +}; + +int +gm20b_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_acr_fwif +gm20b_acr_fwif[] = { + { 0, gm20b_acr_load, &gm20b_acr }, + {} +}; + +int +gm20b_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gm20b_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c new file mode 100644 index 000000000000..d85dc19546a6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +MODULE_FIRMWARE("nvidia/gp102/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp102/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gp104/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp104/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gp106/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp106/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp107/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gp102/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp102/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gp104/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp104/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gp106/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin"); + +static const struct nvkm_acr_func +gp102_acr = { +}; + +int +gp102_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_acr_fwif +gp102_acr_fwif[] = { + { 0, gp102_acr_load, &gp102_acr }, + {} +}; + +int +gp102_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gp102_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c new file mode 100644 index 000000000000..7c9e0375cafd --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin"); + +MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin"); + +static const struct nvkm_acr_func +gp108_acr = { +}; + +static const struct nvkm_acr_fwif +gp108_acr_fwif[] = { + { 0, gp102_acr_load, &gp108_acr }, + {} +}; + +int +gp108_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gp108_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c new file mode 100644 index 000000000000..6ee27829d588 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c @@ -0,0 +1,43 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) +MODULE_FIRMWARE("nvidia/gp10b/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin"); +#endif + +static const struct nvkm_acr_func +gp10b_acr = { +}; + +static const struct nvkm_acr_fwif +gp10b_acr_fwif[] = { + { 0, gm20b_acr_load, &gp10b_acr }, + {} +}; + +int +gp10b_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(gp10b_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h new file mode 100644 index 000000000000..297c8b439589 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -0,0 +1,20 @@ +#ifndef __NVKM_ACR_PRIV_H__ +#define __NVKM_ACR_PRIV_H__ +#include + +struct nvkm_acr_fwif { + int version; + int (*load)(struct nvkm_acr *, int version, + const struct nvkm_acr_fwif *); + const struct nvkm_acr_func *func; +}; + +int gm20b_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); +int gp102_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); + +struct nvkm_acr_func { +}; + +int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int, + struct nvkm_acr **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c index 5e91b3f90065..6b356473e67e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -197,9 +197,6 @@ gm200_secboot_new(struct nvkm_device *device, int index, } -MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gm200/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gm200/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gm200/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gm200/gr/fecs_data.bin"); @@ -213,9 +210,6 @@ MODULE_FIRMWARE("nvidia/gm200/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/gm200/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/gm200/gr/sw_method_init.bin"); -MODULE_FIRMWARE("nvidia/gm204/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gm204/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gm204/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gm204/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gm204/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gm204/gr/fecs_data.bin"); @@ -229,9 +223,6 @@ MODULE_FIRMWARE("nvidia/gm204/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/gm204/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/gm204/gr/sw_method_init.bin"); -MODULE_FIRMWARE("nvidia/gm206/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gm206/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gm206/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gm206/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gm206/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gm206/gr/fecs_data.bin"); @@ -245,9 +236,6 @@ MODULE_FIRMWARE("nvidia/gm206/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/gm206/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/gm206/gr/sw_method_init.bin"); -MODULE_FIRMWARE("nvidia/gp100/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp100/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp100/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp100/gr/fecs_data.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index 32a584c4757f..0de40c80e5ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -150,8 +150,6 @@ gm20b_secboot_new(struct nvkm_device *device, int index, } #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) -MODULE_FIRMWARE("nvidia/gm20b/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_data.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index 4695f1c8e33f..ed5e46c414c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -170,10 +170,6 @@ gp102_secboot_new(struct nvkm_device *device, int index, return 0; } -MODULE_FIRMWARE("nvidia/gp102/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp102/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gp102/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp102/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp102/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp102/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp102/gr/fecs_data.bin"); @@ -193,10 +189,6 @@ MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp104/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp104/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gp104/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp104/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp104/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp104/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp104/gr/fecs_data.bin"); @@ -216,10 +208,6 @@ MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp106/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp106/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp106/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp106/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp106/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp106/gr/fecs_data.bin"); @@ -239,10 +227,6 @@ MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp107/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp107/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp107/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp107/gr/fecs_data.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c index 737a8d50a1f2..d8bfd87c5b78 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c @@ -45,10 +45,6 @@ gp108_secboot_new(struct nvkm_device *device, int index, return nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); } -MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp108/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp108/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp108/gr/fecs_data.bin"); @@ -66,10 +62,6 @@ MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin"); -MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gv100/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gv100/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gv100/gr/fecs_data.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c index d84e85825995..6a5434c75678 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c @@ -73,8 +73,6 @@ gp10b_secboot_new(struct nvkm_device *device, int index, } #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) -MODULE_FIRMWARE("nvidia/gp10b/acr/bl.bin"); -MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_inst.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_data.bin"); -- cgit v1.2.3 From c63fe2e704e2c1fa9a4614f31a567925d00503f1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/acr: add loaders for currently available LS firmware images Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/fw.h | 28 +++ drivers/gpu/drm/nouveau/include/nvfw/ls.h | 53 +++++ .../gpu/drm/nouveau/include/nvkm/core/firmware.h | 6 + drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 54 +++++ drivers/gpu/drm/nouveau/nvkm/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 34 +++ drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild | 3 + drivers/gpu/drm/nouveau/nvkm/nvfw/fw.c | 51 +++++ drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c | 108 +++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 4 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 249 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 6 + 13 files changed, 598 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/fw.h create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/ls.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/fw.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/fw.h b/drivers/gpu/drm/nouveau/include/nvfw/fw.h new file mode 100644 index 000000000000..a7cf1188c9d6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/fw.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVFW_FW_H__ +#define __NVFW_FW_H__ +#include +struct nvkm_subdev; + +struct nvfw_bin_hdr { + u32 bin_magic; + u32 bin_ver; + u32 bin_size; + u32 header_offset; + u32 data_offset; + u32 data_size; +}; + +const struct nvfw_bin_hdr *nvfw_bin_hdr(struct nvkm_subdev *, const void *); + +struct nvfw_bl_desc { + u32 start_tag; + u32 dmem_load_off; + u32 code_off; + u32 code_size; + u32 data_off; + u32 data_size; +}; + +const struct nvfw_bl_desc *nvfw_bl_desc(struct nvkm_subdev *, const void *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvfw/ls.h b/drivers/gpu/drm/nouveau/include/nvfw/ls.h new file mode 100644 index 000000000000..f63692a2a16c --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/ls.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVFW_LS_H__ +#define __NVFW_LS_H__ +#include +struct nvkm_subdev; + +struct nvfw_ls_desc_head { + u32 descriptor_size; + u32 image_size; + u32 tools_version; + u32 app_version; + char date[64]; + u32 bootloader_start_offset; + u32 bootloader_size; + u32 bootloader_imem_offset; + u32 bootloader_entry_point; + u32 app_start_offset; + u32 app_size; + u32 app_imem_offset; + u32 app_imem_entry; + u32 app_dmem_offset; + u32 app_resident_code_offset; + u32 app_resident_code_size; + u32 app_resident_data_offset; + u32 app_resident_data_size; +}; + +struct nvfw_ls_desc { + struct nvfw_ls_desc_head head; + u32 nb_overlays; + struct { + u32 start; + u32 size; + } load_ovl[64]; + u32 compressed; +}; + +const struct nvfw_ls_desc *nvfw_ls_desc(struct nvkm_subdev *, const void *); + +struct nvfw_ls_desc_v1 { + struct nvfw_ls_desc_head head; + u32 nb_imem_overlays; + u32 nb_dmem_overlays; + struct { + u32 start; + u32 size; + } load_ovl[64]; + u32 compressed; +}; + +const struct nvfw_ls_desc_v1 * +nvfw_ls_desc_v1(struct nvkm_subdev *, const void *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h index 55ea2b39a8a8..cb8eed19061d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -11,6 +11,12 @@ int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, const struct firmware **); void nvkm_firmware_put(const struct firmware *); +int nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *path, + const char *name, int ver, struct nvkm_blob *); +int nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *path, + const char *name, int ver, + const struct firmware **); + #define nvkm_firmware_load(s,l,o,p...) ({ \ struct nvkm_subdev *_s = (s); \ const char *_opts = (o); \ diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 52fb5241f5f6..6b342a63e2cb 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -5,9 +5,21 @@ #include struct nvkm_falcon; +enum nvkm_acr_lsf_id { + NVKM_ACR_LSF_PMU = 0, + NVKM_ACR_LSF_GSPLITE = 1, + NVKM_ACR_LSF_FECS = 2, + NVKM_ACR_LSF_GPCCS = 3, + NVKM_ACR_LSF_NVDEC = 4, + NVKM_ACR_LSF_SEC2 = 7, + NVKM_ACR_LSF_MINION = 10, +}; + struct nvkm_acr { const struct nvkm_acr_func *func; struct nvkm_subdev subdev; + + struct list_head lsfw; }; int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **); @@ -15,4 +27,46 @@ int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp108_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp10b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); + +struct nvkm_acr_lsfw { + const struct nvkm_acr_lsf_func *func; + struct nvkm_falcon *falcon; + enum nvkm_acr_lsf_id id; + + struct list_head head; + + struct nvkm_blob img; + + const struct firmware *sig; + + u32 bootloader_size; + u32 bootloader_imem_offset; + + u32 app_size; + u32 app_start_offset; + u32 app_imem_entry; + u32 app_resident_code_offset; + u32 app_resident_code_size; + u32 app_resident_data_offset; + u32 app_resident_data_size; + + u32 ucode_size; + u32 data_size; +}; + +struct nvkm_acr_lsf_func { +}; + +int +nvkm_acr_lsfw_load_sig_image_desc(struct nvkm_subdev *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id, const char *path, + int ver, const struct nvkm_acr_lsf_func *); +int +nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id, const char *path, + int ver, const struct nvkm_acr_lsf_func *); +int +nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id, const char *path, + int ver, const struct nvkm_acr_lsf_func *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/Kbuild index b53de9ba8c73..db3ade125fa9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/Kbuild @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT include $(src)/nvkm/core/Kbuild +include $(src)/nvkm/nvfw/Kbuild include $(src)/nvkm/falcon/Kbuild include $(src)/nvkm/subdev/Kbuild include $(src)/nvkm/engine/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index 50f2c3449afd..1c2909566b2a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -22,6 +22,40 @@ #include #include +int +nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base, + const char *name, int ver, const struct firmware **pfw) +{ + char path[64]; + int ret; + + snprintf(path, sizeof(path), "%s%s", base, name); + ret = nvkm_firmware_get_version(subdev, path, ver, ver, pfw); + if (ret < 0) + return ret; + + return 0; +} + +int +nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *base, + const char *name, int ver, struct nvkm_blob *blob) +{ + const struct firmware *fw; + int ret; + + ret = nvkm_firmware_load_name(subdev, base, name, ver, &fw); + if (ret == 0) { + blob->data = kmemdup(fw->data, fw->size, GFP_KERNEL); + blob->size = fw->size; + nvkm_firmware_put(fw); + if (!blob->data) + return -ENOMEM; + } + + return ret; +} + /** * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory * @subdev subdevice that will use that firmware diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild new file mode 100644 index 000000000000..e05b92ec8568 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: MIT +nvkm-y += nvkm/nvfw/fw.o +nvkm-y += nvkm/nvfw/ls.o diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/fw.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/fw.c new file mode 100644 index 000000000000..746803bd5318 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/fw.c @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include +#include + +const struct nvfw_bin_hdr * +nvfw_bin_hdr(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_bin_hdr *hdr = data; + nvkm_debug(subdev, "binHdr:\n"); + nvkm_debug(subdev, "\tbinMagic : 0x%08x\n", hdr->bin_magic); + nvkm_debug(subdev, "\tbinVer : %d\n", hdr->bin_ver); + nvkm_debug(subdev, "\tbinSize : %d\n", hdr->bin_size); + nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset); + nvkm_debug(subdev, "\tdataOffset : 0x%x\n", hdr->data_offset); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + return hdr; +} + +const struct nvfw_bl_desc * +nvfw_bl_desc(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_bl_desc *hdr = data; + nvkm_debug(subdev, "blDesc\n"); + nvkm_debug(subdev, "\tstartTag : 0x%x\n", hdr->start_tag); + nvkm_debug(subdev, "\tdmemLoadOff : 0x%x\n", hdr->dmem_load_off); + nvkm_debug(subdev, "\tcodeOff : 0x%x\n", hdr->code_off); + nvkm_debug(subdev, "\tcodeSize : 0x%x\n", hdr->code_size); + nvkm_debug(subdev, "\tdataOff : 0x%x\n", hdr->data_off); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + return hdr; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c new file mode 100644 index 000000000000..b847f281ce97 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include +#include + +static void +nvfw_ls_desc_head(struct nvkm_subdev *subdev, + const struct nvfw_ls_desc_head *hdr) +{ + char *date; + + nvkm_debug(subdev, "lsUcodeImgDesc:\n"); + nvkm_debug(subdev, "\tdescriptorSize : %d\n", + hdr->descriptor_size); + nvkm_debug(subdev, "\timageSize : %d\n", hdr->image_size); + nvkm_debug(subdev, "\ttoolsVersion : 0x%x\n", + hdr->tools_version); + nvkm_debug(subdev, "\tappVersion : 0x%x\n", hdr->app_version); + + date = kstrndup(hdr->date, sizeof(hdr->date), GFP_KERNEL); + nvkm_debug(subdev, "\tdate : %s\n", date); + kfree(date); + + nvkm_debug(subdev, "\tbootloaderStartOffset: 0x%x\n", + hdr->bootloader_start_offset); + nvkm_debug(subdev, "\tbootloaderSize : 0x%x\n", + hdr->bootloader_size); + nvkm_debug(subdev, "\tbootloaderImemOffset : 0x%x\n", + hdr->bootloader_imem_offset); + nvkm_debug(subdev, "\tbootloaderEntryPoint : 0x%x\n", + hdr->bootloader_entry_point); + + nvkm_debug(subdev, "\tappStartOffset : 0x%x\n", + hdr->app_start_offset); + nvkm_debug(subdev, "\tappSize : 0x%x\n", hdr->app_size); + nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", + hdr->app_imem_offset); + nvkm_debug(subdev, "\tappImemEntry : 0x%x\n", + hdr->app_imem_entry); + nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", + hdr->app_dmem_offset); + nvkm_debug(subdev, "\tappResidentCodeOffset: 0x%x\n", + hdr->app_resident_code_offset); + nvkm_debug(subdev, "\tappResidentCodeSize : 0x%x\n", + hdr->app_resident_code_size); + nvkm_debug(subdev, "\tappResidentDataOffset: 0x%x\n", + hdr->app_resident_data_offset); + nvkm_debug(subdev, "\tappResidentDataSize : 0x%x\n", + hdr->app_resident_data_size); +} + +const struct nvfw_ls_desc * +nvfw_ls_desc(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_ls_desc *hdr = data; + int i; + + nvfw_ls_desc_head(subdev, &hdr->head); + + nvkm_debug(subdev, "\tnbOverlays : %d\n", hdr->nb_overlays); + for (i = 0; i < ARRAY_SIZE(hdr->load_ovl); i++) { + nvkm_debug(subdev, "\tloadOvl[%d] : 0x%x %d\n", i, + hdr->load_ovl[i].start, hdr->load_ovl[i].size); + } + nvkm_debug(subdev, "\tcompressed : %d\n", hdr->compressed); + + return hdr; +} + +const struct nvfw_ls_desc_v1 * +nvfw_ls_desc_v1(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_ls_desc_v1 *hdr = data; + int i; + + nvfw_ls_desc_head(subdev, &hdr->head); + + nvkm_debug(subdev, "\tnbImemOverlays : %d\n", + hdr->nb_imem_overlays); + nvkm_debug(subdev, "\tnbDmemOverlays : %d\n", + hdr->nb_imem_overlays); + for (i = 0; i < ARRAY_SIZE(hdr->load_ovl); i++) { + nvkm_debug(subdev, "\tloadOvl[%2d] : 0x%x %d\n", i, + hdr->load_ovl[i].start, hdr->load_ovl[i].size); + } + nvkm_debug(subdev, "\tcompressed : %d\n", hdr->compressed); + + return hdr; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index 6a2c08cac414..4f7d8aa1f625 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/subdev/acr/base.o +nvkm-y += nvkm/subdev/acr/lsfw.o nvkm-y += nvkm/subdev/acr/gm200.o nvkm-y += nvkm/subdev/acr/gm20b.o nvkm-y += nvkm/subdev/acr/gp102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 417688a5094a..11658a4afc7a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -27,6 +27,9 @@ static void * nvkm_acr_dtor(struct nvkm_subdev *subdev) { struct nvkm_acr *acr = nvkm_acr(subdev); + + nvkm_acr_lsfw_del_all(acr); + return acr; } @@ -44,6 +47,7 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, if (!(acr = *pacr = kzalloc(sizeof(*acr), GFP_KERNEL))) return -ENOMEM; nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev); + INIT_LIST_HEAD(&acr->lsfw); fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr); if (IS_ERR(fwif)) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c new file mode 100644 index 000000000000..9896462960ea --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -0,0 +1,249 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" +#include +#include +#include +#include + +void +nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *lsfw) +{ + nvkm_blob_dtor(&lsfw->img); + nvkm_firmware_put(lsfw->sig); + list_del(&lsfw->head); + kfree(lsfw); +} + +void +nvkm_acr_lsfw_del_all(struct nvkm_acr *acr) +{ + struct nvkm_acr_lsfw *lsfw, *lsft; + list_for_each_entry_safe(lsfw, lsft, &acr->lsfw, head) { + nvkm_acr_lsfw_del(lsfw); + } +} + +static struct nvkm_acr_lsfw * +nvkm_acr_lsfw_get(struct nvkm_acr *acr, enum nvkm_acr_lsf_id id) +{ + struct nvkm_acr_lsfw *lsfw; + list_for_each_entry(lsfw, &acr->lsfw, head) { + if (lsfw->id == id) + return lsfw; + } + return NULL; +} + +struct nvkm_acr_lsfw * +nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *func, struct nvkm_acr *acr, + struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) +{ + struct nvkm_acr_lsfw *lsfw = nvkm_acr_lsfw_get(acr, id); + + if (lsfw && lsfw->func) { + nvkm_error(&acr->subdev, "LSFW %d redefined\n", id); + return ERR_PTR(-EEXIST); + } + + if (!lsfw) { + if (!(lsfw = kzalloc(sizeof(*lsfw), GFP_KERNEL))) + return ERR_PTR(-ENOMEM); + + lsfw->id = id; + list_add_tail(&lsfw->head, &acr->lsfw); + } + + lsfw->func = func; + lsfw->falcon = falcon; + return lsfw; +} + +static struct nvkm_acr_lsfw * +nvkm_acr_lsfw_load_sig_image_desc_(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func, + const struct firmware **pdesc) +{ + struct nvkm_acr *acr = subdev->device->acr; + struct nvkm_acr_lsfw *lsfw; + int ret; + + if (IS_ERR((lsfw = nvkm_acr_lsfw_add(func, acr, falcon, id)))) + return lsfw; + + ret = nvkm_firmware_load_name(subdev, path, "sig", ver, &lsfw->sig); + if (ret) + goto done; + + ret = nvkm_firmware_load_blob(subdev, path, "image", ver, &lsfw->img); + if (ret) + goto done; + + ret = nvkm_firmware_load_name(subdev, path, "desc", ver, pdesc); +done: + if (ret) { + nvkm_acr_lsfw_del(lsfw); + return ERR_PTR(ret); + } + + return lsfw; +} + +static void +nvkm_acr_lsfw_from_desc(const struct nvfw_ls_desc_head *desc, + struct nvkm_acr_lsfw *lsfw) +{ + lsfw->bootloader_size = ALIGN(desc->bootloader_size, 256); + lsfw->bootloader_imem_offset = desc->bootloader_imem_offset; + + lsfw->app_size = ALIGN(desc->app_size, 256); + lsfw->app_start_offset = desc->app_start_offset; + lsfw->app_imem_entry = desc->app_imem_entry; + lsfw->app_resident_code_offset = desc->app_resident_code_offset; + lsfw->app_resident_code_size = desc->app_resident_code_size; + lsfw->app_resident_data_offset = desc->app_resident_data_offset; + lsfw->app_resident_data_size = desc->app_resident_data_size; + + lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + + lsfw->bootloader_size; + lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - + lsfw->ucode_size; +} + +int +nvkm_acr_lsfw_load_sig_image_desc(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func) +{ + const struct firmware *fw; + struct nvkm_acr_lsfw *lsfw; + + lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, + func, &fw); + if (IS_ERR(lsfw)) + return PTR_ERR(lsfw); + + nvkm_acr_lsfw_from_desc(&nvfw_ls_desc(subdev, fw->data)->head, lsfw); + nvkm_firmware_put(fw); + return 0; +} + +int +nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func) +{ + const struct firmware *fw; + struct nvkm_acr_lsfw *lsfw; + + lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, + func, &fw); + if (IS_ERR(lsfw)) + return PTR_ERR(lsfw); + + nvkm_acr_lsfw_from_desc(&nvfw_ls_desc_v1(subdev, fw->data)->head, lsfw); + nvkm_firmware_put(fw); + return 0; +} + +int +nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *subdev, + struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id, + const char *path, int ver, + const struct nvkm_acr_lsf_func *func) +{ + struct nvkm_acr *acr = subdev->device->acr; + struct nvkm_acr_lsfw *lsfw; + const struct firmware *bl = NULL, *inst = NULL, *data = NULL; + const struct nvfw_bin_hdr *hdr; + const struct nvfw_bl_desc *desc; + u32 *bldata; + int ret; + + if (IS_ERR((lsfw = nvkm_acr_lsfw_add(func, acr, falcon, id)))) + return PTR_ERR(lsfw); + + ret = nvkm_firmware_load_name(subdev, path, "bl", ver, &bl); + if (ret) + goto done; + + hdr = nvfw_bin_hdr(subdev, bl->data); + desc = nvfw_bl_desc(subdev, bl->data + hdr->header_offset); + bldata = (void *)(bl->data + hdr->data_offset); + + ret = nvkm_firmware_load_name(subdev, path, "inst", ver, &inst); + if (ret) + goto done; + + ret = nvkm_firmware_load_name(subdev, path, "data", ver, &data); + if (ret) + goto done; + + ret = nvkm_firmware_load_name(subdev, path, "sig", ver, &lsfw->sig); + if (ret) + goto done; + + lsfw->bootloader_size = ALIGN(desc->code_size, 256); + lsfw->bootloader_imem_offset = desc->start_tag << 8; + + lsfw->app_start_offset = lsfw->bootloader_size; + lsfw->app_imem_entry = 0; + lsfw->app_resident_code_offset = 0; + lsfw->app_resident_code_size = ALIGN(inst->size, 256); + lsfw->app_resident_data_offset = lsfw->app_resident_code_size; + lsfw->app_resident_data_size = ALIGN(data->size, 256); + lsfw->app_size = lsfw->app_resident_code_size + + lsfw->app_resident_data_size; + + lsfw->img.size = lsfw->bootloader_size + lsfw->app_size; + if (!(lsfw->img.data = kzalloc(lsfw->img.size, GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + memcpy(lsfw->img.data, bldata, lsfw->bootloader_size); + memcpy(lsfw->img.data + lsfw->app_start_offset + + lsfw->app_resident_code_offset, inst->data, inst->size); + memcpy(lsfw->img.data + lsfw->app_start_offset + + lsfw->app_resident_data_offset, data->data, data->size); + + lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + + lsfw->bootloader_size; + lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - + lsfw->ucode_size; + +done: + if (ret) + nvkm_acr_lsfw_del(lsfw); + nvkm_firmware_put(data); + nvkm_firmware_put(inst); + nvkm_firmware_put(bl); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index 297c8b439589..882290423c01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -17,4 +17,10 @@ struct nvkm_acr_func { int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int, struct nvkm_acr **); + +struct nvkm_acr_lsfw *nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *, + struct nvkm_acr *, struct nvkm_falcon *, + enum nvkm_acr_lsf_id); +void nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *); +void nvkm_acr_lsfw_del_all(struct nvkm_acr *); #endif -- cgit v1.2.3 From 78b10b74030025f6a216a9b10afbe35ab05d32d1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gsp: select implementation based on available firmware This will allow for further customisation of the subdev depending on what firmware is available. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c | 70 +++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 38 +++----------- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h | 14 +++++ 4 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild index e7c4f068936e..67cc3b320169 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild @@ -1,2 +1,3 @@ # SPDX-License-Identifier: MIT +nvkm-y += nvkm/subdev/gsp/base.o nvkm-y += nvkm/subdev/gsp/gv100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c new file mode 100644 index 000000000000..872280d926a9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" +#include +#include +#include +#include + +static int +nvkm_gsp_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_gsp *gsp = nvkm_gsp(subdev); + + gsp->addr = nvkm_top_addr(subdev->device, subdev->index); + if (!gsp->addr) + return -EINVAL; + + return nvkm_falcon_v1_new(subdev, "GSP", gsp->addr, &gsp->falcon); +} + +static void * +nvkm_gsp_dtor(struct nvkm_subdev *subdev) +{ + struct nvkm_gsp *gsp = nvkm_gsp(subdev); + nvkm_falcon_del(&gsp->falcon); + return gsp; +} + +static const struct nvkm_subdev_func +nvkm_gsp = { + .dtor = nvkm_gsp_dtor, + .oneinit = nvkm_gsp_oneinit, +}; + +int +nvkm_gsp_new_(const struct nvkm_gsp_fwif *fwif, struct nvkm_device *device, + int index, struct nvkm_gsp **pgsp) +{ + struct nvkm_gsp *gsp; + + if (!(gsp = *pgsp = kzalloc(sizeof(*gsp), GFP_KERNEL))) + return -ENOMEM; + + nvkm_subdev_ctor(&nvkm_gsp, device, index, &gsp->subdev); + + fwif = nvkm_firmware_load(&gsp->subdev, fwif, "Gsp", gsp); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index dccfaf1162e2..61188c169b81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -19,44 +19,22 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include +#include "priv.h" static int -gv100_gsp_oneinit(struct nvkm_subdev *subdev) +gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) { - struct nvkm_gsp *gsp = nvkm_gsp(subdev); - - gsp->addr = nvkm_top_addr(subdev->device, subdev->index); - if (!gsp->addr) - return -EINVAL; - - return nvkm_falcon_v1_new(subdev, "GSP", gsp->addr, &gsp->falcon); -} - -static void * -gv100_gsp_dtor(struct nvkm_subdev *subdev) -{ - struct nvkm_gsp *gsp = nvkm_gsp(subdev); - nvkm_falcon_del(&gsp->falcon); - return gsp; + return 0; } -static const struct nvkm_subdev_func -gv100_gsp = { - .dtor = gv100_gsp_dtor, - .oneinit = gv100_gsp_oneinit, +struct nvkm_gsp_fwif +gv100_gsp[] = { + { -1, gv100_gsp_nofw }, + {} }; int gv100_gsp_new(struct nvkm_device *device, int index, struct nvkm_gsp **pgsp) { - struct nvkm_gsp *gsp; - - if (!(gsp = *pgsp = kzalloc(sizeof(*gsp), GFP_KERNEL))) - return -ENOMEM; - - nvkm_subdev_ctor(&gv100_gsp, device, index, &gsp->subdev); - return 0; + return nvkm_gsp_new_(gv100_gsp, device, index, pgsp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h new file mode 100644 index 000000000000..32002091759d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_GSP_PRIV_H__ +#define __NVKM_GSP_PRIV_H__ +#include +enum nvkm_acr_lsf_id; + +struct nvkm_gsp_fwif { + int version; + int (*load)(struct nvkm_gsp *, int ver, const struct nvkm_gsp_fwif *); +}; + +int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, int, + struct nvkm_gsp **); +#endif -- cgit v1.2.3 From 334815ef310a7ad2ba34039ba1f933d5edc80b56 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gsp: initialise SW state for falcon from constructor This will allow us to register the falcon with ACR, and further customise its behaviour by providing the nvkm_falcon_func structure directly. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h | 5 ++--- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c | 19 ++++--------------- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 16 +++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h | 1 + 4 files changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h index 4c672a5c4cd5..06db67610a50 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h @@ -2,12 +2,11 @@ #define __NVKM_GSP_H__ #define nvkm_gsp(p) container_of((p), struct nvkm_gsp, subdev) #include +#include struct nvkm_gsp { struct nvkm_subdev subdev; - u32 addr; - - struct nvkm_falcon *falcon; + struct nvkm_falcon falcon; }; int gv100_gsp_new(struct nvkm_device *, int, struct nvkm_gsp **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c index 872280d926a9..5a32df0f9992 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c @@ -25,30 +25,17 @@ #include #include -static int -nvkm_gsp_oneinit(struct nvkm_subdev *subdev) -{ - struct nvkm_gsp *gsp = nvkm_gsp(subdev); - - gsp->addr = nvkm_top_addr(subdev->device, subdev->index); - if (!gsp->addr) - return -EINVAL; - - return nvkm_falcon_v1_new(subdev, "GSP", gsp->addr, &gsp->falcon); -} - static void * nvkm_gsp_dtor(struct nvkm_subdev *subdev) { struct nvkm_gsp *gsp = nvkm_gsp(subdev); - nvkm_falcon_del(&gsp->falcon); + nvkm_falcon_dtor(&gsp->falcon); return gsp; } static const struct nvkm_subdev_func nvkm_gsp = { .dtor = nvkm_gsp_dtor, - .oneinit = nvkm_gsp_oneinit, }; int @@ -66,5 +53,7 @@ nvkm_gsp_new_(const struct nvkm_gsp_fwif *fwif, struct nvkm_device *device, if (IS_ERR(fwif)) return PTR_ERR(fwif); - return 0; + return nvkm_falcon_ctor(fwif->flcn, &gsp->subdev, + nvkm_subdev_name[gsp->subdev.index], 0, + &gsp->falcon); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index 61188c169b81..e935c1bf6238 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -21,6 +21,20 @@ */ #include "priv.h" +static const struct nvkm_falcon_func +gv100_gsp_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + static int gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) { @@ -29,7 +43,7 @@ gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif) struct nvkm_gsp_fwif gv100_gsp[] = { - { -1, gv100_gsp_nofw }, + { -1, gv100_gsp_nofw, &gv100_gsp_flcn }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h index 32002091759d..92820fb997c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h @@ -7,6 +7,7 @@ enum nvkm_acr_lsf_id; struct nvkm_gsp_fwif { int version; int (*load)(struct nvkm_gsp *, int ver, const struct nvkm_gsp_fwif *); + const struct nvkm_falcon_func *flcn; }; int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, int, -- cgit v1.2.3 From e905736c6d7328ce2d34640741f4b7e75c64a737 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/pmu/gp10b: split from gm20b implementation ACR LS FW loading is moving out of SECBOOT and into their specific subdevs, and the available GM20B/GP10B FWs have interface differences. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 15 +++------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 35 +++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 2 ++ 6 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 4752006880f3..fd250bc48a41 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -43,6 +43,7 @@ int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gm20b_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gp100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); int gp102_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); +int gp10b_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **); /* interface to MEMX process running on PMU */ struct nvkm_memx; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 859bf0c4a0da..b24e64f5e7bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2395,7 +2395,7 @@ nv13b_chipset = { .mc = gp10b_mc_new, .mmu = gp10b_mmu_new, .secboot = gp10b_secboot_new, - .pmu = gm20b_pmu_new, + .pmu = gp10b_pmu_new, .timer = gk20a_timer_new, .top = gk104_top_new, .ce[0] = gp100_ce_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild index e37b6e45eaa2..a76c2a7bd696 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild @@ -12,3 +12,4 @@ nvkm-y += nvkm/subdev/pmu/gm107.o nvkm-y += nvkm/subdev/pmu/gm20b.o nvkm-y += nvkm/subdev/pmu/gp100.o nvkm-y += nvkm/subdev/pmu/gp102.o +nvkm-y += nvkm/subdev/pmu/gp10b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 31c843145c7a..9ed7e4852f3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -19,12 +19,11 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - -#include -#include #include "priv.h" +#include +#include -static void +void gm20b_pmu_recv(struct nvkm_pmu *pmu) { if (!pmu->queue) { @@ -46,11 +45,5 @@ gm20b_pmu = { int gm20b_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - int ret; - - ret = nvkm_pmu_new_(&gm20b_pmu, device, index, ppmu); - if (ret) - return ret; - - return 0; + return nvkm_pmu_new_(&gm20b_pmu, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c new file mode 100644 index 000000000000..d028f50090ae --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ +#include "priv.h" + +static const struct nvkm_pmu_func +gp10b_pmu = { + .enabled = gf100_pmu_enabled, + .intr = gt215_pmu_intr, + .recv = gm20b_pmu_recv, +}; + +int +gp10b_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) +{ + return nvkm_pmu_new_(&gp10b_pmu, device, index, ppmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 26d73f9cd6d3..82a0a15d800b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -42,4 +42,6 @@ bool gf100_pmu_enabled(struct nvkm_pmu *); void gf100_pmu_reset(struct nvkm_pmu *); void gk110_pmu_pgob(struct nvkm_pmu *, bool); + +void gm20b_pmu_recv(struct nvkm_pmu *); #endif -- cgit v1.2.3 From 989863d7cbe58180cf0e69fd5ed72279c7fac901 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/pmu: select implementation based on available firmware This will allow for further customisation of the subdev depending on what firmware is available. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 15 ++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c | 14 ++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c | 12 ++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 28 ++++++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 19 ++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 8 ++++++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 20 ++++++++++++---- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 3 --- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c | 3 --- 16 files changed, 149 insertions(+), 29 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index ea2e11771bca..1c308227ad6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -23,6 +23,7 @@ */ #include "priv.h" +#include #include #include @@ -160,22 +161,28 @@ nvkm_pmu = { }; int -nvkm_pmu_ctor(const struct nvkm_pmu_func *func, struct nvkm_device *device, +nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, int index, struct nvkm_pmu *pmu) { nvkm_subdev_ctor(&nvkm_pmu, device, index, &pmu->subdev); - pmu->func = func; + INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); init_waitqueue_head(&pmu->recv.wait); + + fwif = nvkm_firmware_load(&pmu->subdev, fwif, "Pmu", pmu); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + pmu->func = fwif->func; return 0; } int -nvkm_pmu_new_(const struct nvkm_pmu_func *func, struct nvkm_device *device, +nvkm_pmu_new_(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { struct nvkm_pmu *pmu; if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) return -ENOMEM; - return nvkm_pmu_ctor(func, device, index, *ppmu); + return nvkm_pmu_ctor(fwif, device, index, *ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c index 0b458656e870..bc48dfcfcb0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c @@ -55,8 +55,20 @@ gf100_pmu = { .recv = gt215_pmu_recv, }; +int +gf100_pmu_nofw(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_pmu_fwif +gf100_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gf100_pmu }, + {} +}; + int gf100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gf100_pmu, device, index, ppmu); + return nvkm_pmu_new_(gf100_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c index 3dfa79d4fb13..b4c81e272706 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c @@ -39,8 +39,14 @@ gf119_pmu = { .recv = gt215_pmu_recv, }; +static const struct nvkm_pmu_fwif +gf119_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gf119_pmu }, + {} +}; + int gf119_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gf119_pmu, device, index, ppmu); + return nvkm_pmu_new_(gf119_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c index 8f7ec10fd2a4..c497525d65ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c @@ -119,8 +119,14 @@ gk104_pmu = { .pgob = gk104_pmu_pgob, }; +static const struct nvkm_pmu_fwif +gk104_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gk104_pmu }, + {} +}; + int gk104_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gk104_pmu, device, index, ppmu); + return nvkm_pmu_new_(gk104_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c index 345741d55a56..aa0b9e7c5a99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c @@ -98,8 +98,14 @@ gk110_pmu = { .pgob = gk110_pmu_pgob, }; +static const struct nvkm_pmu_fwif +gk110_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gk110_pmu }, + {} +}; + int gk110_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gk110_pmu, device, index, ppmu); + return nvkm_pmu_new_(gk110_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c index e4acf7876ea1..47a5ed32dcc5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c @@ -40,8 +40,14 @@ gk208_pmu = { .pgob = gk110_pmu_pgob, }; +static const struct nvkm_pmu_fwif +gk208_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gk208_pmu }, + {} +}; + int gk208_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gk208_pmu, device, index, ppmu); + return nvkm_pmu_new_(gk208_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c index 05e81855c367..67f65c54c7fd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -202,19 +202,27 @@ gk20a_pmu = { .reset = gf100_pmu_reset, }; +static const struct nvkm_pmu_fwif +gk20a_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gk20a_pmu }, + {} +}; + int gk20a_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { struct gk20a_pmu *pmu; + int ret; if (!(pmu = kzalloc(sizeof(*pmu), GFP_KERNEL))) return -ENOMEM; *ppmu = &pmu->base; - nvkm_pmu_ctor(&gk20a_pmu, device, index, &pmu->base); + ret = nvkm_pmu_ctor(gk20a_pmu_fwif, device, index, &pmu->base); + if (ret) + return ret; pmu->data = &gk20a_dvfs_data; nvkm_alarm_init(&pmu->alarm, gk20a_pmu_dvfs_work); - return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c index 459df1ef9e70..7dd4bec148d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c @@ -41,8 +41,14 @@ gm107_pmu = { .recv = gt215_pmu_recv, }; +static const struct nvkm_pmu_fwif +gm107_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gm107_pmu }, + {} +}; + int gm107_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gm107_pmu, device, index, ppmu); + return nvkm_pmu_new_(gm107_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 9ed7e4852f3a..1a7cfdef2d9c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -21,7 +21,11 @@ */ #include "priv.h" #include -#include +#include + +static const struct nvkm_acr_lsf_func +gm20b_pmu_acr = { +}; void gm20b_pmu_recv(struct nvkm_pmu *pmu) @@ -42,8 +46,28 @@ gm20b_pmu = { .recv = gm20b_pmu_recv, }; +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +MODULE_FIRMWARE("nvidia/gm20b/pmu/desc.bin"); +MODULE_FIRMWARE("nvidia/gm20b/pmu/image.bin"); +MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin"); +#endif + +int +gm20b_pmu_load(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif) +{ + return nvkm_acr_lsfw_load_sig_image_desc(&pmu->subdev, pmu->falcon, + NVKM_ACR_LSF_PMU, "pmu/", + ver, fwif->acr); +} + +static const struct nvkm_pmu_fwif +gm20b_pmu_fwif[] = { + { 0, gm20b_pmu_load, &gm20b_pmu, &gm20b_pmu_acr }, + {} +}; + int gm20b_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gm20b_pmu, device, index, ppmu); + return nvkm_pmu_new_(gm20b_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c index e210cd6af816..3b7f26c187f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c @@ -29,8 +29,14 @@ gp100_pmu = { .reset = gf100_pmu_reset, }; +static const struct nvkm_pmu_fwif +gp100_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gp100_pmu }, + {} +}; + int gp100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gp100_pmu, device, index, ppmu); + return nvkm_pmu_new_(gp100_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 98c7a2a8afc4..08fda8088c49 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -43,8 +43,14 @@ gp102_pmu = { .reset = gp102_pmu_reset, }; +static const struct nvkm_pmu_fwif +gp102_pmu_fwif[] = { + { -1, gf100_pmu_nofw, &gp102_pmu }, + {} +}; + int gp102_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gp102_pmu, device, index, ppmu); + return nvkm_pmu_new_(gp102_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index d028f50090ae..2440e230f398 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -20,6 +20,11 @@ * DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include + +static const struct nvkm_acr_lsf_func +gp10b_pmu_acr = { +}; static const struct nvkm_pmu_func gp10b_pmu = { @@ -28,8 +33,20 @@ gp10b_pmu = { .recv = gm20b_pmu_recv, }; +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin"); +MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin"); +MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin"); +#endif + +static const struct nvkm_pmu_fwif +gp10b_pmu_fwif[] = { + { 0, gm20b_pmu_load, &gp10b_pmu, &gp10b_pmu_acr }, + {} +}; + int gp10b_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(&gp10b_pmu, device, index, ppmu); + return nvkm_pmu_new_(gp10b_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index e04216daea58..f52d7519b8e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -256,8 +256,14 @@ gt215_pmu = { .recv = gt215_pmu_recv, }; +static const struct nvkm_pmu_fwif +gt215_pmu_fwif[] = { + { -1, gf100_pmu_nofw, >215_pmu }, + {} +}; + int gt215_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu) { - return nvkm_pmu_new_(>215_pmu, device, index, ppmu); + return nvkm_pmu_new_(gt215_pmu_fwif, device, index, ppmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 82a0a15d800b..32b2182ce67f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -5,11 +5,6 @@ #include #include -int nvkm_pmu_ctor(const struct nvkm_pmu_func *, struct nvkm_device *, - int index, struct nvkm_pmu *); -int nvkm_pmu_new_(const struct nvkm_pmu_func *, struct nvkm_device *, - int index, struct nvkm_pmu **); - struct nvkm_pmu_func { struct { u32 *data; @@ -44,4 +39,19 @@ void gf100_pmu_reset(struct nvkm_pmu *); void gk110_pmu_pgob(struct nvkm_pmu *, bool); void gm20b_pmu_recv(struct nvkm_pmu *); + +struct nvkm_pmu_fwif { + int version; + int (*load)(struct nvkm_pmu *, int ver, const struct nvkm_pmu_fwif *); + const struct nvkm_pmu_func *func; + const struct nvkm_acr_lsf_func *acr; +}; + +int gf100_pmu_nofw(struct nvkm_pmu *, int, const struct nvkm_pmu_fwif *); +int gm20b_pmu_load(struct nvkm_pmu *, int, const struct nvkm_pmu_fwif *); + +int nvkm_pmu_ctor(const struct nvkm_pmu_fwif *, struct nvkm_device *, + int index, struct nvkm_pmu *); +int nvkm_pmu_new_(const struct nvkm_pmu_fwif *, struct nvkm_device *, + int index, struct nvkm_pmu **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index 0de40c80e5ca..31be89d717cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -160,7 +160,4 @@ MODULE_FIRMWARE("nvidia/gm20b/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/sw_method_init.bin"); -MODULE_FIRMWARE("nvidia/gm20b/pmu/desc.bin"); -MODULE_FIRMWARE("nvidia/gm20b/pmu/image.bin"); -MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin"); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c index 6a5434c75678..509d4536dc00 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c @@ -85,7 +85,4 @@ MODULE_FIRMWARE("nvidia/gp10b/gr/sw_ctx.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/sw_nonctx.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/sw_bundle_init.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/sw_method_init.bin"); -MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin"); -MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin"); -MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin"); #endif -- cgit v1.2.3 From 2952a2b42e17ea0f72ee52de061975dddb9c62ec Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/pmu: initialise SW state for falcon from constructor This will allow us to register the falcon with ACR, and further customise its behaviour by providing the nvkm_falcon_func structure directly. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 15 +++++---------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c | 9 +++++---- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 15 +++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 3 +++ drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c | 4 ++-- .../drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c | 6 +++--- 20 files changed, 49 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index fd250bc48a41..0b72d63b2427 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -2,12 +2,12 @@ #ifndef __NVKM_PMU_H__ #define __NVKM_PMU_H__ #include -#include +#include struct nvkm_pmu { const struct nvkm_pmu_func *func; struct nvkm_subdev subdev; - struct nvkm_falcon *falcon; + struct nvkm_falcon falcon; struct nvkm_msgqueue *queue; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 1c308227ad6b..60e14f9a5415 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -134,19 +134,12 @@ nvkm_pmu_init(struct nvkm_subdev *subdev) return ret; } -static int -nvkm_pmu_oneinit(struct nvkm_subdev *subdev) -{ - struct nvkm_pmu *pmu = nvkm_pmu(subdev); - return nvkm_falcon_v1_new(&pmu->subdev, "PMU", 0x10a000, &pmu->falcon); -} - static void * nvkm_pmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); nvkm_msgqueue_del(&pmu->queue); - nvkm_falcon_del(&pmu->falcon); + nvkm_falcon_dtor(&pmu->falcon); return nvkm_pmu(subdev); } @@ -154,7 +147,6 @@ static const struct nvkm_subdev_func nvkm_pmu = { .dtor = nvkm_pmu_dtor, .preinit = nvkm_pmu_preinit, - .oneinit = nvkm_pmu_oneinit, .init = nvkm_pmu_init, .fini = nvkm_pmu_fini, .intr = nvkm_pmu_intr, @@ -174,7 +166,10 @@ nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, return PTR_ERR(fwif); pmu->func = fwif->func; - return 0; + + return nvkm_falcon_ctor(pmu->func->flcn, &pmu->subdev, + nvkm_subdev_name[pmu->subdev.index], 0x10a000, + &pmu->falcon); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c index bc48dfcfcb0c..3ecb3d9cbcf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c @@ -42,6 +42,7 @@ gf100_pmu_enabled(struct nvkm_pmu *pmu) static const struct nvkm_pmu_func gf100_pmu = { + .flcn = >215_pmu_flcn, .code.data = gf100_pmu_code, .code.size = sizeof(gf100_pmu_code), .data.data = gf100_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c index b4c81e272706..8dd0271aaaee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c @@ -26,6 +26,7 @@ static const struct nvkm_pmu_func gf119_pmu = { + .flcn = >215_pmu_flcn, .code.data = gf119_pmu_code, .code.size = sizeof(gf119_pmu_code), .data.data = gf119_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c index c497525d65ca..8b70cc17a634 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c @@ -105,6 +105,7 @@ gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable) static const struct nvkm_pmu_func gk104_pmu = { + .flcn = >215_pmu_flcn, .code.data = gk104_pmu_code, .code.size = sizeof(gk104_pmu_code), .data.data = gk104_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c index aa0b9e7c5a99..0081f2141b10 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c @@ -84,6 +84,7 @@ gk110_pmu_pgob(struct nvkm_pmu *pmu, bool enable) static const struct nvkm_pmu_func gk110_pmu = { + .flcn = >215_pmu_flcn, .code.data = gk110_pmu_code, .code.size = sizeof(gk110_pmu_code), .data.data = gk110_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c index 47a5ed32dcc5..b227c701a5e7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c @@ -26,6 +26,7 @@ static const struct nvkm_pmu_func gk208_pmu = { + .flcn = >215_pmu_flcn, .code.data = gk208_pmu_code, .code.size = sizeof(gk208_pmu_code), .data.data = gk208_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c index 67f65c54c7fd..26c1adf8f44c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c @@ -95,7 +95,7 @@ static void gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu *pmu, struct gk20a_pmu_dvfs_dev_status *status) { - struct nvkm_falcon *falcon = pmu->base.falcon; + struct nvkm_falcon *falcon = &pmu->base.falcon; status->busy = nvkm_falcon_rd32(falcon, 0x508 + (BUSY_SLOT * 0x10)); status->total= nvkm_falcon_rd32(falcon, 0x508 + (CLK_SLOT * 0x10)); @@ -104,7 +104,7 @@ gk20a_pmu_dvfs_get_dev_status(struct gk20a_pmu *pmu, static void gk20a_pmu_dvfs_reset_dev_status(struct gk20a_pmu *pmu) { - struct nvkm_falcon *falcon = pmu->base.falcon; + struct nvkm_falcon *falcon = &pmu->base.falcon; nvkm_falcon_wr32(falcon, 0x508 + (BUSY_SLOT * 0x10), 0x80000000); nvkm_falcon_wr32(falcon, 0x508 + (CLK_SLOT * 0x10), 0x80000000); @@ -160,7 +160,7 @@ gk20a_pmu_fini(struct nvkm_pmu *pmu) struct gk20a_pmu *gpmu = gk20a_pmu(pmu); nvkm_timer_alarm(pmu->subdev.device->timer, 0, &gpmu->alarm); - nvkm_falcon_put(pmu->falcon, &pmu->subdev); + nvkm_falcon_put(&pmu->falcon, &pmu->subdev); } static int @@ -169,7 +169,7 @@ gk20a_pmu_init(struct nvkm_pmu *pmu) struct gk20a_pmu *gpmu = gk20a_pmu(pmu); struct nvkm_subdev *subdev = &pmu->subdev; struct nvkm_device *device = pmu->subdev.device; - struct nvkm_falcon *falcon = pmu->falcon; + struct nvkm_falcon *falcon = &pmu->falcon; int ret; ret = nvkm_falcon_get(falcon, subdev); @@ -196,6 +196,7 @@ gk20a_dvfs_data= { static const struct nvkm_pmu_func gk20a_pmu = { + .flcn = >215_pmu_flcn, .enabled = gf100_pmu_enabled, .init = gk20a_pmu_init, .fini = gk20a_pmu_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c index 7dd4bec148d2..5afb55e58b51 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c @@ -28,6 +28,7 @@ static const struct nvkm_pmu_func gm107_pmu = { + .flcn = >215_pmu_flcn, .code.data = gm107_pmu_code, .code.size = sizeof(gm107_pmu_code), .data.data = gm107_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 1a7cfdef2d9c..5c262a28aa23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -41,6 +41,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) static const struct nvkm_pmu_func gm20b_pmu = { + .flcn = >215_pmu_flcn, .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, @@ -55,7 +56,7 @@ MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin"); int gm20b_pmu_load(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif) { - return nvkm_acr_lsfw_load_sig_image_desc(&pmu->subdev, pmu->falcon, + return nvkm_acr_lsfw_load_sig_image_desc(&pmu->subdev, &pmu->falcon, NVKM_ACR_LSF_PMU, "pmu/", ver, fwif->acr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c index 3b7f26c187f4..09e05db21ff5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c @@ -25,6 +25,7 @@ static const struct nvkm_pmu_func gp100_pmu = { + .flcn = >215_pmu_flcn, .enabled = gf100_pmu_enabled, .reset = gf100_pmu_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c index 08fda8088c49..262b8a3dd507 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c @@ -39,6 +39,7 @@ gp102_pmu_enabled(struct nvkm_pmu *pmu) static const struct nvkm_pmu_func gp102_pmu = { + .flcn = >215_pmu_flcn, .enabled = gp102_pmu_enabled, .reset = gp102_pmu_reset, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 2440e230f398..7134ef9d91af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -28,6 +28,7 @@ gp10b_pmu_acr = { static const struct nvkm_pmu_func gp10b_pmu = { + .flcn = >215_pmu_flcn, .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index f52d7519b8e0..073558972e42 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -241,8 +241,23 @@ gt215_pmu_init(struct nvkm_pmu *pmu) return 0; } +const struct nvkm_falcon_func +gt215_pmu_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + static const struct nvkm_pmu_func gt215_pmu = { + .flcn = >215_pmu_flcn, .code.data = gt215_pmu_code, .code.size = sizeof(gt215_pmu_code), .data.data = gt215_pmu_data, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 32b2182ce67f..91b4a2d3ad4c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -6,6 +6,8 @@ #include struct nvkm_pmu_func { + const struct nvkm_falcon_func *flcn; + struct { u32 *data; u32 size; @@ -27,6 +29,7 @@ struct nvkm_pmu_func { void (*pgob)(struct nvkm_pmu *, bool); }; +extern const struct nvkm_falcon_func gt215_pmu_flcn; int gt215_pmu_init(struct nvkm_pmu *); void gt215_pmu_fini(struct nvkm_pmu *); void gt215_pmu_intr(struct nvkm_pmu *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index 7af971db91bc..53770ecdbb2f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -1150,7 +1150,7 @@ acr_r352_generate_pmu_bl_desc(const struct nvkm_acr *acr, base = wpr_addr + img->ucode_off + pdesc->app_start_offset; addr_code = (base + pdesc->app_resident_code_offset) >> 8; addr_data = (base + pdesc->app_resident_data_offset) >> 8; - addr_args = pmu->falcon->data.limit; + addr_args = pmu->falcon.data.limit; addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; desc->dma_idx = FALCON_DMAIDX_UCODE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c index f6b2d20d7fc3..513445856f22 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c @@ -126,7 +126,7 @@ acr_r361_generate_pmu_bl_desc(const struct nvkm_acr *acr, base = wpr_addr + img->ucode_off + pdesc->app_start_offset; addr_code = base + pdesc->app_resident_code_offset; addr_data = base + pdesc->app_resident_data_offset; - addr_args = pmu->falcon->data.limit; + addr_args = pmu->falcon.data.limit; addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; desc->dma_idx = FALCON_DMAIDX_UCODE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c index 8f0647766038..7112ad74e3c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c @@ -40,7 +40,7 @@ acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr, base = wpr_addr + img->ucode_off + pdesc->app_start_offset; addr_code = base + pdesc->app_resident_code_offset; addr_data = base + pdesc->app_resident_data_offset; - addr_args = pmu->falcon->data.limit; + addr_args = pmu->falcon.data.limit; addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; desc->ctx_dma = FALCON_DMAIDX_UCODE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c index ee29c6c11afd..36ae6918beae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c @@ -133,13 +133,13 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev) switch (sb->acr->boot_falcon) { case NVKM_SECBOOT_FALCON_PMU: - sb->halt_falcon = sb->boot_falcon = subdev->device->pmu->falcon; + sb->halt_falcon = sb->boot_falcon = &subdev->device->pmu->falcon; break; case NVKM_SECBOOT_FALCON_SEC2: /* we must keep SEC2 alive forever since ACR will run on it */ nvkm_engine_ref(&subdev->device->sec2->engine); sb->boot_falcon = subdev->device->sec2->falcon; - sb->halt_falcon = subdev->device->pmu->falcon; + sb->halt_falcon = &subdev->device->pmu->falcon; break; default: nvkm_error(subdev, "Unmanaged boot falcon %s!\n", diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c index a84a999445bb..472f38a56639 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c @@ -110,7 +110,7 @@ acr_ls_ucode_load_pmu(const struct nvkm_secboot *sb, int maxver, return ret; /* Allocate the PMU queue corresponding to the FW version */ - ret = nvkm_msgqueue_new(img->ucode_desc.app_version, pmu->falcon, + ret = nvkm_msgqueue_new(img->ucode_desc.app_version, &pmu->falcon, sb, &pmu->queue); if (ret) return ret; @@ -123,10 +123,10 @@ acr_ls_pmu_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) { struct nvkm_device *device = sb->subdev.device; struct nvkm_pmu *pmu = device->pmu; - u32 addr_args = pmu->falcon->data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; + u32 addr_args = pmu->falcon.data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; int ret; - ret = acr_ls_msgqueue_post_run(pmu->queue, pmu->falcon, addr_args); + ret = acr_ls_msgqueue_post_run(pmu->queue, &pmu->falcon, addr_args); if (ret) return ret; -- cgit v1.2.3 From 6f0add0ad6e965e8ae1382b43501e67b30988d26 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gf100-: use nvkm_blob structure for fecs/gpccs fw It serves the exact same purpose. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 21 +++++++-------------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 20 +++++++------------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 12 ++++++------ 3 files changed, 20 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 6aefb2bb6e06..a9d4b6073b3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1636,7 +1636,7 @@ gf100_gr_intr(struct nvkm_gr *base) static void gf100_gr_init_fw(struct nvkm_falcon *falcon, - struct gf100_gr_fuc *code, struct gf100_gr_fuc *data) + struct nvkm_blob *code, struct nvkm_blob *data) { nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0); nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false); @@ -2013,13 +2013,6 @@ gf100_gr_fini_(struct nvkm_gr *base, bool suspend) return 0; } -void -gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc) -{ - kfree(fuc->data); - fuc->data = NULL; -} - static void gf100_gr_dtor_init(struct gf100_gr_pack *pack) { @@ -2036,10 +2029,10 @@ gf100_gr_dtor(struct nvkm_gr *base) nvkm_falcon_del(&gr->gpccs.falcon); nvkm_falcon_del(&gr->fecs.falcon); - gf100_gr_dtor_fw(&gr->fuc409c); - gf100_gr_dtor_fw(&gr->fuc409d); - gf100_gr_dtor_fw(&gr->fuc41ac); - gf100_gr_dtor_fw(&gr->fuc41ad); + nvkm_blob_dtor(&gr->fuc409c); + nvkm_blob_dtor(&gr->fuc409d); + nvkm_blob_dtor(&gr->fuc41ac); + nvkm_blob_dtor(&gr->fuc41ad); gf100_gr_dtor_init(gr->fuc_bundle); gf100_gr_dtor_init(gr->fuc_method); @@ -2067,7 +2060,7 @@ gf100_gr_ = { int gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname, - struct gf100_gr_fuc *fuc, int ret) + struct nvkm_blob *fuc, int ret) { struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; @@ -2111,7 +2104,7 @@ gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname, int gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, - struct gf100_gr_fuc *fuc) + struct nvkm_blob *fuc) { const struct firmware *fw; int ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 5cd5ab76926f..928ffad82766 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -55,11 +55,6 @@ struct gf100_gr_mmio { int buffer; }; -struct gf100_gr_fuc { - u32 *data; - u32 size; -}; - struct gf100_gr_zbc_color { u32 format; u32 ds[4]; @@ -92,10 +87,10 @@ struct gf100_gr { struct nvkm_falcon *falcon; } gpccs; - struct gf100_gr_fuc fuc409c; - struct gf100_gr_fuc fuc409d; - struct gf100_gr_fuc fuc41ac; - struct gf100_gr_fuc fuc41ad; + struct nvkm_blob fuc409c; + struct nvkm_blob fuc409d; + struct nvkm_blob fuc41ac; + struct nvkm_blob fuc41ad; bool firmware; /* @@ -269,9 +264,8 @@ struct gf100_gr_chan { void gf100_gr_ctxctl_debug(struct gf100_gr *); -void gf100_gr_dtor_fw(struct gf100_gr_fuc *); int gf100_gr_ctor_fw(struct gf100_gr *, const char *, - struct gf100_gr_fuc *); + struct nvkm_blob *); u64 gf100_gr_units(struct nvkm_gr *); void gf100_gr_zbc_init(struct gf100_gr *); @@ -294,8 +288,8 @@ struct gf100_gr_pack { for (init = pack->init; init && init->count; init++) struct gf100_gr_ucode { - struct gf100_gr_fuc code; - struct gf100_gr_fuc data; + struct nvkm_blob code; + struct nvkm_blob data; }; extern struct gf100_gr_ucode gf100_gr_fecs_ucode; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index b57ab5cea9a1..43b83baed2a5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -36,7 +36,7 @@ int gk20a_gr_av_to_init(struct gf100_gr *gr, const char *fw_name, struct gf100_gr_pack **ppack) { - struct gf100_gr_fuc fuc; + struct nvkm_blob fuc; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; @@ -70,7 +70,7 @@ gk20a_gr_av_to_init(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - gf100_gr_dtor_fw(&fuc); + nvkm_blob_dtor(&fuc); return ret; } @@ -85,7 +85,7 @@ int gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *fw_name, struct gf100_gr_pack **ppack) { - struct gf100_gr_fuc fuc; + struct nvkm_blob fuc; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; @@ -119,7 +119,7 @@ gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - gf100_gr_dtor_fw(&fuc); + nvkm_blob_dtor(&fuc); return ret; } @@ -127,7 +127,7 @@ int gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, struct gf100_gr_pack **ppack) { - struct gf100_gr_fuc fuc; + struct nvkm_blob fuc; struct gf100_gr_init *init; struct gf100_gr_pack *pack; /* We don't suppose we will initialize more than 16 classes here... */ @@ -179,7 +179,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - gf100_gr_dtor_fw(&fuc); + nvkm_blob_dtor(&fuc); return ret; } -- cgit v1.2.3 From a2bfb50e72aeb139801109e3b4eb73ac53bde314 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gk20a,gm200-: use nvkm_firmware_load_blob for sw init Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 10 +--- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 74 ++++++++++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 8 ++- 3 files changed, 44 insertions(+), 48 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 928ffad82766..231fe7ef4a67 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -244,6 +244,8 @@ void gp100_gr_zbc_clear_depth(struct gf100_gr *, int); void gp102_gr_init_swdx_pes_mask(struct gf100_gr *); extern const struct gf100_gr_func_zbc gp102_gr_zbc; +int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver); + #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) #include @@ -304,14 +306,6 @@ void gf100_gr_icmd(struct gf100_gr *, const struct gf100_gr_pack *); void gf100_gr_mthd(struct gf100_gr *, const struct gf100_gr_pack *); int gf100_gr_init_ctxctl(struct gf100_gr *); -/* external bundles loading functions */ -int gk20a_gr_av_to_init(struct gf100_gr *, const char *, - struct gf100_gr_pack **); -int gk20a_gr_aiv_to_init(struct gf100_gr *, const char *, - struct gf100_gr_pack **); -int gk20a_gr_av_to_method(struct gf100_gr *, const char *, - struct gf100_gr_pack **); - int gm200_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, int, struct nvkm_gr **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 43b83baed2a5..357870c6338e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -22,6 +22,7 @@ #include "gf100.h" #include "ctxgf100.h" +#include #include #include @@ -33,21 +34,22 @@ struct gk20a_fw_av }; int -gk20a_gr_av_to_init(struct gf100_gr *gr, const char *fw_name, - struct gf100_gr_pack **ppack) +gk20a_gr_av_to_init(struct gf100_gr *gr, const char *path, const char *name, + int ver, struct gf100_gr_pack **ppack) { - struct nvkm_blob fuc; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; int ret; int i; - ret = gf100_gr_ctor_fw(gr, fw_name, &fuc); + ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); if (ret) return ret; - nent = (fuc.size / sizeof(struct gk20a_fw_av)); + nent = (blob.size / sizeof(struct gk20a_fw_av)); pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); if (!pack) { ret = -ENOMEM; @@ -59,7 +61,7 @@ gk20a_gr_av_to_init(struct gf100_gr *gr, const char *fw_name, for (i = 0; i < nent; i++) { struct gf100_gr_init *ent = &init[i]; - struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i]; ent->addr = av->addr; ent->data = av->data; @@ -70,7 +72,7 @@ gk20a_gr_av_to_init(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - nvkm_blob_dtor(&fuc); + nvkm_blob_dtor(&blob); return ret; } @@ -82,21 +84,22 @@ struct gk20a_fw_aiv }; int -gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *fw_name, - struct gf100_gr_pack **ppack) +gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *path, const char *name, + int ver, struct gf100_gr_pack **ppack) { - struct nvkm_blob fuc; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; int nent; int ret; int i; - ret = gf100_gr_ctor_fw(gr, fw_name, &fuc); + ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); if (ret) return ret; - nent = (fuc.size / sizeof(struct gk20a_fw_aiv)); + nent = (blob.size / sizeof(struct gk20a_fw_aiv)); pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1))); if (!pack) { ret = -ENOMEM; @@ -108,7 +111,7 @@ gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *fw_name, for (i = 0; i < nent; i++) { struct gf100_gr_init *ent = &init[i]; - struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)fuc.data)[i]; + struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob.data)[i]; ent->addr = av->addr; ent->data = av->data; @@ -119,15 +122,16 @@ gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - nvkm_blob_dtor(&fuc); + nvkm_blob_dtor(&blob); return ret; } int -gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, - struct gf100_gr_pack **ppack) +gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name, + int ver, struct gf100_gr_pack **ppack) { - struct nvkm_blob fuc; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_blob blob; struct gf100_gr_init *init; struct gf100_gr_pack *pack; /* We don't suppose we will initialize more than 16 classes here... */ @@ -137,11 +141,11 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, int ret; int i; - ret = gf100_gr_ctor_fw(gr, fw_name, &fuc); + ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob); if (ret) return ret; - nent = (fuc.size / sizeof(struct gk20a_fw_av)); + nent = (blob.size / sizeof(struct gk20a_fw_av)); pack = vzalloc((sizeof(*pack) * (max_classes + 1)) + (sizeof(*init) * (nent + max_classes + 1))); @@ -153,7 +157,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, init = (void *)(pack + max_classes + 1); for (i = 0; i < nent; i++, init++) { - struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i]; + struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i]; u32 class = av->addr & 0xffff; u32 addr = (av->addr & 0xffff0000) >> 14; @@ -179,7 +183,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *fw_name, *ppack = pack; end: - nvkm_blob_dtor(&fuc); + nvkm_blob_dtor(&blob); return ret; } @@ -303,6 +307,18 @@ gk20a_gr = { } }; +int +gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver) +{ + if (gk20a_gr_av_to_init(gr, path, "sw_nonctx", ver, &gr->fuc_sw_nonctx) || + gk20a_gr_aiv_to_init(gr, path, "sw_ctx", ver, &gr->fuc_sw_ctx) || + gk20a_gr_av_to_init(gr, path, "sw_bundle_init", ver, &gr->fuc_bundle) || + gk20a_gr_av_to_method(gr, path, "sw_method_init", ver, &gr->fuc_method)) + return -ENOENT; + + return 0; +} + int gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { @@ -323,21 +339,9 @@ gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) return -ENODEV; - ret = gk20a_gr_av_to_init(gr, "sw_nonctx", &gr->fuc_sw_nonctx); - if (ret) - return ret; - - ret = gk20a_gr_aiv_to_init(gr, "sw_ctx", &gr->fuc_sw_ctx); - if (ret) - return ret; - - ret = gk20a_gr_av_to_init(gr, "sw_bundle_init", &gr->fuc_bundle); + ret = gk20a_gr_load_sw(gr, "", 0); if (ret) - return ret; - - ret = gk20a_gr_av_to_method(gr, "sw_method_init", &gr->fuc_method); - if (ret) - return ret; + return -ENODEV; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index eff30662b984..775ada042b3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -153,11 +153,9 @@ gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return ret; } - if ((ret = gk20a_gr_av_to_init(gr, "gr/sw_nonctx", &gr->fuc_sw_nonctx)) || - (ret = gk20a_gr_aiv_to_init(gr, "gr/sw_ctx", &gr->fuc_sw_ctx)) || - (ret = gk20a_gr_av_to_init(gr, "gr/sw_bundle_init", &gr->fuc_bundle)) || - (ret = gk20a_gr_av_to_method(gr, "gr/sw_method_init", &gr->fuc_method))) - return ret; + ret = gk20a_gr_load_sw(gr, "gr/", 0); + if (ret) + return -ENODEV; return 0; } -- cgit v1.2.3 From 0033f15b44bc29ec6fe5b58de18d801c3de74c88 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gf100-: drop fuc_ prefix on sw init Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 12 ++++++------ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 18 ++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 8 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 10 +++++----- 6 files changed, 27 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 284d7e022213..4338e515040d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1368,7 +1368,7 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) nvkm_mc_unk260(device, 0); - if (!gr->fuc_sw_ctx) { + if (!gr->sw_ctx) { gf100_gr_mmio(gr, grctx->hub); gf100_gr_mmio(gr, grctx->gpc_0); gf100_gr_mmio(gr, grctx->zcull); @@ -1376,7 +1376,7 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) gf100_gr_mmio(gr, grctx->tpc); gf100_gr_mmio(gr, grctx->ppc); } else { - gf100_gr_mmio(gr, gr->fuc_sw_ctx); + gf100_gr_mmio(gr, gr->sw_ctx); } gf100_gr_wait_idle(gr); @@ -1395,8 +1395,8 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) gf100_gr_wait_idle(gr); if (grctx->r400088) grctx->r400088(gr, false); - if (gr->fuc_bundle) - gf100_gr_icmd(gr, gr->fuc_bundle); + if (gr->bundle) + gf100_gr_icmd(gr, gr->bundle); else gf100_gr_icmd(gr, grctx->icmd); if (grctx->sw_veid_bundle_init) @@ -1405,8 +1405,8 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) nvkm_wr32(device, 0x404154, idle_timeout); - if (gr->fuc_method) - gf100_gr_mthd(gr, gr->fuc_method); + if (gr->method) + gf100_gr_mthd(gr, gr->method); else gf100_gr_mthd(gr, grctx->mthd); nvkm_mc_unk260(device, 1); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c index 896d473dcc0f..c0d36bc601f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c @@ -32,7 +32,7 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) u32 idle_timeout; int i; - gf100_gr_mmio(gr, gr->fuc_sw_ctx); + gf100_gr_mmio(gr, gr->sw_ctx); gf100_gr_wait_idle(gr); @@ -56,10 +56,10 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) nvkm_wr32(device, 0x404154, idle_timeout); gf100_gr_wait_idle(gr); - gf100_gr_mthd(gr, gr->fuc_method); + gf100_gr_mthd(gr, gr->method); gf100_gr_wait_idle(gr); - gf100_gr_icmd(gr, gr->fuc_bundle); + gf100_gr_icmd(gr, gr->bundle); grctx->pagepool(info); grctx->bundle(info); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c index a1d9e114ebeb..6b92f8aa18a3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c @@ -29,7 +29,7 @@ gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) u32 idle_timeout; int i, tmp; - gf100_gr_mmio(gr, gr->fuc_sw_ctx); + gf100_gr_mmio(gr, gr->sw_ctx); gf100_gr_wait_idle(gr); @@ -59,10 +59,10 @@ gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) nvkm_wr32(device, 0x404154, idle_timeout); gf100_gr_wait_idle(gr); - gf100_gr_mthd(gr, gr->fuc_method); + gf100_gr_mthd(gr, gr->method); gf100_gr_wait_idle(gr); - gf100_gr_icmd(gr, gr->fuc_bundle); + gf100_gr_icmd(gr, gr->bundle); grctx->pagepool(info); grctx->bundle(info); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index a9d4b6073b3a..f0925d40e6fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2013,12 +2013,6 @@ gf100_gr_fini_(struct nvkm_gr *base, bool suspend) return 0; } -static void -gf100_gr_dtor_init(struct gf100_gr_pack *pack) -{ - vfree(pack); -} - void * gf100_gr_dtor(struct nvkm_gr *base) { @@ -2034,10 +2028,10 @@ gf100_gr_dtor(struct nvkm_gr *base) nvkm_blob_dtor(&gr->fuc41ac); nvkm_blob_dtor(&gr->fuc41ad); - gf100_gr_dtor_init(gr->fuc_bundle); - gf100_gr_dtor_init(gr->fuc_method); - gf100_gr_dtor_init(gr->fuc_sw_ctx); - gf100_gr_dtor_init(gr->fuc_sw_nonctx); + vfree(gr->bundle); + vfree(gr->method); + vfree(gr->sw_ctx); + vfree(gr->sw_nonctx); return gr; } @@ -2303,8 +2297,8 @@ gf100_gr_init(struct gf100_gr *gr) gr->func->init_gpc_mmu(gr); - if (gr->fuc_sw_nonctx) - gf100_gr_mmio(gr, gr->fuc_sw_nonctx); + if (gr->sw_nonctx) + gf100_gr_mmio(gr, gr->sw_nonctx); else gf100_gr_mmio(gr, gr->func->mmio); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 231fe7ef4a67..bece3c753433 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -97,10 +97,10 @@ struct gf100_gr { * Used if the register packs are loaded from NVIDIA fw instead of * using hardcoded arrays. To be allocated with vzalloc(). */ - struct gf100_gr_pack *fuc_sw_nonctx; - struct gf100_gr_pack *fuc_sw_ctx; - struct gf100_gr_pack *fuc_bundle; - struct gf100_gr_pack *fuc_method; + struct gf100_gr_pack *sw_nonctx; + struct gf100_gr_pack *sw_ctx; + struct gf100_gr_pack *bundle; + struct gf100_gr_pack *method; struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_CNT]; struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 357870c6338e..a6ee5d61e715 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -229,7 +229,7 @@ gk20a_gr_init(struct gf100_gr *gr) /* Clear SCC RAM */ nvkm_wr32(device, 0x40802c, 0x1); - gf100_gr_mmio(gr, gr->fuc_sw_nonctx); + gf100_gr_mmio(gr, gr->sw_nonctx); ret = gk20a_gr_wait_mem_scrubbing(gr); if (ret) @@ -310,10 +310,10 @@ gk20a_gr = { int gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver) { - if (gk20a_gr_av_to_init(gr, path, "sw_nonctx", ver, &gr->fuc_sw_nonctx) || - gk20a_gr_aiv_to_init(gr, path, "sw_ctx", ver, &gr->fuc_sw_ctx) || - gk20a_gr_av_to_init(gr, path, "sw_bundle_init", ver, &gr->fuc_bundle) || - gk20a_gr_av_to_method(gr, path, "sw_method_init", ver, &gr->fuc_method)) + if (gk20a_gr_av_to_init(gr, path, "sw_nonctx", ver, &gr->sw_nonctx) || + gk20a_gr_aiv_to_init(gr, path, "sw_ctx", ver, &gr->sw_ctx) || + gk20a_gr_av_to_init(gr, path, "sw_bundle_init", ver, &gr->bundle) || + gk20a_gr_av_to_method(gr, path, "sw_method_init", ver, &gr->method)) return -ENOENT; return 0; -- cgit v1.2.3 From 00e1b5dcf76648e7e0de9f56358fee86263df1ca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gf100-: move fecs/gpccs ucode into their substructures Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 22 ++++++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 9 +++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 8 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 8 ++++---- 4 files changed, 25 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index f0925d40e6fe..8ee193b6224f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1701,12 +1701,14 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS); else - gf100_gr_init_fw(gr->fecs.falcon, &gr->fuc409c, &gr->fuc409d); + gf100_gr_init_fw(gr->fecs.falcon, &gr->fecs.inst, + &gr->fecs.data); if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS); else - gf100_gr_init_fw(gr->gpccs.falcon, &gr->fuc41ac, &gr->fuc41ad); + gf100_gr_init_fw(gr->gpccs.falcon, &gr->gpccs.inst, + &gr->gpccs.data); if (secboot_mask != 0) { int ret = nvkm_secboot_reset(sb, secboot_mask); @@ -2023,10 +2025,10 @@ gf100_gr_dtor(struct nvkm_gr *base) nvkm_falcon_del(&gr->gpccs.falcon); nvkm_falcon_del(&gr->fecs.falcon); - nvkm_blob_dtor(&gr->fuc409c); - nvkm_blob_dtor(&gr->fuc409d); - nvkm_blob_dtor(&gr->fuc41ac); - nvkm_blob_dtor(&gr->fuc41ad); + nvkm_blob_dtor(&gr->fecs.inst); + nvkm_blob_dtor(&gr->fecs.data); + nvkm_blob_dtor(&gr->gpccs.inst); + nvkm_blob_dtor(&gr->gpccs.data); vfree(gr->bundle); vfree(gr->method); @@ -2146,10 +2148,10 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return ret; if (gr->firmware) { - if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) || - gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) || - gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) || - gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) + if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fecs.inst) || + gf100_gr_ctor_fw(gr, "fecs_data", &gr->fecs.data) || + gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->gpccs.inst) || + gf100_gr_ctor_fw(gr, "gpccs_data", &gr->gpccs.data)) return -ENODEV; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index bece3c753433..c048a87ee4df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -79,18 +79,19 @@ struct gf100_gr { struct { struct nvkm_falcon *falcon; + struct nvkm_blob inst; + struct nvkm_blob data; + struct mutex mutex; u32 disable; } fecs; struct { struct nvkm_falcon *falcon; + struct nvkm_blob inst; + struct nvkm_blob data; } gpccs; - struct nvkm_blob fuc409c; - struct nvkm_blob fuc409d; - struct nvkm_blob fuc41ac; - struct nvkm_blob fuc41ad; bool firmware; /* diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index a6ee5d61e715..2ee733984407 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -333,10 +333,10 @@ gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) if (ret) return ret; - if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) || - gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) || - gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) || - gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) + if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fecs.inst) || + gf100_gr_ctor_fw(gr, "fecs_data", &gr->fecs.data) || + gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->gpccs.inst) || + gf100_gr_ctor_fw(gr, "gpccs_data", &gr->gpccs.data)) return -ENODEV; ret = gk20a_gr_load_sw(gr, "", 0); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 775ada042b3e..085f5e32a3d9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -142,14 +142,14 @@ gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, /* Load firmwares for non-secure falcons */ if (!nvkm_secboot_is_managed(device->secboot, NVKM_SECBOOT_FALCON_FECS)) { - if ((ret = gf100_gr_ctor_fw(gr, "gr/fecs_inst", &gr->fuc409c)) || - (ret = gf100_gr_ctor_fw(gr, "gr/fecs_data", &gr->fuc409d))) + if ((ret = gf100_gr_ctor_fw(gr, "gr/fecs_inst", &gr->fecs.inst)) || + (ret = gf100_gr_ctor_fw(gr, "gr/fecs_data", &gr->fecs.data))) return ret; } if (!nvkm_secboot_is_managed(device->secboot, NVKM_SECBOOT_FALCON_GPCCS)) { - if ((ret = gf100_gr_ctor_fw(gr, "gr/gpccs_inst", &gr->fuc41ac)) || - (ret = gf100_gr_ctor_fw(gr, "gr/gpccs_data", &gr->fuc41ad))) + if ((ret = gf100_gr_ctor_fw(gr, "gr/gpccs_inst", &gr->gpccs.inst)) || + (ret = gf100_gr_ctor_fw(gr, "gr/gpccs_data", &gr->gpccs.data))) return ret; } -- cgit v1.2.3 From a096ff19811e21e5c9215e72637bdd2c05d13471 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gp108: split from gp107 ACR LS FW loading is moving out of SECBOOT and into their specific subdevs, and the available GP107/GP108 FWs have interface differences. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c | 28 +++++++++++++++++++++++ 6 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h index 2cde36f3c064..612383b31ece 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h @@ -50,6 +50,7 @@ int gp100_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp102_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp104_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp107_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int gp108_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp10b_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gv100_gr_new(struct nvkm_device *, int, struct nvkm_gr **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index b24e64f5e7bc..8817ecaf4e7e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2374,7 +2374,7 @@ nv138_chipset = { .disp = gp102_disp_new, .dma = gf119_dma_new, .fifo = gp100_fifo_new, - .gr = gp107_gr_new, + .gr = gp108_gr_new, .nvdec[0] = gp102_nvdec_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild index 73724a8cb861..02a1025d0060 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild @@ -36,6 +36,7 @@ nvkm-y += nvkm/engine/gr/gp100.o nvkm-y += nvkm/engine/gr/gp102.o nvkm-y += nvkm/engine/gr/gp104.o nvkm-y += nvkm/engine/gr/gp107.o +nvkm-y += nvkm/engine/gr/gp108.o nvkm-y += nvkm/engine/gr/gp10b.o nvkm-y += nvkm/engine/gr/gv100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index c048a87ee4df..b4c15ebc53ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -245,6 +245,8 @@ void gp100_gr_zbc_clear_depth(struct gf100_gr *, int); void gp102_gr_init_swdx_pes_mask(struct gf100_gr *); extern const struct gf100_gr_func_zbc gp102_gr_zbc; +extern const struct gf100_gr_func gp107_gr; + int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver); #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c index 812aba91653f..70e9d43ec802 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c @@ -26,7 +26,7 @@ #include -static const struct gf100_gr_func +const struct gf100_gr_func gp107_gr = { .oneinit_tiles = gm200_gr_oneinit_tiles, .oneinit_sm_id = gm200_gr_oneinit_sm_id, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c new file mode 100644 index 000000000000..4e344470d56a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "gf100.h" + +int +gp108_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gm200_gr_new_(&gp107_gr, device, index, pgr); +} -- cgit v1.2.3 From ef16dc278ec22ddbf8da54bd06a6e662719c1420 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gf100-: select implementation based on available FW This will allow for further customisation of the subdev depending on what firmware is available. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 156 +++++++++------------ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 38 +++-- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c | 43 +++--- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c | 9 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 118 +++++++++++----- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 51 ++++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 21 ++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c | 21 ++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c | 34 ++++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c | 21 ++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c | 31 +++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 29 +++- drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 21 ++- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c | 53 ------- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 13 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 48 ------- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c | 24 ---- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c | 15 -- 27 files changed, 498 insertions(+), 329 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 8ee193b6224f..c174f4aeab60 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2055,86 +2055,8 @@ gf100_gr_ = { }; int -gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname, - struct nvkm_blob *fuc, int ret) -{ - struct nvkm_subdev *subdev = &gr->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const struct firmware *fw; - char f[32]; - - /* see if this firmware has a legacy path */ - if (!strcmp(fwname, "fecs_inst")) - fwname = "fuc409c"; - else if (!strcmp(fwname, "fecs_data")) - fwname = "fuc409d"; - else if (!strcmp(fwname, "gpccs_inst")) - fwname = "fuc41ac"; - else if (!strcmp(fwname, "gpccs_data")) - fwname = "fuc41ad"; - else { - /* nope, let's just return the error we got */ - nvkm_error(subdev, "failed to load %s\n", fwname); - return ret; - } - - /* yes, try to load from the legacy path */ - nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname); - - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); - ret = request_firmware(&fw, f, device->dev); - if (ret) { - snprintf(f, sizeof(f), "nouveau/%s", fwname); - ret = request_firmware(&fw, f, device->dev); - if (ret) { - nvkm_error(subdev, "failed to load %s\n", fwname); - return ret; - } - } - - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - release_firmware(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -int -gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, - struct nvkm_blob *fuc) -{ - const struct firmware *fw; - int ret; - - ret = nvkm_firmware_get(&gr->base.engine.subdev, fwname, &fw); - if (ret) { - ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); - if (ret) - return -ENODEV; - return 0; - } - - fuc->size = fw->size; - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); - nvkm_firmware_put(fw); - return (fuc->data != NULL) ? 0 : -ENOMEM; -} - -int -gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, - int index, struct gf100_gr *gr) -{ - gr->func = func; - gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW", - func->fecs.ucode == NULL); - - return nvkm_gr_ctor(&gf100_gr_, device, index, - gr->firmware || func->fecs.ucode != NULL, - &gr->base); -} - -int -gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, - int index, struct nvkm_gr **pgr) +gf100_gr_new_(const struct gf100_gr_fwif *fwif, + struct nvkm_device *device, int index, struct nvkm_gr **pgr) { struct gf100_gr *gr; int ret; @@ -2143,18 +2065,15 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return -ENOMEM; *pgr = &gr->base; - ret = gf100_gr_ctor(func, device, index, gr); + ret = nvkm_gr_ctor(&gf100_gr_, device, index, true, &gr->base); if (ret) return ret; - if (gr->firmware) { - if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fecs.inst) || - gf100_gr_ctor_fw(gr, "fecs_data", &gr->fecs.data) || - gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->gpccs.inst) || - gf100_gr_ctor_fw(gr, "gpccs_data", &gr->gpccs.data)) - return -ENODEV; - } + fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr); + if (IS_ERR(fwif)) + return -ENODEV; + gr->func = fwif->func; return 0; } @@ -2457,8 +2376,67 @@ gf100_gr = { } }; +int +gf100_gr_nofw(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + gr->firmware = false; + return 0; +} + +static int +gf100_gr_load_fw(struct gf100_gr *gr, const char *name, + struct nvkm_blob *blob) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + const struct firmware *fw; + char f[32]; + int ret; + + snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, name); + ret = request_firmware(&fw, f, device->dev); + if (ret) { + snprintf(f, sizeof(f), "nouveau/%s", name); + ret = request_firmware(&fw, f, device->dev); + if (ret) { + nvkm_error(subdev, "failed to load %s\n", name); + return ret; + } + } + + blob->size = fw->size; + blob->data = kmemdup(fw->data, blob->size, GFP_KERNEL); + release_firmware(fw); + return (blob->data != NULL) ? 0 : -ENOMEM; +} + +int +gf100_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + if (!nvkm_boolopt(device->cfgopt, "NvGrUseFW", false)) + return -EINVAL; + + if (gf100_gr_load_fw(gr, "fuc409c", &gr->fecs.inst) || + gf100_gr_load_fw(gr, "fuc409d", &gr->fecs.data) || + gf100_gr_load_fw(gr, "fuc41ac", &gr->gpccs.inst) || + gf100_gr_load_fw(gr, "fuc41ad", &gr->gpccs.data)) + return -ENOENT; + + gr->firmware = true; + return 0; +} + +static const struct gf100_gr_fwif +gf100_gr_fwif[] = { + { -1, gf100_gr_load, &gf100_gr }, + { -1, gf100_gr_nofw, &gf100_gr }, + {} +}; + int gf100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf100_gr, device, index, pgr); + return gf100_gr_new_(gf100_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index b4c15ebc53ec..d01d1683b50c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -136,12 +136,6 @@ struct gf100_gr { u32 size_pm; }; -int gf100_gr_ctor(const struct gf100_gr_func *, struct nvkm_device *, - int, struct gf100_gr *); -int gf100_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, - int, struct nvkm_gr **); -void *gf100_gr_dtor(struct nvkm_gr *); - int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst); struct gf100_gr_func_zbc { @@ -247,8 +241,6 @@ extern const struct gf100_gr_func_zbc gp102_gr_zbc; extern const struct gf100_gr_func gp107_gr; -int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver); - #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) #include @@ -269,8 +261,6 @@ struct gf100_gr_chan { void gf100_gr_ctxctl_debug(struct gf100_gr *); -int gf100_gr_ctor_fw(struct gf100_gr *, const char *, - struct nvkm_blob *); u64 gf100_gr_units(struct nvkm_gr *); void gf100_gr_zbc_init(struct gf100_gr *); @@ -309,9 +299,6 @@ void gf100_gr_icmd(struct gf100_gr *, const struct gf100_gr_pack *); void gf100_gr_mthd(struct gf100_gr *, const struct gf100_gr_pack *); int gf100_gr_init_ctxctl(struct gf100_gr *); -int gm200_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, int, - struct nvkm_gr **); - /* register init value lists */ extern const struct gf100_gr_init gf100_gr_init_main_0[]; @@ -394,4 +381,29 @@ extern const struct gf100_gr_init gm107_gr_init_cbm_0[]; void gm107_gr_init_bios(struct gf100_gr *); void gm200_gr_init_gpc_mmu(struct gf100_gr *); + +struct gf100_gr_fwif { + int version; + int (*load)(struct gf100_gr *, int ver, const struct gf100_gr_fwif *); + const struct gf100_gr_func *func; + const struct nvkm_acr_lsf_func *fecs; + const struct nvkm_acr_lsf_func *gpccs; +}; + +int gf100_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *); +int gf100_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *); + +int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver); + +int gm200_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *); +extern const struct nvkm_acr_lsf_func gm200_gr_gpccs_acr; +extern const struct nvkm_acr_lsf_func gm200_gr_fecs_acr; + +extern const struct nvkm_acr_lsf_func gm20b_gr_fecs_acr; + +extern const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr; +extern const struct nvkm_acr_lsf_func gp108_gr_fecs_acr; + +int gf100_gr_new_(const struct gf100_gr_fwif *, struct nvkm_device *, int, + struct nvkm_gr **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index 42c2fd9fc04e..0536fe8b2b92 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -144,8 +144,15 @@ gf104_gr = { } }; +static const struct gf100_gr_fwif +gf104_gr_fwif[] = { + { -1, gf100_gr_load, &gf104_gr }, + { -1, gf100_gr_nofw, &gf104_gr }, + {} +}; + int gf104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf104_gr, device, index, pgr); + return gf100_gr_new_(gf104_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index 4731a460adc7..14284b06112f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -143,8 +143,15 @@ gf108_gr = { } }; +const struct gf100_gr_fwif +gf108_gr_fwif[] = { + { -1, gf100_gr_load, &gf108_gr }, + { -1, gf100_gr_nofw, &gf108_gr }, + {} +}; + int gf108_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf108_gr, device, index, pgr); + return gf100_gr_new_(gf108_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index cdf759c8cd7f..280752551a3a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -119,8 +119,15 @@ gf110_gr = { } }; +static const struct gf100_gr_fwif +gf110_gr_fwif[] = { + { -1, gf100_gr_load, &gf110_gr }, + { -1, gf100_gr_nofw, &gf110_gr }, + {} +}; + int gf110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf110_gr, device, index, pgr); + return gf100_gr_new_(gf110_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index a4158f84c649..235c3fbe4b95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -184,8 +184,15 @@ gf117_gr = { } }; +static const struct gf100_gr_fwif +gf117_gr_fwif[] = { + { -1, gf100_gr_load, &gf117_gr }, + { -1, gf100_gr_nofw, &gf117_gr }, + {} +}; + int gf117_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf117_gr, device, index, pgr); + return gf100_gr_new_(gf117_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index 4197844870b3..7eac385ece97 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -210,8 +210,15 @@ gf119_gr = { } }; +static const struct gf100_gr_fwif +gf119_gr_fwif[] = { + { -1, gf100_gr_load, &gf119_gr }, + { -1, gf100_gr_nofw, &gf119_gr }, + {} +}; + int gf119_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gf119_gr, device, index, pgr); + return gf100_gr_new_(gf119_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 477fee3e3715..89f51d76082b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -489,8 +489,15 @@ gk104_gr = { } }; +static const struct gf100_gr_fwif +gk104_gr_fwif[] = { + { -1, gf100_gr_load, &gk104_gr }, + { -1, gf100_gr_nofw, &gk104_gr }, + {} +}; + int gk104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gk104_gr, device, index, pgr); + return gf100_gr_new_(gk104_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index 7cd628c84e07..735f05e54d62 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -385,8 +385,15 @@ gk110_gr = { } }; +static const struct gf100_gr_fwif +gk110_gr_fwif[] = { + { -1, gf100_gr_load, &gk110_gr }, + { -1, gf100_gr_nofw, &gk110_gr }, + {} +}; + int gk110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gk110_gr, device, index, pgr); + return gf100_gr_new_(gk110_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index a38faa215635..adc971be8f3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -136,8 +136,15 @@ gk110b_gr = { } }; +static const struct gf100_gr_fwif +gk110b_gr_fwif[] = { + { -1, gf100_gr_load, &gk110b_gr }, + { -1, gf100_gr_nofw, &gk110b_gr }, + {} +}; + int gk110b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gk110b_gr, device, index, pgr); + return gf100_gr_new_(gk110b_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 58456660e603..aa0eff6795ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -194,8 +194,15 @@ gk208_gr = { } }; +static const struct gf100_gr_fwif +gk208_gr_fwif[] = { + { -1, gf100_gr_load, &gk208_gr }, + { -1, gf100_gr_nofw, &gk208_gr }, + {} +}; + int gk208_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gk208_gr, device, index, pgr); + return gf100_gr_new_(gk208_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c index 2ee733984407..4209b24a46d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c @@ -319,29 +319,34 @@ gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver) return 0; } -int -gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +static int +gk20a_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) { - struct gf100_gr *gr; - int ret; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; - if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) - return -ENOMEM; - *pgr = &gr->base; + if (nvkm_firmware_load_blob(subdev, "", "fecs_inst", ver, + &gr->fecs.inst) || + nvkm_firmware_load_blob(subdev, "", "fecs_data", ver, + &gr->fecs.data) || + nvkm_firmware_load_blob(subdev, "", "gpccs_inst", ver, + &gr->gpccs.inst) || + nvkm_firmware_load_blob(subdev, "", "gpccs_data", ver, + &gr->gpccs.data)) + return -ENOENT; - ret = gf100_gr_ctor(&gk20a_gr, device, index, gr); - if (ret) - return ret; + gr->firmware = true; - if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fecs.inst) || - gf100_gr_ctor_fw(gr, "fecs_data", &gr->fecs.data) || - gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->gpccs.inst) || - gf100_gr_ctor_fw(gr, "gpccs_data", &gr->gpccs.data)) - return -ENODEV; + return gk20a_gr_load_sw(gr, "", ver); +} - ret = gk20a_gr_load_sw(gr, "", 0); - if (ret) - return -ENODEV; +static const struct gf100_gr_fwif +gk20a_gr_fwif[] = { + { -1, gk20a_gr_load, &gk20a_gr }, + {} +}; - return 0; +int +gk20a_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(gk20a_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c index 92e31d397207..09bb78ba9d00 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c @@ -429,8 +429,15 @@ gm107_gr = { } }; +static const struct gf100_gr_fwif +gm107_gr_fwif[] = { + { -1, gf100_gr_load, &gm107_gr }, + { -1, gf100_gr_nofw, &gm107_gr }, + {} +}; + int gm107_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gf100_gr_new_(&gm107_gr, device, index, pgr); + return gf100_gr_new_(gm107_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 085f5e32a3d9..d3907d8a7d03 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -24,6 +24,8 @@ #include "gf100.h" #include "ctxgf100.h" +#include +#include #include #include @@ -32,6 +34,14 @@ * PGRAPH engine/subdev functions ******************************************************************************/ +const struct nvkm_acr_lsf_func +gm200_gr_gpccs_acr = { +}; + +const struct nvkm_acr_lsf_func +gm200_gr_fecs_acr = { +}; + int gm200_gr_rops(struct gf100_gr *gr) { @@ -124,42 +134,6 @@ gm200_gr_oneinit_tiles(struct gf100_gr *gr) } } -int -gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, - int index, struct nvkm_gr **pgr) -{ - struct gf100_gr *gr; - int ret; - - if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL))) - return -ENOMEM; - *pgr = &gr->base; - - ret = gf100_gr_ctor(func, device, index, gr); - if (ret) - return ret; - - /* Load firmwares for non-secure falcons */ - if (!nvkm_secboot_is_managed(device->secboot, - NVKM_SECBOOT_FALCON_FECS)) { - if ((ret = gf100_gr_ctor_fw(gr, "gr/fecs_inst", &gr->fecs.inst)) || - (ret = gf100_gr_ctor_fw(gr, "gr/fecs_data", &gr->fecs.data))) - return ret; - } - if (!nvkm_secboot_is_managed(device->secboot, - NVKM_SECBOOT_FALCON_GPCCS)) { - if ((ret = gf100_gr_ctor_fw(gr, "gr/gpccs_inst", &gr->gpccs.inst)) || - (ret = gf100_gr_ctor_fw(gr, "gr/gpccs_data", &gr->gpccs.data))) - return ret; - } - - ret = gk20a_gr_load_sw(gr, "gr/", 0); - if (ret) - return -ENODEV; - - return 0; -} - static const struct gf100_gr_func gm200_gr = { .oneinit_tiles = gm200_gr_oneinit_tiles, @@ -195,8 +169,78 @@ gm200_gr = { } }; +int +gm200_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + int ret; + + ret = nvkm_acr_lsfw_load_bl_inst_data_sig(&gr->base.engine.subdev, + gr->fecs.falcon, + NVKM_ACR_LSF_FECS, + "gr/fecs_", ver, fwif->fecs); + if (ret) + return ret; + + ret = nvkm_acr_lsfw_load_bl_inst_data_sig(&gr->base.engine.subdev, + gr->gpccs.falcon, + NVKM_ACR_LSF_GPCCS, + "gr/gpccs_", ver, + fwif->gpccs); + if (ret) + return ret; + + gr->firmware = true; + + return gk20a_gr_load_sw(gr, "gr/", ver); +} + +MODULE_FIRMWARE("nvidia/gm200/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gm200/gr/sw_method_init.bin"); + +MODULE_FIRMWARE("nvidia/gm204/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gm204/gr/sw_method_init.bin"); + +MODULE_FIRMWARE("nvidia/gm206/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gm206/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gm200_gr_fwif[] = { + { 0, gm200_gr_load, &gm200_gr, &gm200_gr_fecs_acr, &gm200_gr_gpccs_acr }, + {} +}; + int gm200_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gm200_gr, device, index, pgr); + return gf100_gr_new_(gm200_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c index a667770ce3cb..d5a6210921c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -22,10 +22,16 @@ #include "gf100.h" #include "ctxgf100.h" +#include +#include #include #include +const struct nvkm_acr_lsf_func +gm20b_gr_fecs_acr = { +}; + static void gm20b_gr_init_gpc_mmu(struct gf100_gr *gr) { @@ -85,8 +91,51 @@ gm20b_gr = { } }; +static int +gm20b_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) +{ + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + int ret; + + ret = nvkm_acr_lsfw_load_bl_inst_data_sig(subdev, gr->fecs.falcon, + NVKM_ACR_LSF_FECS, + "gr/fecs_", ver, fwif->fecs); + if (ret) + return ret; + + + if (nvkm_firmware_load_blob(subdev, "gr/", "gpccs_inst", ver, + &gr->gpccs.inst) || + nvkm_firmware_load_blob(subdev, "gr/", "gpccs_data", ver, + &gr->gpccs.data)) + return -ENOENT; + + gr->firmware = true; + + return gk20a_gr_load_sw(gr, "gr/", ver); +} + +#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) +MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gm20b/gr/sw_method_init.bin"); +#endif + +static const struct gf100_gr_fwif +gm20b_gr_fwif[] = { + { 0, gm20b_gr_load, &gm20b_gr, &gm20b_gr_fecs_acr }, + {} +}; + int gm20b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gm20b_gr, device, index, pgr); + return gf100_gr_new_(gm20b_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index 9d0521ce309a..bd5d8cc66987 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -135,8 +135,27 @@ gp100_gr = { } }; +MODULE_FIRMWARE("nvidia/gp100/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp100/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gp100_gr_fwif[] = { + { 0, gm200_gr_load, &gp100_gr, &gm200_gr_fecs_acr, &gm200_gr_gpccs_acr }, + {} +}; + int gp100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp100_gr, device, index, pgr); + return gf100_gr_new_(gp100_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c index 37f7d739bf80..7baf67f743f4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c @@ -131,8 +131,27 @@ gp102_gr = { } }; +MODULE_FIRMWARE("nvidia/gp102/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp102/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gp102_gr_fwif[] = { + { 0, gm200_gr_load, &gp102_gr, &gm200_gr_fecs_acr, &gm200_gr_gpccs_acr }, + {} +}; + int gp102_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp102_gr, device, index, pgr); + return gf100_gr_new_(gp102_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c index 4573c914c021..d9b8ef875f8d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c @@ -59,8 +59,40 @@ gp104_gr = { } }; +MODULE_FIRMWARE("nvidia/gp104/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp104/gr/sw_method_init.bin"); + +MODULE_FIRMWARE("nvidia/gp106/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp106/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gp104_gr_fwif[] = { + { 0, gm200_gr_load, &gp104_gr, &gm200_gr_fecs_acr, &gm200_gr_gpccs_acr }, + {} +}; + int gp104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp104_gr, device, index, pgr); + return gf100_gr_new_(gp104_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c index 70e9d43ec802..2b1ad5522184 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c @@ -61,8 +61,27 @@ gp107_gr = { } }; +MODULE_FIRMWARE("nvidia/gp107/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp107/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gp107_gr_fwif[] = { + { 0, gm200_gr_load, &gp107_gr, &gm200_gr_fecs_acr, &gm200_gr_gpccs_acr }, + {} +}; + int gp107_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp107_gr, device, index, pgr); + return gf100_gr_new_(gp107_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c index 4e344470d56a..1fe58461095a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c @@ -21,8 +21,37 @@ */ #include "gf100.h" +#include + +const struct nvkm_acr_lsf_func +gp108_gr_gpccs_acr = { +}; + +const struct nvkm_acr_lsf_func +gp108_gr_fecs_acr = { +}; + +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gp108_gr_fwif[] = { + { 0, gm200_gr_load, &gp107_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, + {} +}; + int gp108_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp107_gr, device, index, pgr); + return gf100_gr_new_(gp108_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index 303dceddd4a8..e22211906b42 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -23,8 +23,14 @@ #include "gf100.h" #include "ctxgf100.h" +#include + #include +static const struct nvkm_acr_lsf_func +gp10b_gr_gpccs_acr = { +}; + static const struct gf100_gr_func gp10b_gr = { .oneinit_tiles = gm200_gr_oneinit_tiles, @@ -59,8 +65,29 @@ gp10b_gr = { } }; +#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) +MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp10b/gr/sw_method_init.bin"); +#endif + +static const struct gf100_gr_fwif +gp10b_gr_fwif[] = { + { 0, gm200_gr_load, &gp10b_gr, &gm20b_gr_fecs_acr, &gp10b_gr_gpccs_acr }, + {} +}; + int gp10b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gp10b_gr, device, index, pgr); + return gf100_gr_new_(gp10b_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index 3b3327789ae7..b2cab983a11c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -120,8 +120,27 @@ gv100_gr = { } }; +MODULE_FIRMWARE("nvidia/gv100/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gv100/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +gv100_gr_fwif[] = { + { 0, gm200_gr_load, &gv100_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, + {} +}; + int gv100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) { - return gm200_gr_new_(&gv100_gr, device, index, pgr); + return gf100_gr_new_(gv100_gr_fwif, device, index, pgr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c index 6b356473e67e..d6f8b904af65 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -195,56 +195,3 @@ gm200_secboot_new(struct nvkm_device *device, int index, return 0; } - - -MODULE_FIRMWARE("nvidia/gm200/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gm200/gr/sw_method_init.bin"); - -MODULE_FIRMWARE("nvidia/gm204/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gm204/gr/sw_method_init.bin"); - -MODULE_FIRMWARE("nvidia/gm206/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gm206/gr/sw_method_init.bin"); - -MODULE_FIRMWARE("nvidia/gp100/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp100/gr/sw_method_init.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c index 31be89d717cf..d047bfeaf5d4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -148,16 +148,3 @@ gm20b_secboot_new(struct nvkm_device *device, int index, return 0; } - -#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) -MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gm20b/gr/sw_method_init.bin"); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index ed5e46c414c9..adacb3e0e01f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -170,18 +170,6 @@ gp102_secboot_new(struct nvkm_device *device, int index, return 0; } -MODULE_FIRMWARE("nvidia/gp102/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp102/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin"); @@ -189,18 +177,6 @@ MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp104/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin"); @@ -208,18 +184,6 @@ MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp106/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin"); @@ -227,18 +191,6 @@ MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp107/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c index d8bfd87c5b78..98bde86a295a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c @@ -45,35 +45,11 @@ gp108_secboot_new(struct nvkm_device *device, int index, return nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); } -MODULE_FIRMWARE("nvidia/gp108/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp108/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gv100/gr/sw_method_init.bin"); MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); MODULE_FIRMWARE("nvidia/gv100/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gv100/sec2/image.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c index 509d4536dc00..b36fcc4f43bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c @@ -71,18 +71,3 @@ gp10b_secboot_new(struct nvkm_device *device, int index, return 0; } - -#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) -MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_data.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_bl.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_inst.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_data.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/gpccs_sig.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/sw_ctx.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/sw_nonctx.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/sw_bundle_init.bin"); -MODULE_FIRMWARE("nvidia/gp10b/gr/sw_method_init.bin"); -#endif -- cgit v1.2.3 From 4f556362a3f6efbfa22ada34178c91a795f9548a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/gr/gf100-: initialise SW state for falcon from constructor This will allow us to register the falcon with ACR, and further customise its behaviour by providing the nvkm_falcon_func structure directly. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 74 ++++++++++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 4 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 2 +- 4 files changed, 50 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index c174f4aeab60..c55d6804aef7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1701,14 +1701,14 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS); else - gf100_gr_init_fw(gr->fecs.falcon, &gr->fecs.inst, - &gr->fecs.data); + gf100_gr_init_fw(&gr->fecs.falcon, &gr->fecs.inst, + &gr->fecs.data); if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS); else - gf100_gr_init_fw(gr->gpccs.falcon, &gr->gpccs.inst, - &gr->gpccs.data); + gf100_gr_init_fw(&gr->gpccs.falcon, &gr->gpccs.inst, + &gr->gpccs.data); if (secboot_mask != 0) { int ret = nvkm_secboot_reset(sb, secboot_mask); @@ -1723,8 +1723,8 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); - nvkm_falcon_start(gr->gpccs.falcon); - nvkm_falcon_start(gr->fecs.falcon); + nvkm_falcon_start(&gr->gpccs.falcon); + nvkm_falcon_start(&gr->fecs.falcon); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x00000001) @@ -1786,18 +1786,18 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) /* load HUB microcode */ nvkm_mc_unk260(device, 0); - nvkm_falcon_load_dmem(gr->fecs.falcon, + nvkm_falcon_load_dmem(&gr->fecs.falcon, gr->func->fecs.ucode->data.data, 0x0, gr->func->fecs.ucode->data.size, 0); - nvkm_falcon_load_imem(gr->fecs.falcon, + nvkm_falcon_load_imem(&gr->fecs.falcon, gr->func->fecs.ucode->code.data, 0x0, gr->func->fecs.ucode->code.size, 0, 0, false); /* load GPC microcode */ - nvkm_falcon_load_dmem(gr->gpccs.falcon, + nvkm_falcon_load_dmem(&gr->gpccs.falcon, gr->func->gpccs.ucode->data.data, 0x0, gr->func->gpccs.ucode->data.size, 0); - nvkm_falcon_load_imem(gr->gpccs.falcon, + nvkm_falcon_load_imem(&gr->gpccs.falcon, gr->func->gpccs.ucode->code.data, 0x0, gr->func->gpccs.ucode->code.size, 0, 0, false); nvkm_mc_unk260(device, 1); @@ -1943,17 +1943,6 @@ gf100_gr_oneinit(struct nvkm_gr *base) struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; int i, j; - int ret; - - ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs.falcon); - if (ret) - return ret; - - mutex_init(&gr->fecs.mutex); - - ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs.falcon); - if (ret) - return ret; nvkm_pmu_pgob(device->pmu, false); @@ -1994,11 +1983,11 @@ gf100_gr_init_(struct nvkm_gr *base) nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false); - ret = nvkm_falcon_get(gr->fecs.falcon, subdev); + ret = nvkm_falcon_get(&gr->fecs.falcon, subdev); if (ret) return ret; - ret = nvkm_falcon_get(gr->gpccs.falcon, subdev); + ret = nvkm_falcon_get(&gr->gpccs.falcon, subdev); if (ret) return ret; @@ -2006,12 +1995,12 @@ gf100_gr_init_(struct nvkm_gr *base) } static int -gf100_gr_fini_(struct nvkm_gr *base, bool suspend) +gf100_gr_fini(struct nvkm_gr *base, bool suspend) { struct gf100_gr *gr = gf100_gr(base); struct nvkm_subdev *subdev = &gr->base.engine.subdev; - nvkm_falcon_put(gr->gpccs.falcon, subdev); - nvkm_falcon_put(gr->fecs.falcon, subdev); + nvkm_falcon_put(&gr->gpccs.falcon, subdev); + nvkm_falcon_put(&gr->fecs.falcon, subdev); return 0; } @@ -2022,8 +2011,8 @@ gf100_gr_dtor(struct nvkm_gr *base) kfree(gr->data); - nvkm_falcon_del(&gr->gpccs.falcon); - nvkm_falcon_del(&gr->fecs.falcon); + nvkm_falcon_dtor(&gr->gpccs.falcon); + nvkm_falcon_dtor(&gr->fecs.falcon); nvkm_blob_dtor(&gr->fecs.inst); nvkm_blob_dtor(&gr->fecs.data); @@ -2043,7 +2032,7 @@ gf100_gr_ = { .dtor = gf100_gr_dtor, .oneinit = gf100_gr_oneinit, .init = gf100_gr_init_, - .fini = gf100_gr_fini_, + .fini = gf100_gr_fini, .intr = gf100_gr_intr, .units = gf100_gr_units, .chan_new = gf100_gr_chan_new, @@ -2054,6 +2043,20 @@ gf100_gr_ = { .ctxsw.inst = gf100_gr_ctxsw_inst, }; +static const struct nvkm_falcon_func +gf100_gr_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + int gf100_gr_new_(const struct gf100_gr_fwif *fwif, struct nvkm_device *device, int index, struct nvkm_gr **pgr) @@ -2074,6 +2077,19 @@ gf100_gr_new_(const struct gf100_gr_fwif *fwif, return -ENODEV; gr->func = fwif->func; + + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, + "fecs", 0x409000, &gr->fecs.falcon); + if (ret) + return ret; + + mutex_init(&gr->fecs.mutex); + + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, + "gpccs", 0x41a000, &gr->gpccs.falcon); + if (ret) + return ret; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index d01d1683b50c..aa5c9ddfd93c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -78,7 +78,7 @@ struct gf100_gr { struct nvkm_gr base; struct { - struct nvkm_falcon *falcon; + struct nvkm_falcon falcon; struct nvkm_blob inst; struct nvkm_blob data; @@ -87,7 +87,7 @@ struct gf100_gr { } fecs; struct { - struct nvkm_falcon *falcon; + struct nvkm_falcon falcon; struct nvkm_blob inst; struct nvkm_blob data; } gpccs; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index d3907d8a7d03..3ad94d791fcf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -175,14 +175,14 @@ gm200_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) int ret; ret = nvkm_acr_lsfw_load_bl_inst_data_sig(&gr->base.engine.subdev, - gr->fecs.falcon, + &gr->fecs.falcon, NVKM_ACR_LSF_FECS, "gr/fecs_", ver, fwif->fecs); if (ret) return ret; ret = nvkm_acr_lsfw_load_bl_inst_data_sig(&gr->base.engine.subdev, - gr->gpccs.falcon, + &gr->gpccs.falcon, NVKM_ACR_LSF_GPCCS, "gr/gpccs_", ver, fwif->gpccs); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c index d5a6210921c7..aaf5aff036f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -97,7 +97,7 @@ gm20b_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) struct nvkm_subdev *subdev = &gr->base.engine.subdev; int ret; - ret = nvkm_acr_lsfw_load_bl_inst_data_sig(subdev, gr->fecs.falcon, + ret = nvkm_acr_lsfw_load_bl_inst_data_sig(subdev, &gr->fecs.falcon, NVKM_ACR_LSF_FECS, "gr/fecs_", ver, fwif->fecs); if (ret) -- cgit v1.2.3 From e14e5e6c33746247d442ddd4d79e3b83878a39b4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/sec2/gp108: split from gp102 implementation ACR LS FW loading is moving out of SECBOOT and into their specific subdevs, and the available GP108/GV100 FWs differ from the other GP10x boards. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c | 28 ++++++++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 33078f86c779..8e4959e41c39 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -13,5 +13,6 @@ struct nvkm_sec2 { }; int gp102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); +int gp108_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); int tu102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 8817ecaf4e7e..d63478beeb5d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2376,7 +2376,7 @@ nv138_chipset = { .fifo = gp100_fifo_new, .gr = gp108_gr_new, .nvdec[0] = gp102_nvdec_new, - .sec2 = gp102_sec2_new, + .sec2 = gp108_sec2_new, .sw = gf100_sw_new, }; @@ -2444,7 +2444,7 @@ nv140_chipset = { .fifo = gv100_fifo_new, .gr = gv100_gr_new, .nvdec[0] = gp102_nvdec_new, - .sec2 = gp102_sec2_new, + .sec2 = gp108_sec2_new, }; static const struct nvkm_device_chip diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild index 97c4696171f0..63cd2be3de08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild @@ -1,4 +1,5 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/sec2/base.o nvkm-y += nvkm/engine/sec2/gp102.o +nvkm-y += nvkm/engine/sec2/gp108.o nvkm-y += nvkm/engine/sec2/tu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c new file mode 100644 index 000000000000..31a55611edc2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +int +gp108_sec2_new(struct nvkm_device *device, int index, struct nvkm_sec2 **psec2) +{ + return nvkm_sec2_new_(device, index, 0, psec2); +} -- cgit v1.2.3 From 7adc40c593c621fb8059e6c651b4fa299c086860 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/sec2: select implementation based on available firmware This will allow for further customisation of the subdev depending on what firmware is available. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 38 ++++++++----- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 62 ++++++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c | 13 ++++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 17 +++++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 22 ++++++-- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 24 --------- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c | 7 --- 8 files changed, 130 insertions(+), 55 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 8e4959e41c39..b9ef4472c20e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_SEC2_H__ #define __NVKM_SEC2_H__ +#define nvkm_sec2(p) container_of((p), struct nvkm_sec2, engine) #include struct nvkm_sec2 { + const struct nvkm_sec2_func *func; struct nvkm_engine engine; u32 addr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 1b49e5b6717f..50c183347cae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -21,19 +21,11 @@ */ #include "priv.h" +#include #include #include #include -static void * -nvkm_sec2_dtor(struct nvkm_engine *engine) -{ - struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - nvkm_msgqueue_del(&sec2->queue); - nvkm_falcon_del(&sec2->falcon); - return sec2; -} - static void nvkm_sec2_intr(struct nvkm_engine *engine) { @@ -94,6 +86,15 @@ nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) return 0; } +static void * +nvkm_sec2_dtor(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + nvkm_msgqueue_del(&sec2->queue); + nvkm_falcon_del(&sec2->falcon); + return sec2; +} + static const struct nvkm_engine_func nvkm_sec2 = { .dtor = nvkm_sec2_dtor, @@ -103,15 +104,26 @@ nvkm_sec2 = { }; int -nvkm_sec2_new_(struct nvkm_device *device, int index, u32 addr, - struct nvkm_sec2 **psec2) +nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, + int index, u32 addr, struct nvkm_sec2 **psec2) { struct nvkm_sec2 *sec2; + int ret; if (!(sec2 = *psec2 = kzalloc(sizeof(*sec2), GFP_KERNEL))) return -ENOMEM; sec2->addr = addr; - INIT_WORK(&sec2->work, nvkm_sec2_recv); - return nvkm_engine_ctor(&nvkm_sec2, device, index, true, &sec2->engine); + ret = nvkm_engine_ctor(&nvkm_sec2, device, index, true, &sec2->engine); + if (ret) + return ret; + + fwif = nvkm_firmware_load(&sec2->engine.subdev, fwif, "Sec2", sec2); + if (IS_ERR(fwif)) + return PTR_ERR(fwif); + + sec2->func = fwif->func; + + INIT_WORK(&sec2->work, nvkm_sec2_recv); + return 0; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 858cf27fa010..befeee374cc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -19,12 +19,66 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - #include "priv.h" +#include + +static const struct nvkm_acr_lsf_func +gp102_sec2_acr_0 = { +}; + +const struct nvkm_sec2_func +gp102_sec2 = { +}; + +MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); + +const struct nvkm_acr_lsf_func +gp102_sec2_acr_1 = { +}; + +int +gp102_sec2_load(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev, + sec2->falcon, + NVKM_ACR_LSF_SEC2, "sec2/", + ver, fwif->acr); +} + +MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin"); +MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin"); + +static const struct nvkm_sec2_fwif +gp102_sec2_fwif[] = { + { 1, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 }, + { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_0 }, + {} +}; int -gp102_sec2_new(struct nvkm_device *device, int index, - struct nvkm_sec2 **psec2) +gp102_sec2_new(struct nvkm_device *device, int index, struct nvkm_sec2 **psec2) { - return nvkm_sec2_new_(device, index, 0, psec2); + return nvkm_sec2_new_(gp102_sec2_fwif, device, index, 0, psec2); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c index 31a55611edc2..232a9d7c51e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp108.c @@ -20,9 +20,20 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include + +MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); + +static const struct nvkm_sec2_fwif +gp108_sec2_fwif[] = { + { 0, gp102_sec2_load, &gp102_sec2, &gp102_sec2_acr_1 }, + {} +}; int gp108_sec2_new(struct nvkm_device *device, int index, struct nvkm_sec2 **psec2) { - return nvkm_sec2_new_(device, index, 0, psec2); + return nvkm_sec2_new_(gp108_sec2_fwif, device, index, 0, psec2); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index b331b00517e6..d37d315295b5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -3,7 +3,20 @@ #define __NVKM_SEC2_PRIV_H__ #include -#define nvkm_sec2(p) container_of((p), struct nvkm_sec2, engine) +struct nvkm_sec2_func { +}; -int nvkm_sec2_new_(struct nvkm_device *, int, u32 addr, struct nvkm_sec2 **); +struct nvkm_sec2_fwif { + int version; + int (*load)(struct nvkm_sec2 *, int ver, const struct nvkm_sec2_fwif *); + const struct nvkm_sec2_func *func; + const struct nvkm_acr_lsf_func *acr; +}; + +int gp102_sec2_load(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *); +extern const struct nvkm_sec2_func gp102_sec2; +extern const struct nvkm_acr_lsf_func gp102_sec2_acr_1; + +int nvkm_sec2_new_(const struct nvkm_sec2_fwif *, struct nvkm_device *, + int, u32 addr, struct nvkm_sec2 **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index d655576164b1..c8258658b503 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -19,15 +19,29 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ - #include "priv.h" +static const struct nvkm_sec2_func +tu102_sec2 = { +}; + +static int +tu102_sec2_nofw(struct nvkm_sec2 *sec2, int ver, + const struct nvkm_sec2_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_sec2_fwif +tu102_sec2_fwif[] = { + { -1, tu102_sec2_nofw, &tu102_sec2 } +}; + int -tu102_sec2_new(struct nvkm_device *device, int index, - struct nvkm_sec2 **psec2) +tu102_sec2_new(struct nvkm_device *device, int index, struct nvkm_sec2 **psec2) { /* TOP info wasn't updated on Turing to reflect the PRI * address change for some reason. We override it here. */ - return nvkm_sec2_new_(device, index, 0x840000, psec2); + return nvkm_sec2_new_(tu102_sec2_fwif, device, index, 0x840000, psec2); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index adacb3e0e01f..b378a50e151a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -171,30 +171,6 @@ gp102_secboot_new(struct nvkm_device *device, int index, } MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/desc-1.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/image-1.bin"); -MODULE_FIRMWARE("nvidia/gp102/sec2/sig-1.bin"); MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/desc-1.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/image-1.bin"); -MODULE_FIRMWARE("nvidia/gp104/sec2/sig-1.bin"); MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/desc-1.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/image-1.bin"); -MODULE_FIRMWARE("nvidia/gp106/sec2/sig-1.bin"); MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/desc-1.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/image-1.bin"); -MODULE_FIRMWARE("nvidia/gp107/sec2/sig-1.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c index 98bde86a295a..5161b9cfb73a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c @@ -46,11 +46,4 @@ gp108_secboot_new(struct nvkm_device *device, int index, } MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); - MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gv100/sec2/desc.bin"); -MODULE_FIRMWARE("nvidia/gv100/sec2/image.bin"); -MODULE_FIRMWARE("nvidia/gv100/sec2/sig.bin"); -- cgit v1.2.3 From edd757d17891b5330a5dbc1ce0bb710a5017e530 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/sec2: initialise SW state for falcon from constructor This will allow us to register the falcon with ACR, and further customise its behaviour by providing the nvkm_falcon_func structure directly. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 3 ++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 25 ++++++---------------- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 18 +++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 15 +++++++++++++ .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c | 2 +- .../nvkm/subdev/secboot/ls_ucode_msgqueue.c | 4 ++-- 9 files changed, 46 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index b9ef4472c20e..2ffa125a15d7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -3,13 +3,14 @@ #define __NVKM_SEC2_H__ #define nvkm_sec2(p) container_of((p), struct nvkm_sec2, engine) #include +#include struct nvkm_sec2 { const struct nvkm_sec2_func *func; struct nvkm_engine engine; + struct nvkm_falcon falcon; u32 addr; - struct nvkm_falcon *falcon; struct nvkm_msgqueue *queue; struct work_struct work; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 50c183347cae..5554e9f4df88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -24,7 +24,6 @@ #include #include #include -#include static void nvkm_sec2_intr(struct nvkm_engine *engine) @@ -62,22 +61,6 @@ nvkm_sec2_recv(struct work_struct *work) nvkm_msgqueue_recv(sec2->queue); } - -static int -nvkm_sec2_oneinit(struct nvkm_engine *engine) -{ - struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - struct nvkm_subdev *subdev = &sec2->engine.subdev; - - if (!sec2->addr) { - sec2->addr = nvkm_top_addr(subdev->device, subdev->index); - if (WARN_ON(!sec2->addr)) - return -EINVAL; - } - - return nvkm_falcon_v1_new(subdev, "SEC2", sec2->addr, &sec2->falcon); -} - static int nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { @@ -91,14 +74,13 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); nvkm_msgqueue_del(&sec2->queue); - nvkm_falcon_del(&sec2->falcon); + nvkm_falcon_dtor(&sec2->falcon); return sec2; } static const struct nvkm_engine_func nvkm_sec2 = { .dtor = nvkm_sec2_dtor, - .oneinit = nvkm_sec2_oneinit, .fini = nvkm_sec2_fini, .intr = nvkm_sec2_intr, }; @@ -124,6 +106,11 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, sec2->func = fwif->func; + ret = nvkm_falcon_ctor(sec2->func->flcn, &sec2->engine.subdev, + nvkm_subdev_name[index], addr, &sec2->falcon); + if (ret) + return ret; + INIT_WORK(&sec2->work, nvkm_sec2_recv); return 0; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index befeee374cc6..75407cb8a88a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -26,8 +26,24 @@ static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { }; + +static const struct nvkm_falcon_func +gp102_sec2_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + const struct nvkm_sec2_func gp102_sec2 = { + .flcn = &gp102_sec2_flcn, }; MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); @@ -52,7 +68,7 @@ gp102_sec2_load(struct nvkm_sec2 *sec2, int ver, const struct nvkm_sec2_fwif *fwif) { return nvkm_acr_lsfw_load_sig_image_desc_v1(&sec2->engine.subdev, - sec2->falcon, + &sec2->falcon, NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index d37d315295b5..6e28b969573b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -4,6 +4,7 @@ #include struct nvkm_sec2_func { + const struct nvkm_falcon_func *flcn; }; struct nvkm_sec2_fwif { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index c8258658b503..5192b3a1e40c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -21,8 +21,23 @@ */ #include "priv.h" +static const struct nvkm_falcon_func +tu102_sec2_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + static const struct nvkm_sec2_func tu102_sec2 = { + .flcn = &tu102_sec2_flcn, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c index 513445856f22..e6dd0a4bf581 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c @@ -172,7 +172,7 @@ acr_r361_generate_sec2_bl_desc(const struct nvkm_acr *acr, /* For some reason we should not add app_resident_code_offset here */ addr_code = base; addr_data = base + pdesc->app_resident_data_offset; - addr_args = sec->falcon->data.limit; + addr_args = sec->falcon.data.limit; addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; desc->dma_idx = FALCON_SEC2_DMAIDX_UCODE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c index e821d0fd6217..f850c3be261a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c @@ -96,7 +96,7 @@ acr_r370_generate_sec2_bl_desc(const struct nvkm_acr *acr, /* For some reason we should not add app_resident_code_offset here */ addr_code = base; addr_data = base + pdesc->app_resident_data_offset; - addr_args = sec->falcon->data.limit; + addr_args = sec->falcon.data.limit; addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; desc->ctx_dma = FALCON_SEC2_DMAIDX_UCODE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c index 36ae6918beae..993f01b1d155 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c @@ -138,7 +138,7 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev) case NVKM_SECBOOT_FALCON_SEC2: /* we must keep SEC2 alive forever since ACR will run on it */ nvkm_engine_ref(&subdev->device->sec2->engine); - sb->boot_falcon = subdev->device->sec2->falcon; + sb->boot_falcon = &subdev->device->sec2->falcon; sb->halt_falcon = &subdev->device->pmu->falcon; break; default: diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c index 472f38a56639..39dda09fc344 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c @@ -148,7 +148,7 @@ acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, int maxver, return ver; /* Allocate the PMU queue corresponding to the FW version */ - ret = nvkm_msgqueue_new(img->ucode_desc.app_version, sec->falcon, + ret = nvkm_msgqueue_new(img->ucode_desc.app_version, &sec->falcon, sb, &sec->queue); if (ret) return ret; @@ -166,7 +166,7 @@ acr_ls_sec2_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) const u32 addr_args = 0x01000000; int ret; - ret = acr_ls_msgqueue_post_run(sec->queue, sec->falcon, addr_args); + ret = acr_ls_msgqueue_post_run(sec->queue, &sec->falcon, addr_args); if (ret) return ret; -- cgit v1.2.3 From 555a0002d3c6d0792df4df33a8a2d7140bc61812 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/sec2: use falcon funcs Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 14 ++++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 2ffa125a15d7..25f016fefe15 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -9,7 +9,6 @@ struct nvkm_sec2 { const struct nvkm_sec2_func *func; struct nvkm_engine engine; struct nvkm_falcon falcon; - u32 addr; struct nvkm_msgqueue *queue; struct work_struct work; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 5554e9f4df88..f4cf682786c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -29,21 +29,20 @@ static void nvkm_sec2_intr(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - struct nvkm_subdev *subdev = &engine->subdev; - struct nvkm_device *device = subdev->device; - u32 disp = nvkm_rd32(device, sec2->addr + 0x01c); - u32 intr = nvkm_rd32(device, sec2->addr + 0x008) & disp & ~(disp >> 16); + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + u32 disp = nvkm_falcon_rd32(falcon, 0x01c); + u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); if (intr & 0x00000040) { schedule_work(&sec2->work); - nvkm_wr32(device, sec2->addr + 0x004, 0x00000040); + nvkm_falcon_wr32(falcon, 0x004, 0x00000040); intr &= ~0x00000040; } if (intr) { nvkm_error(subdev, "unhandled intr %08x\n", intr); - nvkm_wr32(device, sec2->addr + 0x004, intr); - + nvkm_falcon_wr32(falcon, 0x004, intr); } } @@ -94,7 +93,6 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, if (!(sec2 = *psec2 = kzalloc(sizeof(*sec2), GFP_KERNEL))) return -ENOMEM; - sec2->addr = addr; ret = nvkm_engine_ctor(&nvkm_sec2, device, index, true, &sec2->engine); if (ret) -- cgit v1.2.3 From c9af47bcbde4d3eef3e68c69a29c580e0301a416 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/sec2: move interrupt handler to hw-specific module Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 28 ++++++------------------ drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 20 +++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 3 +++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 1 + 4 files changed, 31 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index f4cf682786c9..bb79488f414d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -25,27 +25,6 @@ #include #include -static void -nvkm_sec2_intr(struct nvkm_engine *engine) -{ - struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - struct nvkm_subdev *subdev = &sec2->engine.subdev; - struct nvkm_falcon *falcon = &sec2->falcon; - u32 disp = nvkm_falcon_rd32(falcon, 0x01c); - u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); - - if (intr & 0x00000040) { - schedule_work(&sec2->work); - nvkm_falcon_wr32(falcon, 0x004, 0x00000040); - intr &= ~0x00000040; - } - - if (intr) { - nvkm_error(subdev, "unhandled intr %08x\n", intr); - nvkm_falcon_wr32(falcon, 0x004, intr); - } -} - static void nvkm_sec2_recv(struct work_struct *work) { @@ -60,6 +39,13 @@ nvkm_sec2_recv(struct work_struct *work) nvkm_msgqueue_recv(sec2->queue); } +static void +nvkm_sec2_intr(struct nvkm_engine *engine) +{ + struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + sec2->func->intr(sec2); +} + static int nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 75407cb8a88a..c6919f2886de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -26,6 +26,25 @@ static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { }; +void +gp102_sec2_intr(struct nvkm_sec2 *sec2) +{ + struct nvkm_subdev *subdev = &sec2->engine.subdev; + struct nvkm_falcon *falcon = &sec2->falcon; + u32 disp = nvkm_falcon_rd32(falcon, 0x01c); + u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16); + + if (intr & 0x00000040) { + schedule_work(&sec2->work); + nvkm_falcon_wr32(falcon, 0x004, 0x00000040); + intr &= ~0x00000040; + } + + if (intr) { + nvkm_error(subdev, "unhandled intr %08x\n", intr); + nvkm_falcon_wr32(falcon, 0x004, intr); + } +} static const struct nvkm_falcon_func gp102_sec2_flcn = { @@ -44,6 +63,7 @@ gp102_sec2_flcn = { const struct nvkm_sec2_func gp102_sec2 = { .flcn = &gp102_sec2_flcn, + .intr = gp102_sec2_intr, }; MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index 6e28b969573b..e5ba6df3d500 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -5,8 +5,11 @@ struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; + void (*intr)(struct nvkm_sec2 *); }; +void gp102_sec2_intr(struct nvkm_sec2 *); + struct nvkm_sec2_fwif { int version; int (*load)(struct nvkm_sec2 *, int ver, const struct nvkm_sec2_fwif *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index 5192b3a1e40c..e3eb08f4e9a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -38,6 +38,7 @@ tu102_sec2_flcn = { static const struct nvkm_sec2_func tu102_sec2 = { .flcn = &tu102_sec2_flcn, + .intr = gp102_sec2_intr, }; static int -- cgit v1.2.3 From 98a34d99501042b7e055cdc4b6f65926ecfcf10c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/nvdec: select implementation based on available fw This will allow for further customisation of the subdev depending on what firmware is available. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c | 19 +++++++++++++++---- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c | 20 ++++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h | 13 ++++++++++++- 4 files changed, 46 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h index 7c7d7f0abfcc..b941fbf465d1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h @@ -5,6 +5,7 @@ #include struct nvkm_nvdec { + const struct nvkm_nvdec_func *func; struct nvkm_engine engine; u32 addr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c index 4a63581bdd5e..ae7a7616113a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c @@ -21,6 +21,7 @@ */ #include "priv.h" +#include #include #include @@ -54,14 +55,24 @@ nvkm_nvdec = { }; int -nvkm_nvdec_new_(struct nvkm_device *device, int index, - struct nvkm_nvdec **pnvdec) +nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, + int index, struct nvkm_nvdec **pnvdec) { struct nvkm_nvdec *nvdec; + int ret; if (!(nvdec = *pnvdec = kzalloc(sizeof(*nvdec), GFP_KERNEL))) return -ENOMEM; - return nvkm_engine_ctor(&nvkm_nvdec, device, index, true, - &nvdec->engine); + ret = nvkm_engine_ctor(&nvkm_nvdec, device, index, true, + &nvdec->engine); + if (ret) + return ret; + + fwif = nvkm_firmware_load(&nvdec->engine.subdev, fwif, "Nvdec", nvdec); + if (IS_ERR(fwif)) + return -ENODEV; + + nvdec->func = fwif->func; + return 0; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c index fde6328c6d71..f2cc69c424b1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c @@ -19,12 +19,28 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - #include "priv.h" +static const struct nvkm_nvdec_func +gp102_nvdec = { +}; + +static int +gp102_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, + const struct nvkm_nvdec_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_nvdec_fwif +gp102_nvdec_fwif[] = { + { -1, gp102_nvdec_nofw, &gp102_nvdec }, + {} +}; + int gp102_nvdec_new(struct nvkm_device *device, int index, struct nvkm_nvdec **pnvdec) { - return nvkm_nvdec_new_(device, index, pnvdec); + return nvkm_nvdec_new_(gp102_nvdec_fwif, device, index, pnvdec); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h index 57bfa3aa1835..c23c1f48c967 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h @@ -3,5 +3,16 @@ #define __NVKM_NVDEC_PRIV_H__ #include -int nvkm_nvdec_new_(struct nvkm_device *, int, struct nvkm_nvdec **); +struct nvkm_nvdec_func { +}; + +struct nvkm_nvdec_fwif { + int version; + int (*load)(struct nvkm_nvdec *, int ver, + const struct nvkm_nvdec_fwif *); + const struct nvkm_nvdec_func *func; +}; + +int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, + struct nvkm_device *, int, struct nvkm_nvdec **); #endif -- cgit v1.2.3 From 3a900a5d9ce325fb83ad6759c20a318a84b2068c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/nvdec: initialise SW state for falcon from constructor This will allow us to register the falcon with ACR, and further customise its behaviour by providing the nvkm_falcon_func structure directly. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/engine/nvdec.h | 5 ++--- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c | 25 ++++------------------ drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c | 15 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h | 1 + .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 2 +- 5 files changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h index b941fbf465d1..ae3c294a63d5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h @@ -3,13 +3,12 @@ #define __NVKM_NVDEC_H__ #define nvkm_nvdec(p) container_of((p), struct nvkm_nvdec, engine) #include +#include struct nvkm_nvdec { const struct nvkm_nvdec_func *func; struct nvkm_engine engine; - u32 addr; - - struct nvkm_falcon *falcon; + struct nvkm_falcon falcon; }; int gp102_nvdec_new(struct nvkm_device *, int, struct nvkm_nvdec **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c index ae7a7616113a..9b23c1b70ebf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c @@ -20,38 +20,19 @@ * DEALINGS IN THE SOFTWARE. */ #include "priv.h" - #include -#include -#include - -static int -nvkm_nvdec_oneinit(struct nvkm_engine *engine) -{ - struct nvkm_nvdec *nvdec = nvkm_nvdec(engine); - struct nvkm_subdev *subdev = &nvdec->engine.subdev; - - nvdec->addr = nvkm_top_addr(subdev->device, subdev->index); - if (!nvdec->addr) - return -EINVAL; - - /*XXX: fix naming of this when adding support for multiple-NVDEC */ - return nvkm_falcon_v1_new(subdev, "NVDEC", nvdec->addr, - &nvdec->falcon); -} static void * nvkm_nvdec_dtor(struct nvkm_engine *engine) { struct nvkm_nvdec *nvdec = nvkm_nvdec(engine); - nvkm_falcon_del(&nvdec->falcon); + nvkm_falcon_dtor(&nvdec->falcon); return nvdec; } static const struct nvkm_engine_func nvkm_nvdec = { .dtor = nvkm_nvdec_dtor, - .oneinit = nvkm_nvdec_oneinit, }; int @@ -74,5 +55,7 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device, return -ENODEV; nvdec->func = fwif->func; - return 0; + + return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev, + nvkm_subdev_name[index], 0, &nvdec->falcon); }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c index f2cc69c424b1..bd520c77b206 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c @@ -21,8 +21,23 @@ */ #include "priv.h" +static const struct nvkm_falcon_func +gp102_nvdec_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + static const struct nvkm_nvdec_func gp102_nvdec = { + .flcn = &gp102_nvdec_flcn, }; static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h index c23c1f48c967..e14da8b000d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h @@ -4,6 +4,7 @@ #include struct nvkm_nvdec_func { + const struct nvkm_falcon_func *flcn; }; struct nvkm_nvdec_fwif { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index b378a50e151a..5f4357de54be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -62,7 +62,7 @@ gp102_run_secure_scrub(struct nvkm_secboot *sb) engine = nvkm_engine_ref(&device->nvdec[0]->engine); if (IS_ERR(engine)) return PTR_ERR(engine); - falcon = device->nvdec[0]->falcon; + falcon = &device->nvdec[0]->falcon; nvkm_falcon_get(falcon, &sb->subdev); -- cgit v1.2.3 From 68f02444946be707ee3beefabf5e4d5e6374f13a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/nvdec/gm107: rename from gp102 implementation NVDEC is available from GM107, and we currently only have a stub implementation anyway, let's make it explicit. Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/engine/nvdec.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 22 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 61 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c | 61 ---------------------- 5 files changed, 74 insertions(+), 74 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h index ae3c294a63d5..1b3183e31606 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h @@ -11,5 +11,5 @@ struct nvkm_nvdec { struct nvkm_falcon falcon; }; -int gp102_nvdec_new(struct nvkm_device *, int, struct nvkm_nvdec **); +int gm107_nvdec_new(struct nvkm_device *, int, struct nvkm_nvdec **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index d63478beeb5d..9dbbdbb9c019 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2227,7 +2227,7 @@ nv132_chipset = { .dma = gf119_dma_new, .fifo = gp100_fifo_new, .gr = gp102_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2264,7 +2264,7 @@ nv134_chipset = { .dma = gf119_dma_new, .fifo = gp100_fifo_new, .gr = gp104_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2301,7 +2301,7 @@ nv136_chipset = { .dma = gf119_dma_new, .fifo = gp100_fifo_new, .gr = gp104_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2338,7 +2338,7 @@ nv137_chipset = { .dma = gf119_dma_new, .fifo = gp100_fifo_new, .gr = gp107_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2375,7 +2375,7 @@ nv138_chipset = { .dma = gf119_dma_new, .fifo = gp100_fifo_new, .gr = gp108_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp108_sec2_new, .sw = gf100_sw_new, }; @@ -2443,7 +2443,7 @@ nv140_chipset = { .dma = gv100_dma_new, .fifo = gv100_fifo_new, .gr = gv100_gr_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = gp108_sec2_new, }; @@ -2478,7 +2478,7 @@ nv162_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; @@ -2513,7 +2513,7 @@ nv164_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; @@ -2548,7 +2548,7 @@ nv166_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; @@ -2583,7 +2583,7 @@ nv167_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; @@ -2618,7 +2618,7 @@ nv168_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, - .nvdec[0] = gp102_nvdec_new, + .nvdec[0] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild index cdf631822282..9a0fd9812750 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild @@ -1,3 +1,3 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/nvdec/base.o -nvkm-y += nvkm/engine/nvdec/gp102.o +nvkm-y += nvkm/engine/nvdec/gm107.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c new file mode 100644 index 000000000000..2cc9172bd1ad --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. + */ +#include "priv.h" + +static const struct nvkm_falcon_func +gm107_nvdec_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + +static const struct nvkm_nvdec_func +gm107_nvdec = { + .flcn = &gm107_nvdec_flcn, +}; + +static int +gm107_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, + const struct nvkm_nvdec_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_nvdec_fwif +gm107_nvdec_fwif[] = { + { -1, gm107_nvdec_nofw, &gm107_nvdec }, + {} +}; + +int +gm107_nvdec_new(struct nvkm_device *device, int index, + struct nvkm_nvdec **pnvdec) +{ + return nvkm_nvdec_new_(gm107_nvdec_fwif, device, index, pnvdec); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c deleted file mode 100644 index bd520c77b206..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gp102.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ -#include "priv.h" - -static const struct nvkm_falcon_func -gp102_nvdec_flcn = { - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .clear_interrupt = nvkm_falcon_v1_clear_interrupt, - .set_start_addr = nvkm_falcon_v1_set_start_addr, - .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, -}; - -static const struct nvkm_nvdec_func -gp102_nvdec = { - .flcn = &gp102_nvdec_flcn, -}; - -static int -gp102_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, - const struct nvkm_nvdec_fwif *fwif) -{ - return 0; -} - -static const struct nvkm_nvdec_fwif -gp102_nvdec_fwif[] = { - { -1, gp102_nvdec_nofw, &gp102_nvdec }, - {} -}; - -int -gp102_nvdec_new(struct nvkm_device *device, int index, - struct nvkm_nvdec **pnvdec) -{ - return nvkm_nvdec_new_(gp102_nvdec_fwif, device, index, pnvdec); -} -- cgit v1.2.3 From a5482b9ff194226ea1b549234285c80a44c69aa6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/nvdec/gm107-: add missing engine instances Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 9dbbdbb9c019..53019ab7d04c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -1987,6 +1987,7 @@ nv117_chipset = { .dma = gf119_dma_new, .fifo = gm107_fifo_new, .gr = gm107_gr_new, + .nvdec[0] = gm107_nvdec_new, .sw = gf100_sw_new, }; @@ -2057,6 +2058,7 @@ nv120_chipset = { .dma = gf119_dma_new, .fifo = gm200_fifo_new, .gr = gm200_gr_new, + .nvdec[0] = gm107_nvdec_new, .sw = gf100_sw_new, }; @@ -2093,6 +2095,7 @@ nv124_chipset = { .dma = gf119_dma_new, .fifo = gm200_fifo_new, .gr = gm200_gr_new, + .nvdec[0] = gm107_nvdec_new, .sw = gf100_sw_new, }; @@ -2129,6 +2132,7 @@ nv126_chipset = { .dma = gf119_dma_new, .fifo = gm200_fifo_new, .gr = gm200_gr_new, + .nvdec[0] = gm107_nvdec_new, .sw = gf100_sw_new, }; @@ -2192,6 +2196,7 @@ nv130_chipset = { .disp = gp100_disp_new, .fifo = gp100_fifo_new, .gr = gp100_gr_new, + .nvdec[0] = gm107_nvdec_new, .sw = gf100_sw_new, }; @@ -2514,6 +2519,7 @@ nv164_chipset = { .dma = gv100_dma_new, .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, + .nvdec[1] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; @@ -2549,6 +2555,8 @@ nv166_chipset = { .dma = gv100_dma_new, .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, + .nvdec[1] = gm107_nvdec_new, + .nvdec[2] = gm107_nvdec_new, .sec2 = tu102_sec2_new, }; -- cgit v1.2.3 From 10e43bfd2f8dd8dfff4d40615b529327745bb0b2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/nvenc: add a stub implementation for the GPUs where it should be supported Mostly so we don't lose info hidden in falcon. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 4 +- .../gpu/drm/nouveau/include/nvkm/engine/nvenc.h | 10 ++++ drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 30 +++++++++-- drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild | 3 +- drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c | 63 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c | 62 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h | 19 +++++++ 7 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 3d42139c3f37..5598a36f11ec 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -171,7 +171,7 @@ struct nvkm_device { struct nvkm_engine *mspdec; struct nvkm_engine *msppp; struct nvkm_engine *msvld; - struct nvkm_engine *nvenc[3]; + struct nvkm_nvenc *nvenc[3]; struct nvkm_nvdec *nvdec[3]; struct nvkm_pm *pm; struct nvkm_engine *sec; @@ -245,7 +245,7 @@ struct nvkm_device_chip { int (*mspdec )(struct nvkm_device *, int idx, struct nvkm_engine **); int (*msppp )(struct nvkm_device *, int idx, struct nvkm_engine **); int (*msvld )(struct nvkm_device *, int idx, struct nvkm_engine **); - int (*nvenc[3])(struct nvkm_device *, int idx, struct nvkm_engine **); + int (*nvenc[3])(struct nvkm_device *, int idx, struct nvkm_nvenc **); int (*nvdec[3])(struct nvkm_device *, int idx, struct nvkm_nvdec **); int (*pm )(struct nvkm_device *, int idx, struct nvkm_pm **); int (*sec )(struct nvkm_device *, int idx, struct nvkm_engine **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h index 21624046d0a1..33e6ba8adc8d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvenc.h @@ -1,5 +1,15 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_NVENC_H__ #define __NVKM_NVENC_H__ +#define nvkm_nvenc(p) container_of((p), struct nvkm_nvenc, engine) #include +#include + +struct nvkm_nvenc { + const struct nvkm_nvenc_func *func; + struct nvkm_engine engine; + struct nvkm_falcon falcon; +}; + +int gm107_nvenc_new(struct nvkm_device *, int, struct nvkm_nvenc **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 53019ab7d04c..f98065b12c24 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -1988,6 +1988,7 @@ nv117_chipset = { .fifo = gm107_fifo_new, .gr = gm107_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sw = gf100_sw_new, }; @@ -2059,6 +2060,8 @@ nv120_chipset = { .fifo = gm200_fifo_new, .gr = gm200_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, .sw = gf100_sw_new, }; @@ -2096,6 +2099,8 @@ nv124_chipset = { .fifo = gm200_fifo_new, .gr = gm200_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, .sw = gf100_sw_new, }; @@ -2133,6 +2138,7 @@ nv126_chipset = { .fifo = gm200_fifo_new, .gr = gm200_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sw = gf100_sw_new, }; @@ -2197,6 +2203,9 @@ nv130_chipset = { .fifo = gp100_fifo_new, .gr = gp100_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, + .nvenc[2] = gm107_nvenc_new, .sw = gf100_sw_new, }; @@ -2233,6 +2242,8 @@ nv132_chipset = { .fifo = gp100_fifo_new, .gr = gp102_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2270,6 +2281,8 @@ nv134_chipset = { .fifo = gp100_fifo_new, .gr = gp104_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2307,6 +2320,7 @@ nv136_chipset = { .fifo = gp100_fifo_new, .gr = gp104_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2344,6 +2358,8 @@ nv137_chipset = { .fifo = gp100_fifo_new, .gr = gp107_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, .sec2 = gp102_sec2_new, .sw = gf100_sw_new, }; @@ -2449,6 +2465,9 @@ nv140_chipset = { .fifo = gv100_fifo_new, .gr = gv100_gr_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, + .nvenc[1] = gm107_nvenc_new, + .nvenc[2] = gm107_nvenc_new, .sec2 = gp108_sec2_new, }; @@ -2484,6 +2503,7 @@ nv162_chipset = { .dma = gv100_dma_new, .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, }; @@ -2520,6 +2540,7 @@ nv164_chipset = { .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, .nvdec[1] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, }; @@ -2557,6 +2578,7 @@ nv166_chipset = { .nvdec[0] = gm107_nvdec_new, .nvdec[1] = gm107_nvdec_new, .nvdec[2] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, }; @@ -2592,6 +2614,7 @@ nv167_chipset = { .dma = gv100_dma_new, .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, }; @@ -2627,6 +2650,7 @@ nv168_chipset = { .dma = gv100_dma_new, .fifo = tu102_fifo_new, .nvdec[0] = gm107_nvdec_new, + .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, }; @@ -2724,9 +2748,9 @@ nvkm_device_engine(struct nvkm_device *device, int index) _(MSPDEC , device->mspdec , device->mspdec); _(MSPPP , device->msppp , device->msppp); _(MSVLD , device->msvld , device->msvld); - _(NVENC0 , device->nvenc[0], device->nvenc[0]); - _(NVENC1 , device->nvenc[1], device->nvenc[1]); - _(NVENC2 , device->nvenc[2], device->nvenc[2]); + _(NVENC0 , device->nvenc[0], &device->nvenc[0]->engine); + _(NVENC1 , device->nvenc[1], &device->nvenc[1]->engine); + _(NVENC2 , device->nvenc[2], &device->nvenc[2]->engine); _(NVDEC0 , device->nvdec[0], &device->nvdec[0]->engine); _(NVDEC1 , device->nvdec[1], &device->nvdec[1]->engine); _(NVDEC2 , device->nvdec[2], &device->nvdec[2]->engine); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild index f316de8d45a8..75bf4436bf3f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/Kbuild @@ -1,2 +1,3 @@ # SPDX-License-Identifier: MIT -#nvkm-y += nvkm/engine/nvenc/base.o +nvkm-y += nvkm/engine/nvenc/base.o +nvkm-y += nvkm/engine/nvenc/gm107.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c new file mode 100644 index 000000000000..484100e15668 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/base.c @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#include "priv.h" +#include + +static void * +nvkm_nvenc_dtor(struct nvkm_engine *engine) +{ + struct nvkm_nvenc *nvenc = nvkm_nvenc(engine); + nvkm_falcon_dtor(&nvenc->falcon); + return nvenc; +} + +static const struct nvkm_engine_func +nvkm_nvenc = { + .dtor = nvkm_nvenc_dtor, +}; + +int +nvkm_nvenc_new_(const struct nvkm_nvenc_fwif *fwif, struct nvkm_device *device, + int index, struct nvkm_nvenc **pnvenc) +{ + struct nvkm_nvenc *nvenc; + int ret; + + if (!(nvenc = *pnvenc = kzalloc(sizeof(*nvenc), GFP_KERNEL))) + return -ENOMEM; + + ret = nvkm_engine_ctor(&nvkm_nvenc, device, index, true, + &nvenc->engine); + if (ret) + return ret; + + fwif = nvkm_firmware_load(&nvenc->engine.subdev, fwif, "Nvenc", nvenc); + if (IS_ERR(fwif)) + return -ENODEV; + + nvenc->func = fwif->func; + + return nvkm_falcon_ctor(nvenc->func->flcn, &nvenc->engine.subdev, + nvkm_subdev_name[index], 0, &nvenc->falcon); +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c new file mode 100644 index 000000000000..e8a13ed04c63 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Red Hat 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. + */ + +#include "priv.h" + +static const struct nvkm_falcon_func +gm107_nvenc_flcn = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, + .set_start_addr = nvkm_falcon_v1_set_start_addr, + .start = nvkm_falcon_v1_start, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, +}; + +static const struct nvkm_nvenc_func +gm107_nvenc = { + .flcn = &gm107_nvenc_flcn, +}; + +static int +gm107_nvenc_nofw(struct nvkm_nvenc *nvenc, int ver, + const struct nvkm_nvenc_fwif *fwif) +{ + return 0; +} + +static const struct nvkm_nvenc_fwif +gm107_nvenc_fwif[] = { + { -1, gm107_nvenc_nofw, &gm107_nvenc }, + {} +}; + +int +gm107_nvenc_new(struct nvkm_device *device, int index, + struct nvkm_nvenc **pnvenc) +{ + return nvkm_nvenc_new_(gm107_nvenc_fwif, device, index, pnvenc); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h new file mode 100644 index 000000000000..100fa5ebbeef --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/priv.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_NVENC_PRIV_H__ +#define __NVKM_NVENC_PRIV_H__ +#include + +struct nvkm_nvenc_func { + const struct nvkm_falcon_func *flcn; +}; + +struct nvkm_nvenc_fwif { + int version; + int (*load)(struct nvkm_nvenc *, int ver, + const struct nvkm_nvenc_fwif *); + const struct nvkm_nvenc_func *func; +}; + +int nvkm_nvenc_new_(const struct nvkm_nvenc_fwif *, struct nvkm_device *, + int, struct nvkm_nvenc **pnvenc); +#endif -- cgit v1.2.3 From fb0a5bbe31572948a7afb80ba9f1f2236296b7dd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: specify FBIF offset from subdev Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h | 3 +++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 16 +--------------- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 1 + 9 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index b7733694faed..adf33bfffa9f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -78,6 +78,9 @@ struct nvkm_falcon_func { } data; void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + + u32 fbif; + void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index c55d6804aef7..8314f10c359a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2045,6 +2045,7 @@ gf100_gr_ = { static const struct nvkm_falcon_func gf100_gr_flcn = { + .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c index 2cc9172bd1ad..1478079d9580 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -23,6 +23,7 @@ static const struct nvkm_falcon_func gm107_nvdec_flcn = { + .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c index e8a13ed04c63..d249c8ffb2d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c @@ -24,6 +24,7 @@ static const struct nvkm_falcon_func gm107_nvenc_flcn = { + .fbif = 0x800, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index c6919f2886de..444512ea5a31 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -48,6 +48,7 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2) static const struct nvkm_falcon_func gp102_sec2_flcn = { + .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index e3eb08f4e9a1..f1796f32c89b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -23,6 +23,7 @@ static const struct nvkm_falcon_func tu102_sec2_flcn = { + .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 49ea8a54061f..5c490528b0df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -183,8 +183,8 @@ void nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) { struct nvkm_device *device = falcon->owner->device; + const u32 fbif = falcon->func->fbif; u32 inst_loc; - u32 fbif; /* disable instance block binding */ if (ctx == NULL) { @@ -192,20 +192,6 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) return; } - switch (falcon->owner->index) { - case NVKM_ENGINE_NVENC0: - case NVKM_ENGINE_NVENC1: - case NVKM_ENGINE_NVENC2: - fbif = 0x800; - break; - case NVKM_SUBDEV_PMU: - fbif = 0xe00; - break; - default: - fbif = 0x600; - break; - } - nvkm_falcon_wr32(falcon, 0x10c, 0x1); /* setup apertures - virtual */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index e935c1bf6238..45fde8521c26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -23,6 +23,7 @@ static const struct nvkm_falcon_func gv100_gsp_flcn = { + .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index 073558972e42..c38a80bc7e53 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -243,6 +243,7 @@ gt215_pmu_init(struct nvkm_pmu *pmu) const struct nvkm_falcon_func gt215_pmu_flcn = { + .fbif = 0xe00, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, -- cgit v1.2.3 From ca3190e3c7e3f9cdd08fce158f852ced4f1afe80 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: move bind_context WAR out of common code Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 42 +++++++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 2 +- drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 36 ------------------- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 2 +- 5 files changed, 45 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 0fa6e09b57ee..2bfa9ff1170b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -17,4 +17,6 @@ void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr); void nvkm_falcon_v1_start(struct nvkm_falcon *); int nvkm_falcon_v1_enable(struct nvkm_falcon *); void nvkm_falcon_v1_disable(struct nvkm_falcon *); + +void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 444512ea5a31..278eb4dfedd7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -21,6 +21,7 @@ */ #include "priv.h" #include +#include static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { @@ -46,13 +47,52 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2) } } +void +gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, + struct nvkm_memory *ctx) +{ + struct nvkm_device *device = falcon->owner->device; + + nvkm_falcon_v1_bind_context(falcon, ctx); + if (!ctx) + return; + + /* Not sure if this is a WAR for a HW issue, or some additional + * programming sequence that's needed to properly complete the + * context switch we trigger above. + * + * Fixes unreliability of booting the SEC2 RTOS on Quadro P620, + * particularly when resuming from suspend. + * + * Also removes the need for an odd workaround where we needed + * to program SEC2's FALCON_CPUCTL_ALIAS_STARTCPU twice before + * the SEC2 RTOS would begin executing. + */ + nvkm_msec(device, 10, + u32 irqstat = nvkm_falcon_rd32(falcon, 0x008); + u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); + if ((irqstat & 0x00000008) && + (flcn0dc & 0x00007000) == 0x00005000) + break; + ); + + nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008); + nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002); + + nvkm_msec(device, 10, + u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); + if ((flcn0dc & 0x00007000) == 0x00000000) + break; + ); +} + static const struct nvkm_falcon_func gp102_sec2_flcn = { .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, + .bind_context = gp102_sec2_flcn_bind_context, .wait_for_halt = nvkm_falcon_v1_wait_for_halt, .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index f1796f32c89b..cbd89b429163 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -27,7 +27,7 @@ tu102_sec2_flcn = { .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, + .bind_context = gp102_sec2_flcn_bind_context, .wait_for_halt = nvkm_falcon_v1_wait_for_halt, .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 5c490528b0df..93e97c31df6c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -182,7 +182,6 @@ nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, void nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) { - struct nvkm_device *device = falcon->owner->device; const u32 fbif = falcon->func->fbif; u32 inst_loc; @@ -220,41 +219,6 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000); nvkm_falcon_mask(falcon, 0x0a4, 0x8, 0x8); - - /* Not sure if this is a WAR for a HW issue, or some additional - * programming sequence that's needed to properly complete the - * context switch we trigger above. - * - * Fixes unreliability of booting the SEC2 RTOS on Quadro P620, - * particularly when resuming from suspend. - * - * Also removes the need for an odd workaround where we needed - * to program SEC2's FALCON_CPUCTL_ALIAS_STARTCPU twice before - * the SEC2 RTOS would begin executing. - */ - switch (falcon->owner->index) { - case NVKM_SUBDEV_GSP: - case NVKM_ENGINE_SEC2: - nvkm_msec(device, 10, - u32 irqstat = nvkm_falcon_rd32(falcon, 0x008); - u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); - if ((irqstat & 0x00000008) && - (flcn0dc & 0x00007000) == 0x00005000) - break; - ); - - nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008); - nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002); - - nvkm_msec(device, 10, - u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc); - if ((flcn0dc & 0x00007000) == 0x00000000) - break; - ); - break; - default: - break; - } } void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index 45fde8521c26..36e640d3e9c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -27,7 +27,7 @@ gv100_gsp_flcn = { .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, + .bind_context = gp102_sec2_flcn_bind_context, .wait_for_halt = nvkm_falcon_v1_wait_for_halt, .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, -- cgit v1.2.3 From bc3cfd18acaf026d156a29f9a01aabdd70cb9d11 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: specify EMEM address from subdev Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 1 - drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 12 ++++++------ 5 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index adf33bfffa9f..e9e3fde9d6a1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -30,7 +30,6 @@ struct nvkm_falcon { u8 version; u8 secret; bool debug; - bool has_emem; struct nvkm_memory *core; bool external; @@ -84,6 +83,7 @@ struct nvkm_falcon_func { void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); + u32 emem_addr; void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *); int (*wait_for_halt)(struct nvkm_falcon *, u32); int (*clear_interrupt)(struct nvkm_falcon *, u32); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 278eb4dfedd7..9ef562345761 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -92,6 +92,7 @@ gp102_sec2_flcn = { .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, + .emem_addr = 0x01000000, .bind_context = gp102_sec2_flcn_bind_context, .wait_for_halt = nvkm_falcon_v1_wait_for_halt, .clear_interrupt = nvkm_falcon_v1_clear_interrupt, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index cbd89b429163..f4dd2a4814b0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -27,6 +27,7 @@ tu102_sec2_flcn = { .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, .read_dmem = nvkm_falcon_v1_read_dmem, + .emem_addr = 0x01000000, .bind_context = gp102_sec2_flcn_bind_context, .wait_for_halt = nvkm_falcon_v1_wait_for_halt, .clear_interrupt = nvkm_falcon_v1_clear_interrupt, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index fc66cdb82572..9e9e6808afb7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -170,7 +170,6 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon) break; case NVKM_ENGINE_SEC2: debug_reg = 0x408; - falcon->has_emem = true; break; case NVKM_SUBDEV_GSP: debug_reg = 0x0; /*XXX*/ diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 93e97c31df6c..1ff9b9c2e651 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -89,18 +89,17 @@ nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start, } } -static const u32 EMEM_START_ADDR = 0x1000000; - void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, u32 size, u8 port) { + const struct nvkm_falcon_func *func = falcon->func; u8 rem = size % 4; int i; - if (start >= EMEM_START_ADDR && falcon->has_emem) + if (func->emem_addr && start >= func->emem_addr) return nvkm_falcon_v1_load_emem(falcon, data, - start - EMEM_START_ADDR, size, + start - func->emem_addr, size, port); size -= rem; @@ -152,11 +151,12 @@ void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, void *data) { + const struct nvkm_falcon_func *func = falcon->func; u8 rem = size % 4; int i; - if (start >= EMEM_START_ADDR && falcon->has_emem) - return nvkm_falcon_v1_read_emem(falcon, start - EMEM_START_ADDR, + if (func->emem_addr && start >= func->emem_addr) + return nvkm_falcon_v1_read_emem(falcon, start - func->emem_addr, size, port, data); size -= rem; -- cgit v1.2.3 From e938c4e723a0dc5976f3e2c022c6ac30c9f14026 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: specify debug/production register offset from subdev Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/engine/falcon.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/base.c | 29 +++------------------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 1 + 6 files changed, 8 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index e9e3fde9d6a1..fbb57e114c72 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -78,6 +78,7 @@ struct nvkm_falcon_func { void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + u32 debug; u32 fbif; void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c index 1478079d9580..0ab27ab4d8ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c @@ -23,6 +23,7 @@ static const struct nvkm_falcon_func gm107_nvdec_flcn = { + .debug = 0xd00, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 9ef562345761..bb95a2d72b89 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -88,6 +88,7 @@ gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, static const struct nvkm_falcon_func gp102_sec2_flcn = { + .debug = 0x408, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index f4dd2a4814b0..c35752765ced 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -23,6 +23,7 @@ static const struct nvkm_falcon_func tu102_sec2_flcn = { + .debug = 0x408, .fbif = 0x600, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 9e9e6808afb7..c6a3448180d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -138,8 +138,8 @@ nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask) static int nvkm_falcon_oneinit(struct nvkm_falcon *falcon) { + const struct nvkm_falcon_func *func = falcon->func; const struct nvkm_subdev *subdev = falcon->owner; - u32 debug_reg; u32 reg; if (!falcon->addr) { @@ -158,31 +158,8 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon) falcon->code.limit = (reg & 0x1ff) << 8; falcon->data.limit = (reg & 0x3fe00) >> 1; - switch (subdev->index) { - case NVKM_ENGINE_GR: - debug_reg = 0x0; - break; - case NVKM_SUBDEV_PMU: - debug_reg = 0xc08; - break; - case NVKM_ENGINE_NVDEC0: - debug_reg = 0xd00; - break; - case NVKM_ENGINE_SEC2: - debug_reg = 0x408; - break; - case NVKM_SUBDEV_GSP: - debug_reg = 0x0; /*XXX*/ - break; - default: - nvkm_warn(subdev, "unsupported falcon %s!\n", - nvkm_subdev_name[subdev->index]); - debug_reg = 0; - break; - } - - if (debug_reg) { - u32 val = nvkm_falcon_rd32(falcon, debug_reg); + if (func->debug) { + u32 val = nvkm_falcon_rd32(falcon, func->debug); falcon->debug = (val >> 20) & 0x1; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index c38a80bc7e53..0e23325f94a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -243,6 +243,7 @@ gt215_pmu_init(struct nvkm_pmu *pmu) const struct nvkm_falcon_func gt215_pmu_flcn = { + .debug = 0xc08, .fbif = 0xe00, .load_imem = nvkm_falcon_v1_load_imem, .load_dmem = nvkm_falcon_v1_load_dmem, -- cgit v1.2.3 From b826f48a1c127396df2b5e4889994fed6ef3c4a7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:21 +1000 Subject: drm/nouveau/flcn: specify queue register offsets from subdev Also fixes the values for Turing, even though we don't use it yet. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h | 6 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 19 +------------------ .../gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 11 +++++++---- .../gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 13 +++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c | 2 ++ 7 files changed, 29 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index fbb57e114c72..46b2424e30f0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -93,6 +93,12 @@ struct nvkm_falcon_func { int (*enable)(struct nvkm_falcon *falcon); void (*disable)(struct nvkm_falcon *falcon); + struct { + u32 head; + u32 tail; + u32 stride; + } cmdq, msgq; + struct nvkm_sclass sclass[]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index bb95a2d72b89..0f6e8d002eea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -101,6 +101,8 @@ gp102_sec2_flcn = { .start = nvkm_falcon_v1_start, .enable = nvkm_falcon_v1_enable, .disable = nvkm_falcon_v1_disable, + .cmdq = { 0xa00, 0xa04, 8 }, + .msgq = { 0xa30, 0xa34, 8 }, }; const struct nvkm_sec2_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index c35752765ced..fe9993526f16 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -36,6 +36,8 @@ tu102_sec2_flcn = { .start = nvkm_falcon_v1_start, .enable = nvkm_falcon_v1_enable, .disable = nvkm_falcon_v1_disable, + .cmdq = { 0xc00, 0xc04, 8 }, + .msgq = { 0xc80, 0xc84, 8 }, }; static const struct nvkm_sec2_func diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index a8bee1e046aa..4d7039d8e498 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -384,27 +384,10 @@ msgqueue_handle_init_msg(struct nvkm_msgqueue *priv, { struct nvkm_falcon *falcon = priv->falcon; const struct nvkm_subdev *subdev = falcon->owner; + const u32 tail_reg = falcon->func->msgq.tail; u32 tail; - u32 tail_reg; int ret; - /* - * Of course the message queue registers vary depending on the falcon - * used... - */ - switch (falcon->owner->index) { - case NVKM_SUBDEV_PMU: - tail_reg = 0x4cc; - break; - case NVKM_ENGINE_SEC2: - tail_reg = 0xa34; - break; - default: - nvkm_error(subdev, "falcon %s unsupported for msgqueue!\n", - nvkm_subdev_name[falcon->owner->index]); - return -EINVAL; - } - /* * Read the message - queues are not initialized yet so we cannot rely * on msg_queue_read() diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index fec0273158f6..68de203d80a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -136,6 +136,7 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) u16 sw_managed_area_offset; u16 sw_managed_area_size; } *init = (void *)hdr; + const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; int i; @@ -159,11 +160,13 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) queue->size = init->queue_info[i].size; if (i != MSGQUEUE_0137C63D_MESSAGE_QUEUE) { - queue->head_reg = 0x4a0 + (queue->index * 4); - queue->tail_reg = 0x4b0 + (queue->index * 4); + queue->head_reg = func->cmdq.head + queue->index * + func->cmdq.stride; + queue->tail_reg = func->cmdq.tail + queue->index * + func->cmdq.stride; } else { - queue->head_reg = 0x4c8; - queue->tail_reg = 0x4cc; + queue->head_reg = func->msgq.head; + queue->tail_reg = func->msgq.tail; } nvkm_debug(subdev, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 9424803b9ef4..651bef2e3270 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -105,6 +105,7 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) u16 sw_managed_area_offset; u16 sw_managed_area_size; } *init = (void *)hdr; + const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; int i; @@ -129,11 +130,15 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) queue->size = init->queue_info[i].size; if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) { - queue->head_reg = 0xa30 + (queue->index * 8); - queue->tail_reg = 0xa34 + (queue->index * 8); + queue->head_reg = func->msgq.head + queue->index * + func->msgq.stride; + queue->tail_reg = func->msgq.tail + queue->index * + func->msgq.stride; } else { - queue->head_reg = 0xa00 + (queue->index * 8); - queue->tail_reg = 0xa04 + (queue->index * 8); + queue->head_reg = func->cmdq.head + queue->index * + func->cmdq.stride; + queue->tail_reg = func->cmdq.tail + queue->index * + func->cmdq.stride; } nvkm_debug(subdev, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c index 0e23325f94a7..88b909913ff9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c @@ -255,6 +255,8 @@ gt215_pmu_flcn = { .start = nvkm_falcon_v1_start, .enable = nvkm_falcon_v1_enable, .disable = nvkm_falcon_v1_disable, + .cmdq = { 0x4a0, 0x4b0, 4 }, + .msgq = { 0x4c8, 0x4cc, 0 }, }; static const struct nvkm_pmu_func -- cgit v1.2.3 From af696a61a22118dd12250c9dbc0ffcee8eb0d2a9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn: reset sec2/gsp falcons harder Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 11 ++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 2bfa9ff1170b..269814e06e93 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -19,4 +19,5 @@ int nvkm_falcon_v1_enable(struct nvkm_falcon *); void nvkm_falcon_v1_disable(struct nvkm_falcon *); void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); +int gp102_sec2_flcn_enable(struct nvkm_falcon *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index 46b2424e30f0..27c1f868552c 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -92,6 +92,7 @@ struct nvkm_falcon_func { void (*start)(struct nvkm_falcon *); int (*enable)(struct nvkm_falcon *falcon); void (*disable)(struct nvkm_falcon *falcon); + int (*reset)(struct nvkm_falcon *); struct { u32 head; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 0f6e8d002eea..9a5bae1a03cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -47,6 +47,15 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2) } } +int +gp102_sec2_flcn_enable(struct nvkm_falcon *falcon) +{ + nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001); + udelay(10); + nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000); + return nvkm_falcon_v1_enable(falcon); +} + void gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) @@ -99,7 +108,7 @@ gp102_sec2_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, + .enable = gp102_sec2_flcn_enable, .disable = nvkm_falcon_v1_disable, .cmdq = { 0xa00, 0xa04, 8 }, .msgq = { 0xa30, 0xa34, 8 }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c index 36e640d3e9c3..2114f9b00a28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c @@ -32,7 +32,7 @@ gv100_gsp_flcn = { .clear_interrupt = nvkm_falcon_v1_clear_interrupt, .set_start_addr = nvkm_falcon_v1_set_start_addr, .start = nvkm_falcon_v1_start, - .enable = nvkm_falcon_v1_enable, + .enable = gp102_sec2_flcn_enable, .disable = nvkm_falcon_v1_disable, }; -- cgit v1.2.3 From 3d0482ec28ebc506b9a720be9ff146e9bf343042 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn: add printk macros Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 269814e06e93..7bef0e666bd4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -20,4 +20,13 @@ void nvkm_falcon_v1_disable(struct nvkm_falcon *); void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *); int gp102_sec2_flcn_enable(struct nvkm_falcon *); + +#define FLCN_PRINTK(t,f,fmt,a...) do { \ + if (nvkm_subdev_name[(f)->owner->index] != (f)->name) \ + nvkm_##t((f)->owner, "%s: "fmt"\n", (f)->name, ##a); \ + else \ + nvkm_##t((f)->owner, fmt"\n", ##a); \ +} while(0) +#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK(debug, (f), fmt, ##a) +#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK(error, (f), fmt, ##a) #endif -- cgit v1.2.3 From 7e1659cc3b33e8765ea155b4b46d8e658d5277d2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn: split msgqueue into multiple pieces To make things clearer while modifying the interfaces, split msgqueue into Queue Manager, Command Queue, and Message Queue. There should be no code changes here, these will be done incrementally. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild | 3 + drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 185 +++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 216 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 410 ------------------------- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c | 56 ++++ drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 14 + 6 files changed, 474 insertions(+), 410 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild index b5665ada850a..004d1cd4e37e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild @@ -1,5 +1,8 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/falcon/base.o +nvkm-y += nvkm/falcon/cmdq.o +nvkm-y += nvkm/falcon/msgq.o +nvkm-y += nvkm/falcon/qmgr.o nvkm-y += nvkm/falcon/v1.o nvkm-y += nvkm/falcon/msgqueue.o nvkm-y += nvkm/falcon/msgqueue_0137c63d.o diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c new file mode 100644 index 000000000000..4785a563c183 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. + * + */ +#include "qmgr.h" + +static bool +cmd_queue_has_room(struct nvkm_msgqueue *priv, + struct nvkm_msgqueue_queue *queue, u32 size, bool *rewind) +{ + struct nvkm_falcon *falcon = priv->falcon; + u32 head = nvkm_falcon_rd32(falcon, queue->head_reg); + u32 tail = nvkm_falcon_rd32(falcon, queue->tail_reg); + u32 free; + + size = ALIGN(size, QUEUE_ALIGNMENT); + + if (head >= tail) { + free = queue->offset + queue->size - head; + free -= HDR_SIZE; + + if (size > free) { + *rewind = true; + head = queue->offset; + } + } + + if (head < tail) + free = tail - head - 1; + + return size <= free; +} + +static int +cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + void *data, u32 size) +{ + nvkm_falcon_load_dmem(priv->falcon, data, queue->position, size, 0); + queue->position += ALIGN(size, QUEUE_ALIGNMENT); + return 0; +} + +/* REWIND unit is always 0x00 */ +#define MSGQUEUE_UNIT_REWIND 0x00 + +static void +cmd_queue_rewind(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +{ + const struct nvkm_subdev *subdev = priv->falcon->owner; + struct nvkm_msgqueue_hdr cmd; + int err; + + cmd.unit_id = MSGQUEUE_UNIT_REWIND; + cmd.size = sizeof(cmd); + err = cmd_queue_push(priv, queue, &cmd, cmd.size); + if (err) + nvkm_error(subdev, "queue %d rewind failed\n", queue->index); + else + nvkm_error(subdev, "queue %d rewinded\n", queue->index); + + queue->position = queue->offset; +} + +static int +cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + u32 size) +{ + struct nvkm_falcon *falcon = priv->falcon; + const struct nvkm_subdev *subdev = priv->falcon->owner; + bool rewind = false; + + mutex_lock(&queue->mutex); + + if (!cmd_queue_has_room(priv, queue, size, &rewind)) { + nvkm_error(subdev, "queue full\n"); + mutex_unlock(&queue->mutex); + return -EAGAIN; + } + + queue->position = nvkm_falcon_rd32(falcon, queue->head_reg); + + if (rewind) + cmd_queue_rewind(priv, queue); + + return 0; +} + +static void +cmd_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + bool commit) +{ + struct nvkm_falcon *falcon = priv->falcon; + + if (commit) + nvkm_falcon_wr32(falcon, queue->head_reg, queue->position); + + mutex_unlock(&queue->mutex); +} + +static int +cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, + struct nvkm_msgqueue_queue *queue) +{ + const struct nvkm_subdev *subdev = priv->falcon->owner; + static unsigned timeout = 2000; + unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); + int ret = -EAGAIN; + bool commit = true; + + while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) + ret = cmd_queue_open(priv, queue, cmd->size); + if (ret) { + nvkm_error(subdev, "pmu_queue_open_write failed\n"); + return ret; + } + + ret = cmd_queue_push(priv, queue, cmd, cmd->size); + if (ret) { + nvkm_error(subdev, "pmu_queue_push failed\n"); + commit = false; + } + + cmd_queue_close(priv, queue, commit); + return ret; +} + +/* specifies that we want to know the command status in the answer message */ +#define CMD_FLAGS_STATUS BIT(0) +/* specifies that we want an interrupt when the answer message is queued */ +#define CMD_FLAGS_INTR BIT(1) + +int +nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, + struct nvkm_msgqueue_hdr *cmd, nvkm_msgqueue_callback cb, + struct completion *completion, bool wait_init) +{ + struct nvkm_msgqueue_seq *seq; + struct nvkm_msgqueue_queue *queue; + int ret; + + if (wait_init && !wait_for_completion_timeout(&priv->init_done, + msecs_to_jiffies(1000))) + return -ETIMEDOUT; + + queue = priv->func->cmd_queue(priv, prio); + if (IS_ERR(queue)) + return PTR_ERR(queue); + + seq = msgqueue_seq_acquire(priv); + if (IS_ERR(seq)) + return PTR_ERR(seq); + + cmd->seq_id = seq->id; + cmd->ctrl_flags = CMD_FLAGS_STATUS | CMD_FLAGS_INTR; + + seq->callback = cb; + seq->state = SEQ_STATE_USED; + seq->completion = completion; + + ret = cmd_write(priv, cmd, queue); + if (ret) { + seq->state = SEQ_STATE_PENDING; + msgqueue_seq_release(priv, seq); + } + + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c new file mode 100644 index 000000000000..5db0b41bc2c8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. + * + */ +#include "qmgr.h" + +static int +msg_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +{ + struct nvkm_falcon *falcon = priv->falcon; + mutex_lock(&queue->mutex); + queue->position = nvkm_falcon_rd32(falcon, queue->tail_reg); + return 0; +} + +static void +msg_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + bool commit) +{ + struct nvkm_falcon *falcon = priv->falcon; + + if (commit) + nvkm_falcon_wr32(falcon, queue->tail_reg, queue->position); + + mutex_unlock(&queue->mutex); +} + +static bool +msg_queue_empty(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +{ + struct nvkm_falcon *falcon = priv->falcon; + u32 head = nvkm_falcon_rd32(falcon, queue->head_reg); + u32 tail = nvkm_falcon_rd32(falcon, queue->tail_reg); + return head == tail; +} + +static int +msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + void *data, u32 size) +{ + struct nvkm_falcon *falcon = priv->falcon; + const struct nvkm_subdev *subdev = priv->falcon->owner; + u32 head, tail, available; + + head = nvkm_falcon_rd32(falcon, queue->head_reg); + /* has the buffer looped? */ + if (head < queue->position) + queue->position = queue->offset; + + tail = queue->position; + + available = head - tail; + + if (available == 0) { + nvkm_warn(subdev, "no message data available\n"); + return 0; + } + + if (size > available) { + nvkm_warn(subdev, "message data smaller than read request\n"); + size = available; + } + + nvkm_falcon_read_dmem(priv->falcon, tail, size, 0, data); + queue->position += ALIGN(size, QUEUE_ALIGNMENT); + return size; +} + +static int +msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, + struct nvkm_msgqueue_hdr *hdr) +{ + const struct nvkm_subdev *subdev = priv->falcon->owner; + int ret; + + ret = msg_queue_open(priv, queue); + if (ret) { + nvkm_error(subdev, "fail to open queue %d\n", queue->index); + return ret; + } + + if (msg_queue_empty(priv, queue)) { + ret = 0; + goto close; + } + + ret = msg_queue_pop(priv, queue, hdr, HDR_SIZE); + if (ret >= 0 && ret != HDR_SIZE) + ret = -EINVAL; + if (ret < 0) { + nvkm_error(subdev, "failed to read message header: %d\n", ret); + goto close; + } + + if (hdr->size > MSG_BUF_SIZE) { + nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); + ret = -ENOSPC; + goto close; + } + + if (hdr->size > HDR_SIZE) { + u32 read_size = hdr->size - HDR_SIZE; + + ret = msg_queue_pop(priv, queue, (hdr + 1), read_size); + if (ret >= 0 && ret != read_size) + ret = -EINVAL; + if (ret < 0) { + nvkm_error(subdev, "failed to read message: %d\n", ret); + goto close; + } + } + +close: + msg_queue_close(priv, queue, (ret >= 0)); + return ret; +} + +static int +msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *hdr) +{ + const struct nvkm_subdev *subdev = priv->falcon->owner; + struct nvkm_msgqueue_seq *seq; + + seq = &priv->seq[hdr->seq_id]; + if (seq->state != SEQ_STATE_USED && seq->state != SEQ_STATE_CANCELLED) { + nvkm_error(subdev, "msg for unknown sequence %d", seq->id); + return -EINVAL; + } + + if (seq->state == SEQ_STATE_USED) { + if (seq->callback) + seq->callback(priv, hdr); + } + + if (seq->completion) + complete(seq->completion); + + msgqueue_seq_release(priv, seq); + return 0; +} + +static int +msgqueue_handle_init_msg(struct nvkm_msgqueue *priv, + struct nvkm_msgqueue_hdr *hdr) +{ + struct nvkm_falcon *falcon = priv->falcon; + const struct nvkm_subdev *subdev = falcon->owner; + const u32 tail_reg = falcon->func->msgq.tail; + u32 tail; + int ret; + + /* + * Read the message - queues are not initialized yet so we cannot rely + * on msg_queue_read() + */ + tail = nvkm_falcon_rd32(falcon, tail_reg); + nvkm_falcon_read_dmem(falcon, tail, HDR_SIZE, 0, hdr); + + if (hdr->size > MSG_BUF_SIZE) { + nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); + return -ENOSPC; + } + + nvkm_falcon_read_dmem(falcon, tail + HDR_SIZE, hdr->size - HDR_SIZE, 0, + (hdr + 1)); + + tail += ALIGN(hdr->size, QUEUE_ALIGNMENT); + nvkm_falcon_wr32(falcon, tail_reg, tail); + + ret = priv->func->init_func->init_callback(priv, hdr); + if (ret) + return ret; + + return 0; +} + +void +nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, + struct nvkm_msgqueue_queue *queue) +{ + /* + * We are invoked from a worker thread, so normally we have plenty of + * stack space to work with. + */ + u8 msg_buffer[MSG_BUF_SIZE]; + struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer; + int ret; + + /* the first message we receive must be the init message */ + if ((!priv->init_msg_received)) { + ret = msgqueue_handle_init_msg(priv, hdr); + if (!ret) + priv->init_msg_received = true; + } else { + while (msg_queue_read(priv, queue, hdr) > 0) + msgqueue_msg_handle(priv, hdr); + } +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index 4d7039d8e498..eb2af85f3e3c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -26,416 +26,6 @@ #include - -#define HDR_SIZE sizeof(struct nvkm_msgqueue_hdr) -#define QUEUE_ALIGNMENT 4 -/* max size of the messages we can receive */ -#define MSG_BUF_SIZE 128 - -static int -msg_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) -{ - struct nvkm_falcon *falcon = priv->falcon; - - mutex_lock(&queue->mutex); - - queue->position = nvkm_falcon_rd32(falcon, queue->tail_reg); - - return 0; -} - -static void -msg_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - bool commit) -{ - struct nvkm_falcon *falcon = priv->falcon; - - if (commit) - nvkm_falcon_wr32(falcon, queue->tail_reg, queue->position); - - mutex_unlock(&queue->mutex); -} - -static bool -msg_queue_empty(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) -{ - struct nvkm_falcon *falcon = priv->falcon; - u32 head, tail; - - head = nvkm_falcon_rd32(falcon, queue->head_reg); - tail = nvkm_falcon_rd32(falcon, queue->tail_reg); - - return head == tail; -} - -static int -msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - void *data, u32 size) -{ - struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = priv->falcon->owner; - u32 head, tail, available; - - head = nvkm_falcon_rd32(falcon, queue->head_reg); - /* has the buffer looped? */ - if (head < queue->position) - queue->position = queue->offset; - - tail = queue->position; - - available = head - tail; - - if (available == 0) { - nvkm_warn(subdev, "no message data available\n"); - return 0; - } - - if (size > available) { - nvkm_warn(subdev, "message data smaller than read request\n"); - size = available; - } - - nvkm_falcon_read_dmem(priv->falcon, tail, size, 0, data); - queue->position += ALIGN(size, QUEUE_ALIGNMENT); - - return size; -} - -static int -msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - struct nvkm_msgqueue_hdr *hdr) -{ - const struct nvkm_subdev *subdev = priv->falcon->owner; - int err; - - err = msg_queue_open(priv, queue); - if (err) { - nvkm_error(subdev, "fail to open queue %d\n", queue->index); - return err; - } - - if (msg_queue_empty(priv, queue)) { - err = 0; - goto close; - } - - err = msg_queue_pop(priv, queue, hdr, HDR_SIZE); - if (err >= 0 && err != HDR_SIZE) - err = -EINVAL; - if (err < 0) { - nvkm_error(subdev, "failed to read message header: %d\n", err); - goto close; - } - - if (hdr->size > MSG_BUF_SIZE) { - nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); - err = -ENOSPC; - goto close; - } - - if (hdr->size > HDR_SIZE) { - u32 read_size = hdr->size - HDR_SIZE; - - err = msg_queue_pop(priv, queue, (hdr + 1), read_size); - if (err >= 0 && err != read_size) - err = -EINVAL; - if (err < 0) { - nvkm_error(subdev, "failed to read message: %d\n", err); - goto close; - } - } - -close: - msg_queue_close(priv, queue, (err >= 0)); - - return err; -} - -static bool -cmd_queue_has_room(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - u32 size, bool *rewind) -{ - struct nvkm_falcon *falcon = priv->falcon; - u32 head, tail, free; - - size = ALIGN(size, QUEUE_ALIGNMENT); - - head = nvkm_falcon_rd32(falcon, queue->head_reg); - tail = nvkm_falcon_rd32(falcon, queue->tail_reg); - - if (head >= tail) { - free = queue->offset + queue->size - head; - free -= HDR_SIZE; - - if (size > free) { - *rewind = true; - head = queue->offset; - } - } - - if (head < tail) - free = tail - head - 1; - - return size <= free; -} - -static int -cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - void *data, u32 size) -{ - nvkm_falcon_load_dmem(priv->falcon, data, queue->position, size, 0); - queue->position += ALIGN(size, QUEUE_ALIGNMENT); - - return 0; -} - -/* REWIND unit is always 0x00 */ -#define MSGQUEUE_UNIT_REWIND 0x00 - -static void -cmd_queue_rewind(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) -{ - const struct nvkm_subdev *subdev = priv->falcon->owner; - struct nvkm_msgqueue_hdr cmd; - int err; - - cmd.unit_id = MSGQUEUE_UNIT_REWIND; - cmd.size = sizeof(cmd); - err = cmd_queue_push(priv, queue, &cmd, cmd.size); - if (err) - nvkm_error(subdev, "queue %d rewind failed\n", queue->index); - else - nvkm_error(subdev, "queue %d rewinded\n", queue->index); - - queue->position = queue->offset; -} - -static int -cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - u32 size) -{ - struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = priv->falcon->owner; - bool rewind = false; - - mutex_lock(&queue->mutex); - - if (!cmd_queue_has_room(priv, queue, size, &rewind)) { - nvkm_error(subdev, "queue full\n"); - mutex_unlock(&queue->mutex); - return -EAGAIN; - } - - queue->position = nvkm_falcon_rd32(falcon, queue->head_reg); - - if (rewind) - cmd_queue_rewind(priv, queue); - - return 0; -} - -static void -cmd_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - bool commit) -{ - struct nvkm_falcon *falcon = priv->falcon; - - if (commit) - nvkm_falcon_wr32(falcon, queue->head_reg, queue->position); - - mutex_unlock(&queue->mutex); -} - -static int -cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, - struct nvkm_msgqueue_queue *queue) -{ - const struct nvkm_subdev *subdev = priv->falcon->owner; - static unsigned timeout = 2000; - unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); - int ret = -EAGAIN; - bool commit = true; - - while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) - ret = cmd_queue_open(priv, queue, cmd->size); - if (ret) { - nvkm_error(subdev, "pmu_queue_open_write failed\n"); - return ret; - } - - ret = cmd_queue_push(priv, queue, cmd, cmd->size); - if (ret) { - nvkm_error(subdev, "pmu_queue_push failed\n"); - commit = false; - } - - cmd_queue_close(priv, queue, commit); - - return ret; -} - -static struct nvkm_msgqueue_seq * -msgqueue_seq_acquire(struct nvkm_msgqueue *priv) -{ - const struct nvkm_subdev *subdev = priv->falcon->owner; - struct nvkm_msgqueue_seq *seq; - u32 index; - - mutex_lock(&priv->seq_lock); - - index = find_first_zero_bit(priv->seq_tbl, NVKM_MSGQUEUE_NUM_SEQUENCES); - - if (index >= NVKM_MSGQUEUE_NUM_SEQUENCES) { - nvkm_error(subdev, "no free sequence available\n"); - mutex_unlock(&priv->seq_lock); - return ERR_PTR(-EAGAIN); - } - - set_bit(index, priv->seq_tbl); - - mutex_unlock(&priv->seq_lock); - - seq = &priv->seq[index]; - seq->state = SEQ_STATE_PENDING; - - return seq; -} - -static void -msgqueue_seq_release(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_seq *seq) -{ - /* no need to acquire seq_lock since clear_bit is atomic */ - seq->state = SEQ_STATE_FREE; - seq->callback = NULL; - seq->completion = NULL; - clear_bit(seq->id, priv->seq_tbl); -} - -/* specifies that we want to know the command status in the answer message */ -#define CMD_FLAGS_STATUS BIT(0) -/* specifies that we want an interrupt when the answer message is queued */ -#define CMD_FLAGS_INTR BIT(1) - -int -nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, - struct nvkm_msgqueue_hdr *cmd, nvkm_msgqueue_callback cb, - struct completion *completion, bool wait_init) -{ - struct nvkm_msgqueue_seq *seq; - struct nvkm_msgqueue_queue *queue; - int ret; - - if (wait_init && !wait_for_completion_timeout(&priv->init_done, - msecs_to_jiffies(1000))) - return -ETIMEDOUT; - - queue = priv->func->cmd_queue(priv, prio); - if (IS_ERR(queue)) - return PTR_ERR(queue); - - seq = msgqueue_seq_acquire(priv); - if (IS_ERR(seq)) - return PTR_ERR(seq); - - cmd->seq_id = seq->id; - cmd->ctrl_flags = CMD_FLAGS_STATUS | CMD_FLAGS_INTR; - - seq->callback = cb; - seq->state = SEQ_STATE_USED; - seq->completion = completion; - - ret = cmd_write(priv, cmd, queue); - if (ret) { - seq->state = SEQ_STATE_PENDING; - msgqueue_seq_release(priv, seq); - } - - return ret; -} - -static int -msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *hdr) -{ - const struct nvkm_subdev *subdev = priv->falcon->owner; - struct nvkm_msgqueue_seq *seq; - - seq = &priv->seq[hdr->seq_id]; - if (seq->state != SEQ_STATE_USED && seq->state != SEQ_STATE_CANCELLED) { - nvkm_error(subdev, "msg for unknown sequence %d", seq->id); - return -EINVAL; - } - - if (seq->state == SEQ_STATE_USED) { - if (seq->callback) - seq->callback(priv, hdr); - } - - if (seq->completion) - complete(seq->completion); - - msgqueue_seq_release(priv, seq); - - return 0; -} - -static int -msgqueue_handle_init_msg(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_hdr *hdr) -{ - struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = falcon->owner; - const u32 tail_reg = falcon->func->msgq.tail; - u32 tail; - int ret; - - /* - * Read the message - queues are not initialized yet so we cannot rely - * on msg_queue_read() - */ - tail = nvkm_falcon_rd32(falcon, tail_reg); - nvkm_falcon_read_dmem(falcon, tail, HDR_SIZE, 0, hdr); - - if (hdr->size > MSG_BUF_SIZE) { - nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); - return -ENOSPC; - } - - nvkm_falcon_read_dmem(falcon, tail + HDR_SIZE, hdr->size - HDR_SIZE, 0, - (hdr + 1)); - - tail += ALIGN(hdr->size, QUEUE_ALIGNMENT); - nvkm_falcon_wr32(falcon, tail_reg, tail); - - ret = priv->func->init_func->init_callback(priv, hdr); - if (ret) - return ret; - - return 0; -} - -void -nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_queue *queue) -{ - /* - * We are invoked from a worker thread, so normally we have plenty of - * stack space to work with. - */ - u8 msg_buffer[MSG_BUF_SIZE]; - struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer; - int ret; - - /* the first message we receive must be the init message */ - if ((!priv->init_msg_received)) { - ret = msgqueue_handle_init_msg(priv, hdr); - if (!ret) - priv->init_msg_received = true; - } else { - while (msg_queue_read(priv, queue, hdr) > 0) - msgqueue_msg_handle(priv, hdr); - } -} - void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf) { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c new file mode 100644 index 000000000000..edf941559aec --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. + * + */ +#include "qmgr.h" + +struct nvkm_msgqueue_seq * +msgqueue_seq_acquire(struct nvkm_msgqueue *priv) +{ + const struct nvkm_subdev *subdev = priv->falcon->owner; + struct nvkm_msgqueue_seq *seq; + u32 index; + + mutex_lock(&priv->seq_lock); + index = find_first_zero_bit(priv->seq_tbl, NVKM_MSGQUEUE_NUM_SEQUENCES); + if (index >= NVKM_MSGQUEUE_NUM_SEQUENCES) { + nvkm_error(subdev, "no free sequence available\n"); + mutex_unlock(&priv->seq_lock); + return ERR_PTR(-EAGAIN); + } + + set_bit(index, priv->seq_tbl); + mutex_unlock(&priv->seq_lock); + + seq = &priv->seq[index]; + seq->state = SEQ_STATE_PENDING; + return seq; +} + +void +msgqueue_seq_release(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_seq *seq) +{ + /* no need to acquire seq_lock since clear_bit is atomic */ + seq->state = SEQ_STATE_FREE; + seq->callback = NULL; + seq->completion = NULL; + clear_bit(seq->id, priv->seq_tbl); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h new file mode 100644 index 000000000000..db00c5ee6124 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_FALCON_QMGR_H__ +#define __NVKM_FALCON_QMGR_H__ +#include +#include "msgqueue.h" + +#define HDR_SIZE sizeof(struct nvkm_msgqueue_hdr) +#define QUEUE_ALIGNMENT 4 +/* max size of the messages we can receive */ +#define MSG_BUF_SIZE 128 + +struct nvkm_msgqueue_seq *msgqueue_seq_acquire(struct nvkm_msgqueue *); +void msgqueue_seq_release(struct nvkm_msgqueue *, struct nvkm_msgqueue_seq *); +#endif -- cgit v1.2.3 From 8763955ba73807c6f5d38364074c1802d8415172 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/qmgr: explicitly create queue manager from subdevs Code to interface with LS firmwares is being moved to the subdevs where it belongs, rather than living in the common falcon code. This is an incremental step towards that goal. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 4 ++++ drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 4 ++++ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c | 23 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 4 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 16 ++++++++++++--- 8 files changed, 52 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 7bef0e666bd4..043bd498e5c9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -29,4 +29,8 @@ int gp102_sec2_flcn_enable(struct nvkm_falcon *); } while(0) #define FLCN_DBG(f,fmt,a...) FLCN_PRINTK(debug, (f), fmt, ##a) #define FLCN_ERR(f,fmt,a...) FLCN_PRINTK(error, (f), fmt, ##a) + +struct nvkm_falcon_qmgr; +int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **); +void nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 25f016fefe15..3b6586e6c8f8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -10,6 +10,7 @@ struct nvkm_sec2 { struct nvkm_engine engine; struct nvkm_falcon falcon; + struct nvkm_falcon_qmgr *qmgr; struct nvkm_msgqueue *queue; struct work_struct work; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 0b72d63b2427..10b3c71ccf4b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -8,6 +8,8 @@ struct nvkm_pmu { const struct nvkm_pmu_func *func; struct nvkm_subdev subdev; struct nvkm_falcon falcon; + + struct nvkm_falcon_qmgr *qmgr; struct nvkm_msgqueue *queue; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index bb79488f414d..542f88a6fc39 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -59,6 +59,7 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); nvkm_msgqueue_del(&sec2->queue); + nvkm_falcon_qmgr_del(&sec2->qmgr); nvkm_falcon_dtor(&sec2->falcon); return sec2; } @@ -95,6 +96,9 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, if (ret) return ret; + if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr))) + return ret; + INIT_WORK(&sec2->work, nvkm_sec2_recv); return 0; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 13b54f8d8e04..e978fb15d3b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -132,6 +132,7 @@ struct nvkm_msgqueue_func { * @tail_reg: address of the TAIL register for this queue */ struct nvkm_msgqueue_queue { + struct nvkm_falcon_qmgr *qmgr; struct mutex mutex; u32 index; u32 offset; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c index edf941559aec..f1469ecb7a4e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c @@ -54,3 +54,26 @@ msgqueue_seq_release(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_seq *seq) seq->completion = NULL; clear_bit(seq->id, priv->seq_tbl); } + +void +nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **pqmgr) +{ + struct nvkm_falcon_qmgr *qmgr = *pqmgr; + if (qmgr) { + kfree(*pqmgr); + *pqmgr = NULL; + } +} + +int +nvkm_falcon_qmgr_new(struct nvkm_falcon *falcon, + struct nvkm_falcon_qmgr **pqmgr) +{ + struct nvkm_falcon_qmgr *qmgr; + + if (!(qmgr = *pqmgr = kzalloc(sizeof(*qmgr), GFP_KERNEL))) + return -ENOMEM; + + qmgr->falcon = falcon; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index db00c5ee6124..9c8d77c11fd9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -9,6 +9,10 @@ /* max size of the messages we can receive */ #define MSG_BUF_SIZE 128 +struct nvkm_falcon_qmgr { + struct nvkm_falcon *falcon; +}; + struct nvkm_msgqueue_seq *msgqueue_seq_acquire(struct nvkm_msgqueue *); void msgqueue_seq_release(struct nvkm_msgqueue *, struct nvkm_msgqueue_seq *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 60e14f9a5415..850939f7e287 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -139,6 +139,7 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); nvkm_msgqueue_del(&pmu->queue); + nvkm_falcon_qmgr_del(&pmu->qmgr); nvkm_falcon_dtor(&pmu->falcon); return nvkm_pmu(subdev); } @@ -156,6 +157,8 @@ int nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, int index, struct nvkm_pmu *pmu) { + int ret; + nvkm_subdev_ctor(&nvkm_pmu, device, index, &pmu->subdev); INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); @@ -167,9 +170,16 @@ nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, pmu->func = fwif->func; - return nvkm_falcon_ctor(pmu->func->flcn, &pmu->subdev, - nvkm_subdev_name[pmu->subdev.index], 0x10a000, - &pmu->falcon); + ret = nvkm_falcon_ctor(pmu->func->flcn, &pmu->subdev, + nvkm_subdev_name[pmu->subdev.index], 0x10a000, + &pmu->falcon); + if (ret) + return ret; + + if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr))) + return ret; + + return 0; } int -- cgit v1.2.3 From acc466ab46574f0d9de65606f0796cff07c9a7d5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: explicitly create command queue(s) from subdevs Code to interface with LS firmwares is being moved to the subdevs where it belongs, rather than living in the common falcon code. This is an incremental step towards that goal. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 8 ++++ drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 2 + drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 2 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 5 ++- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 45 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 1 + .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 24 ++++++------ .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 14 +++---- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 5 +++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 9 ++++- 11 files changed, 95 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 043bd498e5c9..c4d9431fd63b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -33,4 +33,12 @@ int gp102_sec2_flcn_enable(struct nvkm_falcon *); struct nvkm_falcon_qmgr; int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **); void nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **); + +struct nvkm_falcon_cmdq; +int nvkm_falcon_cmdq_new(struct nvkm_falcon_qmgr *, const char *name, + struct nvkm_falcon_cmdq **); +void nvkm_falcon_cmdq_del(struct nvkm_falcon_cmdq **); +void nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *, + u32 index, u32 offset, u32 size); +void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index 1218f28c14ba..5ae6c10f0fa4 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -3,6 +3,8 @@ #define __NVKM_SUBDEV_H__ #include +#define nvkm_falcon_cmdq nvkm_msgqueue_queue + struct nvkm_subdev { const struct nvkm_subdev_func *func; struct nvkm_device *device; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 3b6586e6c8f8..e52ea3b99a4d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -11,6 +11,7 @@ struct nvkm_sec2 { struct nvkm_falcon falcon; struct nvkm_falcon_qmgr *qmgr; + struct nvkm_falcon_cmdq *cmdq; struct nvkm_msgqueue *queue; struct work_struct work; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 10b3c71ccf4b..6c0cfef2d1fa 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -10,6 +10,8 @@ struct nvkm_pmu { struct nvkm_falcon falcon; struct nvkm_falcon_qmgr *qmgr; + struct nvkm_falcon_cmdq *hpq; + struct nvkm_falcon_cmdq *lpq; struct nvkm_msgqueue *queue; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 542f88a6fc39..38ed27fa0d70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -51,6 +51,7 @@ nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); flush_work(&sec2->work); + nvkm_falcon_cmdq_fini(sec2->cmdq); return 0; } @@ -59,6 +60,7 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); nvkm_msgqueue_del(&sec2->queue); + nvkm_falcon_cmdq_del(&sec2->cmdq); nvkm_falcon_qmgr_del(&sec2->qmgr); nvkm_falcon_dtor(&sec2->falcon); return sec2; @@ -96,7 +98,8 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, if (ret) return ret; - if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr))) + if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr)) || + (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq))) return ret; INIT_WORK(&sec2->work, nvkm_sec2_recv); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 4785a563c183..8b7796df697a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -183,3 +183,48 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, return ret; } + +void +nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *cmdq) +{ +} + +void +nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *cmdq, + u32 index, u32 offset, u32 size) +{ + const struct nvkm_falcon_func *func = cmdq->qmgr->falcon->func; + + cmdq->head_reg = func->cmdq.head + index * func->cmdq.stride; + cmdq->tail_reg = func->cmdq.tail + index * func->cmdq.stride; + cmdq->offset = offset; + cmdq->size = size; + + FLCNQ_DBG(cmdq, "initialised @ index %d offset 0x%08x size 0x%08x", + index, cmdq->offset, cmdq->size); +} + +void +nvkm_falcon_cmdq_del(struct nvkm_falcon_cmdq **pcmdq) +{ + struct nvkm_falcon_cmdq *cmdq = *pcmdq; + if (cmdq) { + kfree(*pcmdq); + *pcmdq = NULL; + } +} + +int +nvkm_falcon_cmdq_new(struct nvkm_falcon_qmgr *qmgr, const char *name, + struct nvkm_falcon_cmdq **pcmdq) +{ + struct nvkm_falcon_cmdq *cmdq = *pcmdq; + + if (!(cmdq = *pcmdq = kzalloc(sizeof(*cmdq), GFP_KERNEL))) + return -ENOMEM; + + cmdq->qmgr = qmgr; + cmdq->name = name; + mutex_init(&cmdq->mutex); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index e978fb15d3b6..6729a7b52742 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -133,6 +133,7 @@ struct nvkm_msgqueue_func { */ struct nvkm_msgqueue_queue { struct nvkm_falcon_qmgr *qmgr; + const char *name; struct mutex mutex; u32 index; u32 offset; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index 68de203d80a8..fd6303b62aa4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -22,14 +22,11 @@ */ #include "msgqueue.h" #include +#include #include /* Queues identifiers */ enum { - /* High Priority Command Queue for Host -> PMU communication */ - MSGQUEUE_0137C63D_COMMAND_QUEUE_HPQ = 0, - /* Low Priority Command Queue for Host -> PMU communication */ - MSGQUEUE_0137C63D_COMMAND_QUEUE_LPQ = 1, /* Message queue for PMU -> Host communication */ MSGQUEUE_0137C63D_MESSAGE_QUEUE = 4, MSGQUEUE_0137C63D_NUM_QUEUES = 5, @@ -61,9 +58,9 @@ msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue, switch (priority) { case MSGQUEUE_MSG_PRIORITY_HIGH: - return &priv->queue[MSGQUEUE_0137C63D_COMMAND_QUEUE_HPQ]; + return subdev->device->pmu->hpq; case MSGQUEUE_MSG_PRIORITY_LOW: - return &priv->queue[MSGQUEUE_0137C63D_COMMAND_QUEUE_LPQ]; + return subdev->device->pmu->lpq; default: nvkm_error(subdev, "invalid command queue!\n"); return ERR_PTR(-EINVAL); @@ -138,6 +135,7 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) } *init = (void *)hdr; const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; + struct nvkm_pmu *pmu = subdev->device->pmu; int i; if (init->base.hdr.unit_id != MSGQUEUE_0137C63D_UNIT_INIT) { @@ -159,12 +157,7 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) queue->offset = init->queue_info[i].offset; queue->size = init->queue_info[i].size; - if (i != MSGQUEUE_0137C63D_MESSAGE_QUEUE) { - queue->head_reg = func->cmdq.head + queue->index * - func->cmdq.stride; - queue->tail_reg = func->cmdq.tail + queue->index * - func->cmdq.stride; - } else { + if (i == MSGQUEUE_0137C63D_MESSAGE_QUEUE) { queue->head_reg = func->msgq.head; queue->tail_reg = func->msgq.tail; } @@ -174,6 +167,13 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) i, queue->index, queue->offset, queue->size); } + nvkm_falcon_cmdq_init(pmu->hpq, init->queue_info[0].index, + init->queue_info[0].offset, + init->queue_info[0].size); + nvkm_falcon_cmdq_init(pmu->lpq, init->queue_info[1].index, + init->queue_info[1].offset, + init->queue_info[1].size); + /* Complete initialization by initializing WPR region */ return acr_init_wpr(&priv->base); } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 651bef2e3270..8193bec3c031 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -23,6 +23,7 @@ #include "msgqueue.h" #include +#include #include /* @@ -48,9 +49,7 @@ static struct nvkm_msgqueue_queue * msgqueue_0148cdec_cmd_queue(struct nvkm_msgqueue *queue, enum msgqueue_msg_priority priority) { - struct msgqueue_0148cdec *priv = msgqueue_0148cdec(queue); - - return &priv->queue[MSGQUEUE_0148CDEC_COMMAND_QUEUE]; + return queue->falcon->owner->device->sec2->cmdq; } static void @@ -107,6 +106,7 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) } *init = (void *)hdr; const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; + struct nvkm_sec2 *sec2 = subdev->device->sec2; int i; if (init->base.hdr.unit_id != MSGQUEUE_0148CDEC_UNIT_INIT) { @@ -135,10 +135,10 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) queue->tail_reg = func->msgq.tail + queue->index * func->msgq.stride; } else { - queue->head_reg = func->cmdq.head + queue->index * - func->cmdq.stride; - queue->tail_reg = func->cmdq.tail + queue->index * - func->cmdq.stride; + nvkm_falcon_cmdq_init(sec2->cmdq, + init->queue_info[i].index, + init->queue_info[i].offset, + init->queue_info[i].size); } nvkm_debug(subdev, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 9c8d77c11fd9..7b89fdd0c13e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -15,4 +15,9 @@ struct nvkm_falcon_qmgr { struct nvkm_msgqueue_seq *msgqueue_seq_acquire(struct nvkm_msgqueue *); void msgqueue_seq_release(struct nvkm_msgqueue *, struct nvkm_msgqueue_seq *); + +#define FLCNQ_PRINTK(t,q,f,a...) \ + FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a) +#define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK(debug, (q), f, ##a) +#define FLCNQ_ERR(q,f,a...) FLCNQ_PRINTK(error, (q), f, ##a) #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 850939f7e287..9dc0a002f530 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -86,6 +86,9 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) pmu->func->fini(pmu); flush_work(&pmu->recv.work); + + nvkm_falcon_cmdq_fini(pmu->lpq); + nvkm_falcon_cmdq_fini(pmu->hpq); return 0; } @@ -139,6 +142,8 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); nvkm_msgqueue_del(&pmu->queue); + nvkm_falcon_cmdq_del(&pmu->lpq); + nvkm_falcon_cmdq_del(&pmu->hpq); nvkm_falcon_qmgr_del(&pmu->qmgr); nvkm_falcon_dtor(&pmu->falcon); return nvkm_pmu(subdev); @@ -176,7 +181,9 @@ nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, if (ret) return ret; - if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr))) + if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr)) || + (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "hpq", &pmu->hpq)) || + (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq))) return ret; return 0; -- cgit v1.2.3 From 22431189d6690071db01079606feb1daa2784afe Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: explicitly create message queue from subdevs Code to interface with LS firmwares is being moved to the subdevs where it belongs, rather than living in the common falcon code. This is an incremental step towards that goal. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 7 ++++ drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 4 ++- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 39 ++++++++++++++++++++++ .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 34 +++---------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 29 +++------------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 4 ++- 9 files changed, 64 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index c4d9431fd63b..2cd5a06673a1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -41,4 +41,11 @@ void nvkm_falcon_cmdq_del(struct nvkm_falcon_cmdq **); void nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *, u32 index, u32 offset, u32 size); void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *); + +struct nvkm_falcon_msgq; +int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name, + struct nvkm_falcon_msgq **); +void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **); +void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *, + u32 index, u32 offset, u32 size); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index 5ae6c10f0fa4..b632a43c16ef 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -4,6 +4,7 @@ #include #define nvkm_falcon_cmdq nvkm_msgqueue_queue +#define nvkm_falcon_msgq nvkm_msgqueue_queue struct nvkm_subdev { const struct nvkm_subdev_func *func; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index e52ea3b99a4d..ca1b227a81f9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -12,6 +12,7 @@ struct nvkm_sec2 { struct nvkm_falcon_qmgr *qmgr; struct nvkm_falcon_cmdq *cmdq; + struct nvkm_falcon_msgq *msgq; struct nvkm_msgqueue *queue; struct work_struct work; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 6c0cfef2d1fa..39fb218f943e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -12,6 +12,7 @@ struct nvkm_pmu { struct nvkm_falcon_qmgr *qmgr; struct nvkm_falcon_cmdq *hpq; struct nvkm_falcon_cmdq *lpq; + struct nvkm_falcon_msgq *msgq; struct nvkm_msgqueue *queue; struct { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 38ed27fa0d70..d85aeb059c87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -60,6 +60,7 @@ nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); nvkm_msgqueue_del(&sec2->queue); + nvkm_falcon_msgq_del(&sec2->msgq); nvkm_falcon_cmdq_del(&sec2->cmdq); nvkm_falcon_qmgr_del(&sec2->qmgr); nvkm_falcon_dtor(&sec2->falcon); @@ -99,7 +100,8 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device, return ret; if ((ret = nvkm_falcon_qmgr_new(&sec2->falcon, &sec2->qmgr)) || - (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq))) + (ret = nvkm_falcon_cmdq_new(sec2->qmgr, "cmdq", &sec2->cmdq)) || + (ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq))) return ret; INIT_WORK(&sec2->work, nvkm_sec2_recv); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 5db0b41bc2c8..7be610427eef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -214,3 +214,42 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, msgqueue_msg_handle(priv, hdr); } } + +void +nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *msgq, + u32 index, u32 offset, u32 size) +{ + const struct nvkm_falcon_func *func = msgq->qmgr->falcon->func; + + msgq->head_reg = func->msgq.head + index * func->msgq.stride; + msgq->tail_reg = func->msgq.tail + index * func->msgq.stride; + msgq->offset = offset; + + FLCNQ_DBG(msgq, "initialised @ index %d offset 0x%08x size 0x%08x", + index, msgq->offset, size); +} + +void +nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **pmsgq) +{ + struct nvkm_falcon_msgq *msgq = *pmsgq; + if (msgq) { + kfree(*pmsgq); + *pmsgq = NULL; + } +} + +int +nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *qmgr, const char *name, + struct nvkm_falcon_msgq **pmsgq) +{ + struct nvkm_falcon_msgq *msgq = *pmsgq; + + if (!(msgq = *pmsgq = kzalloc(sizeof(*msgq), GFP_KERNEL))) + return -ENOMEM; + + msgq->qmgr = qmgr; + msgq->name = name; + mutex_init(&msgq->mutex); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index fd6303b62aa4..48a0f0de3453 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -27,15 +27,11 @@ /* Queues identifiers */ enum { - /* Message queue for PMU -> Host communication */ - MSGQUEUE_0137C63D_MESSAGE_QUEUE = 4, MSGQUEUE_0137C63D_NUM_QUEUES = 5, }; struct msgqueue_0137c63d { struct nvkm_msgqueue base; - - struct nvkm_msgqueue_queue queue[MSGQUEUE_0137C63D_NUM_QUEUES]; }; #define msgqueue_0137c63d(q) \ container_of(q, struct msgqueue_0137c63d, base) @@ -70,11 +66,7 @@ msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue, static void msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue) { - struct msgqueue_0137c63d *priv = msgqueue_0137c63d(queue); - struct nvkm_msgqueue_queue *q_queue = - &priv->queue[MSGQUEUE_0137C63D_MESSAGE_QUEUE]; - - nvkm_msgqueue_process_msgs(&priv->base, q_queue); + nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->pmu->msgq); } /* Init unit */ @@ -133,10 +125,8 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) u16 sw_managed_area_offset; u16 sw_managed_area_size; } *init = (void *)hdr; - const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; struct nvkm_pmu *pmu = subdev->device->pmu; - int i; if (init->base.hdr.unit_id != MSGQUEUE_0137C63D_UNIT_INIT) { nvkm_error(subdev, "expected message from init unit\n"); @@ -148,31 +138,15 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) return -EINVAL; } - for (i = 0; i < MSGQUEUE_0137C63D_NUM_QUEUES; i++) { - struct nvkm_msgqueue_queue *queue = &priv->queue[i]; - - mutex_init(&queue->mutex); - - queue->index = init->queue_info[i].index; - queue->offset = init->queue_info[i].offset; - queue->size = init->queue_info[i].size; - - if (i == MSGQUEUE_0137C63D_MESSAGE_QUEUE) { - queue->head_reg = func->msgq.head; - queue->tail_reg = func->msgq.tail; - } - - nvkm_debug(subdev, - "queue %d: index %d, offset 0x%08x, size 0x%08x\n", - i, queue->index, queue->offset, queue->size); - } - nvkm_falcon_cmdq_init(pmu->hpq, init->queue_info[0].index, init->queue_info[0].offset, init->queue_info[0].size); nvkm_falcon_cmdq_init(pmu->lpq, init->queue_info[1].index, init->queue_info[1].offset, init->queue_info[1].size); + nvkm_falcon_msgq_init(pmu->msgq, init->queue_info[4].index, + init->queue_info[4].offset, + init->queue_info[4].size); /* Complete initialization by initializing WPR region */ return acr_init_wpr(&priv->base); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 8193bec3c031..12d5ad6b7422 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -39,8 +39,6 @@ enum { struct msgqueue_0148cdec { struct nvkm_msgqueue base; - - struct nvkm_msgqueue_queue queue[MSGQUEUE_0148CDEC_NUM_QUEUES]; }; #define msgqueue_0148cdec(q) \ container_of(q, struct msgqueue_0148cdec, base) @@ -55,11 +53,7 @@ msgqueue_0148cdec_cmd_queue(struct nvkm_msgqueue *queue, static void msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue) { - struct msgqueue_0148cdec *priv = msgqueue_0148cdec(queue); - struct nvkm_msgqueue_queue *q_queue = - &priv->queue[MSGQUEUE_0148CDEC_MESSAGE_QUEUE]; - - nvkm_msgqueue_process_msgs(&priv->base, q_queue); + nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->sec2->msgq); } @@ -87,7 +81,6 @@ init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) static int init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) { - struct msgqueue_0148cdec *priv = msgqueue_0148cdec(_queue); struct { struct nvkm_msgqueue_msg base; @@ -104,7 +97,6 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) u16 sw_managed_area_offset; u16 sw_managed_area_size; } *init = (void *)hdr; - const struct nvkm_falcon_func *func = _queue->falcon->func; const struct nvkm_subdev *subdev = _queue->falcon->owner; struct nvkm_sec2 *sec2 = subdev->device->sec2; int i; @@ -121,29 +113,18 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) for (i = 0; i < MSGQUEUE_0148CDEC_NUM_QUEUES; i++) { u8 id = init->queue_info[i].id; - struct nvkm_msgqueue_queue *queue = &priv->queue[id]; - - mutex_init(&queue->mutex); - - queue->index = init->queue_info[i].index; - queue->offset = init->queue_info[i].offset; - queue->size = init->queue_info[i].size; if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) { - queue->head_reg = func->msgq.head + queue->index * - func->msgq.stride; - queue->tail_reg = func->msgq.tail + queue->index * - func->msgq.stride; + nvkm_falcon_msgq_init(sec2->msgq, + init->queue_info[i].index, + init->queue_info[i].offset, + init->queue_info[i].size); } else { nvkm_falcon_cmdq_init(sec2->cmdq, init->queue_info[i].index, init->queue_info[i].offset, init->queue_info[i].size); } - - nvkm_debug(subdev, - "queue %d: index %d, offset 0x%08x, size 0x%08x\n", - id, queue->index, queue->offset, queue->size); } complete_all(&_queue->init_done); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 9dc0a002f530..86af2ddb3e78 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -142,6 +142,7 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); nvkm_msgqueue_del(&pmu->queue); + nvkm_falcon_msgq_del(&pmu->msgq); nvkm_falcon_cmdq_del(&pmu->lpq); nvkm_falcon_cmdq_del(&pmu->hpq); nvkm_falcon_qmgr_del(&pmu->qmgr); @@ -183,7 +184,8 @@ nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr)) || (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "hpq", &pmu->hpq)) || - (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq))) + (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq)) || + (ret = nvkm_falcon_msgq_new(pmu->qmgr, "msgq", &pmu->msgq))) return ret; return 0; -- cgit v1.2.3 From 0ae59432ba6d647297f2e1bed97139147ce140ac Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/qmgr: move sequence tracking from nvkm_msgqueue to nvkm_falcon_qmgr Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 4 +-- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 10 ++++--- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 5 ---- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 39 +------------------------ drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c | 10 +++++-- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 40 ++++++++++++++++++++++++-- 6 files changed, 55 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 8b7796df697a..1cf6453fdd70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -164,7 +164,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, if (IS_ERR(queue)) return PTR_ERR(queue); - seq = msgqueue_seq_acquire(priv); + seq = nvkm_falcon_qmgr_seq_acquire(queue->qmgr); if (IS_ERR(seq)) return PTR_ERR(seq); @@ -178,7 +178,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, ret = cmd_write(priv, cmd, queue); if (ret) { seq->state = SEQ_STATE_PENDING; - msgqueue_seq_release(priv, seq); + nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); } return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 7be610427eef..303f9faf3423 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -134,12 +134,14 @@ close: } static int -msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *hdr) +msgqueue_msg_handle(struct nvkm_msgqueue *priv, + struct nvkm_falcon_msgq *msgq, + struct nvkm_msgqueue_hdr *hdr) { const struct nvkm_subdev *subdev = priv->falcon->owner; struct nvkm_msgqueue_seq *seq; - seq = &priv->seq[hdr->seq_id]; + seq = &msgq->qmgr->seq[hdr->seq_id]; if (seq->state != SEQ_STATE_USED && seq->state != SEQ_STATE_CANCELLED) { nvkm_error(subdev, "msg for unknown sequence %d", seq->id); return -EINVAL; @@ -153,7 +155,7 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *hdr) if (seq->completion) complete(seq->completion); - msgqueue_seq_release(priv, seq); + nvkm_falcon_qmgr_seq_release(msgq->qmgr, seq); return 0; } @@ -211,7 +213,7 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, priv->init_msg_received = true; } else { while (msg_queue_read(priv, queue, hdr) > 0) - msgqueue_msg_handle(priv, hdr); + msgqueue_msg_handle(priv, queue, hdr); } } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index eb2af85f3e3c..db3e4a3489bf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -136,13 +136,8 @@ nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func, struct nvkm_falcon *falcon, struct nvkm_msgqueue *queue) { - int i; - queue->func = func; queue->falcon = falcon; - mutex_init(&queue->seq_lock); - for (i = 0; i < NVKM_MSGQUEUE_NUM_SEQUENCES; i++) - queue->seq[i].id = i; init_completion(&queue->init_done); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 6729a7b52742..4cfa6b21d3df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -144,36 +144,6 @@ struct nvkm_msgqueue_queue { u32 tail_reg; }; -/** - * struct nvkm_msgqueue_seq - keep track of ongoing commands - * - * Every time a command is sent, a sequence is assigned to it so the - * corresponding message can be matched. Upon receiving the message, a callback - * can be called and/or a completion signaled. - * - * @id: sequence ID - * @state: current state - * @callback: callback to call upon receiving matching message - * @completion: completion to signal after callback is called - */ -struct nvkm_msgqueue_seq { - u16 id; - enum { - SEQ_STATE_FREE = 0, - SEQ_STATE_PENDING, - SEQ_STATE_USED, - SEQ_STATE_CANCELLED - } state; - nvkm_msgqueue_callback callback; - struct completion *completion; -}; - -/* - * We can have an arbitrary number of sequences, but realistically we will - * probably not use that much simultaneously. - */ -#define NVKM_MSGQUEUE_NUM_SEQUENCES 16 - /** * struct nvkm_msgqueue - manage a command/message based FW on a falcon * @@ -181,20 +151,13 @@ struct nvkm_msgqueue_seq { * @func: implementation of the firmware to use * @init_msg_received: whether the init message has already been received * @init_done: whether all init is complete and commands can be processed - * @seq_lock: protects seq and seq_tbl - * @seq: sequences to match commands and messages - * @seq_tbl: bitmap of sequences currently in use - */ + */ struct nvkm_msgqueue { struct nvkm_falcon *falcon; const struct nvkm_msgqueue_func *func; u32 fw_version; bool init_msg_received; struct completion init_done; - - struct mutex seq_lock; - struct nvkm_msgqueue_seq seq[NVKM_MSGQUEUE_NUM_SEQUENCES]; - unsigned long seq_tbl[BITS_TO_LONGS(NVKM_MSGQUEUE_NUM_SEQUENCES)]; }; void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c index f1469ecb7a4e..0cc192b55cc3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c @@ -23,7 +23,7 @@ #include "qmgr.h" struct nvkm_msgqueue_seq * -msgqueue_seq_acquire(struct nvkm_msgqueue *priv) +nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *priv) { const struct nvkm_subdev *subdev = priv->falcon->owner; struct nvkm_msgqueue_seq *seq; @@ -46,7 +46,8 @@ msgqueue_seq_acquire(struct nvkm_msgqueue *priv) } void -msgqueue_seq_release(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_seq *seq) +nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *priv, + struct nvkm_msgqueue_seq *seq) { /* no need to acquire seq_lock since clear_bit is atomic */ seq->state = SEQ_STATE_FREE; @@ -70,10 +71,15 @@ nvkm_falcon_qmgr_new(struct nvkm_falcon *falcon, struct nvkm_falcon_qmgr **pqmgr) { struct nvkm_falcon_qmgr *qmgr; + int i; if (!(qmgr = *pqmgr = kzalloc(sizeof(*qmgr), GFP_KERNEL))) return -ENOMEM; qmgr->falcon = falcon; + mutex_init(&qmgr->seq_lock); + for (i = 0; i < NVKM_MSGQUEUE_NUM_SEQUENCES; i++) + qmgr->seq[i].id = i; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 7b89fdd0c13e..35ac2cc85d2c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -9,12 +9,48 @@ /* max size of the messages we can receive */ #define MSG_BUF_SIZE 128 +/** + * struct nvkm_msgqueue_seq - keep track of ongoing commands + * + * Every time a command is sent, a sequence is assigned to it so the + * corresponding message can be matched. Upon receiving the message, a callback + * can be called and/or a completion signaled. + * + * @id: sequence ID + * @state: current state + * @callback: callback to call upon receiving matching message + * @completion: completion to signal after callback is called + */ +struct nvkm_msgqueue_seq { + u16 id; + enum { + SEQ_STATE_FREE = 0, + SEQ_STATE_PENDING, + SEQ_STATE_USED, + SEQ_STATE_CANCELLED + } state; + nvkm_msgqueue_callback callback; + struct completion *completion; +}; + +/* + * We can have an arbitrary number of sequences, but realistically we will + * probably not use that much simultaneously. + */ +#define NVKM_MSGQUEUE_NUM_SEQUENCES 16 + struct nvkm_falcon_qmgr { struct nvkm_falcon *falcon; + + struct mutex seq_lock; + struct nvkm_msgqueue_seq seq[NVKM_MSGQUEUE_NUM_SEQUENCES]; + unsigned long seq_tbl[BITS_TO_LONGS(NVKM_MSGQUEUE_NUM_SEQUENCES)]; }; -struct nvkm_msgqueue_seq *msgqueue_seq_acquire(struct nvkm_msgqueue *); -void msgqueue_seq_release(struct nvkm_msgqueue *, struct nvkm_msgqueue_seq *); +struct nvkm_msgqueue_seq * +nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *); +void nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *, + struct nvkm_msgqueue_seq *); #define FLCNQ_PRINTK(t,q,f,a...) \ FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a) -- cgit v1.2.3 From c80157a25e712daf69cbba8cafa0463c0895f56c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/qmgr: allow arbtrary priv + return code for callbacks Code to interface with LS firmwares is being moved to the subdevs where it belongs, rather than living in the common falcon code. Arbitrary private data passed to callbacks is to allow for something other than struct nvkm_msgqueue to be passed into the callback (like the pointer to the subdev itself, for example), and the return code will be used where we'd like to detect failure from synchronous messages. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 18 ++++++++++ drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 3 +- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 15 ++++---- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 6 ++-- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 40 +++++++++++++--------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 15 ++++---- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 6 ++-- 7 files changed, 65 insertions(+), 38 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 2cd5a06673a1..75d095048b67 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -30,10 +30,28 @@ int gp102_sec2_flcn_enable(struct nvkm_falcon *); #define FLCN_DBG(f,fmt,a...) FLCN_PRINTK(debug, (f), fmt, ##a) #define FLCN_ERR(f,fmt,a...) FLCN_PRINTK(error, (f), fmt, ##a) +/** + * struct nv_falcon_msg - header for all messages + * + * @unit_id: id of firmware process that sent the message + * @size: total size of message + * @ctrl_flags: control flags + * @seq_id: used to match a message from its corresponding command + */ +struct nv_falcon_msg { + u8 unit_id; + u8 size; + u8 ctrl_flags; + u8 seq_id; +}; + struct nvkm_falcon_qmgr; int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **); void nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **); +typedef int +(*nvkm_falcon_qmgr_callback)(void *priv, struct nv_falcon_msg *); + struct nvkm_falcon_cmdq; int nvkm_falcon_cmdq_new(struct nvkm_falcon_qmgr *, const char *name, struct nvkm_falcon_cmdq **); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 1cf6453fdd70..f0d28985f055 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -149,7 +149,7 @@ cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, int nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, - struct nvkm_msgqueue_hdr *cmd, nvkm_msgqueue_callback cb, + struct nvkm_msgqueue_hdr *cmd, nvkm_falcon_qmgr_callback cb, struct completion *completion, bool wait_init) { struct nvkm_msgqueue_seq *seq; @@ -172,6 +172,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, cmd->ctrl_flags = CMD_FLAGS_STATUS | CMD_FLAGS_INTR; seq->callback = cb; + seq->priv = priv; seq->state = SEQ_STATE_USED; seq->completion = completion; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 303f9faf3423..7f84a5ef7905 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -86,7 +86,7 @@ msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, static int msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - struct nvkm_msgqueue_hdr *hdr) + struct nv_falcon_msg *hdr) { const struct nvkm_subdev *subdev = priv->falcon->owner; int ret; @@ -136,7 +136,7 @@ close: static int msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_falcon_msgq *msgq, - struct nvkm_msgqueue_hdr *hdr) + struct nv_falcon_msg *hdr) { const struct nvkm_subdev *subdev = priv->falcon->owner; struct nvkm_msgqueue_seq *seq; @@ -149,7 +149,7 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, if (seq->state == SEQ_STATE_USED) { if (seq->callback) - seq->callback(priv, hdr); + seq->result = seq->callback(seq->priv, hdr); } if (seq->completion) @@ -160,12 +160,13 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, } static int -msgqueue_handle_init_msg(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_hdr *hdr) +msgqueue_handle_init_msg(struct nvkm_msgqueue *priv) { struct nvkm_falcon *falcon = priv->falcon; const struct nvkm_subdev *subdev = falcon->owner; const u32 tail_reg = falcon->func->msgq.tail; + u8 msg_buffer[MSG_BUF_SIZE]; + struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer; u32 tail; int ret; @@ -203,12 +204,12 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, * stack space to work with. */ u8 msg_buffer[MSG_BUF_SIZE]; - struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer; + struct nv_falcon_msg *hdr = (void *)msg_buffer; int ret; /* the first message we receive must be the init message */ if ((!priv->init_msg_received)) { - ret = msgqueue_handle_init_msg(priv, hdr); + ret = msgqueue_handle_init_msg(priv); if (!ret) priv->init_msg_received = true; } else { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 4cfa6b21d3df..542ecae806ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -23,7 +23,7 @@ #ifndef __NVKM_CORE_FALCON_MSGQUEUE_H #define __NVKM_CORE_FALCON_MSGQUEUE_H - +#include #include /* @@ -83,8 +83,6 @@ struct nvkm_msgqueue_msg { }; struct nvkm_msgqueue; -typedef void -(*nvkm_msgqueue_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *); /** * struct nvkm_msgqueue_init_func - msgqueue functions related to initialization @@ -163,7 +161,7 @@ struct nvkm_msgqueue { void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, struct nvkm_msgqueue *); int nvkm_msgqueue_post(struct nvkm_msgqueue *, enum msgqueue_msg_priority, - struct nvkm_msgqueue_hdr *, nvkm_msgqueue_callback, + struct nvkm_msgqueue_hdr *, nvkm_falcon_qmgr_callback, struct completion *, bool); void nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *, struct nvkm_msgqueue_queue *); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index 48a0f0de3453..a8931cd96bca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -169,12 +169,13 @@ enum { ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03, }; -static void -acr_init_wpr_callback(struct nvkm_msgqueue *queue, - struct nvkm_msgqueue_hdr *hdr) +static int +acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) { + struct nvkm_msgqueue *queue = priv; struct { - struct nvkm_msgqueue_msg base; + struct nv_falcon_msg base; + u8 msg_type; u32 error_code; } *msg = (void *)hdr; const struct nvkm_subdev *subdev = queue->falcon->owner; @@ -182,11 +183,12 @@ acr_init_wpr_callback(struct nvkm_msgqueue *queue, if (msg->error_code) { nvkm_error(subdev, "ACR WPR init failure: %d\n", msg->error_code); - return; + return -EINVAL; } nvkm_debug(subdev, "ACR WPR init complete\n"); complete_all(&queue->init_done); + return 0; } static int @@ -217,13 +219,13 @@ acr_init_wpr(struct nvkm_msgqueue *queue) } -static void -acr_boot_falcon_callback(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_hdr *hdr) +static int +acr_boot_falcon_callback(void *_priv, struct nv_falcon_msg *hdr) { + struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { - struct nvkm_msgqueue_msg base; - + struct nv_falcon_msg base; + u8 msg_type; u32 falcon_id; } *msg = (void *)hdr; const struct nvkm_subdev *subdev = priv->falcon->owner; @@ -232,9 +234,11 @@ acr_boot_falcon_callback(struct nvkm_msgqueue *priv, if (falcon_id >= NVKM_SECBOOT_FALCON_END) { nvkm_error(subdev, "in bootstrap falcon callback:\n"); nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id); - return; + return -EINVAL; } + nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]); + return 0; } enum { @@ -273,13 +277,13 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) return 0; } -static void -acr_boot_multiple_falcons_callback(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_hdr *hdr) +static int +acr_boot_multiple_falcons_callback(void *_priv, struct nv_falcon_msg *hdr) { + struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { - struct nvkm_msgqueue_msg base; - + struct nv_falcon_msg base; + u8 msg_type; u32 falcon_mask; } *msg = (void *)hdr; const struct nvkm_subdev *subdev = priv->falcon->owner; @@ -296,8 +300,10 @@ acr_boot_multiple_falcons_callback(struct nvkm_msgqueue *priv, nvkm_error(subdev, "in bootstrap falcon callback:\n"); nvkm_error(subdev, "invalid falcon mask 0x%x\n", msg->falcon_mask); - return; + return -EINVAL; } + + return 0; } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 12d5ad6b7422..92b8351e9e35 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -147,13 +147,13 @@ enum { ACR_CMD_BOOTSTRAP_FALCON = 0x00, }; -static void -acr_boot_falcon_callback(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_hdr *hdr) +static int +acr_boot_falcon_callback(void *_priv, struct nv_falcon_msg *hdr) { + struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { - struct nvkm_msgqueue_msg base; - + struct nv_falcon_msg base; + u8 msg_type; u32 error_code; u32 falcon_id; } *msg = (void *)hdr; @@ -164,16 +164,17 @@ acr_boot_falcon_callback(struct nvkm_msgqueue *priv, nvkm_error(subdev, "in bootstrap falcon callback:\n"); nvkm_error(subdev, "expected error code 0x%x\n", msg->error_code); - return; + return -EINVAL; } if (falcon_id >= NVKM_SECBOOT_FALCON_END) { nvkm_error(subdev, "in bootstrap falcon callback:\n"); nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id); - return; + return -EINVAL; } nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]); + return 0; } enum { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 35ac2cc85d2c..ca2e71a0e043 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -4,7 +4,7 @@ #include #include "msgqueue.h" -#define HDR_SIZE sizeof(struct nvkm_msgqueue_hdr) +#define HDR_SIZE sizeof(struct nv_falcon_msg) #define QUEUE_ALIGNMENT 4 /* max size of the messages we can receive */ #define MSG_BUF_SIZE 128 @@ -29,8 +29,10 @@ struct nvkm_msgqueue_seq { SEQ_STATE_USED, SEQ_STATE_CANCELLED } state; - nvkm_msgqueue_callback callback; + nvkm_falcon_qmgr_callback callback; + void *priv; struct completion *completion; + int result; }; /* -- cgit v1.2.3 From 8e90a98dfb804f4a86a9bc40706e9f00e870a2ba Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/qmgr: support syncronous command submission from common code Functions implementing FW commands had to implement this themselves, let's move that to common code and plumb the return code from callbacks through. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 13 +++++++++-- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 8 ++++--- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 26 ++++++---------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 9 ++------ drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c | 6 +++-- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 3 ++- 6 files changed, 31 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index f0d28985f055..d6e84a667845 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -171,15 +171,24 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, cmd->seq_id = seq->id; cmd->ctrl_flags = CMD_FLAGS_STATUS | CMD_FLAGS_INTR; + seq->state = SEQ_STATE_USED; + seq->async = !completion; seq->callback = cb; seq->priv = priv; - seq->state = SEQ_STATE_USED; - seq->completion = completion; ret = cmd_write(priv, cmd, queue); if (ret) { seq->state = SEQ_STATE_PENDING; nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); + return ret; + } + + if (!seq->async) { + if (!wait_for_completion_timeout(&seq->done, + msecs_to_jiffies(1000))) + return -ETIMEDOUT; + ret = seq->result; + nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); } return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 7f84a5ef7905..7e9e82da7ea7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -152,10 +152,12 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, seq->result = seq->callback(seq->priv, hdr); } - if (seq->completion) - complete(seq->completion); + if (seq->async) { + nvkm_falcon_qmgr_seq_release(msgq->qmgr, seq); + return 0; + } - nvkm_falcon_qmgr_seq_release(msgq->qmgr, seq); + complete_all(&seq->done); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index a8931cd96bca..164722f617a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -211,11 +211,8 @@ acr_init_wpr(struct nvkm_msgqueue *queue) cmd.cmd_type = ACR_CMD_INIT_WPR_REGION; cmd.region_id = 0x01; cmd.wpr_offset = 0x00; - - nvkm_msgqueue_post(queue, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_init_wpr_callback, NULL, false); - - return 0; + return nvkm_msgqueue_post(queue, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, + acr_init_wpr_callback, NULL, false); } @@ -268,13 +265,8 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; cmd.falcon_id = falcon; - nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_falcon_callback, &completed, true); - - if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000))) - return -ETIMEDOUT; - - return 0; + return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, + acr_boot_falcon_callback, &completed, true); } static int @@ -334,13 +326,9 @@ acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) cmd.falcon_mask = falcon_mask; cmd.wpr_lo = lower_32_bits(queue->wpr_addr); cmd.wpr_hi = upper_32_bits(queue->wpr_addr); - nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_multiple_falcons_callback, &completed, true); - - if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000))) - return -ETIMEDOUT; - - return 0; + return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, + acr_boot_multiple_falcons_callback, + &completed, true); } static const struct nvkm_msgqueue_acr_func diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 92b8351e9e35..28917969293e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -204,13 +204,8 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; cmd.falcon_id = falcon; - nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_falcon_callback, &completed, true); - - if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000))) - return -ETIMEDOUT; - - return 0; + return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, + acr_boot_falcon_callback, &completed, true); } const struct nvkm_msgqueue_acr_func diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c index 0cc192b55cc3..b67e85b169aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c @@ -52,7 +52,7 @@ nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *priv, /* no need to acquire seq_lock since clear_bit is atomic */ seq->state = SEQ_STATE_FREE; seq->callback = NULL; - seq->completion = NULL; + reinit_completion(&seq->done); clear_bit(seq->id, priv->seq_tbl); } @@ -78,8 +78,10 @@ nvkm_falcon_qmgr_new(struct nvkm_falcon *falcon, qmgr->falcon = falcon; mutex_init(&qmgr->seq_lock); - for (i = 0; i < NVKM_MSGQUEUE_NUM_SEQUENCES; i++) + for (i = 0; i < NVKM_MSGQUEUE_NUM_SEQUENCES; i++) { qmgr->seq[i].id = i; + init_completion(&qmgr->seq[i].done); + } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index ca2e71a0e043..905a625b3348 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -29,9 +29,10 @@ struct nvkm_msgqueue_seq { SEQ_STATE_USED, SEQ_STATE_CANCELLED } state; + bool async; nvkm_falcon_qmgr_callback callback; void *priv; - struct completion *completion; + struct completion done; int result; }; -- cgit v1.2.3 From a15d8f580ccbe387dbc8c1d11a71fa737edd7e7f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/qmgr: rename remaining nvkm_msgqueue bits to nvkm_falcon_qmgr Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 2 +- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c | 38 +++++++++++++++--------------- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 18 +++++++------- 4 files changed, 32 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index d6e84a667845..a674548f6168 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -152,7 +152,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, struct nvkm_msgqueue_hdr *cmd, nvkm_falcon_qmgr_callback cb, struct completion *completion, bool wait_init) { - struct nvkm_msgqueue_seq *seq; + struct nvkm_falcon_qmgr_seq *seq; struct nvkm_msgqueue_queue *queue; int ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 7e9e82da7ea7..eb499b796fe5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -139,9 +139,9 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nv_falcon_msg *hdr) { const struct nvkm_subdev *subdev = priv->falcon->owner; - struct nvkm_msgqueue_seq *seq; + struct nvkm_falcon_qmgr_seq *seq; - seq = &msgq->qmgr->seq[hdr->seq_id]; + seq = &msgq->qmgr->seq.id[hdr->seq_id]; if (seq->state != SEQ_STATE_USED && seq->state != SEQ_STATE_CANCELLED) { nvkm_error(subdev, "msg for unknown sequence %d", seq->id); return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c index b67e85b169aa..a453de341a75 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.c @@ -22,38 +22,38 @@ */ #include "qmgr.h" -struct nvkm_msgqueue_seq * -nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *priv) +struct nvkm_falcon_qmgr_seq * +nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *qmgr) { - const struct nvkm_subdev *subdev = priv->falcon->owner; - struct nvkm_msgqueue_seq *seq; + const struct nvkm_subdev *subdev = qmgr->falcon->owner; + struct nvkm_falcon_qmgr_seq *seq; u32 index; - mutex_lock(&priv->seq_lock); - index = find_first_zero_bit(priv->seq_tbl, NVKM_MSGQUEUE_NUM_SEQUENCES); - if (index >= NVKM_MSGQUEUE_NUM_SEQUENCES) { + mutex_lock(&qmgr->seq.mutex); + index = find_first_zero_bit(qmgr->seq.tbl, NVKM_FALCON_QMGR_SEQ_NUM); + if (index >= NVKM_FALCON_QMGR_SEQ_NUM) { nvkm_error(subdev, "no free sequence available\n"); - mutex_unlock(&priv->seq_lock); + mutex_unlock(&qmgr->seq.mutex); return ERR_PTR(-EAGAIN); } - set_bit(index, priv->seq_tbl); - mutex_unlock(&priv->seq_lock); + set_bit(index, qmgr->seq.tbl); + mutex_unlock(&qmgr->seq.mutex); - seq = &priv->seq[index]; + seq = &qmgr->seq.id[index]; seq->state = SEQ_STATE_PENDING; return seq; } void -nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *priv, - struct nvkm_msgqueue_seq *seq) +nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *qmgr, + struct nvkm_falcon_qmgr_seq *seq) { - /* no need to acquire seq_lock since clear_bit is atomic */ + /* no need to acquire seq.mutex since clear_bit is atomic */ seq->state = SEQ_STATE_FREE; seq->callback = NULL; reinit_completion(&seq->done); - clear_bit(seq->id, priv->seq_tbl); + clear_bit(seq->id, qmgr->seq.tbl); } void @@ -77,10 +77,10 @@ nvkm_falcon_qmgr_new(struct nvkm_falcon *falcon, return -ENOMEM; qmgr->falcon = falcon; - mutex_init(&qmgr->seq_lock); - for (i = 0; i < NVKM_MSGQUEUE_NUM_SEQUENCES; i++) { - qmgr->seq[i].id = i; - init_completion(&qmgr->seq[i].done); + mutex_init(&qmgr->seq.mutex); + for (i = 0; i < NVKM_FALCON_QMGR_SEQ_NUM; i++) { + qmgr->seq.id[i].id = i; + init_completion(&qmgr->seq.id[i].done); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 905a625b3348..935858c6a621 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -10,7 +10,7 @@ #define MSG_BUF_SIZE 128 /** - * struct nvkm_msgqueue_seq - keep track of ongoing commands + * struct nvkm_falcon_qmgr_seq - keep track of ongoing commands * * Every time a command is sent, a sequence is assigned to it so the * corresponding message can be matched. Upon receiving the message, a callback @@ -21,7 +21,7 @@ * @callback: callback to call upon receiving matching message * @completion: completion to signal after callback is called */ -struct nvkm_msgqueue_seq { +struct nvkm_falcon_qmgr_seq { u16 id; enum { SEQ_STATE_FREE = 0, @@ -40,20 +40,22 @@ struct nvkm_msgqueue_seq { * We can have an arbitrary number of sequences, but realistically we will * probably not use that much simultaneously. */ -#define NVKM_MSGQUEUE_NUM_SEQUENCES 16 +#define NVKM_FALCON_QMGR_SEQ_NUM 16 struct nvkm_falcon_qmgr { struct nvkm_falcon *falcon; - struct mutex seq_lock; - struct nvkm_msgqueue_seq seq[NVKM_MSGQUEUE_NUM_SEQUENCES]; - unsigned long seq_tbl[BITS_TO_LONGS(NVKM_MSGQUEUE_NUM_SEQUENCES)]; + struct { + struct mutex mutex; + struct nvkm_falcon_qmgr_seq id[NVKM_FALCON_QMGR_SEQ_NUM]; + unsigned long tbl[BITS_TO_LONGS(NVKM_FALCON_QMGR_SEQ_NUM)]; + } seq; }; -struct nvkm_msgqueue_seq * +struct nvkm_falcon_qmgr_seq * nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *); void nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *, - struct nvkm_msgqueue_seq *); + struct nvkm_falcon_qmgr_seq *); #define FLCNQ_PRINTK(t,q,f,a...) \ FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a) -- cgit v1.2.3 From 2e8a65973b9afeebbff5e8a8e51e7cdd14f745a7 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: split the condition for queue readiness vs pmu acr readiness This is to allow for proper separation of the LS interface code from the queue handling code. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 13 +++++++++---- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 6 ------ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 16 +++++++++++++++- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 2 -- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 3 +++ 7 files changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 39fb218f943e..21607b40aee6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -15,6 +15,8 @@ struct nvkm_pmu { struct nvkm_falcon_msgq *msgq; struct nvkm_msgqueue *queue; + struct completion wpr_ready; + struct { u32 base; u32 size; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index a674548f6168..d32cc0d354ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -156,14 +156,16 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, struct nvkm_msgqueue_queue *queue; int ret; - if (wait_init && !wait_for_completion_timeout(&priv->init_done, - msecs_to_jiffies(1000))) - return -ETIMEDOUT; - queue = priv->func->cmd_queue(priv, prio); if (IS_ERR(queue)) return PTR_ERR(queue); + if (!wait_for_completion_timeout(&queue->ready, + msecs_to_jiffies(1000))) { + FLCNQ_ERR(queue, "timeout waiting for queue ready"); + return -ETIMEDOUT; + } + seq = nvkm_falcon_qmgr_seq_acquire(queue->qmgr); if (IS_ERR(seq)) return PTR_ERR(seq); @@ -197,6 +199,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *cmdq) { + reinit_completion(&cmdq->ready); } void @@ -209,6 +212,7 @@ nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *cmdq, cmdq->tail_reg = func->cmdq.tail + index * func->cmdq.stride; cmdq->offset = offset; cmdq->size = size; + complete_all(&cmdq->ready); FLCNQ_DBG(cmdq, "initialised @ index %d offset 0x%08x size 0x%08x", index, cmdq->offset, cmdq->size); @@ -236,5 +240,6 @@ nvkm_falcon_cmdq_new(struct nvkm_falcon_qmgr *qmgr, const char *name, cmdq->qmgr = qmgr; cmdq->name = name; mutex_init(&cmdq->mutex); + init_completion(&cmdq->ready); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index db3e4a3489bf..3e14c7bc3e32 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -126,8 +126,6 @@ nvkm_msgqueue_reinit(struct nvkm_msgqueue *queue) return 0; queue->init_msg_received = false; - reinit_completion(&queue->init_done); - return 0; } @@ -138,8 +136,4 @@ nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func, { queue->func = func; queue->falcon = falcon; - - init_completion(&queue->init_done); - - } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 542ecae806ee..98ace0d8465a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -140,6 +140,8 @@ struct nvkm_msgqueue_queue { u32 head_reg; u32 tail_reg; + + struct completion ready; }; /** @@ -148,14 +150,12 @@ struct nvkm_msgqueue_queue { * @falcon: falcon to be managed * @func: implementation of the firmware to use * @init_msg_received: whether the init message has already been received - * @init_done: whether all init is complete and commands can be processed */ struct nvkm_msgqueue { struct nvkm_falcon *falcon; const struct nvkm_msgqueue_func *func; u32 fw_version; bool init_msg_received; - struct completion init_done; }; void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index 164722f617a4..3bd98262f16e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -187,7 +187,7 @@ acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) } nvkm_debug(subdev, "ACR WPR init complete\n"); - complete_all(&queue->init_done); + complete_all(&subdev->device->pmu->wpr_ready); return 0; } @@ -246,6 +246,7 @@ enum { static int acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) { + struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; DECLARE_COMPLETION_ONSTACK(completed); /* * flags - Flag specifying RESET or no RESET. @@ -258,6 +259,12 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) u32 falcon_id; } cmd; + if (!wait_for_completion_timeout(&pmu->wpr_ready, + msecs_to_jiffies(1000))) { + nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n"); + return -ETIMEDOUT; + } + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR; @@ -301,6 +308,7 @@ acr_boot_multiple_falcons_callback(void *_priv, struct nv_falcon_msg *hdr) static int acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) { + struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; DECLARE_COMPLETION_ONSTACK(completed); /* * flags - Flag specifying RESET or no RESET. @@ -317,6 +325,12 @@ acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) } cmd; struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv); + if (!wait_for_completion_timeout(&pmu->wpr_ready, + msecs_to_jiffies(1000))) { + nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n"); + return -ETIMEDOUT; + } + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 28917969293e..1c6077cea865 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -127,8 +127,6 @@ init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) } } - complete_all(&_queue->init_done); - return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 86af2ddb3e78..bc0eb84c2c90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -87,6 +87,8 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) flush_work(&pmu->recv.work); + reinit_completion(&pmu->wpr_ready); + nvkm_falcon_cmdq_fini(pmu->lpq); nvkm_falcon_cmdq_fini(pmu->hpq); return 0; @@ -188,6 +190,7 @@ nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device, (ret = nvkm_falcon_msgq_new(pmu->qmgr, "msgq", &pmu->msgq))) return ret; + init_completion(&pmu->wpr_ready); return 0; } -- cgit v1.2.3 From 2baaffff977593cb1faee8e11d47bc72b1a26e40 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: cmd_queue_push can't fail, remove error handling for it Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index d32cc0d354ee..b91971e15cc9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -49,13 +49,12 @@ cmd_queue_has_room(struct nvkm_msgqueue *priv, return size <= free; } -static int +static void cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, void *data, u32 size) { nvkm_falcon_load_dmem(priv->falcon, data, queue->position, size, 0); queue->position += ALIGN(size, QUEUE_ALIGNMENT); - return 0; } /* REWIND unit is always 0x00 */ @@ -64,17 +63,11 @@ cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, static void cmd_queue_rewind(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) { - const struct nvkm_subdev *subdev = priv->falcon->owner; struct nvkm_msgqueue_hdr cmd; - int err; cmd.unit_id = MSGQUEUE_UNIT_REWIND; cmd.size = sizeof(cmd); - err = cmd_queue_push(priv, queue, &cmd, cmd.size); - if (err) - nvkm_error(subdev, "queue %d rewind failed\n", queue->index); - else - nvkm_error(subdev, "queue %d rewinded\n", queue->index); + cmd_queue_push(priv, queue, &cmd, cmd.size); queue->position = queue->offset; } @@ -132,12 +125,7 @@ cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, return ret; } - ret = cmd_queue_push(priv, queue, cmd, cmd->size); - if (ret) { - nvkm_error(subdev, "pmu_queue_push failed\n"); - commit = false; - } - + cmd_queue_push(priv, queue, cmd, cmd->size); cmd_queue_close(priv, queue, commit); return ret; } -- cgit v1.2.3 From c2c9b243189fd4f92cb2ed52a1ab76277d9807a5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: cmd_queue_close always commits, simplify it Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index b91971e15cc9..13e6e302a09e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -97,14 +97,9 @@ cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, } static void -cmd_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - bool commit) +cmd_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) { - struct nvkm_falcon *falcon = priv->falcon; - - if (commit) - nvkm_falcon_wr32(falcon, queue->head_reg, queue->position); - + nvkm_falcon_wr32(queue->qmgr->falcon, queue->head_reg, queue->position); mutex_unlock(&queue->mutex); } @@ -116,7 +111,6 @@ cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, static unsigned timeout = 2000; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); int ret = -EAGAIN; - bool commit = true; while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) ret = cmd_queue_open(priv, queue, cmd->size); @@ -126,7 +120,7 @@ cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, } cmd_queue_push(priv, queue, cmd, cmd->size); - cmd_queue_close(priv, queue, commit); + cmd_queue_close(priv, queue); return ret; } -- cgit v1.2.3 From baafecbf9a5bb687d499212b19848fc1963f1b1a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: switch to falcon queue printk macros Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 13e6e302a09e..cf090c2c5fa3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -77,13 +77,12 @@ cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, u32 size) { struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = priv->falcon->owner; bool rewind = false; mutex_lock(&queue->mutex); if (!cmd_queue_has_room(priv, queue, size, &rewind)) { - nvkm_error(subdev, "queue full\n"); + FLCNQ_DBG(queue, "queue full"); mutex_unlock(&queue->mutex); return -EAGAIN; } @@ -107,7 +106,6 @@ static int cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, struct nvkm_msgqueue_queue *queue) { - const struct nvkm_subdev *subdev = priv->falcon->owner; static unsigned timeout = 2000; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); int ret = -EAGAIN; @@ -115,7 +113,7 @@ cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) ret = cmd_queue_open(priv, queue, cmd->size); if (ret) { - nvkm_error(subdev, "pmu_queue_open_write failed\n"); + FLCNQ_ERR(queue, "timeout waiting for queue space"); return ret; } @@ -169,8 +167,10 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, if (!seq->async) { if (!wait_for_completion_timeout(&seq->done, - msecs_to_jiffies(1000))) + msecs_to_jiffies(1000))) { + FLCNQ_ERR(queue, "timeout waiting for reply"); return -ETIMEDOUT; + } ret = seq->result; nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); } -- cgit v1.2.3 From 2b287aebb451aceed1f0cb9bbdd319c77010f350 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: drop nvkm_msgqueue argument to functions Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 40 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index cf090c2c5fa3..64884a99500f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -23,12 +23,10 @@ #include "qmgr.h" static bool -cmd_queue_has_room(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_queue *queue, u32 size, bool *rewind) +cmd_queue_has_room(struct nvkm_msgqueue_queue *queue, u32 size, bool *rewind) { - struct nvkm_falcon *falcon = priv->falcon; - u32 head = nvkm_falcon_rd32(falcon, queue->head_reg); - u32 tail = nvkm_falcon_rd32(falcon, queue->tail_reg); + u32 head = nvkm_falcon_rd32(queue->qmgr->falcon, queue->head_reg); + u32 tail = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); u32 free; size = ALIGN(size, QUEUE_ALIGNMENT); @@ -50,10 +48,10 @@ cmd_queue_has_room(struct nvkm_msgqueue *priv, } static void -cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - void *data, u32 size) +cmd_queue_push(struct nvkm_msgqueue_queue *queue, void *data, u32 size) { - nvkm_falcon_load_dmem(priv->falcon, data, queue->position, size, 0); + struct nvkm_falcon *falcon = queue->qmgr->falcon; + nvkm_falcon_load_dmem(falcon, data, queue->position, size, 0); queue->position += ALIGN(size, QUEUE_ALIGNMENT); } @@ -61,27 +59,26 @@ cmd_queue_push(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, #define MSGQUEUE_UNIT_REWIND 0x00 static void -cmd_queue_rewind(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +cmd_queue_rewind(struct nvkm_msgqueue_queue *queue) { struct nvkm_msgqueue_hdr cmd; cmd.unit_id = MSGQUEUE_UNIT_REWIND; cmd.size = sizeof(cmd); - cmd_queue_push(priv, queue, &cmd, cmd.size); + cmd_queue_push(queue, &cmd, cmd.size); queue->position = queue->offset; } static int -cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - u32 size) +cmd_queue_open(struct nvkm_msgqueue_queue *queue, u32 size) { - struct nvkm_falcon *falcon = priv->falcon; + struct nvkm_falcon *falcon = queue->qmgr->falcon; bool rewind = false; mutex_lock(&queue->mutex); - if (!cmd_queue_has_room(priv, queue, size, &rewind)) { + if (!cmd_queue_has_room(queue, size, &rewind)) { FLCNQ_DBG(queue, "queue full"); mutex_unlock(&queue->mutex); return -EAGAIN; @@ -90,35 +87,34 @@ cmd_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, queue->position = nvkm_falcon_rd32(falcon, queue->head_reg); if (rewind) - cmd_queue_rewind(priv, queue); + cmd_queue_rewind(queue); return 0; } static void -cmd_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +cmd_queue_close(struct nvkm_msgqueue_queue *queue) { nvkm_falcon_wr32(queue->qmgr->falcon, queue->head_reg, queue->position); mutex_unlock(&queue->mutex); } static int -cmd_write(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_hdr *cmd, - struct nvkm_msgqueue_queue *queue) +cmd_write(struct nvkm_msgqueue_queue *queue, struct nvkm_msgqueue_hdr *cmd) { static unsigned timeout = 2000; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); int ret = -EAGAIN; while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) - ret = cmd_queue_open(priv, queue, cmd->size); + ret = cmd_queue_open(queue, cmd->size); if (ret) { FLCNQ_ERR(queue, "timeout waiting for queue space"); return ret; } - cmd_queue_push(priv, queue, cmd, cmd->size); - cmd_queue_close(priv, queue); + cmd_queue_push(queue, cmd, cmd->size); + cmd_queue_close(queue); return ret; } @@ -158,7 +154,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, seq->callback = cb; seq->priv = priv; - ret = cmd_write(priv, cmd, queue); + ret = cmd_write(queue, cmd); if (ret) { seq->state = SEQ_STATE_PENDING; nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); -- cgit v1.2.3 From 149745252c65b0abc13e5ac4aa8c9e5f78d54783 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: implement a more explicit send() interface Takes the command queue pointer directly instead of requiring a function to lookup based on an queue type, as well as an explicit timeout value. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 5 ++ drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 21 +++----- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 10 ---- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 60 +++++++--------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 23 +++------ 5 files changed, 40 insertions(+), 79 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 75d095048b67..da7b6766f04f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -45,6 +45,8 @@ struct nv_falcon_msg { u8 seq_id; }; +#define nv_falcon_cmd nv_falcon_msg + struct nvkm_falcon_qmgr; int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **); void nvkm_falcon_qmgr_del(struct nvkm_falcon_qmgr **); @@ -59,6 +61,9 @@ void nvkm_falcon_cmdq_del(struct nvkm_falcon_cmdq **); void nvkm_falcon_cmdq_init(struct nvkm_falcon_cmdq *, u32 index, u32 offset, u32 size); void nvkm_falcon_cmdq_fini(struct nvkm_falcon_cmdq *); +int nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *, struct nv_falcon_cmd *, + nvkm_falcon_qmgr_callback, void *priv, + unsigned long timeout_jiffies); struct nvkm_falcon_msgq; int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index 64884a99500f..e41ceac54f48 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -61,7 +61,7 @@ cmd_queue_push(struct nvkm_msgqueue_queue *queue, void *data, u32 size) static void cmd_queue_rewind(struct nvkm_msgqueue_queue *queue) { - struct nvkm_msgqueue_hdr cmd; + struct nv_falcon_cmd cmd; cmd.unit_id = MSGQUEUE_UNIT_REWIND; cmd.size = sizeof(cmd); @@ -100,7 +100,7 @@ cmd_queue_close(struct nvkm_msgqueue_queue *queue) } static int -cmd_write(struct nvkm_msgqueue_queue *queue, struct nvkm_msgqueue_hdr *cmd) +cmd_write(struct nvkm_msgqueue_queue *queue, struct nv_falcon_cmd *cmd) { static unsigned timeout = 2000; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); @@ -124,18 +124,14 @@ cmd_write(struct nvkm_msgqueue_queue *queue, struct nvkm_msgqueue_hdr *cmd) #define CMD_FLAGS_INTR BIT(1) int -nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, - struct nvkm_msgqueue_hdr *cmd, nvkm_falcon_qmgr_callback cb, - struct completion *completion, bool wait_init) +nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *queue, + struct nv_falcon_cmd *cmd, + nvkm_falcon_qmgr_callback cb, void *priv, + unsigned long timeout) { struct nvkm_falcon_qmgr_seq *seq; - struct nvkm_msgqueue_queue *queue; int ret; - queue = priv->func->cmd_queue(priv, prio); - if (IS_ERR(queue)) - return PTR_ERR(queue); - if (!wait_for_completion_timeout(&queue->ready, msecs_to_jiffies(1000))) { FLCNQ_ERR(queue, "timeout waiting for queue ready"); @@ -150,7 +146,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, cmd->ctrl_flags = CMD_FLAGS_STATUS | CMD_FLAGS_INTR; seq->state = SEQ_STATE_USED; - seq->async = !completion; + seq->async = !timeout; seq->callback = cb; seq->priv = priv; @@ -162,8 +158,7 @@ nvkm_msgqueue_post(struct nvkm_msgqueue *priv, enum msgqueue_msg_priority prio, } if (!seq->async) { - if (!wait_for_completion_timeout(&seq->done, - msecs_to_jiffies(1000))) { + if (!wait_for_completion_timeout(&seq->done, timeout)) { FLCNQ_ERR(queue, "timeout waiting for reply"); return -ETIMEDOUT; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 98ace0d8465a..65a2a045fae7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -52,11 +52,6 @@ * */ -enum msgqueue_msg_priority { - MSGQUEUE_MSG_PRIORITY_HIGH, - MSGQUEUE_MSG_PRIORITY_LOW, -}; - /** * struct nvkm_msgqueue_hdr - header for all commands/messages * @unit_id: id of firmware using receiving the command/sending the message @@ -110,8 +105,6 @@ struct nvkm_msgqueue_func { const struct nvkm_msgqueue_init_func *init_func; const struct nvkm_msgqueue_acr_func *acr_func; void (*dtor)(struct nvkm_msgqueue *); - struct nvkm_msgqueue_queue *(*cmd_queue)(struct nvkm_msgqueue *, - enum msgqueue_msg_priority); void (*recv)(struct nvkm_msgqueue *queue); }; @@ -160,9 +153,6 @@ struct nvkm_msgqueue { void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, struct nvkm_msgqueue *); -int nvkm_msgqueue_post(struct nvkm_msgqueue *, enum msgqueue_msg_priority, - struct nvkm_msgqueue_hdr *, nvkm_falcon_qmgr_callback, - struct completion *, bool); void nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *, struct nvkm_msgqueue_queue *); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index 3bd98262f16e..b8c0fcdff156 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -45,24 +45,6 @@ struct msgqueue_0137bca5 { container_of(container_of(q, struct msgqueue_0137c63d, base), \ struct msgqueue_0137bca5, base); -static struct nvkm_msgqueue_queue * -msgqueue_0137c63d_cmd_queue(struct nvkm_msgqueue *queue, - enum msgqueue_msg_priority priority) -{ - struct msgqueue_0137c63d *priv = msgqueue_0137c63d(queue); - const struct nvkm_subdev *subdev = priv->base.falcon->owner; - - switch (priority) { - case MSGQUEUE_MSG_PRIORITY_HIGH: - return subdev->device->pmu->hpq; - case MSGQUEUE_MSG_PRIORITY_LOW: - return subdev->device->pmu->lpq; - default: - nvkm_error(subdev, "invalid command queue!\n"); - return ERR_PTR(-EINVAL); - } -} - static void msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue) { @@ -172,13 +154,13 @@ enum { static int acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) { - struct nvkm_msgqueue *queue = priv; + struct nvkm_pmu *pmu = priv; + struct nvkm_subdev *subdev = &pmu->subdev; struct { struct nv_falcon_msg base; u8 msg_type; u32 error_code; } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = queue->falcon->owner; if (msg->error_code) { nvkm_error(subdev, "ACR WPR init failure: %d\n", @@ -187,19 +169,20 @@ acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) } nvkm_debug(subdev, "ACR WPR init complete\n"); - complete_all(&subdev->device->pmu->wpr_ready); + complete_all(&pmu->wpr_ready); return 0; } static int acr_init_wpr(struct nvkm_msgqueue *queue) { + struct nvkm_pmu *pmu = queue->falcon->owner->device->pmu; /* * region_id: region ID in WPR region * wpr_offset: offset in WPR region */ struct { - struct nvkm_msgqueue_hdr hdr; + struct nv_falcon_cmd hdr; u8 cmd_type; u32 region_id; u32 wpr_offset; @@ -211,21 +194,20 @@ acr_init_wpr(struct nvkm_msgqueue *queue) cmd.cmd_type = ACR_CMD_INIT_WPR_REGION; cmd.region_id = 0x01; cmd.wpr_offset = 0x00; - return nvkm_msgqueue_post(queue, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_init_wpr_callback, NULL, false); + return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, acr_init_wpr_callback, + pmu, 0); } static int -acr_boot_falcon_callback(void *_priv, struct nv_falcon_msg *hdr) +acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr) { - struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { struct nv_falcon_msg base; u8 msg_type; u32 falcon_id; } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = priv->falcon->owner; + struct nvkm_subdev *subdev = priv; u32 falcon_id = msg->falcon_id; if (falcon_id >= NVKM_SECBOOT_FALCON_END) { @@ -247,13 +229,12 @@ static int acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) { struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; - DECLARE_COMPLETION_ONSTACK(completed); /* * flags - Flag specifying RESET or no RESET. * falcon id - Falcon id specifying falcon to bootstrap. */ struct { - struct nvkm_msgqueue_hdr hdr; + struct nv_falcon_cmd hdr; u8 cmd_type; u32 flags; u32 falcon_id; @@ -272,20 +253,20 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; cmd.falcon_id = falcon; - return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_falcon_callback, &completed, true); + return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, + acr_boot_falcon_callback, &pmu->subdev, + msecs_to_jiffies(1000)); } static int -acr_boot_multiple_falcons_callback(void *_priv, struct nv_falcon_msg *hdr) +acr_boot_multiple_falcons_callback(void *priv, struct nv_falcon_msg *hdr) { - struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { struct nv_falcon_msg base; u8 msg_type; u32 falcon_mask; } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = priv->falcon->owner; + const struct nvkm_subdev *subdev = priv; unsigned long falcon_mask = msg->falcon_mask; u32 falcon_id, falcon_treated = 0; @@ -309,13 +290,12 @@ static int acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) { struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; - DECLARE_COMPLETION_ONSTACK(completed); /* * flags - Flag specifying RESET or no RESET. * falcon id - Falcon id specifying falcon to bootstrap. */ struct { - struct nvkm_msgqueue_hdr hdr; + struct nv_falcon_cmd hdr; u8 cmd_type; u32 flags; u32 falcon_mask; @@ -340,9 +320,9 @@ acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) cmd.falcon_mask = falcon_mask; cmd.wpr_lo = lower_32_bits(queue->wpr_addr); cmd.wpr_hi = upper_32_bits(queue->wpr_addr); - return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_multiple_falcons_callback, - &completed, true); + return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, + acr_boot_multiple_falcons_callback, + &pmu->subdev, msecs_to_jiffies(1000)); } static const struct nvkm_msgqueue_acr_func @@ -366,7 +346,6 @@ static const struct nvkm_msgqueue_func msgqueue_0137c63d_func = { .init_func = &msgqueue_0137c63d_init_func, .acr_func = &msgqueue_0137c63d_acr_func, - .cmd_queue = msgqueue_0137c63d_cmd_queue, .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; @@ -392,7 +371,6 @@ static const struct nvkm_msgqueue_func msgqueue_0137bca5_func = { .init_func = &msgqueue_0137c63d_init_func, .acr_func = &msgqueue_0137bca5_acr_func, - .cmd_queue = msgqueue_0137c63d_cmd_queue, .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 1c6077cea865..2826822cd0fc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -43,13 +43,6 @@ struct msgqueue_0148cdec { #define msgqueue_0148cdec(q) \ container_of(q, struct msgqueue_0148cdec, base) -static struct nvkm_msgqueue_queue * -msgqueue_0148cdec_cmd_queue(struct nvkm_msgqueue *queue, - enum msgqueue_msg_priority priority) -{ - return queue->falcon->owner->device->sec2->cmdq; -} - static void msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue) { @@ -146,16 +139,15 @@ enum { }; static int -acr_boot_falcon_callback(void *_priv, struct nv_falcon_msg *hdr) +acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr) { - struct nvkm_msgqueue *priv = _priv; struct acr_bootstrap_falcon_msg { struct nv_falcon_msg base; u8 msg_type; u32 error_code; u32 falcon_id; } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = priv->falcon->owner; + const struct nvkm_subdev *subdev = priv; u32 falcon_id = msg->falcon_id; if (msg->error_code) { @@ -183,13 +175,13 @@ enum { static int acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) { - DECLARE_COMPLETION_ONSTACK(completed); + struct nvkm_sec2 *sec2 = priv->falcon->owner->device->sec2; /* * flags - Flag specifying RESET or no RESET. * falcon id - Falcon id specifying falcon to bootstrap. */ struct { - struct nvkm_msgqueue_hdr hdr; + struct nv_falcon_cmd hdr; u8 cmd_type; u32 flags; u32 falcon_id; @@ -202,8 +194,10 @@ acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; cmd.falcon_id = falcon; - return nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr, - acr_boot_falcon_callback, &completed, true); + return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.hdr, + acr_boot_falcon_callback, + &sec2->engine.subdev, + msecs_to_jiffies(1000)); } const struct nvkm_msgqueue_acr_func @@ -221,7 +215,6 @@ const struct nvkm_msgqueue_func msgqueue_0148cdec_func = { .init_func = &msgqueue_0148cdec_init_func, .acr_func = &msgqueue_0148cdec_acr_func, - .cmd_queue = msgqueue_0148cdec_cmd_queue, .recv = msgqueue_0148cdec_process_msgs, .dtor = msgqueue_0148cdec_dtor, }; -- cgit v1.2.3 From 25fd061cc7dd3b8cc37f4874565c14fe18f40c8b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: rename cmdq-related nvkm_msqqueue_queue to nvkm_falcon_cmdq Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c | 78 ++++++++++------------ 2 files changed, 38 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index da7b6766f04f..54e1f4d7568f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -46,6 +46,7 @@ struct nv_falcon_msg { }; #define nv_falcon_cmd nv_falcon_msg +#define NV_FALCON_CMD_UNIT_ID_REWIND 0x00 struct nvkm_falcon_qmgr; int nvkm_falcon_qmgr_new(struct nvkm_falcon *, struct nvkm_falcon_qmgr **); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c index e41ceac54f48..40e3f3fc83ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c @@ -23,21 +23,21 @@ #include "qmgr.h" static bool -cmd_queue_has_room(struct nvkm_msgqueue_queue *queue, u32 size, bool *rewind) +nvkm_falcon_cmdq_has_room(struct nvkm_falcon_cmdq *cmdq, u32 size, bool *rewind) { - u32 head = nvkm_falcon_rd32(queue->qmgr->falcon, queue->head_reg); - u32 tail = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); + u32 head = nvkm_falcon_rd32(cmdq->qmgr->falcon, cmdq->head_reg); + u32 tail = nvkm_falcon_rd32(cmdq->qmgr->falcon, cmdq->tail_reg); u32 free; size = ALIGN(size, QUEUE_ALIGNMENT); if (head >= tail) { - free = queue->offset + queue->size - head; + free = cmdq->offset + cmdq->size - head; free -= HDR_SIZE; if (size > free) { *rewind = true; - head = queue->offset; + head = cmdq->offset; } } @@ -48,73 +48,70 @@ cmd_queue_has_room(struct nvkm_msgqueue_queue *queue, u32 size, bool *rewind) } static void -cmd_queue_push(struct nvkm_msgqueue_queue *queue, void *data, u32 size) +nvkm_falcon_cmdq_push(struct nvkm_falcon_cmdq *cmdq, void *data, u32 size) { - struct nvkm_falcon *falcon = queue->qmgr->falcon; - nvkm_falcon_load_dmem(falcon, data, queue->position, size, 0); - queue->position += ALIGN(size, QUEUE_ALIGNMENT); + struct nvkm_falcon *falcon = cmdq->qmgr->falcon; + nvkm_falcon_load_dmem(falcon, data, cmdq->position, size, 0); + cmdq->position += ALIGN(size, QUEUE_ALIGNMENT); } -/* REWIND unit is always 0x00 */ -#define MSGQUEUE_UNIT_REWIND 0x00 - static void -cmd_queue_rewind(struct nvkm_msgqueue_queue *queue) +nvkm_falcon_cmdq_rewind(struct nvkm_falcon_cmdq *cmdq) { struct nv_falcon_cmd cmd; - cmd.unit_id = MSGQUEUE_UNIT_REWIND; + cmd.unit_id = NV_FALCON_CMD_UNIT_ID_REWIND; cmd.size = sizeof(cmd); - cmd_queue_push(queue, &cmd, cmd.size); + nvkm_falcon_cmdq_push(cmdq, &cmd, cmd.size); - queue->position = queue->offset; + cmdq->position = cmdq->offset; } static int -cmd_queue_open(struct nvkm_msgqueue_queue *queue, u32 size) +nvkm_falcon_cmdq_open(struct nvkm_falcon_cmdq *cmdq, u32 size) { - struct nvkm_falcon *falcon = queue->qmgr->falcon; + struct nvkm_falcon *falcon = cmdq->qmgr->falcon; bool rewind = false; - mutex_lock(&queue->mutex); + mutex_lock(&cmdq->mutex); - if (!cmd_queue_has_room(queue, size, &rewind)) { - FLCNQ_DBG(queue, "queue full"); - mutex_unlock(&queue->mutex); + if (!nvkm_falcon_cmdq_has_room(cmdq, size, &rewind)) { + FLCNQ_DBG(cmdq, "queue full"); + mutex_unlock(&cmdq->mutex); return -EAGAIN; } - queue->position = nvkm_falcon_rd32(falcon, queue->head_reg); + cmdq->position = nvkm_falcon_rd32(falcon, cmdq->head_reg); if (rewind) - cmd_queue_rewind(queue); + nvkm_falcon_cmdq_rewind(cmdq); return 0; } static void -cmd_queue_close(struct nvkm_msgqueue_queue *queue) +nvkm_falcon_cmdq_close(struct nvkm_falcon_cmdq *cmdq) { - nvkm_falcon_wr32(queue->qmgr->falcon, queue->head_reg, queue->position); - mutex_unlock(&queue->mutex); + nvkm_falcon_wr32(cmdq->qmgr->falcon, cmdq->head_reg, cmdq->position); + mutex_unlock(&cmdq->mutex); } static int -cmd_write(struct nvkm_msgqueue_queue *queue, struct nv_falcon_cmd *cmd) +nvkm_falcon_cmdq_write(struct nvkm_falcon_cmdq *cmdq, struct nv_falcon_cmd *cmd) { static unsigned timeout = 2000; unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); int ret = -EAGAIN; while (ret == -EAGAIN && time_before(jiffies, end_jiffies)) - ret = cmd_queue_open(queue, cmd->size); + ret = nvkm_falcon_cmdq_open(cmdq, cmd->size); if (ret) { - FLCNQ_ERR(queue, "timeout waiting for queue space"); + FLCNQ_ERR(cmdq, "timeout waiting for queue space"); return ret; } - cmd_queue_push(queue, cmd, cmd->size); - cmd_queue_close(queue); + nvkm_falcon_cmdq_push(cmdq, cmd, cmd->size); + nvkm_falcon_cmdq_close(cmdq); return ret; } @@ -124,21 +121,20 @@ cmd_write(struct nvkm_msgqueue_queue *queue, struct nv_falcon_cmd *cmd) #define CMD_FLAGS_INTR BIT(1) int -nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *queue, - struct nv_falcon_cmd *cmd, +nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *cmdq, struct nv_falcon_cmd *cmd, nvkm_falcon_qmgr_callback cb, void *priv, unsigned long timeout) { struct nvkm_falcon_qmgr_seq *seq; int ret; - if (!wait_for_completion_timeout(&queue->ready, + if (!wait_for_completion_timeout(&cmdq->ready, msecs_to_jiffies(1000))) { - FLCNQ_ERR(queue, "timeout waiting for queue ready"); + FLCNQ_ERR(cmdq, "timeout waiting for queue ready"); return -ETIMEDOUT; } - seq = nvkm_falcon_qmgr_seq_acquire(queue->qmgr); + seq = nvkm_falcon_qmgr_seq_acquire(cmdq->qmgr); if (IS_ERR(seq)) return PTR_ERR(seq); @@ -150,20 +146,20 @@ nvkm_falcon_cmdq_send(struct nvkm_falcon_cmdq *queue, seq->callback = cb; seq->priv = priv; - ret = cmd_write(queue, cmd); + ret = nvkm_falcon_cmdq_write(cmdq, cmd); if (ret) { seq->state = SEQ_STATE_PENDING; - nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); + nvkm_falcon_qmgr_seq_release(cmdq->qmgr, seq); return ret; } if (!seq->async) { if (!wait_for_completion_timeout(&seq->done, timeout)) { - FLCNQ_ERR(queue, "timeout waiting for reply"); + FLCNQ_ERR(cmdq, "timeout waiting for reply"); return -ETIMEDOUT; } ret = seq->result; - nvkm_falcon_qmgr_seq_release(queue->qmgr, seq); + nvkm_falcon_qmgr_seq_release(cmdq->qmgr, seq); } return ret; -- cgit v1.2.3 From 86ce2a71539c47241dc8f471d8724f5bd1e41ae6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/cmdq: move command generation to subdevs This moves the code to generate commands for the ACR unit of the PMU/SEC2 LS firmwares to those subdevs. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/pmu.h | 47 +++++++ drivers/gpu/drm/nouveau/include/nvfw/sec2.h | 30 +++++ .../gpu/drm/nouveau/include/nvkm/core/msgqueue.h | 3 - drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 23 +++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 44 +++++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 28 ---- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 12 -- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 142 --------------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 76 ----------- drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 74 ++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 7 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 34 +++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 36 ++++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 2 + .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 17 +-- 16 files changed, 300 insertions(+), 276 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/pmu.h create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/sec2.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h new file mode 100644 index 000000000000..6e86ce31f963 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h @@ -0,0 +1,47 @@ +#ifndef __NVFW_PMU_H__ +#define __NVFW_PMU_H__ + +#define NV_PMU_UNIT_ACR 0x0a + +struct nv_pmu_acr_cmd { + struct nv_falcon_cmd hdr; +#define NV_PMU_ACR_CMD_INIT_WPR_REGION 0x00 +#define NV_PMU_ACR_CMD_BOOTSTRAP_FALCON 0x01 +#define NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS 0x03 + u8 cmd_type; +}; + +struct nv_pmu_acr_msg { + struct nv_falcon_cmd hdr; + u8 msg_type; +}; + +struct nv_pmu_acr_bootstrap_falcon_cmd { + struct nv_pmu_acr_cmd cmd; +#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000 +#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001 + u32 flags; + u32 falcon_id; +}; + +struct nv_pmu_acr_bootstrap_falcon_msg { + struct nv_pmu_acr_msg msg; + u32 falcon_id; +}; + +struct nv_pmu_acr_bootstrap_multiple_falcons_cmd { + struct nv_pmu_acr_cmd cmd; +#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES 0x00000000 +#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_NO 0x00000001 + u32 flags; + u32 falcon_mask; + u32 use_va_mask; + u32 wpr_lo; + u32 wpr_hi; +}; + +struct nv_pmu_acr_bootstrap_multiple_falcons_msg { + struct nv_pmu_acr_msg msg; + u32 falcon_mask; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h new file mode 100644 index 000000000000..2f7460fe1b76 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h @@ -0,0 +1,30 @@ +#ifndef __NVFW_SEC2_H__ +#define __NVFW_SEC2_H__ + +#define NV_SEC2_UNIT_ACR 0x08 + +struct nv_sec2_acr_cmd { + struct nv_falcon_cmd hdr; +#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00 + u8 cmd_type; +}; + +struct nv_sec2_acr_msg { + struct nv_falcon_cmd hdr; + u8 msg_type; +}; + +struct nv_sec2_acr_bootstrap_falcon_cmd { + struct nv_sec2_acr_cmd cmd; +#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000 +#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001 + u32 flags; + u32 falcon_id; +}; + +struct nv_sec2_acr_bootstrap_falcon_msg { + struct nv_sec2_acr_msg msg; + u32 error_code; + u32 falcon_id; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h index bf3e532665fb..acb339f34bb5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h @@ -37,7 +37,4 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *); /* useful if we run a NVIDIA-signed firmware */ void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *); -/* interface to ACR unit running on falcon (NVIDIA signed firmware) */ -int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long); - #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 6b342a63e2cb..7e51bd4befce 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -13,15 +13,34 @@ enum nvkm_acr_lsf_id { NVKM_ACR_LSF_NVDEC = 4, NVKM_ACR_LSF_SEC2 = 7, NVKM_ACR_LSF_MINION = 10, + NVKM_ACR_LSF_NUM }; +static inline const char * +nvkm_acr_lsf_id(enum nvkm_acr_lsf_id id) +{ + switch (id) { + case NVKM_ACR_LSF_PMU : return "pmu"; + case NVKM_ACR_LSF_GSPLITE: return "gsplite"; + case NVKM_ACR_LSF_FECS : return "fecs"; + case NVKM_ACR_LSF_GPCCS : return "gpccs"; + case NVKM_ACR_LSF_NVDEC : return "nvdec"; + case NVKM_ACR_LSF_SEC2 : return "sec2"; + case NVKM_ACR_LSF_MINION : return "minion"; + default: + return "unknown"; + } +} + struct nvkm_acr { const struct nvkm_acr_func *func; struct nvkm_subdev subdev; - struct list_head lsfw; + struct list_head lsfw, lsf; }; +int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long mask); + int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **); @@ -55,6 +74,8 @@ struct nvkm_acr_lsfw { }; struct nvkm_acr_lsf_func { + int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id); + int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask); }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 9a5bae1a03cd..26f738d1202e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -20,11 +20,53 @@ * DEALINGS IN THE SOFTWARE. */ #include "priv.h" + #include #include +#include + +static int +gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nv_falcon_msg *hdr) +{ + struct nv_sec2_acr_bootstrap_falcon_msg *msg = + container_of(hdr, typeof(*msg), msg.hdr); + struct nvkm_subdev *subdev = priv; + const char *name = nvkm_acr_lsf_id(msg->falcon_id); + + if (msg->error_code) { + nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for " + "falcon %d [%s]: %08x\n", + msg->falcon_id, name, msg->error_code); + return -EINVAL; + } + + nvkm_debug(subdev, "%s booted\n", name); + return 0; +} + +static int +gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id) +{ + struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon); + struct nv_sec2_acr_bootstrap_falcon_cmd cmd = { + .cmd.hdr.unit_id = sec2->func->unit_acr, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON, + .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, + .falcon_id = id, + }; + + return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr, + gp102_sec2_acr_bootstrap_falcon_callback, + &sec2->engine.subdev, + msecs_to_jiffies(1000)); +} + static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { + .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; void @@ -117,6 +159,7 @@ gp102_sec2_flcn = { const struct nvkm_sec2_func gp102_sec2 = { .flcn = &gp102_sec2_flcn, + .unit_acr = NV_SEC2_UNIT_ACR, .intr = gp102_sec2_intr, }; @@ -135,6 +178,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); const struct nvkm_acr_lsf_func gp102_sec2_acr_1 = { + .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index e5ba6df3d500..9c00e6634499 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -5,6 +5,7 @@ struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; + u8 unit_acr; void (*intr)(struct nvkm_sec2 *); }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index 3e14c7bc3e32..9867a32da42a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -35,34 +35,6 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf) queue->func->init_func->gen_cmdline(queue, buf); } -int -nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *queue, - unsigned long falcon_mask) -{ - unsigned long falcon; - - if (!queue || !queue->func->acr_func) - return -ENODEV; - - /* Does the firmware support booting multiple falcons? */ - if (queue->func->acr_func->boot_multiple_falcons) - return queue->func->acr_func->boot_multiple_falcons(queue, - falcon_mask); - - /* Else boot all requested falcons individually */ - if (!queue->func->acr_func->boot_falcon) - return -ENODEV; - - for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) { - int ret = queue->func->acr_func->boot_falcon(queue, falcon); - - if (ret) - return ret; - } - - return 0; -} - int nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, struct nvkm_msgqueue **queue) diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 65a2a045fae7..bf714f391d42 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -90,20 +90,8 @@ struct nvkm_msgqueue_init_func { int (*init_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *); }; -/** - * struct nvkm_msgqueue_acr_func - msgqueue functions related to ACR - * - * @boot_falcon: build and send the command to reset a given falcon - * @boot_multiple_falcons: build and send the command to reset several falcons - */ -struct nvkm_msgqueue_acr_func { - int (*boot_falcon)(struct nvkm_msgqueue *, enum nvkm_secboot_falcon); - int (*boot_multiple_falcons)(struct nvkm_msgqueue *, unsigned long); -}; - struct nvkm_msgqueue_func { const struct nvkm_msgqueue_init_func *init_func; - const struct nvkm_msgqueue_acr_func *acr_func; void (*dtor)(struct nvkm_msgqueue *); void (*recv)(struct nvkm_msgqueue *queue); }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index b8c0fcdff156..7e450a91c62e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -147,8 +147,6 @@ msgqueue_0137c63d_init_func = { enum { ACR_CMD_INIT_WPR_REGION = 0x00, - ACR_CMD_BOOTSTRAP_FALCON = 0x01, - ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03, }; static int @@ -198,144 +196,6 @@ acr_init_wpr(struct nvkm_msgqueue *queue) pmu, 0); } - -static int -acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr) -{ - struct acr_bootstrap_falcon_msg { - struct nv_falcon_msg base; - u8 msg_type; - u32 falcon_id; - } *msg = (void *)hdr; - struct nvkm_subdev *subdev = priv; - u32 falcon_id = msg->falcon_id; - - if (falcon_id >= NVKM_SECBOOT_FALCON_END) { - nvkm_error(subdev, "in bootstrap falcon callback:\n"); - nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id); - return -EINVAL; - } - - nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]); - return 0; -} - -enum { - ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0, - ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1, -}; - -static int -acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) -{ - struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; - /* - * flags - Flag specifying RESET or no RESET. - * falcon id - Falcon id specifying falcon to bootstrap. - */ - struct { - struct nv_falcon_cmd hdr; - u8 cmd_type; - u32 flags; - u32 falcon_id; - } cmd; - - if (!wait_for_completion_timeout(&pmu->wpr_ready, - msecs_to_jiffies(1000))) { - nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n"); - return -ETIMEDOUT; - } - - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR; - cmd.hdr.size = sizeof(cmd); - cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; - cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; - cmd.falcon_id = falcon; - return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, - acr_boot_falcon_callback, &pmu->subdev, - msecs_to_jiffies(1000)); -} - -static int -acr_boot_multiple_falcons_callback(void *priv, struct nv_falcon_msg *hdr) -{ - struct acr_bootstrap_falcon_msg { - struct nv_falcon_msg base; - u8 msg_type; - u32 falcon_mask; - } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = priv; - unsigned long falcon_mask = msg->falcon_mask; - u32 falcon_id, falcon_treated = 0; - - for_each_set_bit(falcon_id, &falcon_mask, NVKM_SECBOOT_FALCON_END) { - nvkm_debug(subdev, "%s booted\n", - nvkm_secboot_falcon_name[falcon_id]); - falcon_treated |= BIT(falcon_id); - } - - if (falcon_treated != msg->falcon_mask) { - nvkm_error(subdev, "in bootstrap falcon callback:\n"); - nvkm_error(subdev, "invalid falcon mask 0x%x\n", - msg->falcon_mask); - return -EINVAL; - } - - return 0; -} - -static int -acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask) -{ - struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu; - /* - * flags - Flag specifying RESET or no RESET. - * falcon id - Falcon id specifying falcon to bootstrap. - */ - struct { - struct nv_falcon_cmd hdr; - u8 cmd_type; - u32 flags; - u32 falcon_mask; - u32 use_va_mask; - u32 wpr_lo; - u32 wpr_hi; - } cmd; - struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv); - - if (!wait_for_completion_timeout(&pmu->wpr_ready, - msecs_to_jiffies(1000))) { - nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n"); - return -ETIMEDOUT; - } - - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR; - cmd.hdr.size = sizeof(cmd); - cmd.cmd_type = ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS; - cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; - cmd.falcon_mask = falcon_mask; - cmd.wpr_lo = lower_32_bits(queue->wpr_addr); - cmd.wpr_hi = upper_32_bits(queue->wpr_addr); - return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, - acr_boot_multiple_falcons_callback, - &pmu->subdev, msecs_to_jiffies(1000)); -} - -static const struct nvkm_msgqueue_acr_func -msgqueue_0137c63d_acr_func = { - .boot_falcon = acr_boot_falcon, -}; - -static const struct nvkm_msgqueue_acr_func -msgqueue_0137bca5_acr_func = { - .boot_falcon = acr_boot_falcon, - .boot_multiple_falcons = acr_boot_multiple_falcons, -}; - static void msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) { @@ -345,7 +205,6 @@ msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) static const struct nvkm_msgqueue_func msgqueue_0137c63d_func = { .init_func = &msgqueue_0137c63d_init_func, - .acr_func = &msgqueue_0137c63d_acr_func, .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; @@ -370,7 +229,6 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, static const struct nvkm_msgqueue_func msgqueue_0137bca5_func = { .init_func = &msgqueue_0137c63d_init_func, - .acr_func = &msgqueue_0137bca5_acr_func, .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 2826822cd0fc..51ae4a10b213 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -130,81 +130,6 @@ msgqueue_0148cdec_init_func = { }; - -/* ACR unit */ -#define MSGQUEUE_0148CDEC_UNIT_ACR 0x08 - -enum { - ACR_CMD_BOOTSTRAP_FALCON = 0x00, -}; - -static int -acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr) -{ - struct acr_bootstrap_falcon_msg { - struct nv_falcon_msg base; - u8 msg_type; - u32 error_code; - u32 falcon_id; - } *msg = (void *)hdr; - const struct nvkm_subdev *subdev = priv; - u32 falcon_id = msg->falcon_id; - - if (msg->error_code) { - nvkm_error(subdev, "in bootstrap falcon callback:\n"); - nvkm_error(subdev, "expected error code 0x%x\n", - msg->error_code); - return -EINVAL; - } - - if (falcon_id >= NVKM_SECBOOT_FALCON_END) { - nvkm_error(subdev, "in bootstrap falcon callback:\n"); - nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id); - return -EINVAL; - } - - nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]); - return 0; -} - -enum { - ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0, - ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1, -}; - -static int -acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon) -{ - struct nvkm_sec2 *sec2 = priv->falcon->owner->device->sec2; - /* - * flags - Flag specifying RESET or no RESET. - * falcon id - Falcon id specifying falcon to bootstrap. - */ - struct { - struct nv_falcon_cmd hdr; - u8 cmd_type; - u32 flags; - u32 falcon_id; - } cmd; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.unit_id = MSGQUEUE_0148CDEC_UNIT_ACR; - cmd.hdr.size = sizeof(cmd); - cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON; - cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; - cmd.falcon_id = falcon; - return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.hdr, - acr_boot_falcon_callback, - &sec2->engine.subdev, - msecs_to_jiffies(1000)); -} - -const struct nvkm_msgqueue_acr_func -msgqueue_0148cdec_acr_func = { - .boot_falcon = acr_boot_falcon, -}; - static void msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue) { @@ -214,7 +139,6 @@ msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue) const struct nvkm_msgqueue_func msgqueue_0148cdec_func = { .init_func = &msgqueue_0148cdec_init_func, - .acr_func = &msgqueue_0148cdec_acr_func, .recv = msgqueue_0148cdec_process_msgs, .dtor = msgqueue_0148cdec_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 11658a4afc7a..6caced3589bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -23,19 +23,90 @@ #include +static struct nvkm_acr_lsf * +nvkm_acr_falcon(struct nvkm_device *device) +{ + struct nvkm_acr *acr = device->acr; + struct nvkm_acr_lsf *lsf; + + if (acr) { + list_for_each_entry(lsf, &acr->lsf, head) { + if (lsf->func->bootstrap_falcon) + return lsf; + } + } + + return NULL; +} + +int +nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) +{ + struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device); + unsigned long id; + + if (!acrflcn) + return -ENOSYS; + + if (acrflcn->func->bootstrap_multiple_falcons) { + return acrflcn->func-> + bootstrap_multiple_falcons(acrflcn->falcon, mask); + } + + for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) { + int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id); + if (ret) + return ret; + } + + return 0; +} + +static void +nvkm_acr_cleanup(struct nvkm_acr *acr) +{ + nvkm_acr_lsfw_del_all(acr); +} + +static int +nvkm_acr_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_acr *acr = nvkm_acr(subdev); + struct nvkm_acr_lsfw *lsfw; + struct nvkm_acr_lsf *lsf; + + list_for_each_entry(lsfw, &acr->lsfw, head) { + if (!(lsf = kmalloc(sizeof(*lsf), GFP_KERNEL))) + return -ENOMEM; + lsf->func = lsfw->func; + lsf->falcon = lsfw->falcon; + lsf->id = lsfw->id; + list_add_tail(&lsf->head, &acr->lsf); + } + + nvkm_acr_cleanup(acr); + return 0; +} + static void * nvkm_acr_dtor(struct nvkm_subdev *subdev) { struct nvkm_acr *acr = nvkm_acr(subdev); + struct nvkm_acr_lsf *lsf, *lst; - nvkm_acr_lsfw_del_all(acr); + list_for_each_entry_safe(lsf, lst, &acr->lsf, head) { + list_del(&lsf->head); + kfree(lsf); + } + nvkm_acr_cleanup(acr); return acr; } static const struct nvkm_subdev_func nvkm_acr = { .dtor = nvkm_acr_dtor, + .oneinit = nvkm_acr_oneinit, }; int @@ -48,6 +119,7 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, return -ENOMEM; nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev); INIT_LIST_HEAD(&acr->lsfw); + INIT_LIST_HEAD(&acr->lsf); fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr); if (IS_ERR(fwif)) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index 882290423c01..808ba7f191b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -18,6 +18,13 @@ struct nvkm_acr_func { int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int, struct nvkm_acr **); +struct nvkm_acr_lsf { + const struct nvkm_acr_lsf_func *func; + struct nvkm_falcon *falcon; + enum nvkm_acr_lsf_id id; + struct list_head head; +}; + struct nvkm_acr_lsfw *nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *, struct nvkm_acr *, struct nvkm_falcon *, enum nvkm_acr_lsf_id); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 5c262a28aa23..e803cc461227 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -20,11 +20,45 @@ * DEALINGS IN THE SOFTWARE. */ #include "priv.h" + #include #include +#include + +static int +gm20b_pmu_acr_bootstrap_falcon_cb(void *priv, struct nv_falcon_msg *hdr) +{ + struct nv_pmu_acr_bootstrap_falcon_msg *msg = + container_of(hdr, typeof(*msg), msg.hdr); + return msg->falcon_id; +} + +int +gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon, + enum nvkm_acr_lsf_id id) +{ + struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon); + struct nv_pmu_acr_bootstrap_falcon_cmd cmd = { + .cmd.hdr.unit_id = NV_PMU_UNIT_ACR, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_FALCON, + .flags = NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES, + .falcon_id = id, + }; + int ret; + + ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr, + gm20b_pmu_acr_bootstrap_falcon_cb, + &pmu->subdev, msecs_to_jiffies(1000)); + if (ret >= 0 && ret != cmd.falcon_id) + ret = -EIO; + return ret; +} + static const struct nvkm_acr_lsf_func gm20b_pmu_acr = { + .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 7134ef9d91af..b2baf9b636a3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -20,10 +20,46 @@ * DEALINGS IN THE SOFTWARE. */ #include "priv.h" + #include +#include + +static int +gp10b_pmu_acr_bootstrap_multiple_falcons_cb(void *priv, + struct nv_falcon_msg *hdr) +{ + struct nv_pmu_acr_bootstrap_multiple_falcons_msg *msg = + container_of(hdr, typeof(*msg), msg.hdr); + return msg->falcon_mask; +} +static int +gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask) +{ + struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon); + struct nv_pmu_acr_bootstrap_multiple_falcons_cmd cmd = { + .cmd.hdr.unit_id = NV_PMU_UNIT_ACR, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS, + .flags = NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES, + .falcon_mask = mask, + .wpr_lo = 0, /*XXX*/ + .wpr_hi = 0, /*XXX*/ + }; + int ret; + + ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr, + gp10b_pmu_acr_bootstrap_multiple_falcons_cb, + &pmu->subdev, msecs_to_jiffies(1000)); + if (ret >= 0 && ret != cmd.falcon_mask) + ret = -EIO; + return ret; +} + static const struct nvkm_acr_lsf_func gp10b_pmu_acr = { + .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, + .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons, }; static const struct nvkm_pmu_func diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 91b4a2d3ad4c..0e7965028dcf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -4,6 +4,7 @@ #define nvkm_pmu(p) container_of((p), struct nvkm_pmu, subdev) #include #include +enum nvkm_acr_lsf_id; struct nvkm_pmu_func { const struct nvkm_falcon_func *flcn; @@ -41,6 +42,7 @@ void gf100_pmu_reset(struct nvkm_pmu *); void gk110_pmu_pgob(struct nvkm_pmu *, bool); +int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id); void gm20b_pmu_recv(struct nvkm_pmu *); struct nvkm_pmu_fwif { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index 53770ecdbb2f..dcb6eb24ba6a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -991,12 +991,13 @@ end: * load the HS firmware and run it, so once the falcon stops all the managed * falcons should have their LS firmware loaded and be ready to run. */ +int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long); + static int acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb, unsigned long falcon_mask) { struct acr_r352 *acr = acr_r352(_acr); - struct nvkm_msgqueue *queue; int falcon; bool wpr_already_set = sb->wpr_set; int ret; @@ -1016,22 +1017,12 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb, return ret; } - switch (_acr->boot_falcon) { - case NVKM_SECBOOT_FALCON_PMU: - queue = sb->subdev.device->pmu->queue; - break; - case NVKM_SECBOOT_FALCON_SEC2: - queue = sb->subdev.device->sec2->queue; - break; - default: - return -EINVAL; - } - /* Otherwise just ask the LS firmware to reset the falcon */ for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) nvkm_debug(&sb->subdev, "resetting %s falcon\n", nvkm_secboot_falcon_name[falcon]); - ret = nvkm_msgqueue_acr_boot_falcons(queue, falcon_mask); + + ret = nvkm_acr_bootstrap_falcons(sb->subdev.device, falcon_mask); if (ret) { nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret); return ret; -- cgit v1.2.3 From f09a3ee36bdc097d197e5188b6d0fd5354ddfa1a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: remove error handling for msg_queue_open(), it can't fail Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index eb499b796fe5..ea3e7c73e990 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -22,13 +22,12 @@ */ #include "qmgr.h" -static int +static void msg_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) { struct nvkm_falcon *falcon = priv->falcon; mutex_lock(&queue->mutex); queue->position = nvkm_falcon_rd32(falcon, queue->tail_reg); - return 0; } static void @@ -91,11 +90,7 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, const struct nvkm_subdev *subdev = priv->falcon->owner; int ret; - ret = msg_queue_open(priv, queue); - if (ret) { - nvkm_error(subdev, "fail to open queue %d\n", queue->index); - return ret; - } + msg_queue_open(priv, queue); if (msg_queue_empty(priv, queue)) { ret = 0; -- cgit v1.2.3 From e9602a1bd7e996aca5c231bc07cad41fff9b290b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: simplify msg_queue_pop() error handling We always want at least requested size, make anything less a more direct error condition. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index ea3e7c73e990..15299ff45685 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -67,20 +67,14 @@ msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, tail = queue->position; available = head - tail; - - if (available == 0) { - nvkm_warn(subdev, "no message data available\n"); - return 0; - } - if (size > available) { nvkm_warn(subdev, "message data smaller than read request\n"); - size = available; + return -EINVAL; } nvkm_falcon_read_dmem(priv->falcon, tail, size, 0, data); queue->position += ALIGN(size, QUEUE_ALIGNMENT); - return size; + return 0; } static int @@ -88,19 +82,15 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, struct nv_falcon_msg *hdr) { const struct nvkm_subdev *subdev = priv->falcon->owner; - int ret; + int ret = 0; msg_queue_open(priv, queue); - if (msg_queue_empty(priv, queue)) { - ret = 0; + if (msg_queue_empty(priv, queue)) goto close; - } ret = msg_queue_pop(priv, queue, hdr, HDR_SIZE); - if (ret >= 0 && ret != HDR_SIZE) - ret = -EINVAL; - if (ret < 0) { + if (ret) { nvkm_error(subdev, "failed to read message header: %d\n", ret); goto close; } @@ -115,14 +105,13 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, u32 read_size = hdr->size - HDR_SIZE; ret = msg_queue_pop(priv, queue, (hdr + 1), read_size); - if (ret >= 0 && ret != read_size) - ret = -EINVAL; - if (ret < 0) { + if (ret) { nvkm_error(subdev, "failed to read message: %d\n", ret); goto close; } } + ret = 1; close: msg_queue_close(priv, queue, (ret >= 0)); return ret; -- cgit v1.2.3 From 77b1ab61fd1c08c7364ee6e184887202995a71e4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: switch to falcon queue printk macros Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 15299ff45685..7fdd81bf3858 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -56,7 +56,6 @@ msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, void *data, u32 size) { struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = priv->falcon->owner; u32 head, tail, available; head = nvkm_falcon_rd32(falcon, queue->head_reg); @@ -68,7 +67,8 @@ msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, available = head - tail; if (size > available) { - nvkm_warn(subdev, "message data smaller than read request\n"); + FLCNQ_ERR(queue, "requested %d bytes, but only %d available", + size, available); return -EINVAL; } @@ -81,7 +81,6 @@ static int msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, struct nv_falcon_msg *hdr) { - const struct nvkm_subdev *subdev = priv->falcon->owner; int ret = 0; msg_queue_open(priv, queue); @@ -91,12 +90,12 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, ret = msg_queue_pop(priv, queue, hdr, HDR_SIZE); if (ret) { - nvkm_error(subdev, "failed to read message header: %d\n", ret); + FLCNQ_ERR(queue, "failed to read message header"); goto close; } if (hdr->size > MSG_BUF_SIZE) { - nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); + FLCNQ_ERR(queue, "message too big, %d bytes", hdr->size); ret = -ENOSPC; goto close; } @@ -106,7 +105,7 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, ret = msg_queue_pop(priv, queue, (hdr + 1), read_size); if (ret) { - nvkm_error(subdev, "failed to read message: %d\n", ret); + FLCNQ_ERR(queue, "failed to read message data"); goto close; } } @@ -122,12 +121,11 @@ msgqueue_msg_handle(struct nvkm_msgqueue *priv, struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) { - const struct nvkm_subdev *subdev = priv->falcon->owner; struct nvkm_falcon_qmgr_seq *seq; seq = &msgq->qmgr->seq.id[hdr->seq_id]; if (seq->state != SEQ_STATE_USED && seq->state != SEQ_STATE_CANCELLED) { - nvkm_error(subdev, "msg for unknown sequence %d", seq->id); + FLCNQ_ERR(msgq, "message for unknown sequence %08x", seq->id); return -EINVAL; } -- cgit v1.2.3 From 2d063981d710391cdea4e8c6483d94b519b1cde2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: drop nvkm_msgqueue argument to functions Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 45 +++++++++++++----------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 7fdd81bf3858..1c7dab86af80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -23,18 +23,16 @@ #include "qmgr.h" static void -msg_queue_open(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +msg_queue_open(struct nvkm_msgqueue_queue *queue) { - struct nvkm_falcon *falcon = priv->falcon; mutex_lock(&queue->mutex); - queue->position = nvkm_falcon_rd32(falcon, queue->tail_reg); + queue->position = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); } static void -msg_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - bool commit) +msg_queue_close(struct nvkm_msgqueue_queue *queue, bool commit) { - struct nvkm_falcon *falcon = priv->falcon; + struct nvkm_falcon *falcon = queue->qmgr->falcon; if (commit) nvkm_falcon_wr32(falcon, queue->tail_reg, queue->position); @@ -43,19 +41,17 @@ msg_queue_close(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, } static bool -msg_queue_empty(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue) +msg_queue_empty(struct nvkm_msgqueue_queue *queue) { - struct nvkm_falcon *falcon = priv->falcon; - u32 head = nvkm_falcon_rd32(falcon, queue->head_reg); - u32 tail = nvkm_falcon_rd32(falcon, queue->tail_reg); + u32 head = nvkm_falcon_rd32(queue->qmgr->falcon, queue->head_reg); + u32 tail = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); return head == tail; } static int -msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - void *data, u32 size) +msg_queue_pop(struct nvkm_msgqueue_queue *queue, void *data, u32 size) { - struct nvkm_falcon *falcon = priv->falcon; + struct nvkm_falcon *falcon = queue->qmgr->falcon; u32 head, tail, available; head = nvkm_falcon_rd32(falcon, queue->head_reg); @@ -72,23 +68,22 @@ msg_queue_pop(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, return -EINVAL; } - nvkm_falcon_read_dmem(priv->falcon, tail, size, 0, data); + nvkm_falcon_read_dmem(falcon, tail, size, 0, data); queue->position += ALIGN(size, QUEUE_ALIGNMENT); return 0; } static int -msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, - struct nv_falcon_msg *hdr) +msg_queue_read(struct nvkm_msgqueue_queue *queue, struct nv_falcon_msg *hdr) { int ret = 0; - msg_queue_open(priv, queue); + msg_queue_open(queue); - if (msg_queue_empty(priv, queue)) + if (msg_queue_empty(queue)) goto close; - ret = msg_queue_pop(priv, queue, hdr, HDR_SIZE); + ret = msg_queue_pop(queue, hdr, HDR_SIZE); if (ret) { FLCNQ_ERR(queue, "failed to read message header"); goto close; @@ -103,7 +98,7 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, if (hdr->size > HDR_SIZE) { u32 read_size = hdr->size - HDR_SIZE; - ret = msg_queue_pop(priv, queue, (hdr + 1), read_size); + ret = msg_queue_pop(queue, (hdr + 1), read_size); if (ret) { FLCNQ_ERR(queue, "failed to read message data"); goto close; @@ -112,14 +107,12 @@ msg_queue_read(struct nvkm_msgqueue *priv, struct nvkm_msgqueue_queue *queue, ret = 1; close: - msg_queue_close(priv, queue, (ret >= 0)); + msg_queue_close(queue, (ret >= 0)); return ret; } static int -msgqueue_msg_handle(struct nvkm_msgqueue *priv, - struct nvkm_falcon_msgq *msgq, - struct nv_falcon_msg *hdr) +msgqueue_msg_handle(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) { struct nvkm_falcon_qmgr_seq *seq; @@ -197,8 +190,8 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, if (!ret) priv->init_msg_received = true; } else { - while (msg_queue_read(priv, queue, hdr) > 0) - msgqueue_msg_handle(priv, queue, hdr); + while (msg_queue_read(queue, hdr) > 0) + msgqueue_msg_handle(queue, hdr); } } -- cgit v1.2.3 From d114a1393fa01c4034d895072905578319a903f9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: move handling of init message to subdevs When the PMU/SEC2 LS FWs have booted, they'll send a message to the host with various information, including the configuration of message/command queues that are available. Move the handling for this to the relevant subdevs. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/pmu.h | 31 ++++++ drivers/gpu/drm/nouveau/include/nvfw/sec2.h | 22 ++++ drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + .../gpu/drm/nouveau/include/nvkm/core/msgqueue.h | 1 - drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 2 + drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 19 +++- drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 32 ++++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 57 ++++------ drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 11 -- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 27 ----- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 118 --------------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 66 ------------ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 72 +++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 2 + .../nvkm/subdev/secboot/ls_ucode_msgqueue.c | 2 - 19 files changed, 202 insertions(+), 265 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h index 6e86ce31f963..f808998e2ea1 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h @@ -1,8 +1,28 @@ #ifndef __NVFW_PMU_H__ #define __NVFW_PMU_H__ +#define NV_PMU_UNIT_INIT 0x07 #define NV_PMU_UNIT_ACR 0x0a +struct nv_pmu_init_msg { + struct nv_falcon_msg hdr; +#define NV_PMU_INIT_MSG_INIT 0x00 + u8 msg_type; + + u8 pad; + u16 os_debug_entry_point; + + struct { + u16 size; + u16 offset; + u8 index; + u8 pad; + } queue_info[5]; + + u16 sw_managed_area_offset; + u16 sw_managed_area_size; +}; + struct nv_pmu_acr_cmd { struct nv_falcon_cmd hdr; #define NV_PMU_ACR_CMD_INIT_WPR_REGION 0x00 @@ -16,6 +36,17 @@ struct nv_pmu_acr_msg { u8 msg_type; }; +struct nv_pmu_acr_init_wpr_region_cmd { + struct nv_pmu_acr_cmd cmd; + u32 region_id; + u32 wpr_offset; +}; + +struct nv_pmu_acr_init_wpr_region_msg { + struct nv_pmu_acr_msg msg; + u32 error_code; +}; + struct nv_pmu_acr_bootstrap_falcon_cmd { struct nv_pmu_acr_cmd cmd; #define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000 diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h index 2f7460fe1b76..80753cfa4cb3 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h @@ -1,8 +1,30 @@ #ifndef __NVFW_SEC2_H__ #define __NVFW_SEC2_H__ +#define NV_SEC2_UNIT_INIT 0x01 #define NV_SEC2_UNIT_ACR 0x08 +struct nv_sec2_init_msg { + struct nv_falcon_msg hdr; +#define NV_SEC2_INIT_MSG_INIT 0x00 + u8 msg_type; + + u8 num_queues; + u16 os_debug_entry_point; + + struct { + u32 offset; + u16 size; + u8 index; +#define NV_SEC2_INIT_MSG_QUEUE_ID_CMDQ 0x00 +#define NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ 0x01 + u8 id; + } queue_info[2]; + + u32 sw_managed_area_offset; + u16 sw_managed_area_size; +}; + struct nv_sec2_acr_cmd { struct nv_falcon_cmd hdr; #define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index 54e1f4d7568f..a37d2008406b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -72,4 +72,5 @@ int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name, void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **); void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *, u32 index, u32 offset, u32 size); +int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h index acb339f34bb5..19f2fdb3e754 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h @@ -32,7 +32,6 @@ int nvkm_msgqueue_new(u32, struct nvkm_falcon *, const struct nvkm_secboot *, struct nvkm_msgqueue **); void nvkm_msgqueue_del(struct nvkm_msgqueue **); void nvkm_msgqueue_recv(struct nvkm_msgqueue *); -int nvkm_msgqueue_reinit(struct nvkm_msgqueue *); /* useful if we run a NVIDIA-signed firmware */ void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index ca1b227a81f9..44da8d3ac86e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -14,7 +14,9 @@ struct nvkm_sec2 { struct nvkm_falcon_cmdq *cmdq; struct nvkm_falcon_msgq *msgq; struct nvkm_msgqueue *queue; + struct work_struct work; + bool initmsg_received; }; int gp102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 21607b40aee6..79351a74642e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -13,6 +13,7 @@ struct nvkm_pmu { struct nvkm_falcon_cmdq *hpq; struct nvkm_falcon_cmdq *lpq; struct nvkm_falcon_msgq *msgq; + bool initmsg_received; struct nvkm_msgqueue *queue; struct completion wpr_ready; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index d85aeb059c87..f6a453dc75ad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -30,6 +30,17 @@ nvkm_sec2_recv(struct work_struct *work) { struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work); + if (!sec2->initmsg_received) { + int ret = sec2->func->initmsg(sec2); + if (ret) { + nvkm_error(&sec2->engine.subdev, + "error parsing init message: %d\n", ret); + return; + } + + sec2->initmsg_received = true; + } + if (!sec2->queue) { nvkm_warn(&sec2->engine.subdev, "recv function called while no firmware set!\n"); @@ -50,8 +61,14 @@ static int nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); + flush_work(&sec2->work); - nvkm_falcon_cmdq_fini(sec2->cmdq); + + if (suspend) { + nvkm_falcon_cmdq_fini(sec2->cmdq); + sec2->initmsg_received = false; + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 26f738d1202e..26a468047747 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -69,6 +69,37 @@ gp102_sec2_acr_0 = { .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; +int +gp102_sec2_initmsg(struct nvkm_sec2 *sec2) +{ + struct nv_sec2_init_msg msg; + int ret, i; + + ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg)); + if (ret) + return ret; + + if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT || + msg.msg_type != NV_SEC2_INIT_MSG_INIT) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) { + if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) { + nvkm_falcon_msgq_init(sec2->msgq, + msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } else { + nvkm_falcon_cmdq_init(sec2->cmdq, + msg.queue_info[i].index, + msg.queue_info[i].offset, + msg.queue_info[i].size); + } + } + + return 0; +} + void gp102_sec2_intr(struct nvkm_sec2 *sec2) { @@ -161,6 +192,7 @@ gp102_sec2 = { .flcn = &gp102_sec2_flcn, .unit_acr = NV_SEC2_UNIT_ACR, .intr = gp102_sec2_intr, + .initmsg = gp102_sec2_initmsg, }; MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index 9c00e6634499..1992391832a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -7,6 +7,7 @@ struct nvkm_sec2_func { const struct nvkm_falcon_func *flcn; u8 unit_acr; void (*intr)(struct nvkm_sec2 *); + int (*initmsg)(struct nvkm_sec2 *); }; void gp102_sec2_intr(struct nvkm_sec2 *); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index 1c7dab86af80..b906534fc7fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -136,40 +136,27 @@ msgqueue_msg_handle(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) return 0; } -static int -msgqueue_handle_init_msg(struct nvkm_msgqueue *priv) +int +nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *msgq, + void *data, u32 size) { - struct nvkm_falcon *falcon = priv->falcon; - const struct nvkm_subdev *subdev = falcon->owner; - const u32 tail_reg = falcon->func->msgq.tail; - u8 msg_buffer[MSG_BUF_SIZE]; - struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer; - u32 tail; + struct nvkm_falcon *falcon = msgq->qmgr->falcon; + struct nv_falcon_msg *hdr = data; int ret; - /* - * Read the message - queues are not initialized yet so we cannot rely - * on msg_queue_read() - */ - tail = nvkm_falcon_rd32(falcon, tail_reg); - nvkm_falcon_read_dmem(falcon, tail, HDR_SIZE, 0, hdr); + msgq->head_reg = falcon->func->msgq.head; + msgq->tail_reg = falcon->func->msgq.tail; + msgq->offset = nvkm_falcon_rd32(falcon, falcon->func->msgq.tail); - if (hdr->size > MSG_BUF_SIZE) { - nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size); - return -ENOSPC; + msg_queue_open(msgq); + ret = msg_queue_pop(msgq, data, size); + if (ret == 0 && hdr->size != size) { + FLCN_ERR(falcon, "unexpected init message size %d vs %d", + hdr->size, size); + ret = -EINVAL; } - - nvkm_falcon_read_dmem(falcon, tail + HDR_SIZE, hdr->size - HDR_SIZE, 0, - (hdr + 1)); - - tail += ALIGN(hdr->size, QUEUE_ALIGNMENT); - nvkm_falcon_wr32(falcon, tail_reg, tail); - - ret = priv->func->init_func->init_callback(priv, hdr); - if (ret) - return ret; - - return 0; + msg_queue_close(msgq, ret == 0); + return ret; } void @@ -182,17 +169,9 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, */ u8 msg_buffer[MSG_BUF_SIZE]; struct nv_falcon_msg *hdr = (void *)msg_buffer; - int ret; - /* the first message we receive must be the init message */ - if ((!priv->init_msg_received)) { - ret = msgqueue_handle_init_msg(priv); - if (!ret) - priv->init_msg_received = true; - } else { - while (msg_queue_read(queue, hdr) > 0) - msgqueue_msg_handle(queue, hdr); - } + while (msg_queue_read(queue, hdr) > 0) + msgqueue_msg_handle(queue, hdr); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index 9867a32da42a..46e88937c453 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -90,17 +90,6 @@ nvkm_msgqueue_recv(struct nvkm_msgqueue *queue) queue->func->recv(queue); } -int -nvkm_msgqueue_reinit(struct nvkm_msgqueue *queue) -{ - /* firmware not set yet... */ - if (!queue) - return 0; - - queue->init_msg_received = false; - return 0; -} - void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func, struct nvkm_falcon *falcon, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index bf714f391d42..1c4780a7856a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -52,31 +52,6 @@ * */ -/** - * struct nvkm_msgqueue_hdr - header for all commands/messages - * @unit_id: id of firmware using receiving the command/sending the message - * @size: total size of command/message - * @ctrl_flags: type of command/message - * @seq_id: used to match a message from its corresponding command - */ -struct nvkm_msgqueue_hdr { - u8 unit_id; - u8 size; - u8 ctrl_flags; - u8 seq_id; -}; - -/** - * struct nvkm_msgqueue_msg - base message. - * - * This is just a header and a message (or command) type. Useful when - * building command-specific structures. - */ -struct nvkm_msgqueue_msg { - struct nvkm_msgqueue_hdr hdr; - u8 msg_type; -}; - struct nvkm_msgqueue; /** @@ -87,7 +62,6 @@ struct nvkm_msgqueue; */ struct nvkm_msgqueue_init_func { void (*gen_cmdline)(struct nvkm_msgqueue *, void *); - int (*init_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *); }; struct nvkm_msgqueue_func { @@ -136,7 +110,6 @@ struct nvkm_msgqueue { struct nvkm_falcon *falcon; const struct nvkm_msgqueue_func *func; u32 fw_version; - bool init_msg_received; }; void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index 7e450a91c62e..f624f9cd9098 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -25,11 +25,6 @@ #include #include -/* Queues identifiers */ -enum { - MSGQUEUE_0137C63D_NUM_QUEUES = 5, -}; - struct msgqueue_0137c63d { struct nvkm_msgqueue base; }; @@ -52,12 +47,6 @@ msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue) } /* Init unit */ -#define MSGQUEUE_0137C63D_UNIT_INIT 0x07 - -enum { - INIT_MSG_INIT = 0x0, -}; - static void init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) { @@ -84,118 +73,11 @@ init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) args->secure_mode = 1; } -/* forward declaration */ -static int acr_init_wpr(struct nvkm_msgqueue *queue); - -static int -init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) -{ - struct msgqueue_0137c63d *priv = msgqueue_0137c63d(_queue); - struct { - struct nvkm_msgqueue_msg base; - - u8 pad; - u16 os_debug_entry_point; - - struct { - u16 size; - u16 offset; - u8 index; - u8 pad; - } queue_info[MSGQUEUE_0137C63D_NUM_QUEUES]; - - u16 sw_managed_area_offset; - u16 sw_managed_area_size; - } *init = (void *)hdr; - const struct nvkm_subdev *subdev = _queue->falcon->owner; - struct nvkm_pmu *pmu = subdev->device->pmu; - - if (init->base.hdr.unit_id != MSGQUEUE_0137C63D_UNIT_INIT) { - nvkm_error(subdev, "expected message from init unit\n"); - return -EINVAL; - } - - if (init->base.msg_type != INIT_MSG_INIT) { - nvkm_error(subdev, "expected PMU init msg\n"); - return -EINVAL; - } - - nvkm_falcon_cmdq_init(pmu->hpq, init->queue_info[0].index, - init->queue_info[0].offset, - init->queue_info[0].size); - nvkm_falcon_cmdq_init(pmu->lpq, init->queue_info[1].index, - init->queue_info[1].offset, - init->queue_info[1].size); - nvkm_falcon_msgq_init(pmu->msgq, init->queue_info[4].index, - init->queue_info[4].offset, - init->queue_info[4].size); - - /* Complete initialization by initializing WPR region */ - return acr_init_wpr(&priv->base); -} - static const struct nvkm_msgqueue_init_func msgqueue_0137c63d_init_func = { .gen_cmdline = init_gen_cmdline, - .init_callback = init_callback, }; - - -/* ACR unit */ -#define MSGQUEUE_0137C63D_UNIT_ACR 0x0a - -enum { - ACR_CMD_INIT_WPR_REGION = 0x00, -}; - -static int -acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) -{ - struct nvkm_pmu *pmu = priv; - struct nvkm_subdev *subdev = &pmu->subdev; - struct { - struct nv_falcon_msg base; - u8 msg_type; - u32 error_code; - } *msg = (void *)hdr; - - if (msg->error_code) { - nvkm_error(subdev, "ACR WPR init failure: %d\n", - msg->error_code); - return -EINVAL; - } - - nvkm_debug(subdev, "ACR WPR init complete\n"); - complete_all(&pmu->wpr_ready); - return 0; -} - -static int -acr_init_wpr(struct nvkm_msgqueue *queue) -{ - struct nvkm_pmu *pmu = queue->falcon->owner->device->pmu; - /* - * region_id: region ID in WPR region - * wpr_offset: offset in WPR region - */ - struct { - struct nv_falcon_cmd hdr; - u8 cmd_type; - u32 region_id; - u32 wpr_offset; - } cmd; - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR; - cmd.hdr.size = sizeof(cmd); - cmd.cmd_type = ACR_CMD_INIT_WPR_REGION; - cmd.region_id = 0x01; - cmd.wpr_offset = 0x00; - return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, acr_init_wpr_callback, - pmu, 0); -} - static void msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) { diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 51ae4a10b213..0dc243b0b774 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -31,12 +31,6 @@ * message queue, and uses a different command line and init message. */ -enum { - MSGQUEUE_0148CDEC_COMMAND_QUEUE = 0, - MSGQUEUE_0148CDEC_MESSAGE_QUEUE = 1, - MSGQUEUE_0148CDEC_NUM_QUEUES, -}; - struct msgqueue_0148cdec { struct nvkm_msgqueue base; }; @@ -50,13 +44,6 @@ msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue) } -/* Init unit */ -#define MSGQUEUE_0148CDEC_UNIT_INIT 0x01 - -enum { - INIT_MSG_INIT = 0x0, -}; - static void init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) { @@ -71,62 +58,9 @@ init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) args->secure_mode = false; } -static int -init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr) -{ - struct { - struct nvkm_msgqueue_msg base; - - u8 num_queues; - u16 os_debug_entry_point; - - struct { - u32 offset; - u16 size; - u8 index; - u8 id; - } queue_info[MSGQUEUE_0148CDEC_NUM_QUEUES]; - - u16 sw_managed_area_offset; - u16 sw_managed_area_size; - } *init = (void *)hdr; - const struct nvkm_subdev *subdev = _queue->falcon->owner; - struct nvkm_sec2 *sec2 = subdev->device->sec2; - int i; - - if (init->base.hdr.unit_id != MSGQUEUE_0148CDEC_UNIT_INIT) { - nvkm_error(subdev, "expected message from init unit\n"); - return -EINVAL; - } - - if (init->base.msg_type != INIT_MSG_INIT) { - nvkm_error(subdev, "expected SEC init msg\n"); - return -EINVAL; - } - - for (i = 0; i < MSGQUEUE_0148CDEC_NUM_QUEUES; i++) { - u8 id = init->queue_info[i].id; - - if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) { - nvkm_falcon_msgq_init(sec2->msgq, - init->queue_info[i].index, - init->queue_info[i].offset, - init->queue_info[i].size); - } else { - nvkm_falcon_cmdq_init(sec2->cmdq, - init->queue_info[i].index, - init->queue_info[i].offset, - init->queue_info[i].size); - } - } - - return 0; -} - static const struct nvkm_msgqueue_init_func msgqueue_0148cdec_init_func = { .gen_cmdline = init_gen_cmdline, - .init_callback = init_callback, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index bc0eb84c2c90..706bbb782844 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -91,6 +91,7 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) nvkm_falcon_cmdq_fini(pmu->lpq); nvkm_falcon_cmdq_fini(pmu->hpq); + pmu->initmsg_received = false; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index e803cc461227..0e550612acc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -61,9 +61,80 @@ gm20b_pmu_acr = { .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, }; +static int +gm20b_pmu_acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr) +{ + struct nv_pmu_acr_init_wpr_region_msg *msg = + container_of(hdr, typeof(*msg), msg.hdr); + struct nvkm_pmu *pmu = priv; + struct nvkm_subdev *subdev = &pmu->subdev; + + if (msg->error_code) { + nvkm_error(subdev, "ACR WPR init failure: %d\n", + msg->error_code); + return -EINVAL; + } + + nvkm_debug(subdev, "ACR WPR init complete\n"); + complete_all(&pmu->wpr_ready); + return 0; +} + +static int +gm20b_pmu_acr_init_wpr(struct nvkm_pmu *pmu) +{ + struct nv_pmu_acr_init_wpr_region_cmd cmd = { + .cmd.hdr.unit_id = NV_PMU_UNIT_ACR, + .cmd.hdr.size = sizeof(cmd), + .cmd.cmd_type = NV_PMU_ACR_CMD_INIT_WPR_REGION, + .region_id = 1, + .wpr_offset = 0, + }; + + return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr, + gm20b_pmu_acr_init_wpr_callback, pmu, 0); +} + +int +gm20b_pmu_initmsg(struct nvkm_pmu *pmu) +{ + struct nv_pmu_init_msg msg; + int ret; + + ret = nvkm_falcon_msgq_recv_initmsg(pmu->msgq, &msg, sizeof(msg)); + if (ret) + return ret; + + if (msg.hdr.unit_id != NV_PMU_UNIT_INIT || + msg.msg_type != NV_PMU_INIT_MSG_INIT) + return -EINVAL; + + nvkm_falcon_cmdq_init(pmu->hpq, msg.queue_info[0].index, + msg.queue_info[0].offset, + msg.queue_info[0].size); + nvkm_falcon_cmdq_init(pmu->lpq, msg.queue_info[1].index, + msg.queue_info[1].offset, + msg.queue_info[1].size); + nvkm_falcon_msgq_init(pmu->msgq, msg.queue_info[4].index, + msg.queue_info[4].offset, + msg.queue_info[4].size); + return gm20b_pmu_acr_init_wpr(pmu); +} + void gm20b_pmu_recv(struct nvkm_pmu *pmu) { + if (!pmu->initmsg_received) { + int ret = pmu->func->initmsg(pmu); + if (ret) { + nvkm_error(&pmu->subdev, + "error parsing init message: %d\n", ret); + return; + } + + pmu->initmsg_received = true; + } + if (!pmu->queue) { nvkm_warn(&pmu->subdev, "recv function called while no firmware set!\n"); @@ -79,6 +150,7 @@ gm20b_pmu = { .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, + .initmsg = gm20b_pmu_initmsg, }; #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index b2baf9b636a3..0e0ebd6857da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -68,6 +68,7 @@ gp10b_pmu = { .enabled = gf100_pmu_enabled, .intr = gt215_pmu_intr, .recv = gm20b_pmu_recv, + .initmsg = gm20b_pmu_initmsg, }; #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 0e7965028dcf..21ca224fc186 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -27,6 +27,7 @@ struct nvkm_pmu_func { int (*send)(struct nvkm_pmu *, u32 reply[2], u32 process, u32 message, u32 data0, u32 data1); void (*recv)(struct nvkm_pmu *); + int (*initmsg)(struct nvkm_pmu *); void (*pgob)(struct nvkm_pmu *, bool); }; @@ -44,6 +45,7 @@ void gk110_pmu_pgob(struct nvkm_pmu *, bool); int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id); void gm20b_pmu_recv(struct nvkm_pmu *); +int gm20b_pmu_initmsg(struct nvkm_pmu *); struct nvkm_pmu_fwif { int version; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c index 39dda09fc344..7994ed1cdf97 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c @@ -85,8 +85,6 @@ acr_ls_msgqueue_post_run(struct nvkm_msgqueue *queue, memset(buf, 0, sizeof(buf)); nvkm_msgqueue_write_cmdline(queue, buf); nvkm_falcon_load_dmem(falcon, buf, addr_args, sizeof(buf), 0); - /* rearm the queue so it will wait for the init message */ - nvkm_msgqueue_reinit(queue); /* Enable interrupts */ nvkm_falcon_wr32(falcon, 0x10, 0xff); -- cgit v1.2.3 From e1cc579898aed48fe6a6ac1bf5a7491784c5d690 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: pass explicit message queue pointer to recv() Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 8 +------- drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 3 +-- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 13 ------------- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 3 --- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 8 -------- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 8 -------- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 8 +------- 9 files changed, 4 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h index a37d2008406b..daa8e4bfb6bf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h @@ -73,4 +73,5 @@ void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **); void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *, u32 index, u32 offset, u32 size); int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size); +void nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h index 19f2fdb3e754..7147c2ddb88d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h @@ -31,7 +31,6 @@ struct nvkm_msgqueue; int nvkm_msgqueue_new(u32, struct nvkm_falcon *, const struct nvkm_secboot *, struct nvkm_msgqueue **); void nvkm_msgqueue_del(struct nvkm_msgqueue **); -void nvkm_msgqueue_recv(struct nvkm_msgqueue *); /* useful if we run a NVIDIA-signed firmware */ void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index f6a453dc75ad..327c92509247 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -41,13 +41,7 @@ nvkm_sec2_recv(struct work_struct *work) sec2->initmsg_received = true; } - if (!sec2->queue) { - nvkm_warn(&sec2->engine.subdev, - "recv function called while no firmware set!\n"); - return; - } - - nvkm_msgqueue_recv(sec2->queue); + nvkm_falcon_msgq_recv(sec2->msgq); } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index b906534fc7fa..f3f2e333a10b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -160,8 +160,7 @@ nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *msgq, } void -nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv, - struct nvkm_msgqueue_queue *queue) +nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *queue) { /* * We are invoked from a worker thread, so normally we have plenty of diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index 46e88937c453..0ac0f7888a52 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -77,19 +77,6 @@ nvkm_msgqueue_del(struct nvkm_msgqueue **queue) } } -void -nvkm_msgqueue_recv(struct nvkm_msgqueue *queue) -{ - if (!queue->func || !queue->func->recv) { - const struct nvkm_subdev *subdev = queue->falcon->owner; - - nvkm_warn(subdev, "missing msgqueue recv function\n"); - return; - } - - queue->func->recv(queue); -} - void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func, struct nvkm_falcon *falcon, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 1c4780a7856a..750e4883cfcd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -67,7 +67,6 @@ struct nvkm_msgqueue_init_func { struct nvkm_msgqueue_func { const struct nvkm_msgqueue_init_func *init_func; void (*dtor)(struct nvkm_msgqueue *); - void (*recv)(struct nvkm_msgqueue *queue); }; /** @@ -114,8 +113,6 @@ struct nvkm_msgqueue { void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, struct nvkm_msgqueue *); -void nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *, - struct nvkm_msgqueue_queue *); int msgqueue_0137c63d_new(struct nvkm_falcon *, const struct nvkm_secboot *, struct nvkm_msgqueue **); diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c index f624f9cd9098..7c42def03675 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c @@ -40,12 +40,6 @@ struct msgqueue_0137bca5 { container_of(container_of(q, struct msgqueue_0137c63d, base), \ struct msgqueue_0137bca5, base); -static void -msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue) -{ - nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->pmu->msgq); -} - /* Init unit */ static void init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) @@ -87,7 +81,6 @@ msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) static const struct nvkm_msgqueue_func msgqueue_0137c63d_func = { .init_func = &msgqueue_0137c63d_init_func, - .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; @@ -111,7 +104,6 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, static const struct nvkm_msgqueue_func msgqueue_0137bca5_func = { .init_func = &msgqueue_0137c63d_init_func, - .recv = msgqueue_0137c63d_process_msgs, .dtor = msgqueue_0137c63d_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c index 0dc243b0b774..351419b4ab44 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c @@ -37,13 +37,6 @@ struct msgqueue_0148cdec { #define msgqueue_0148cdec(q) \ container_of(q, struct msgqueue_0148cdec, base) -static void -msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue) -{ - nvkm_msgqueue_process_msgs(queue, queue->falcon->owner->device->sec2->msgq); -} - - static void init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) { @@ -73,7 +66,6 @@ msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue) const struct nvkm_msgqueue_func msgqueue_0148cdec_func = { .init_func = &msgqueue_0148cdec_init_func, - .recv = msgqueue_0148cdec_process_msgs, .dtor = msgqueue_0148cdec_dtor, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 0e550612acc6..52886ba7ff54 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -135,13 +135,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu) pmu->initmsg_received = true; } - if (!pmu->queue) { - nvkm_warn(&pmu->subdev, - "recv function called while no firmware set!\n"); - return; - } - - nvkm_msgqueue_recv(pmu->queue); + nvkm_falcon_msgq_recv(pmu->msgq); } static const struct nvkm_pmu_func -- cgit v1.2.3 From 91a4e83a2d3e99af33a666508e86b96f4210fae6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/flcn/msgq: rename msgq-related nvkm_msgqueue_queue to nvkm_falcon_msgq Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h | 3 - drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c | 90 +++++++++++----------- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 29 ------- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 26 +++++++ 4 files changed, 71 insertions(+), 77 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index b632a43c16ef..1218f28c14ba 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -3,9 +3,6 @@ #define __NVKM_SUBDEV_H__ #include -#define nvkm_falcon_cmdq nvkm_msgqueue_queue -#define nvkm_falcon_msgq nvkm_msgqueue_queue - struct nvkm_subdev { const struct nvkm_subdev_func *func; struct nvkm_device *device; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c index f3f2e333a10b..cbfe09a561a1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c @@ -23,74 +23,74 @@ #include "qmgr.h" static void -msg_queue_open(struct nvkm_msgqueue_queue *queue) +nvkm_falcon_msgq_open(struct nvkm_falcon_msgq *msgq) { - mutex_lock(&queue->mutex); - queue->position = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); + mutex_lock(&msgq->mutex); + msgq->position = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->tail_reg); } static void -msg_queue_close(struct nvkm_msgqueue_queue *queue, bool commit) +nvkm_falcon_msgq_close(struct nvkm_falcon_msgq *msgq, bool commit) { - struct nvkm_falcon *falcon = queue->qmgr->falcon; + struct nvkm_falcon *falcon = msgq->qmgr->falcon; if (commit) - nvkm_falcon_wr32(falcon, queue->tail_reg, queue->position); + nvkm_falcon_wr32(falcon, msgq->tail_reg, msgq->position); - mutex_unlock(&queue->mutex); + mutex_unlock(&msgq->mutex); } static bool -msg_queue_empty(struct nvkm_msgqueue_queue *queue) +nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *msgq) { - u32 head = nvkm_falcon_rd32(queue->qmgr->falcon, queue->head_reg); - u32 tail = nvkm_falcon_rd32(queue->qmgr->falcon, queue->tail_reg); + u32 head = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->head_reg); + u32 tail = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->tail_reg); return head == tail; } static int -msg_queue_pop(struct nvkm_msgqueue_queue *queue, void *data, u32 size) +nvkm_falcon_msgq_pop(struct nvkm_falcon_msgq *msgq, void *data, u32 size) { - struct nvkm_falcon *falcon = queue->qmgr->falcon; + struct nvkm_falcon *falcon = msgq->qmgr->falcon; u32 head, tail, available; - head = nvkm_falcon_rd32(falcon, queue->head_reg); + head = nvkm_falcon_rd32(falcon, msgq->head_reg); /* has the buffer looped? */ - if (head < queue->position) - queue->position = queue->offset; + if (head < msgq->position) + msgq->position = msgq->offset; - tail = queue->position; + tail = msgq->position; available = head - tail; if (size > available) { - FLCNQ_ERR(queue, "requested %d bytes, but only %d available", + FLCNQ_ERR(msgq, "requested %d bytes, but only %d available", size, available); return -EINVAL; } nvkm_falcon_read_dmem(falcon, tail, size, 0, data); - queue->position += ALIGN(size, QUEUE_ALIGNMENT); + msgq->position += ALIGN(size, QUEUE_ALIGNMENT); return 0; } static int -msg_queue_read(struct nvkm_msgqueue_queue *queue, struct nv_falcon_msg *hdr) +nvkm_falcon_msgq_read(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) { int ret = 0; - msg_queue_open(queue); + nvkm_falcon_msgq_open(msgq); - if (msg_queue_empty(queue)) + if (nvkm_falcon_msgq_empty(msgq)) goto close; - ret = msg_queue_pop(queue, hdr, HDR_SIZE); + ret = nvkm_falcon_msgq_pop(msgq, hdr, HDR_SIZE); if (ret) { - FLCNQ_ERR(queue, "failed to read message header"); + FLCNQ_ERR(msgq, "failed to read message header"); goto close; } if (hdr->size > MSG_BUF_SIZE) { - FLCNQ_ERR(queue, "message too big, %d bytes", hdr->size); + FLCNQ_ERR(msgq, "message too big, %d bytes", hdr->size); ret = -ENOSPC; goto close; } @@ -98,21 +98,21 @@ msg_queue_read(struct nvkm_msgqueue_queue *queue, struct nv_falcon_msg *hdr) if (hdr->size > HDR_SIZE) { u32 read_size = hdr->size - HDR_SIZE; - ret = msg_queue_pop(queue, (hdr + 1), read_size); + ret = nvkm_falcon_msgq_pop(msgq, (hdr + 1), read_size); if (ret) { - FLCNQ_ERR(queue, "failed to read message data"); + FLCNQ_ERR(msgq, "failed to read message data"); goto close; } } ret = 1; close: - msg_queue_close(queue, (ret >= 0)); + nvkm_falcon_msgq_close(msgq, (ret >= 0)); return ret; } static int -msgqueue_msg_handle(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) +nvkm_falcon_msgq_exec(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) { struct nvkm_falcon_qmgr_seq *seq; @@ -136,6 +136,20 @@ msgqueue_msg_handle(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr) return 0; } +void +nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *msgq) +{ + /* + * We are invoked from a worker thread, so normally we have plenty of + * stack space to work with. + */ + u8 msg_buffer[MSG_BUF_SIZE]; + struct nv_falcon_msg *hdr = (void *)msg_buffer; + + while (nvkm_falcon_msgq_read(msgq, hdr) > 0) + nvkm_falcon_msgq_exec(msgq, hdr); +} + int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *msgq, void *data, u32 size) @@ -148,31 +162,17 @@ nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *msgq, msgq->tail_reg = falcon->func->msgq.tail; msgq->offset = nvkm_falcon_rd32(falcon, falcon->func->msgq.tail); - msg_queue_open(msgq); - ret = msg_queue_pop(msgq, data, size); + nvkm_falcon_msgq_open(msgq); + ret = nvkm_falcon_msgq_pop(msgq, data, size); if (ret == 0 && hdr->size != size) { FLCN_ERR(falcon, "unexpected init message size %d vs %d", hdr->size, size); ret = -EINVAL; } - msg_queue_close(msgq, ret == 0); + nvkm_falcon_msgq_close(msgq, ret == 0); return ret; } -void -nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *queue) -{ - /* - * We are invoked from a worker thread, so normally we have plenty of - * stack space to work with. - */ - u8 msg_buffer[MSG_BUF_SIZE]; - struct nv_falcon_msg *hdr = (void *)msg_buffer; - - while (msg_queue_read(queue, hdr) > 0) - msgqueue_msg_handle(queue, hdr); -} - void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *msgq, u32 index, u32 offset, u32 size) diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h index 750e4883cfcd..ec3baefa9004 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h @@ -69,35 +69,6 @@ struct nvkm_msgqueue_func { void (*dtor)(struct nvkm_msgqueue *); }; -/** - * struct nvkm_msgqueue_queue - information about a command or message queue - * - * The number of queues is firmware-dependent. All queues must have their - * information filled by the init message handler. - * - * @mutex_lock: to be acquired when the queue is being used - * @index: physical queue index - * @offset: DMEM offset where this queue begins - * @size: size allocated to this queue in DMEM (in bytes) - * @position: current write position - * @head_reg: address of the HEAD register for this queue - * @tail_reg: address of the TAIL register for this queue - */ -struct nvkm_msgqueue_queue { - struct nvkm_falcon_qmgr *qmgr; - const char *name; - struct mutex mutex; - u32 index; - u32 offset; - u32 size; - u32 position; - - u32 head_reg; - u32 tail_reg; - - struct completion ready; -}; - /** * struct nvkm_msgqueue - manage a command/message based FW on a falcon * diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index 935858c6a621..dca12efc25e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -57,6 +57,32 @@ nvkm_falcon_qmgr_seq_acquire(struct nvkm_falcon_qmgr *); void nvkm_falcon_qmgr_seq_release(struct nvkm_falcon_qmgr *, struct nvkm_falcon_qmgr_seq *); +struct nvkm_falcon_cmdq { + struct nvkm_falcon_qmgr *qmgr; + const char *name; + struct mutex mutex; + struct completion ready; + + u32 head_reg; + u32 tail_reg; + u32 offset; + u32 size; + + u32 position; +}; + +struct nvkm_falcon_msgq { + struct nvkm_falcon_qmgr *qmgr; + const char *name; + struct mutex mutex; + + u32 head_reg; + u32 tail_reg; + u32 offset; + + u32 position; +}; + #define FLCNQ_PRINTK(t,q,f,a...) \ FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a) #define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK(debug, (q), f, ##a) -- cgit v1.2.3 From 7a4dde711b38dd10df71bd71151cb1f59dfbfdac Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/secboot: move code to boot LS falcons to subdevs Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/pmu.h | 20 ++++ drivers/gpu/drm/nouveau/include/nvfw/sec2.h | 8 ++ .../gpu/drm/nouveau/include/nvkm/core/msgqueue.h | 10 -- drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h | 1 - drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 1 + drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 12 ++ drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild | 3 - drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 87 -------------- drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h | 95 --------------- .../drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c | 131 --------------------- .../drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c | 87 -------------- drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 21 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | 2 - drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 11 ++ .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 19 +-- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h | 2 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c | 2 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c | 1 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c | 1 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c | 1 - .../nvkm/subdev/secboot/ls_ucode_msgqueue.c | 75 +----------- 24 files changed, 77 insertions(+), 517 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h index f808998e2ea1..452ed7d03827 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h @@ -1,6 +1,26 @@ #ifndef __NVFW_PMU_H__ #define __NVFW_PMU_H__ +struct nv_pmu_args { + u32 reserved; + u32 freq_hz; + u32 trace_size; + u32 trace_dma_base; + u16 trace_dma_base1; + u8 trace_dma_offset; + u32 trace_dma_idx; + bool secure_mode; + bool raise_priv_sec; + struct { + u32 dma_base; + u16 dma_base1; + u8 dma_offset; + u16 fb_size; + u8 dma_idx; + } gc6_ctx; + u8 pad; +}; + #define NV_PMU_UNIT_INIT 0x07 #define NV_PMU_UNIT_ACR 0x0a diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h index 80753cfa4cb3..03496558b775 100644 --- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h @@ -1,6 +1,14 @@ #ifndef __NVFW_SEC2_H__ #define __NVFW_SEC2_H__ +struct nv_sec2_args { + u32 freq_hz; + u32 falc_trace_size; + u32 falc_trace_dma_base; + u32 falc_trace_dma_idx; + bool secure_mode; +}; + #define NV_SEC2_UNIT_INIT 0x01 #define NV_SEC2_UNIT_ACR 0x08 diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h index 7147c2ddb88d..bd0476bf6253 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h @@ -22,17 +22,7 @@ #ifndef __NVKM_CORE_MSGQUEUE_H #define __NVKM_CORE_MSGQUEUE_H -#include -struct nvkm_msgqueue; /* Hopefully we will never have firmware arguments larger than that... */ #define NVKM_MSGQUEUE_CMDLINE_SIZE 0x100 - -int nvkm_msgqueue_new(u32, struct nvkm_falcon *, const struct nvkm_secboot *, - struct nvkm_msgqueue **); -void nvkm_msgqueue_del(struct nvkm_msgqueue **); - -/* useful if we run a NVIDIA-signed firmware */ -void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *); - #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h index 44da8d3ac86e..34dc765648d5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h @@ -13,7 +13,6 @@ struct nvkm_sec2 { struct nvkm_falcon_qmgr *qmgr; struct nvkm_falcon_cmdq *cmdq; struct nvkm_falcon_msgq *msgq; - struct nvkm_msgqueue *queue; struct work_struct work; bool initmsg_received; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 7e51bd4befce..4b30aeb9d22a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -74,6 +74,7 @@ struct nvkm_acr_lsfw { }; struct nvkm_acr_lsf_func { + int (*boot)(struct nvkm_falcon *); int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id); int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask); }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h index 79351a74642e..da553089d2d8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h @@ -14,7 +14,6 @@ struct nvkm_pmu { struct nvkm_falcon_cmdq *lpq; struct nvkm_falcon_msgq *msgq; bool initmsg_received; - struct nvkm_msgqueue *queue; struct completion wpr_ready; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c index 327c92509247..41318aa0d481 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c @@ -22,7 +22,6 @@ #include "priv.h" #include -#include #include static void @@ -70,7 +69,6 @@ static void * nvkm_sec2_dtor(struct nvkm_engine *engine) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); - nvkm_msgqueue_del(&sec2->queue); nvkm_falcon_msgq_del(&sec2->msgq); nvkm_falcon_cmdq_del(&sec2->cmdq); nvkm_falcon_qmgr_del(&sec2->qmgr); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 26a468047747..4533931e4cb5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -64,8 +64,19 @@ gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, msecs_to_jiffies(1000)); } +static int +gp102_sec2_acr_boot(struct nvkm_falcon *falcon) +{ + struct nv_sec2_args args = {}; + nvkm_falcon_load_dmem(falcon, &args, + falcon->func->emem_addr, sizeof(args), 0); + nvkm_falcon_start(falcon); + return 0; +} + static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { + .boot = gp102_sec2_acr_boot, .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; @@ -210,6 +221,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); const struct nvkm_acr_lsf_func gp102_sec2_acr_1 = { + .boot = gp102_sec2_acr_boot, .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild index 004d1cd4e37e..d79d783904ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild @@ -4,6 +4,3 @@ nvkm-y += nvkm/falcon/cmdq.o nvkm-y += nvkm/falcon/msgq.o nvkm-y += nvkm/falcon/qmgr.o nvkm-y += nvkm/falcon/v1.o -nvkm-y += nvkm/falcon/msgqueue.o -nvkm-y += nvkm/falcon/msgqueue_0137c63d.o -nvkm-y += nvkm/falcon/msgqueue_0148cdec.o diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c deleted file mode 100644 index 0ac0f7888a52..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. - * - */ - -#include "msgqueue.h" -#include - -#include - -void -nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf) -{ - if (!queue || !queue->func || !queue->func->init_func) - return; - - queue->func->init_func->gen_cmdline(queue, buf); -} - -int -nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon, - const struct nvkm_secboot *sb, struct nvkm_msgqueue **queue) -{ - const struct nvkm_subdev *subdev = falcon->owner; - int ret = -EINVAL; - - switch (version) { - case 0x0137c63d: - ret = msgqueue_0137c63d_new(falcon, sb, queue); - break; - case 0x0137bca5: - ret = msgqueue_0137bca5_new(falcon, sb, queue); - break; - case 0x0148cdec: - case 0x015ccf3e: - case 0x0167d263: - ret = msgqueue_0148cdec_new(falcon, sb, queue); - break; - default: - nvkm_error(subdev, "unhandled firmware version 0x%08x\n", - version); - break; - } - - if (ret == 0) { - nvkm_debug(subdev, "firmware version: 0x%08x\n", version); - (*queue)->fw_version = version; - } - - return ret; -} - -void -nvkm_msgqueue_del(struct nvkm_msgqueue **queue) -{ - if (*queue) { - (*queue)->func->dtor(*queue); - *queue = NULL; - } -} - -void -nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func, - struct nvkm_falcon *falcon, - struct nvkm_msgqueue *queue) -{ - queue->func = func; - queue->falcon = falcon; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h deleted file mode 100644 index ec3baefa9004..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 __NVKM_CORE_FALCON_MSGQUEUE_H -#define __NVKM_CORE_FALCON_MSGQUEUE_H -#include -#include - -/* - * The struct nvkm_msgqueue (named so for lack of better candidate) manages - * a firmware (typically, NVIDIA signed firmware) running under a given falcon. - * - * Such firmwares expect to receive commands (through one or several command - * queues) and will reply to such command by sending messages (using one - * message queue). - * - * Each firmware can support one or several units - ACR for managing secure - * falcons, PMU for power management, etc. A unit can be seen as a class to - * which command can be sent. - * - * One usage example would be to send a command to the SEC falcon to ask it to - * reset a secure falcon. The SEC falcon will receive the command, process it, - * and send a message to signal success or failure. Only when the corresponding - * message is received can the requester assume the request has been processed. - * - * Since we expect many variations between the firmwares NVIDIA will release - * across GPU generations, this library is built in a very modular way. Message - * formats and queues details (such as number of usage) are left to - * specializations of struct nvkm_msgqueue, while the functions in msgqueue.c - * take care of posting commands and processing messages in a fashion that is - * universal. - * - */ - -struct nvkm_msgqueue; - -/** - * struct nvkm_msgqueue_init_func - msgqueue functions related to initialization - * - * @gen_cmdline: build the commandline into a pre-allocated buffer - * @init_callback: called to process the init message - */ -struct nvkm_msgqueue_init_func { - void (*gen_cmdline)(struct nvkm_msgqueue *, void *); -}; - -struct nvkm_msgqueue_func { - const struct nvkm_msgqueue_init_func *init_func; - void (*dtor)(struct nvkm_msgqueue *); -}; - -/** - * struct nvkm_msgqueue - manage a command/message based FW on a falcon - * - * @falcon: falcon to be managed - * @func: implementation of the firmware to use - * @init_msg_received: whether the init message has already been received - */ -struct nvkm_msgqueue { - struct nvkm_falcon *falcon; - const struct nvkm_msgqueue_func *func; - u32 fw_version; -}; - -void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *, - struct nvkm_msgqueue *); - -int msgqueue_0137c63d_new(struct nvkm_falcon *, const struct nvkm_secboot *, - struct nvkm_msgqueue **); -int msgqueue_0137bca5_new(struct nvkm_falcon *, const struct nvkm_secboot *, - struct nvkm_msgqueue **); -int msgqueue_0148cdec_new(struct nvkm_falcon *, const struct nvkm_secboot *, - struct nvkm_msgqueue **); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c deleted file mode 100644 index 7c42def03675..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. - * - */ -#include "msgqueue.h" -#include -#include -#include - -struct msgqueue_0137c63d { - struct nvkm_msgqueue base; -}; -#define msgqueue_0137c63d(q) \ - container_of(q, struct msgqueue_0137c63d, base) - -struct msgqueue_0137bca5 { - struct msgqueue_0137c63d base; - - u64 wpr_addr; -}; -#define msgqueue_0137bca5(q) \ - container_of(container_of(q, struct msgqueue_0137c63d, base), \ - struct msgqueue_0137bca5, base); - -/* Init unit */ -static void -init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) -{ - struct { - u32 reserved; - u32 freq_hz; - u32 trace_size; - u32 trace_dma_base; - u16 trace_dma_base1; - u8 trace_dma_offset; - u32 trace_dma_idx; - bool secure_mode; - bool raise_priv_sec; - struct { - u32 dma_base; - u16 dma_base1; - u8 dma_offset; - u16 fb_size; - u8 dma_idx; - } gc6_ctx; - u8 pad; - } *args = buf; - - args->secure_mode = 1; -} - -static const struct nvkm_msgqueue_init_func -msgqueue_0137c63d_init_func = { - .gen_cmdline = init_gen_cmdline, -}; - -static void -msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue) -{ - kfree(msgqueue_0137c63d(queue)); -} - -static const struct nvkm_msgqueue_func -msgqueue_0137c63d_func = { - .init_func = &msgqueue_0137c63d_init_func, - .dtor = msgqueue_0137c63d_dtor, -}; - -int -msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, - struct nvkm_msgqueue **queue) -{ - struct msgqueue_0137c63d *ret; - - ret = kzalloc(sizeof(*ret), GFP_KERNEL); - if (!ret) - return -ENOMEM; - - *queue = &ret->base; - - nvkm_msgqueue_ctor(&msgqueue_0137c63d_func, falcon, &ret->base); - - return 0; -} - -static const struct nvkm_msgqueue_func -msgqueue_0137bca5_func = { - .init_func = &msgqueue_0137c63d_init_func, - .dtor = msgqueue_0137c63d_dtor, -}; - -int -msgqueue_0137bca5_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, - struct nvkm_msgqueue **queue) -{ - struct msgqueue_0137bca5 *ret; - - ret = kzalloc(sizeof(*ret), GFP_KERNEL); - if (!ret) - return -ENOMEM; - - *queue = &ret->base.base; - - /* - * FIXME this must be set to the address of a *GPU* mapping within the - * ACR address space! - */ - /* ret->wpr_addr = sb->wpr_addr; */ - - nvkm_msgqueue_ctor(&msgqueue_0137bca5_func, falcon, &ret->base.base); - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c deleted file mode 100644 index 351419b4ab44..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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. - * - */ - -#include "msgqueue.h" -#include -#include -#include - -/* - * This firmware runs on the SEC falcon. It only has one command and one - * message queue, and uses a different command line and init message. - */ - -struct msgqueue_0148cdec { - struct nvkm_msgqueue base; -}; -#define msgqueue_0148cdec(q) \ - container_of(q, struct msgqueue_0148cdec, base) - -static void -init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf) -{ - struct { - u32 freq_hz; - u32 falc_trace_size; - u32 falc_trace_dma_base; - u32 falc_trace_dma_idx; - bool secure_mode; - } *args = buf; - - args->secure_mode = false; -} - -static const struct nvkm_msgqueue_init_func -msgqueue_0148cdec_init_func = { - .gen_cmdline = init_gen_cmdline, -}; - - -static void -msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue) -{ - kfree(msgqueue_0148cdec(queue)); -} - -const struct nvkm_msgqueue_func -msgqueue_0148cdec_func = { - .init_func = &msgqueue_0148cdec_init_func, - .dtor = msgqueue_0148cdec_dtor, -}; - -int -msgqueue_0148cdec_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb, - struct nvkm_msgqueue **queue) -{ - struct msgqueue_0148cdec *ret; - - ret = kzalloc(sizeof(*ret), GFP_KERNEL); - if (!ret) - return -ENOMEM; - - *queue = &ret->base; - - nvkm_msgqueue_ctor(&msgqueue_0148cdec_func, falcon, &ret->base); - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h index dca12efc25e8..a45cd705e4f7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h @@ -2,7 +2,6 @@ #ifndef __NVKM_FALCON_QMGR_H__ #define __NVKM_FALCON_QMGR_H__ #include -#include "msgqueue.h" #define HDR_SIZE sizeof(struct nv_falcon_msg) #define QUEUE_ALIGNMENT 4 diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 6caced3589bc..1d18e38d9c61 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -62,6 +62,27 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) return 0; } +int +nvkm_acr_boot_ls_falcons(struct nvkm_device *device) +{ + struct nvkm_acr *acr = device->acr; + struct nvkm_acr_lsf *lsf; + int ret; + + if (!acr) + return -ENOSYS; + + list_for_each_entry(lsf, &acr->lsf, head) { + if (lsf->func->boot) { + ret = lsf->func->boot(lsf->falcon); + if (ret) + break; + } + } + + return ret; +} + static void nvkm_acr_cleanup(struct nvkm_acr *acr) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 706bbb782844..a0fe607c9c07 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c @@ -24,7 +24,6 @@ #include "priv.h" #include -#include #include bool @@ -144,7 +143,6 @@ static void * nvkm_pmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); - nvkm_msgqueue_del(&pmu->queue); nvkm_falcon_msgq_del(&pmu->msgq); nvkm_falcon_cmdq_del(&pmu->lpq); nvkm_falcon_cmdq_del(&pmu->hpq); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 52886ba7ff54..ef22678d041a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -56,8 +56,19 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon, return ret; } +int +gm20b_pmu_acr_boot(struct nvkm_falcon *falcon) +{ + struct nv_pmu_args args = { .secure_mode = true }; + const u32 addr_args = falcon->data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; /*XXX*/ + nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0); + nvkm_falcon_start(falcon); + return 0; +} + static const struct nvkm_acr_lsf_func gm20b_pmu_acr = { + .boot = gm20b_pmu_acr_boot, .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index dcb6eb24ba6a..74e00d470ac3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -900,12 +900,12 @@ acr_r352_wpr_is_set(const struct acr_r352 *acr, const struct nvkm_secboot *sb) wpr_hi > wpr_range_lo && wpr_hi <= wpr_range_hi); } +int nvkm_acr_boot_ls_falcons(struct nvkm_device *); + static int acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) { const struct nvkm_subdev *subdev = &sb->subdev; - unsigned long managed_falcons = acr->base.managed_falcons; - int falcon_id; int ret; if (sb->wpr_set) @@ -934,19 +934,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) return -EINVAL; } - /* Run LS firmwares post_run hooks */ - for_each_set_bit(falcon_id, &managed_falcons, NVKM_SECBOOT_FALCON_END) { - const struct acr_r352_ls_func *func = - acr->func->ls_func[falcon_id]; - - if (func->post_run) { - ret = func->post_run(&acr->base, sb); - if (ret) - return ret; - } - } - - return 0; + return nvkm_acr_boot_ls_falcons(subdev->device); } /** @@ -1168,7 +1156,6 @@ acr_r352_ls_pmu_func_0 = { static const struct acr_r352_ls_func acr_r352_ls_pmu_func = { .load = acr_ls_ucode_load_pmu, - .post_run = acr_ls_pmu_post_run, .version_max = 0, .version = { &acr_r352_ls_pmu_func_0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h index e516cab849dd..3197cb83bc27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h @@ -65,12 +65,10 @@ struct acr_r352_lsf_func { * struct acr_r352_ls_func - manages a single LS falcon * * @load: load the external firmware into a ls_ucode_img - * @post_run: hook called right after the ACR is executed */ struct acr_r352_ls_func { int (*load)(const struct nvkm_secboot *, int maxver, struct ls_ucode_img *); - int (*post_run)(const struct nvkm_acr *, const struct nvkm_secboot *); int version_max; const struct acr_r352_lsf_func *version[]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c index e6dd0a4bf581..86d3864c7717 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c @@ -150,7 +150,6 @@ acr_r361_ls_pmu_func_0 = { const struct acr_r352_ls_func acr_r361_ls_pmu_func = { .load = acr_ls_ucode_load_pmu, - .post_run = acr_ls_pmu_post_run, .version_max = 0, .version = { &acr_r361_ls_pmu_func_0, @@ -197,7 +196,6 @@ acr_r361_ls_sec2_func_0 = { static const struct acr_r352_ls_func acr_r361_ls_sec2_func = { .load = acr_ls_ucode_load_sec2, - .post_run = acr_ls_sec2_post_run, .version_max = 0, .version = { &acr_r361_ls_sec2_func_0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c index 472ced29da7e..f75abbe12ecc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c @@ -385,7 +385,6 @@ acr_r367_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb, static const struct acr_r352_ls_func acr_r367_ls_sec2_func = { .load = acr_ls_ucode_load_sec2, - .post_run = acr_ls_sec2_post_run, .version_max = 1, .version = { &acr_r361_ls_sec2_func_0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c index f850c3be261a..3d80e508445f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c @@ -120,7 +120,6 @@ acr_r370_ls_sec2_func_0 = { const struct acr_r352_ls_func acr_r370_ls_sec2_func = { .load = acr_ls_ucode_load_sec2, - .post_run = acr_ls_sec2_post_run, .version_max = 0, .version = { &acr_r370_ls_sec2_func_0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c index 7112ad74e3c8..06cb2f867b80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c @@ -63,7 +63,6 @@ acr_r375_ls_pmu_func_0 = { const struct acr_r352_ls_func acr_r375_ls_pmu_func = { .load = acr_ls_ucode_load_pmu, - .post_run = acr_ls_pmu_post_run, .version_max = 0, .version = { &acr_r375_ls_pmu_func_0, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c index 7994ed1cdf97..7e5282caf00c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c @@ -75,62 +75,16 @@ acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name, return ver; } -static int -acr_ls_msgqueue_post_run(struct nvkm_msgqueue *queue, - struct nvkm_falcon *falcon, u32 addr_args) -{ - struct nvkm_device *device = falcon->owner->device; - u8 buf[NVKM_MSGQUEUE_CMDLINE_SIZE]; - - memset(buf, 0, sizeof(buf)); - nvkm_msgqueue_write_cmdline(queue, buf); - nvkm_falcon_load_dmem(falcon, buf, addr_args, sizeof(buf), 0); - - /* Enable interrupts */ - nvkm_falcon_wr32(falcon, 0x10, 0xff); - nvkm_mc_intr_mask(device, falcon->owner->index, true); - - /* Start LS firmware on boot falcon */ - nvkm_falcon_start(falcon); - - return 0; -} - int acr_ls_ucode_load_pmu(const struct nvkm_secboot *sb, int maxver, struct ls_ucode_img *img) { - struct nvkm_pmu *pmu = sb->subdev.device->pmu; int ret; ret = acr_ls_ucode_load_msgqueue(&sb->subdev, "pmu", maxver, img); if (ret) return ret; - /* Allocate the PMU queue corresponding to the FW version */ - ret = nvkm_msgqueue_new(img->ucode_desc.app_version, &pmu->falcon, - sb, &pmu->queue); - if (ret) - return ret; - - return 0; -} - -int -acr_ls_pmu_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - struct nvkm_pmu *pmu = device->pmu; - u32 addr_args = pmu->falcon.data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; - int ret; - - ret = acr_ls_msgqueue_post_run(pmu->queue, &pmu->falcon, addr_args); - if (ret) - return ret; - - nvkm_debug(&sb->subdev, "%s started\n", - nvkm_secboot_falcon_name[acr->boot_falcon]); - return 0; } @@ -138,38 +92,11 @@ int acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, int maxver, struct ls_ucode_img *img) { - struct nvkm_sec2 *sec = sb->subdev.device->sec2; - int ver, ret; + int ver; ver = acr_ls_ucode_load_msgqueue(&sb->subdev, "sec2", maxver, img); if (ver < 0) return ver; - /* Allocate the PMU queue corresponding to the FW version */ - ret = nvkm_msgqueue_new(img->ucode_desc.app_version, &sec->falcon, - sb, &sec->queue); - if (ret) - return ret; - return ver; } - -int -acr_ls_sec2_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) -{ - const struct nvkm_subdev *subdev = &sb->subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_sec2 *sec = device->sec2; - /* on SEC arguments are always at the beginning of EMEM */ - const u32 addr_args = 0x01000000; - int ret; - - ret = acr_ls_msgqueue_post_run(sec->queue, &sec->falcon, addr_args); - if (ret) - return ret; - - nvkm_debug(&sb->subdev, "%s started\n", - nvkm_secboot_falcon_name[acr->boot_falcon]); - - return 0; -} -- cgit v1.2.3 From ff213b634865b60fa8d445a070ac74951245bb3d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/core/memory: add macros to read/write blocks from objects Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/memory.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h index b23bf6109f2d..74d3f1a809d7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h @@ -84,6 +84,22 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *, nvkm_wo32((o), __a + 4, upper_32_bits(__d)); \ } while(0) +#define nvkm_robj(o,a,p,s) do { \ + u32 _addr = (a), _size = (s) >> 2, *_data = (void *)(p); \ + while (_size--) { \ + *(_data++) = nvkm_ro32((o), _addr); \ + _addr += 4; \ + } \ +} while(0) + +#define nvkm_wobj(o,a,p,s) do { \ + u32 _addr = (a), _size = (s) >> 2, *_data = (void *)(p); \ + while (_size--) { \ + nvkm_wo32((o), _addr, *(_data++)); \ + _addr += 4; \ + } \ +} while(0) + #define nvkm_fill(t,s,o,a,d,c) do { \ u64 _a = (a), _c = (c), _d = (d), _o = _a >> s, _s = _c << s; \ u##t __iomem *_m = nvkm_kmap(o); \ -- cgit v1.2.3 From ebe52a58acca308142ba2811e50a1b3bf047240d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/fb/gp102-: unlock VPR as part of FB init We perform memory allocations long before we hit the code in SECBOOT that would unlock the VPR, which could potentially result in memory allocation within the locked region. Run the scrubber binary right after VRAM init to ensure we don't. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/hs.h | 31 ++++++ drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h | 2 + drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c | 62 +++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 19 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 96 ++++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c | 6 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 10 ++ .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 117 +-------------------- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c | 3 - 10 files changed, 226 insertions(+), 121 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/hs.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/hs.h b/drivers/gpu/drm/nouveau/include/nvfw/hs.h new file mode 100644 index 000000000000..64d0d32200c2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/hs.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVFW_HS_H__ +#define __NVFW_HS_H__ +#include +struct nvkm_subdev; + +struct nvfw_hs_header { + u32 sig_dbg_offset; + u32 sig_dbg_size; + u32 sig_prod_offset; + u32 sig_prod_size; + u32 patch_loc; + u32 patch_sig; + u32 hdr_offset; + u32 hdr_size; +}; + +const struct nvfw_hs_header *nvfw_hs_header(struct nvkm_subdev *, const void *); + +struct nvfw_hs_load_header { + u32 non_sec_code_off; + u32 non_sec_code_size; + u32 data_dma_base; + u32 data_size; + u32 num_apps; + u32 apps[0]; +}; + +const struct nvfw_hs_load_header * +nvfw_hs_load_header(struct nvkm_subdev *, const void *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index 239ad222b95a..34b56b10218a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -33,6 +33,8 @@ struct nvkm_fb { const struct nvkm_fb_func *func; struct nvkm_subdev subdev; + struct nvkm_blob vpr_scrubber; + struct nvkm_ram *ram; struct nvkm_mm tags; diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild index e05b92ec8568..eeff6b4c70b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild @@ -1,3 +1,4 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/nvfw/fw.o +nvkm-y += nvkm/nvfw/hs.o nvkm-y += nvkm/nvfw/ls.o diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c new file mode 100644 index 000000000000..04ed77cb2eba --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include +#include + +const struct nvfw_hs_header * +nvfw_hs_header(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_hs_header *hdr = data; + nvkm_debug(subdev, "hsHeader:\n"); + nvkm_debug(subdev, "\tsigDbgOffset : 0x%x\n", hdr->sig_dbg_offset); + nvkm_debug(subdev, "\tsigDbgSize : 0x%x\n", hdr->sig_dbg_size); + nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset); + nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size); + nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc); + nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig); + nvkm_debug(subdev, "\thdrOffset : 0x%x\n", hdr->hdr_offset); + nvkm_debug(subdev, "\thdrSize : 0x%x\n", hdr->hdr_size); + return hdr; +} + +const struct nvfw_hs_load_header * +nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data) +{ + const struct nvfw_hs_load_header *hdr = data; + int i; + + nvkm_debug(subdev, "hsLoadHeader:\n"); + nvkm_debug(subdev, "\tnonSecCodeOff : 0x%x\n", + hdr->non_sec_code_off); + nvkm_debug(subdev, "\tnonSecCodeSize : 0x%x\n", + hdr->non_sec_code_size); + nvkm_debug(subdev, "\tdataDmaBase : 0x%x\n", hdr->data_dma_base); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\tnumApps : 0x%x\n", hdr->num_apps); + for (i = 0; i < hdr->num_apps; i++) { + nvkm_debug(subdev, + "\tApp[%d] : offset 0x%x size 0x%x\n", i, + hdr->apps[(i * 2) + 0], hdr->apps[(i * 2) + 1]); + } + + return hdr; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index b2bb5a3ccb02..d09db7c6b7ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -154,6 +154,23 @@ nvkm_fb_init(struct nvkm_subdev *subdev) if (fb->func->init_unkn) fb->func->init_unkn(fb); + + if (fb->func->vpr.scrub_required && + fb->func->vpr.scrub_required(fb)) { + nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); + + ret = fb->func->vpr.scrub(fb); + if (ret) + return ret; + + if (fb->func->vpr.scrub_required(fb)) { + nvkm_error(subdev, "VPR still locked after scrub!\n"); + return -EIO; + } + + nvkm_debug(subdev, "VPR scrubber binary successful\n"); + } + return 0; } @@ -172,6 +189,8 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev) nvkm_mm_fini(&fb->tags); nvkm_ram_del(&fb->ram); + nvkm_blob_dtor(&fb->vpr_scrubber); + if (fb->func->dtor) return fb->func->dtor(fb); return fb; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index b4d74e815674..9be7316c6642 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -24,7 +24,81 @@ #include "gf100.h" #include "ram.h" +#include #include +#include +#include +#include + +int +gp102_fb_vpr_scrub(struct nvkm_fb *fb) +{ + struct nvkm_subdev *subdev = &fb->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_falcon *falcon = &device->nvdec[0]->falcon; + struct nvkm_blob *blob = &fb->vpr_scrubber; + const struct nvfw_bin_hdr *hsbin_hdr; + const struct nvfw_hs_header *fw_hdr; + const struct nvfw_hs_load_header *lhdr; + void *scrub_data; + u32 patch_loc, patch_sig; + int ret; + + nvkm_falcon_get(falcon, subdev); + + hsbin_hdr = nvfw_bin_hdr(subdev, blob->data); + fw_hdr = nvfw_hs_header(subdev, blob->data + hsbin_hdr->header_offset); + lhdr = nvfw_hs_load_header(subdev, blob->data + fw_hdr->hdr_offset); + scrub_data = blob->data + hsbin_hdr->data_offset; + + patch_loc = *(u32 *)(blob->data + fw_hdr->patch_loc); + patch_sig = *(u32 *)(blob->data + fw_hdr->patch_sig); + if (falcon->debug) { + memcpy(scrub_data + patch_loc, + blob->data + fw_hdr->sig_dbg_offset + patch_sig, + fw_hdr->sig_dbg_size); + } else { + memcpy(scrub_data + patch_loc, + blob->data + fw_hdr->sig_prod_offset + patch_sig, + fw_hdr->sig_prod_size); + } + + nvkm_falcon_reset(falcon); + nvkm_falcon_bind_context(falcon, NULL); + + nvkm_falcon_load_imem(falcon, scrub_data, lhdr->non_sec_code_off, + lhdr->non_sec_code_size, + lhdr->non_sec_code_off >> 8, 0, false); + nvkm_falcon_load_imem(falcon, scrub_data + lhdr->apps[0], + ALIGN(lhdr->apps[0], 0x100), + lhdr->apps[1], + lhdr->apps[0] >> 8, 0, true); + nvkm_falcon_load_dmem(falcon, scrub_data + lhdr->data_dma_base, 0, + lhdr->data_size, 0); + + nvkm_falcon_set_start_addr(falcon, 0x0); + nvkm_falcon_start(falcon); + + ret = nvkm_falcon_wait_for_halt(falcon, 500); + if (ret < 0) { + ret = -ETIMEDOUT; + goto end; + } + + /* put nvdec in clean state - without reset it will remain in HS mode */ + nvkm_falcon_reset(falcon); +end: + nvkm_falcon_put(falcon, subdev); + return ret; +} + +bool +gp102_fb_vpr_scrub_required(struct nvkm_fb *fb) +{ + struct nvkm_device *device = fb->subdev.device; + nvkm_wr32(device, 0x100cd0, 0x2); + return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0; +} static const struct nvkm_fb_func gp102_fb = { @@ -33,11 +107,31 @@ gp102_fb = { .init = gp100_fb_init, .init_remapper = gp100_fb_init_remapper, .init_page = gm200_fb_init_page, + .vpr.scrub_required = gp102_fb_vpr_scrub_required, + .vpr.scrub = gp102_fb_vpr_scrub, .ram_new = gp100_ram_new, }; +int +gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, + int index, struct nvkm_fb **pfb) +{ + int ret = gf100_fb_new_(func, device, index, pfb); + if (ret) + return ret; + + return nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, + &(*pfb)->vpr_scrubber); +} + int gp102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) { - return gf100_fb_new_(&gp102_fb, device, index, pfb); + return gp102_fb_new_(&gp102_fb, device, index, pfb); } + +MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index 3c5e02e9794a..e4326bf674b8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -35,6 +35,8 @@ gv100_fb = { .init = gp100_fb_init, .init_page = gv100_fb_init_page, .init_unkn = gp100_fb_init_unkn, + .vpr.scrub_required = gp102_fb_vpr_scrub_required, + .vpr.scrub = gp102_fb_vpr_scrub, .ram_new = gp100_ram_new, .default_bigpage = 16, }; @@ -42,5 +44,7 @@ gv100_fb = { int gv100_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) { - return gf100_fb_new_(&gv100_fb, device, index, pfb); + return gp102_fb_new_(&gv100_fb, device, index, pfb); } + +MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index c4e9f55af283..5be9c563350d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -16,6 +16,11 @@ struct nvkm_fb_func { void (*init_unkn)(struct nvkm_fb *); void (*intr)(struct nvkm_fb *); + struct { + bool (*scrub_required)(struct nvkm_fb *); + int (*scrub)(struct nvkm_fb *); + } vpr; + struct { int regions; void (*init)(struct nvkm_fb *, int i, u32 addr, u32 size, @@ -72,4 +77,9 @@ int gm200_fb_init_page(struct nvkm_fb *); void gp100_fb_init_remapper(struct nvkm_fb *); void gp100_fb_init_unkn(struct nvkm_fb *); + +int gp102_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, int, + struct nvkm_fb **); +bool gp102_fb_vpr_scrub_required(struct nvkm_fb *); +int gp102_fb_vpr_scrub(struct nvkm_fb *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index 5f4357de54be..49dad16fb3ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -23,122 +23,12 @@ #include "acr.h" #include "gm200.h" -#include "ls_ucode.h" -#include "hs_ucode.h" -#include -#include -#include -#include - -static bool -gp102_secboot_scrub_required(struct nvkm_secboot *sb) -{ - struct nvkm_subdev *subdev = &sb->subdev; - struct nvkm_device *device = subdev->device; - u32 reg; - - nvkm_wr32(device, 0x100cd0, 0x2); - reg = nvkm_rd32(device, 0x100cd0); - - return (reg & BIT(4)); -} - -static int -gp102_run_secure_scrub(struct nvkm_secboot *sb) -{ - struct nvkm_subdev *subdev = &sb->subdev; - struct nvkm_device *device = subdev->device; - struct nvkm_engine *engine; - struct nvkm_falcon *falcon; - void *scrub_image; - struct fw_bin_header *hsbin_hdr; - struct hsf_fw_header *fw_hdr; - struct hsf_load_header *lhdr; - void *scrub_data; - int ret; - - nvkm_debug(subdev, "running VPR scrubber binary on NVDEC...\n"); - - engine = nvkm_engine_ref(&device->nvdec[0]->engine); - if (IS_ERR(engine)) - return PTR_ERR(engine); - falcon = &device->nvdec[0]->falcon; - - nvkm_falcon_get(falcon, &sb->subdev); - - scrub_image = hs_ucode_load_blob(subdev, falcon, "nvdec/scrubber"); - if (IS_ERR(scrub_image)) - return PTR_ERR(scrub_image); - - nvkm_falcon_reset(falcon); - nvkm_falcon_bind_context(falcon, NULL); - - hsbin_hdr = scrub_image; - fw_hdr = scrub_image + hsbin_hdr->header_offset; - lhdr = scrub_image + fw_hdr->hdr_offset; - scrub_data = scrub_image + hsbin_hdr->data_offset; - - nvkm_falcon_load_imem(falcon, scrub_data, lhdr->non_sec_code_off, - lhdr->non_sec_code_size, - lhdr->non_sec_code_off >> 8, 0, false); - nvkm_falcon_load_imem(falcon, scrub_data + lhdr->apps[0], - ALIGN(lhdr->apps[0], 0x100), - lhdr->apps[1], - lhdr->apps[0] >> 8, 0, true); - nvkm_falcon_load_dmem(falcon, scrub_data + lhdr->data_dma_base, 0, - lhdr->data_size, 0); - - kfree(scrub_image); - - nvkm_falcon_set_start_addr(falcon, 0x0); - nvkm_falcon_start(falcon); - - ret = nvkm_falcon_wait_for_halt(falcon, 500); - if (ret < 0) { - nvkm_error(subdev, "failed to run VPR scrubber binary!\n"); - ret = -ETIMEDOUT; - goto end; - } - - /* put nvdec in clean state - without reset it will remain in HS mode */ - nvkm_falcon_reset(falcon); - - if (gp102_secboot_scrub_required(sb)) { - nvkm_error(subdev, "VPR scrubber binary failed!\n"); - ret = -EINVAL; - goto end; - } - - nvkm_debug(subdev, "VPR scrub successfully completed\n"); - -end: - nvkm_falcon_put(falcon, &sb->subdev); - nvkm_engine_unref(&engine); - return ret; -} - -static int -gp102_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, - struct nvkm_falcon *falcon) -{ - int ret; - - /* make sure the VPR region is unlocked */ - if (gp102_secboot_scrub_required(sb)) { - ret = gp102_run_secure_scrub(sb); - if (ret) - return ret; - } - - return gm200_secboot_run_blob(sb, blob, falcon); -} - const struct nvkm_secboot_func gp102_secboot = { .dtor = gm200_secboot_dtor, .oneinit = gm200_secboot_oneinit, .fini = gm200_secboot_fini, - .run_blob = gp102_secboot_run_blob, + .run_blob = gm200_secboot_run_blob, }; int @@ -169,8 +59,3 @@ gp102_secboot_new(struct nvkm_device *device, int index, return 0; } - -MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp104/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp106/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gp107/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c index 5161b9cfb73a..03d0428079fa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c @@ -44,6 +44,3 @@ gp108_secboot_new(struct nvkm_device *device, int index, return nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); } - -MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); -MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); -- cgit v1.2.3 From 22dcda45a3d1dfe6eeb4ab0a3b9aaa2333cb649d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/acr: implement new subdev to replace "secure boot" ACR is responsible for managing the firmware for LS (Low Secure) falcons, this was previously handled in the driver by SECBOOT. This rewrite started from some test code that attempted to replicate the procedure RM uses in order to debug early Turing ACR firmwares that were provided by NVIDIA for development. Compared with SECBOOT, the code is structured into more individual steps, with the aim of making the process easier to follow/debug, whilst making it possible to support newer firmware versions that may have a different binary format or API interface. The HS (High Secure) binary(s) are now booted earlier in device init, to match the behaviour of RM, whereas SECBOOT would delay this until we try to boot the first LS falcon. There's also additional debugging features available, with the intention of making it easier to solve issues during FW/HW bring-up in the future. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvfw/acr.h | 152 ++++++++ drivers/gpu/drm/nouveau/include/nvfw/flcn.h | 97 +++++ drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 33 +- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 12 - drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 26 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 4 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c | 40 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 45 +++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c | 40 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 6 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 72 ++++ drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c | 4 + drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild | 3 + drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c | 165 +++++++++ drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.c | 115 ++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 287 ++++++++++++++- drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 409 +++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c | 85 +++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 213 +++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c | 61 +++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c | 14 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c | 180 +++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 118 ++++++ drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 56 ++- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 6 + drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h | 4 + .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 4 +- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h | 1 - 30 files changed, 2207 insertions(+), 47 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/acr.h create mode 100644 drivers/gpu/drm/nouveau/include/nvfw/flcn.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvfw/acr.h b/drivers/gpu/drm/nouveau/include/nvfw/acr.h new file mode 100644 index 000000000000..e65d6a8db104 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/acr.h @@ -0,0 +1,152 @@ +#ifndef __NVFW_ACR_H__ +#define __NVFW_ACR_H__ + +struct wpr_header { +#define WPR_HEADER_V0_FALCON_ID_INVALID 0xffffffff + u32 falcon_id; + u32 lsb_offset; + u32 bootstrap_owner; + u32 lazy_bootstrap; +#define WPR_HEADER_V0_STATUS_NONE 0 +#define WPR_HEADER_V0_STATUS_COPY 1 +#define WPR_HEADER_V0_STATUS_VALIDATION_CODE_FAILED 2 +#define WPR_HEADER_V0_STATUS_VALIDATION_DATA_FAILED 3 +#define WPR_HEADER_V0_STATUS_VALIDATION_DONE 4 +#define WPR_HEADER_V0_STATUS_VALIDATION_SKIPPED 5 +#define WPR_HEADER_V0_STATUS_BOOTSTRAP_READY 6 + u32 status; +}; + +void wpr_header_dump(struct nvkm_subdev *, const struct wpr_header *); + +struct wpr_header_v1 { +#define WPR_HEADER_V1_FALCON_ID_INVALID 0xffffffff + u32 falcon_id; + u32 lsb_offset; + u32 bootstrap_owner; + u32 lazy_bootstrap; + u32 bin_version; +#define WPR_HEADER_V1_STATUS_NONE 0 +#define WPR_HEADER_V1_STATUS_COPY 1 +#define WPR_HEADER_V1_STATUS_VALIDATION_CODE_FAILED 2 +#define WPR_HEADER_V1_STATUS_VALIDATION_DATA_FAILED 3 +#define WPR_HEADER_V1_STATUS_VALIDATION_DONE 4 +#define WPR_HEADER_V1_STATUS_VALIDATION_SKIPPED 5 +#define WPR_HEADER_V1_STATUS_BOOTSTRAP_READY 6 +#define WPR_HEADER_V1_STATUS_REVOCATION_CHECK_FAILED 7 + u32 status; +}; + +void wpr_header_v1_dump(struct nvkm_subdev *, const struct wpr_header_v1 *); + +struct lsf_signature { + u8 prd_keys[2][16]; + u8 dbg_keys[2][16]; + u32 b_prd_present; + u32 b_dbg_present; + u32 falcon_id; +}; + +struct lsf_signature_v1 { + u8 prd_keys[2][16]; + u8 dbg_keys[2][16]; + u32 b_prd_present; + u32 b_dbg_present; + u32 falcon_id; + u32 supports_versioning; + u32 version; + u32 depmap_count; + u8 depmap[11/*LSF_LSB_DEPMAP_SIZE*/ * 2 * 4]; + u8 kdf[16]; +}; + +struct lsb_header_tail { + u32 ucode_off; + u32 ucode_size; + u32 data_size; + u32 bl_code_size; + u32 bl_imem_off; + u32 bl_data_off; + u32 bl_data_size; + u32 app_code_off; + u32 app_code_size; + u32 app_data_off; + u32 app_data_size; + u32 flags; +}; + +struct lsb_header { + struct lsf_signature signature; + struct lsb_header_tail tail; +}; + +void lsb_header_dump(struct nvkm_subdev *, struct lsb_header *); + +struct lsb_header_v1 { + struct lsf_signature_v1 signature; + struct lsb_header_tail tail; +}; + +void lsb_header_v1_dump(struct nvkm_subdev *, struct lsb_header_v1 *); + +struct flcn_acr_desc { + union { + u8 reserved_dmem[0x200]; + u32 signatures[4]; + } ucode_reserved_space; + u32 wpr_region_id; + u32 wpr_offset; + u32 mmu_mem_range; + struct { + u32 no_regions; + struct { + u32 start_addr; + u32 end_addr; + u32 region_id; + u32 read_mask; + u32 write_mask; + u32 client_mask; + } region_props[2]; + } regions; + u32 ucode_blob_size; + u64 ucode_blob_base __aligned(8); + struct { + u32 vpr_enabled; + u32 vpr_start; + u32 vpr_end; + u32 hdcp_policies; + } vpr_desc; +}; + +void flcn_acr_desc_dump(struct nvkm_subdev *, struct flcn_acr_desc *); + +struct flcn_acr_desc_v1 { + u8 reserved_dmem[0x200]; + u32 signatures[4]; + u32 wpr_region_id; + u32 wpr_offset; + u32 mmu_memory_range; + struct { + u32 no_regions; + struct { + u32 start_addr; + u32 end_addr; + u32 region_id; + u32 read_mask; + u32 write_mask; + u32 client_mask; + u32 shadow_mem_start_addr; + } region_props[2]; + } regions; + u32 ucode_blob_size; + u64 ucode_blob_base __aligned(8); + struct { + u32 vpr_enabled; + u32 vpr_start; + u32 vpr_end; + u32 hdcp_policies; + } vpr_desc; +}; + +void flcn_acr_desc_v1_dump(struct nvkm_subdev *, struct flcn_acr_desc_v1 *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvfw/flcn.h b/drivers/gpu/drm/nouveau/include/nvfw/flcn.h new file mode 100644 index 000000000000..e090f347d220 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvfw/flcn.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVFW_FLCN_H__ +#define __NVFW_FLCN_H__ +#include +struct nvkm_subdev; + +struct loader_config { + u32 dma_idx; + u32 code_dma_base; + u32 code_size_total; + u32 code_size_to_load; + u32 code_entry_point; + u32 data_dma_base; + u32 data_size; + u32 overlay_dma_base; + u32 argc; + u32 argv; + u32 code_dma_base1; + u32 data_dma_base1; + u32 overlay_dma_base1; +}; + +void +loader_config_dump(struct nvkm_subdev *, const struct loader_config *); + +struct loader_config_v1 { + u32 reserved; + u32 dma_idx; + u64 code_dma_base; + u32 code_size_total; + u32 code_size_to_load; + u32 code_entry_point; + u64 data_dma_base; + u32 data_size; + u64 overlay_dma_base; + u32 argc; + u32 argv; +} __packed; + +void +loader_config_v1_dump(struct nvkm_subdev *, const struct loader_config_v1 *); + +struct flcn_bl_dmem_desc { + u32 reserved[4]; + u32 signature[4]; + u32 ctx_dma; + u32 code_dma_base; + u32 non_sec_code_off; + u32 non_sec_code_size; + u32 sec_code_off; + u32 sec_code_size; + u32 code_entry_point; + u32 data_dma_base; + u32 data_size; + u32 code_dma_base1; + u32 data_dma_base1; +}; + +void +flcn_bl_dmem_desc_dump(struct nvkm_subdev *, const struct flcn_bl_dmem_desc *); + +struct flcn_bl_dmem_desc_v1 { + u32 reserved[4]; + u32 signature[4]; + u32 ctx_dma; + u64 code_dma_base; + u32 non_sec_code_off; + u32 non_sec_code_size; + u32 sec_code_off; + u32 sec_code_size; + u32 code_entry_point; + u64 data_dma_base; + u32 data_size; +} __packed; + +void flcn_bl_dmem_desc_v1_dump(struct nvkm_subdev *, + const struct flcn_bl_dmem_desc_v1 *); + +struct flcn_bl_dmem_desc_v2 { + u32 reserved[4]; + u32 signature[4]; + u32 ctx_dma; + u64 code_dma_base; + u32 non_sec_code_off; + u32 non_sec_code_size; + u32 sec_code_off; + u32 sec_code_size; + u32 code_entry_point; + u64 data_dma_base; + u32 data_size; + u32 argc; + u32 argv; +} __packed; + +void flcn_bl_dmem_desc_v2_dump(struct nvkm_subdev *, + const struct flcn_bl_dmem_desc_v2 *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 4b30aeb9d22a..9e5284f63bd5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -3,7 +3,7 @@ #define __NVKM_ACR_H__ #define nvkm_acr(p) container_of((p), struct nvkm_acr, subdev) #include -struct nvkm_falcon; +#include enum nvkm_acr_lsf_id { NVKM_ACR_LSF_PMU = 0, @@ -36,9 +36,25 @@ struct nvkm_acr { const struct nvkm_acr_func *func; struct nvkm_subdev subdev; + struct list_head hsfw, hsf; struct list_head lsfw, lsf; + + struct nvkm_memory *wpr; + u64 wpr_start; + u64 wpr_end; + u64 shadow_start; + + struct nvkm_memory *inst; + struct nvkm_vmm *vmm; + + bool done; + + const struct firmware *wpr_fw; + bool wpr_comp; + u64 wpr_prev; }; +bool nvkm_acr_managed_falcon(struct nvkm_device *, enum nvkm_acr_lsf_id); int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long mask); int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **); @@ -71,9 +87,24 @@ struct nvkm_acr_lsfw { u32 ucode_size; u32 data_size; + + struct { + u32 lsb; + u32 img; + u32 bld; + } offset; + u32 bl_data_size; }; struct nvkm_acr_lsf_func { +/* The (currently) map directly to LSB header flags. */ +#define NVKM_ACR_LSF_LOAD_CODE_AT_0 0x00000001 +#define NVKM_ACR_LSF_DMACTL_REQ_CTX 0x00000004 +#define NVKM_ACR_LSF_FORCE_PRIV_LOAD 0x00000008 + u32 flags; + u32 bld_size; + void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *); + void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust); int (*boot)(struct nvkm_falcon *); int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id); int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index f98065b12c24..b452ef2cd27d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2048,7 +2048,6 @@ nv120_chipset = { .pci = gk104_pci_new, .pmu = gm107_pmu_new, .therm = gm200_therm_new, - .secboot = gm200_secboot_new, .timer = gk20a_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -2087,7 +2086,6 @@ nv124_chipset = { .pci = gk104_pci_new, .pmu = gm107_pmu_new, .therm = gm200_therm_new, - .secboot = gm200_secboot_new, .timer = gk20a_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -2126,7 +2124,6 @@ nv126_chipset = { .pci = gk104_pci_new, .pmu = gm107_pmu_new, .therm = gm200_therm_new, - .secboot = gm200_secboot_new, .timer = gk20a_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -2157,7 +2154,6 @@ nv12b_chipset = { .mc = gk20a_mc_new, .mmu = gm20b_mmu_new, .pmu = gm20b_pmu_new, - .secboot = gm20b_secboot_new, .timer = gk20a_timer_new, .top = gk104_top_new, .ce[2] = gm200_ce_new, @@ -2187,7 +2183,6 @@ nv130_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gm200_secboot_new, .pci = gp100_pci_new, .pmu = gp100_pmu_new, .timer = gk20a_timer_new, @@ -2228,7 +2223,6 @@ nv132_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2267,7 +2261,6 @@ nv134_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2306,7 +2299,6 @@ nv136_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2344,7 +2336,6 @@ nv137_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2383,7 +2374,6 @@ nv138_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, - .secboot = gp108_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2415,7 +2405,6 @@ nv13b_chipset = { .ltc = gp10b_ltc_new, .mc = gp10b_mc_new, .mmu = gp10b_mmu_new, - .secboot = gp10b_secboot_new, .pmu = gp10b_pmu_new, .timer = gk20a_timer_new, .top = gk104_top_new, @@ -2447,7 +2436,6 @@ nv140_chipset = { .mmu = gv100_mmu_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, - .secboot = gp108_secboot_new, .therm = gp100_therm_new, .timer = gk20a_timer_new, .top = gk104_top_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 8314f10c359a..6c1a1e074721 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -26,9 +26,9 @@ #include "fuc/os.h" #include -#include #include -#include +#include +#include #include #include #include @@ -1690,28 +1690,30 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) { struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_secboot *sb = device->secboot; - u32 secboot_mask = 0; + u32 lsf_mask = 0; int ret; /* load fuc microcode */ nvkm_mc_unk260(device, 0); /* securely-managed falcons must be reset using secure boot */ - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS); - else + + if (!nvkm_acr_managed_falcon(device, NVKM_ACR_LSF_FECS)) { gf100_gr_init_fw(&gr->fecs.falcon, &gr->fecs.inst, &gr->fecs.data); + } else { + lsf_mask |= BIT(NVKM_ACR_LSF_FECS); + } - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS); - else + if (!nvkm_acr_managed_falcon(device, NVKM_ACR_LSF_GPCCS)) { gf100_gr_init_fw(&gr->gpccs.falcon, &gr->gpccs.inst, &gr->gpccs.data); + } else { + lsf_mask |= BIT(NVKM_ACR_LSF_GPCCS); + } - if (secboot_mask != 0) { - int ret = nvkm_secboot_reset(sb, secboot_mask); + if (lsf_mask) { + ret = nvkm_acr_bootstrap_falcons(device, lsf_mask); if (ret) return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index aa5c9ddfd93c..67286bb57e55 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -31,6 +31,8 @@ #include #include +struct nvkm_acr_lsfw; + #define GPC_MAX 32 #define TPC_MAX_PER_GPC 8 #define TPC_MAX (GPC_MAX * TPC_MAX_PER_GPC) @@ -400,6 +402,8 @@ extern const struct nvkm_acr_lsf_func gm200_gr_gpccs_acr; extern const struct nvkm_acr_lsf_func gm200_gr_fecs_acr; extern const struct nvkm_acr_lsf_func gm20b_gr_fecs_acr; +void gm20b_gr_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); +void gm20b_gr_acr_bld_patch(struct nvkm_acr *, u32, s64); extern const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr; extern const struct nvkm_acr_lsf_func gp108_gr_fecs_acr; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c index 3ad94d791fcf..3d67cfb08395 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c @@ -28,18 +28,58 @@ #include #include +#include + #include /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ +static void +gm200_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct flcn_bl_dmem_desc_v1 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + flcn_bl_dmem_desc_v1_dump(&acr->subdev, &hdr); +} + +static void +gm200_gr_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const u64 base = lsfw->offset.img + lsfw->app_start_offset; + const u64 code = base + lsfw->app_resident_code_offset; + const u64 data = base + lsfw->app_resident_data_offset; + const struct flcn_bl_dmem_desc_v1 hdr = { + .ctx_dma = FALCON_DMAIDX_UCODE, + .code_dma_base = code, + .non_sec_code_off = lsfw->app_resident_code_offset, + .non_sec_code_size = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = data, + .data_size = lsfw->app_resident_data_size, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + const struct nvkm_acr_lsf_func gm200_gr_gpccs_acr = { + .flags = NVKM_ACR_LSF_FORCE_PRIV_LOAD, + .bld_size = sizeof(struct flcn_bl_dmem_desc_v1), + .bld_write = gm200_gr_acr_bld_write, + .bld_patch = gm200_gr_acr_bld_patch, }; const struct nvkm_acr_lsf_func gm200_gr_fecs_acr = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v1), + .bld_write = gm200_gr_acr_bld_write, + .bld_patch = gm200_gr_acr_bld_patch, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c index aaf5aff036f2..b45e8f10ec73 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -26,10 +26,55 @@ #include #include +#include + #include +void +gm20b_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct flcn_bl_dmem_desc hdr; + u64 addr; + + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + addr = ((u64)hdr.code_dma_base1 << 40 | hdr.code_dma_base << 8); + hdr.code_dma_base = lower_32_bits((addr + adjust) >> 8); + hdr.code_dma_base1 = upper_32_bits((addr + adjust) >> 8); + addr = ((u64)hdr.data_dma_base1 << 40 | hdr.data_dma_base << 8); + hdr.data_dma_base = lower_32_bits((addr + adjust) >> 8); + hdr.data_dma_base1 = upper_32_bits((addr + adjust) >> 8); + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + + flcn_bl_dmem_desc_dump(&acr->subdev, &hdr); +} + +void +gm20b_gr_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const u64 base = lsfw->offset.img + lsfw->app_start_offset; + const u64 code = (base + lsfw->app_resident_code_offset) >> 8; + const u64 data = (base + lsfw->app_resident_data_offset) >> 8; + const struct flcn_bl_dmem_desc hdr = { + .ctx_dma = FALCON_DMAIDX_UCODE, + .code_dma_base = lower_32_bits(code), + .non_sec_code_off = lsfw->app_resident_code_offset, + .non_sec_code_size = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lower_32_bits(data), + .data_size = lsfw->app_resident_data_size, + .code_dma_base1 = upper_32_bits(code), + .data_dma_base1 = upper_32_bits(data), + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + const struct nvkm_acr_lsf_func gm20b_gr_fecs_acr = { + .bld_size = sizeof(struct flcn_bl_dmem_desc), + .bld_write = gm20b_gr_acr_bld_write, + .bld_patch = gm20b_gr_acr_bld_patch, }; static void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c index 1fe58461095a..113e4c1ba9e8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c @@ -23,12 +23,52 @@ #include +#include + +static void +gp108_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct flcn_bl_dmem_desc_v2 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); +} + +static void +gp108_gr_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const u64 base = lsfw->offset.img + lsfw->app_start_offset; + const u64 code = base + lsfw->app_resident_code_offset; + const u64 data = base + lsfw->app_resident_data_offset; + const struct flcn_bl_dmem_desc_v2 hdr = { + .ctx_dma = FALCON_DMAIDX_UCODE, + .code_dma_base = code, + .non_sec_code_off = lsfw->app_resident_code_offset, + .non_sec_code_size = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = data, + .data_size = lsfw->app_resident_data_size, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr = { + .flags = NVKM_ACR_LSF_FORCE_PRIV_LOAD, + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp108_gr_acr_bld_write, + .bld_patch = gp108_gr_acr_bld_patch, }; const struct nvkm_acr_lsf_func gp108_gr_fecs_acr = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp108_gr_acr_bld_write, + .bld_patch = gp108_gr_acr_bld_patch, }; MODULE_FIRMWARE("nvidia/gp108/gr/fecs_bl.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index e22211906b42..a3db2a95ff9a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -27,8 +27,14 @@ #include +#include + static const struct nvkm_acr_lsf_func gp10b_gr_gpccs_acr = { + .flags = NVKM_ACR_LSF_FORCE_PRIV_LOAD, + .bld_size = sizeof(struct flcn_bl_dmem_desc), + .bld_write = gm20b_gr_acr_bld_write, + .bld_patch = gm20b_gr_acr_bld_patch, }; static const struct gf100_gr_func diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c index 4533931e4cb5..368f2a0042ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c @@ -21,9 +21,11 @@ */ #include "priv.h" +#include #include #include +#include #include static int @@ -74,8 +76,44 @@ gp102_sec2_acr_boot(struct nvkm_falcon *falcon) return 0; } +static void +gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct loader_config_v1 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + hdr.overlay_dma_base = hdr.overlay_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + loader_config_v1_dump(&acr->subdev, &hdr); +} + +static void +gp102_sec2_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const struct loader_config_v1 hdr = { + .dma_idx = FALCON_SEC2_DMAIDX_UCODE, + .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .code_size_total = lsfw->app_size, + .code_size_to_load = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + + lsfw->app_resident_data_offset, + .data_size = lsfw->app_resident_data_size, + .overlay_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .argc = 1, + .argv = lsfw->falcon->func->emem_addr, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + static const struct nvkm_acr_lsf_func gp102_sec2_acr_0 = { + .bld_size = sizeof(struct loader_config_v1), + .bld_write = gp102_sec2_acr_bld_write, + .bld_patch = gp102_sec2_acr_bld_patch, .boot = gp102_sec2_acr_boot, .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; @@ -219,8 +257,42 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin"); MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin"); +static void +gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct flcn_bl_dmem_desc_v2 hdr; + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + hdr.code_dma_base = hdr.code_dma_base + adjust; + hdr.data_dma_base = hdr.data_dma_base + adjust; + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr); +} + +static void +gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const struct flcn_bl_dmem_desc_v2 hdr = { + .ctx_dma = FALCON_SEC2_DMAIDX_UCODE, + .code_dma_base = lsfw->offset.img + lsfw->app_start_offset, + .non_sec_code_off = lsfw->app_resident_code_offset, + .non_sec_code_size = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lsfw->offset.img + lsfw->app_start_offset + + lsfw->app_resident_data_offset, + .data_size = lsfw->app_resident_data_size, + .argc = 1, + .argv = lsfw->falcon->func->emem_addr, + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + const struct nvkm_acr_lsf_func gp102_sec2_acr_1 = { + .bld_size = sizeof(struct flcn_bl_dmem_desc_v2), + .bld_write = gp102_sec2_acr_bld_write_1, + .bld_patch = gp102_sec2_acr_bld_patch_1, .boot = gp102_sec2_acr_boot, .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h index 1992391832a1..bb88117e018a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h @@ -11,6 +11,7 @@ struct nvkm_sec2_func { }; void gp102_sec2_intr(struct nvkm_sec2 *); +int gp102_sec2_initmsg(struct nvkm_sec2 *); struct nvkm_sec2_fwif { int version; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c index fe9993526f16..b6ebd95c9ba1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ #include "priv.h" +#include static const struct nvkm_falcon_func tu102_sec2_flcn = { @@ -43,7 +44,9 @@ tu102_sec2_flcn = { static const struct nvkm_sec2_func tu102_sec2 = { .flcn = &tu102_sec2_flcn, + .unit_acr = 0x07, .intr = gp102_sec2_intr, + .initmsg = gp102_sec2_initmsg, }; static int @@ -55,6 +58,7 @@ tu102_sec2_nofw(struct nvkm_sec2 *sec2, int ver, static const struct nvkm_sec2_fwif tu102_sec2_fwif[] = { + { 0, gp102_sec2_load, &tu102_sec2, &gp102_sec2_acr_1 }, { -1, tu102_sec2_nofw, &tu102_sec2 } }; diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild index eeff6b4c70b3..41d75f98e603 100644 --- a/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/Kbuild @@ -2,3 +2,6 @@ nvkm-y += nvkm/nvfw/fw.o nvkm-y += nvkm/nvfw/hs.o nvkm-y += nvkm/nvfw/ls.o + +nvkm-y += nvkm/nvfw/acr.o +nvkm-y += nvkm/nvfw/flcn.o diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c new file mode 100644 index 000000000000..0d063b8317f7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c @@ -0,0 +1,165 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include +#include + +void +wpr_header_dump(struct nvkm_subdev *subdev, const struct wpr_header *hdr) +{ + nvkm_debug(subdev, "wprHeader\n"); + nvkm_debug(subdev, "\tfalconID : %d\n", hdr->falcon_id); + nvkm_debug(subdev, "\tlsbOffset : 0x%x\n", hdr->lsb_offset); + nvkm_debug(subdev, "\tbootstrapOwner: %d\n", hdr->bootstrap_owner); + nvkm_debug(subdev, "\tlazyBootstrap : %d\n", hdr->lazy_bootstrap); + nvkm_debug(subdev, "\tstatus : %d\n", hdr->status); +} + +void +wpr_header_v1_dump(struct nvkm_subdev *subdev, const struct wpr_header_v1 *hdr) +{ + nvkm_debug(subdev, "wprHeader\n"); + nvkm_debug(subdev, "\tfalconID : %d\n", hdr->falcon_id); + nvkm_debug(subdev, "\tlsbOffset : 0x%x\n", hdr->lsb_offset); + nvkm_debug(subdev, "\tbootstrapOwner: %d\n", hdr->bootstrap_owner); + nvkm_debug(subdev, "\tlazyBootstrap : %d\n", hdr->lazy_bootstrap); + nvkm_debug(subdev, "\tbinVersion : %d\n", hdr->bin_version); + nvkm_debug(subdev, "\tstatus : %d\n", hdr->status); +} + +void +lsb_header_tail_dump(struct nvkm_subdev *subdev, + struct lsb_header_tail *hdr) +{ + nvkm_debug(subdev, "lsbHeader\n"); + nvkm_debug(subdev, "\tucodeOff : 0x%x\n", hdr->ucode_off); + nvkm_debug(subdev, "\tucodeSize : 0x%x\n", hdr->ucode_size); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\tblCodeSize : 0x%x\n", hdr->bl_code_size); + nvkm_debug(subdev, "\tblImemOff : 0x%x\n", hdr->bl_imem_off); + nvkm_debug(subdev, "\tblDataOff : 0x%x\n", hdr->bl_data_off); + nvkm_debug(subdev, "\tblDataSize : 0x%x\n", hdr->bl_data_size); + nvkm_debug(subdev, "\tappCodeOff : 0x%x\n", hdr->app_code_off); + nvkm_debug(subdev, "\tappCodeSize : 0x%x\n", hdr->app_code_size); + nvkm_debug(subdev, "\tappDataOff : 0x%x\n", hdr->app_data_off); + nvkm_debug(subdev, "\tappDataSize : 0x%x\n", hdr->app_data_size); + nvkm_debug(subdev, "\tflags : 0x%x\n", hdr->flags); +} + +void +lsb_header_dump(struct nvkm_subdev *subdev, struct lsb_header *hdr) +{ + lsb_header_tail_dump(subdev, &hdr->tail); +} + +void +lsb_header_v1_dump(struct nvkm_subdev *subdev, struct lsb_header_v1 *hdr) +{ + lsb_header_tail_dump(subdev, &hdr->tail); +} + +void +flcn_acr_desc_dump(struct nvkm_subdev *subdev, struct flcn_acr_desc *hdr) +{ + int i; + + nvkm_debug(subdev, "acrDesc\n"); + nvkm_debug(subdev, "\twprRegionId : %d\n", hdr->wpr_region_id); + nvkm_debug(subdev, "\twprOffset : 0x%x\n", hdr->wpr_offset); + nvkm_debug(subdev, "\tmmuMemRange : 0x%x\n", + hdr->mmu_mem_range); + nvkm_debug(subdev, "\tnoRegions : %d\n", + hdr->regions.no_regions); + + for (i = 0; i < ARRAY_SIZE(hdr->regions.region_props); i++) { + nvkm_debug(subdev, "\tregion[%d] :\n", i); + nvkm_debug(subdev, "\t startAddr : 0x%x\n", + hdr->regions.region_props[i].start_addr); + nvkm_debug(subdev, "\t endAddr : 0x%x\n", + hdr->regions.region_props[i].end_addr); + nvkm_debug(subdev, "\t regionId : %d\n", + hdr->regions.region_props[i].region_id); + nvkm_debug(subdev, "\t readMask : 0x%x\n", + hdr->regions.region_props[i].read_mask); + nvkm_debug(subdev, "\t writeMask : 0x%x\n", + hdr->regions.region_props[i].write_mask); + nvkm_debug(subdev, "\t clientMask : 0x%x\n", + hdr->regions.region_props[i].client_mask); + } + + nvkm_debug(subdev, "\tucodeBlobSize: %d\n", + hdr->ucode_blob_size); + nvkm_debug(subdev, "\tucodeBlobBase: 0x%llx\n", + hdr->ucode_blob_base); + nvkm_debug(subdev, "\tvprEnabled : %d\n", + hdr->vpr_desc.vpr_enabled); + nvkm_debug(subdev, "\tvprStart : 0x%x\n", + hdr->vpr_desc.vpr_start); + nvkm_debug(subdev, "\tvprEnd : 0x%x\n", + hdr->vpr_desc.vpr_end); + nvkm_debug(subdev, "\thdcpPolicies : 0x%x\n", + hdr->vpr_desc.hdcp_policies); +} + +void +flcn_acr_desc_v1_dump(struct nvkm_subdev *subdev, struct flcn_acr_desc_v1 *hdr) +{ + int i; + + nvkm_debug(subdev, "acrDesc\n"); + nvkm_debug(subdev, "\twprRegionId : %d\n", hdr->wpr_region_id); + nvkm_debug(subdev, "\twprOffset : 0x%x\n", hdr->wpr_offset); + nvkm_debug(subdev, "\tmmuMemoryRange : 0x%x\n", + hdr->mmu_memory_range); + nvkm_debug(subdev, "\tnoRegions : %d\n", + hdr->regions.no_regions); + + for (i = 0; i < ARRAY_SIZE(hdr->regions.region_props); i++) { + nvkm_debug(subdev, "\tregion[%d] :\n", i); + nvkm_debug(subdev, "\t startAddr : 0x%x\n", + hdr->regions.region_props[i].start_addr); + nvkm_debug(subdev, "\t endAddr : 0x%x\n", + hdr->regions.region_props[i].end_addr); + nvkm_debug(subdev, "\t regionId : %d\n", + hdr->regions.region_props[i].region_id); + nvkm_debug(subdev, "\t readMask : 0x%x\n", + hdr->regions.region_props[i].read_mask); + nvkm_debug(subdev, "\t writeMask : 0x%x\n", + hdr->regions.region_props[i].write_mask); + nvkm_debug(subdev, "\t clientMask : 0x%x\n", + hdr->regions.region_props[i].client_mask); + nvkm_debug(subdev, "\t shadowMemStartAddr: 0x%x\n", + hdr->regions.region_props[i].shadow_mem_start_addr); + } + + nvkm_debug(subdev, "\tucodeBlobSize : %d\n", + hdr->ucode_blob_size); + nvkm_debug(subdev, "\tucodeBlobBase : 0x%llx\n", + hdr->ucode_blob_base); + nvkm_debug(subdev, "\tvprEnabled : %d\n", + hdr->vpr_desc.vpr_enabled); + nvkm_debug(subdev, "\tvprStart : 0x%x\n", + hdr->vpr_desc.vpr_start); + nvkm_debug(subdev, "\tvprEnd : 0x%x\n", + hdr->vpr_desc.vpr_end); + nvkm_debug(subdev, "\thdcpPolicies : 0x%x\n", + hdr->vpr_desc.hdcp_policies); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.c new file mode 100644 index 000000000000..00ec764e1aab --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/flcn.c @@ -0,0 +1,115 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include +#include + +void +loader_config_dump(struct nvkm_subdev *subdev, const struct loader_config *hdr) +{ + nvkm_debug(subdev, "loaderConfig\n"); + nvkm_debug(subdev, "\tdmaIdx : %d\n", hdr->dma_idx); + nvkm_debug(subdev, "\tcodeDmaBase : 0x%xx\n", hdr->code_dma_base); + nvkm_debug(subdev, "\tcodeSizeTotal : 0x%x\n", hdr->code_size_total); + nvkm_debug(subdev, "\tcodeSizeToLoad: 0x%x\n", hdr->code_size_to_load); + nvkm_debug(subdev, "\tcodeEntryPoint: 0x%x\n", hdr->code_entry_point); + nvkm_debug(subdev, "\tdataDmaBase : 0x%x\n", hdr->data_dma_base); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\toverlayDmaBase: 0x%x\n", hdr->overlay_dma_base); + nvkm_debug(subdev, "\targc : 0x%08x\n", hdr->argc); + nvkm_debug(subdev, "\targv : 0x%08x\n", hdr->argv); + nvkm_debug(subdev, "\tcodeDmaBase1 : 0x%x\n", hdr->code_dma_base1); + nvkm_debug(subdev, "\tdataDmaBase1 : 0x%x\n", hdr->data_dma_base1); + nvkm_debug(subdev, "\tovlyDmaBase1 : 0x%x\n", hdr->overlay_dma_base1); +} + +void +loader_config_v1_dump(struct nvkm_subdev *subdev, + const struct loader_config_v1 *hdr) +{ + nvkm_debug(subdev, "loaderConfig\n"); + nvkm_debug(subdev, "\treserved : 0x%08x\n", hdr->reserved); + nvkm_debug(subdev, "\tdmaIdx : %d\n", hdr->dma_idx); + nvkm_debug(subdev, "\tcodeDmaBase : 0x%llxx\n", hdr->code_dma_base); + nvkm_debug(subdev, "\tcodeSizeTotal : 0x%x\n", hdr->code_size_total); + nvkm_debug(subdev, "\tcodeSizeToLoad: 0x%x\n", hdr->code_size_to_load); + nvkm_debug(subdev, "\tcodeEntryPoint: 0x%x\n", hdr->code_entry_point); + nvkm_debug(subdev, "\tdataDmaBase : 0x%llx\n", hdr->data_dma_base); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\toverlayDmaBase: 0x%llx\n", hdr->overlay_dma_base); + nvkm_debug(subdev, "\targc : 0x%08x\n", hdr->argc); + nvkm_debug(subdev, "\targv : 0x%08x\n", hdr->argv); +} + +void +flcn_bl_dmem_desc_dump(struct nvkm_subdev *subdev, + const struct flcn_bl_dmem_desc *hdr) +{ + nvkm_debug(subdev, "flcnBlDmemDesc\n"); + nvkm_debug(subdev, "\treserved : 0x%08x 0x%08x 0x%08x 0x%08x\n", + hdr->reserved[0], hdr->reserved[1], hdr->reserved[2], + hdr->reserved[3]); + nvkm_debug(subdev, "\tsignature : 0x%08x 0x%08x 0x%08x 0x%08x\n", + hdr->signature[0], hdr->signature[1], hdr->signature[2], + hdr->signature[3]); + nvkm_debug(subdev, "\tctxDma : %d\n", hdr->ctx_dma); + nvkm_debug(subdev, "\tcodeDmaBase : 0x%x\n", hdr->code_dma_base); + nvkm_debug(subdev, "\tnonSecCodeOff : 0x%x\n", hdr->non_sec_code_off); + nvkm_debug(subdev, "\tnonSecCodeSize: 0x%x\n", hdr->non_sec_code_size); + nvkm_debug(subdev, "\tsecCodeOff : 0x%x\n", hdr->sec_code_off); + nvkm_debug(subdev, "\tsecCodeSize : 0x%x\n", hdr->sec_code_size); + nvkm_debug(subdev, "\tcodeEntryPoint: 0x%x\n", hdr->code_entry_point); + nvkm_debug(subdev, "\tdataDmaBase : 0x%x\n", hdr->data_dma_base); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); + nvkm_debug(subdev, "\tcodeDmaBase1 : 0x%x\n", hdr->code_dma_base1); + nvkm_debug(subdev, "\tdataDmaBase1 : 0x%x\n", hdr->data_dma_base1); +} + +void +flcn_bl_dmem_desc_v1_dump(struct nvkm_subdev *subdev, + const struct flcn_bl_dmem_desc_v1 *hdr) +{ + nvkm_debug(subdev, "flcnBlDmemDesc\n"); + nvkm_debug(subdev, "\treserved : 0x%08x 0x%08x 0x%08x 0x%08x\n", + hdr->reserved[0], hdr->reserved[1], hdr->reserved[2], + hdr->reserved[3]); + nvkm_debug(subdev, "\tsignature : 0x%08x 0x%08x 0x%08x 0x%08x\n", + hdr->signature[0], hdr->signature[1], hdr->signature[2], + hdr->signature[3]); + nvkm_debug(subdev, "\tctxDma : %d\n", hdr->ctx_dma); + nvkm_debug(subdev, "\tcodeDmaBase : 0x%llx\n", hdr->code_dma_base); + nvkm_debug(subdev, "\tnonSecCodeOff : 0x%x\n", hdr->non_sec_code_off); + nvkm_debug(subdev, "\tnonSecCodeSize: 0x%x\n", hdr->non_sec_code_size); + nvkm_debug(subdev, "\tsecCodeOff : 0x%x\n", hdr->sec_code_off); + nvkm_debug(subdev, "\tsecCodeSize : 0x%x\n", hdr->sec_code_size); + nvkm_debug(subdev, "\tcodeEntryPoint: 0x%x\n", hdr->code_entry_point); + nvkm_debug(subdev, "\tdataDmaBase : 0x%llx\n", hdr->data_dma_base); + nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size); +} + +void +flcn_bl_dmem_desc_v2_dump(struct nvkm_subdev *subdev, + const struct flcn_bl_dmem_desc_v2 *hdr) +{ + flcn_bl_dmem_desc_v1_dump(subdev, (void *)hdr); + nvkm_debug(subdev, "\targc : 0x%08x\n", hdr->argc); + nvkm_debug(subdev, "\targv : 0x%08x\n", hdr->argv); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index 4f7d8aa1f625..4a77f3a0853f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -1,5 +1,6 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/subdev/acr/base.o +nvkm-y += nvkm/subdev/acr/hsfw.o nvkm-y += nvkm/subdev/acr/lsfw.o nvkm-y += nvkm/subdev/acr/gm200.o nvkm-y += nvkm/subdev/acr/gm20b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index 1d18e38d9c61..c154f3b9d536 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -22,6 +22,101 @@ #include "priv.h" #include +#include +#include + +static struct nvkm_acr_hsf * +nvkm_acr_hsf_find(struct nvkm_acr *acr, const char *name) +{ + struct nvkm_acr_hsf *hsf; + list_for_each_entry(hsf, &acr->hsf, head) { + if (!strcmp(hsf->name, name)) + return hsf; + } + return NULL; +} + +int +nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_acr_hsf *hsf; + int ret; + + hsf = nvkm_acr_hsf_find(acr, name); + if (!hsf) + return -EINVAL; + + nvkm_debug(subdev, "executing %s binary\n", hsf->name); + ret = nvkm_falcon_get(hsf->falcon, subdev); + if (ret) + return ret; + + ret = hsf->func->boot(acr, hsf); + nvkm_falcon_put(hsf->falcon, subdev); + if (ret) { + nvkm_error(subdev, "%s binary failed\n", hsf->name); + return ret; + } + + nvkm_debug(subdev, "%s binary completed successfully\n", hsf->name); + return 0; +} + +static void +nvkm_acr_unload(struct nvkm_acr *acr) +{ + if (acr->done) { + nvkm_acr_hsf_boot(acr, "unload"); + acr->done = false; + } +} + +static int +nvkm_acr_load(struct nvkm_acr *acr) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_acr_lsf *lsf; + u64 start, limit; + int ret; + + if (list_empty(&acr->lsf)) { + nvkm_debug(subdev, "No LSF(s) present.\n"); + return 0; + } + + ret = acr->func->init(acr); + if (ret) + return ret; + + acr->func->wpr_check(acr, &start, &limit); + + if (start != acr->wpr_start || limit != acr->wpr_end) { + nvkm_error(subdev, "WPR not configured as expected: " + "%016llx-%016llx vs %016llx-%016llx\n", + acr->wpr_start, acr->wpr_end, start, limit); + return -EIO; + } + + acr->done = true; + + list_for_each_entry(lsf, &acr->lsf, head) { + if (lsf->func->boot) { + ret = lsf->func->boot(lsf->falcon); + if (ret) + break; + } + } + + return ret; +} + +static int +nvkm_acr_reload(struct nvkm_acr *acr) +{ + nvkm_acr_unload(acr); + return nvkm_acr_load(acr); +} static struct nvkm_acr_lsf * nvkm_acr_falcon(struct nvkm_device *device) @@ -43,10 +138,16 @@ int nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) { struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device); + struct nvkm_acr *acr = device->acr; unsigned long id; - if (!acrflcn) - return -ENOSYS; + if (!acrflcn) { + int ret = nvkm_acr_reload(acr); + if (ret) + return ret; + + return acr->done ? 0 : -EINVAL; + } if (acrflcn->func->bootstrap_multiple_falcons) { return acrflcn->func-> @@ -62,41 +163,79 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) return 0; } -int -nvkm_acr_boot_ls_falcons(struct nvkm_device *device) +bool +nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id) { struct nvkm_acr *acr = device->acr; struct nvkm_acr_lsf *lsf; - int ret; - if (!acr) - return -ENOSYS; - - list_for_each_entry(lsf, &acr->lsf, head) { - if (lsf->func->boot) { - ret = lsf->func->boot(lsf->falcon); - if (ret) - break; + if (acr) { + list_for_each_entry(lsf, &acr->lsf, head) { + if (lsf->id == id) + return true; } } - return ret; + return false; +} + +static int +nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend) +{ + nvkm_acr_unload(nvkm_acr(subdev)); + return 0; +} + +static int +nvkm_acr_init(struct nvkm_subdev *subdev) +{ + if (!nvkm_acr_falcon(subdev->device)) + return 0; + + return nvkm_acr_load(nvkm_acr(subdev)); } static void nvkm_acr_cleanup(struct nvkm_acr *acr) { nvkm_acr_lsfw_del_all(acr); + nvkm_acr_hsfw_del_all(acr); + nvkm_firmware_put(acr->wpr_fw); + acr->wpr_fw = NULL; } static int nvkm_acr_oneinit(struct nvkm_subdev *subdev) { + struct nvkm_device *device = subdev->device; struct nvkm_acr *acr = nvkm_acr(subdev); - struct nvkm_acr_lsfw *lsfw; + struct nvkm_acr_hsfw *hsfw; + struct nvkm_acr_lsfw *lsfw, *lsft; struct nvkm_acr_lsf *lsf; + u32 wpr_size = 0; + int ret, i; + + /* Determine layout/size of WPR image up-front, as we need to know + * it to allocate memory before we begin constructing it. + */ + list_for_each_entry_safe(lsfw, lsft, &acr->lsfw, head) { + /* Cull unknown falcons that are present in WPR image. */ + if (acr->wpr_fw) { + if (!lsfw->func) { + nvkm_acr_lsfw_del(lsfw); + continue; + } + + wpr_size = acr->wpr_fw->size; + } + + /* Ensure we've fetched falcon configuration. */ + ret = nvkm_falcon_get(lsfw->falcon, subdev); + if (ret) + return ret; + + nvkm_falcon_put(lsfw->falcon, subdev); - list_for_each_entry(lsfw, &acr->lsfw, head) { if (!(lsf = kmalloc(sizeof(*lsf), GFP_KERNEL))) return -ENOMEM; lsf->func = lsfw->func; @@ -105,6 +244,70 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) list_add_tail(&lsf->head, &acr->lsf); } + if (!acr->wpr_fw || acr->wpr_comp) + wpr_size = acr->func->wpr_layout(acr); + + /* Allocate/Locate WPR + fill ucode blob pointer. + * + * dGPU: allocate WPR + shadow blob + * Tegra: locate WPR with regs, ensure size is sufficient, + * allocate ucode blob. + */ + ret = acr->func->wpr_alloc(acr, wpr_size); + if (ret) + return ret; + + nvkm_debug(subdev, "WPR region is from 0x%llx-0x%llx (shadow 0x%llx)\n", + acr->wpr_start, acr->wpr_end, acr->shadow_start); + + /* Write WPR to ucode blob. */ + nvkm_kmap(acr->wpr); + if (acr->wpr_fw && !acr->wpr_comp) + nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size); + + if (!acr->wpr_fw || acr->wpr_comp) + acr->func->wpr_build(acr, nvkm_acr_falcon(device)); + acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev); + + if (acr->wpr_fw && acr->wpr_comp) { + nvkm_kmap(acr->wpr); + for (i = 0; i < acr->wpr_fw->size; i += 4) { + u32 us = nvkm_ro32(acr->wpr, i); + u32 fw = ((u32 *)acr->wpr_fw->data)[i/4]; + if (fw != us) { + nvkm_warn(subdev, "%08x: %08x %08x\n", + i, us, fw); + } + } + return -EINVAL; + } + nvkm_done(acr->wpr); + + /* Allocate instance block for ACR-related stuff. */ + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true, + &acr->inst); + if (ret) + return ret; + + ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "acr", &acr->vmm); + if (ret) + return ret; + + acr->vmm->debug = acr->subdev.debug; + + ret = nvkm_vmm_join(acr->vmm, acr->inst); + if (ret) + return ret; + + /* Load HS firmware blobs into ACR VMM. */ + list_for_each_entry(hsfw, &acr->hsfw, head) { + nvkm_debug(subdev, "loading %s fw\n", hsfw->name); + ret = hsfw->func->load(acr, hsfw); + if (ret) + return ret; + } + + /* Kill temporary data. */ nvkm_acr_cleanup(acr); return 0; } @@ -113,8 +316,23 @@ static void * nvkm_acr_dtor(struct nvkm_subdev *subdev) { struct nvkm_acr *acr = nvkm_acr(subdev); + struct nvkm_acr_hsf *hsf, *hst; struct nvkm_acr_lsf *lsf, *lst; + list_for_each_entry_safe(hsf, hst, &acr->hsf, head) { + nvkm_vmm_put(acr->vmm, &hsf->vma); + nvkm_memory_unref(&hsf->ucode); + kfree(hsf->imem); + list_del(&hsf->head); + kfree(hsf); + } + + nvkm_vmm_part(acr->vmm, acr->inst); + nvkm_vmm_unref(&acr->vmm); + nvkm_memory_unref(&acr->inst); + + nvkm_memory_unref(&acr->wpr); + list_for_each_entry_safe(lsf, lst, &acr->lsf, head) { list_del(&lsf->head); kfree(lsf); @@ -128,18 +346,47 @@ static const struct nvkm_subdev_func nvkm_acr = { .dtor = nvkm_acr_dtor, .oneinit = nvkm_acr_oneinit, + .init = nvkm_acr_init, + .fini = nvkm_acr_fini, }; +static int +nvkm_acr_ctor_wpr(struct nvkm_acr *acr, int ver) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_device *device = subdev->device; + int ret; + + ret = nvkm_firmware_get_version(subdev, "acr/wpr", ver, ver, + &acr->wpr_fw); + if (ret < 0) + return ret; + + /* Pre-add LSFs in the order they appear in the FW WPR image so that + * we're able to do a binary comparison with our own generator. + */ + ret = acr->func->wpr_parse(acr); + if (ret) + return ret; + + acr->wpr_comp = nvkm_boolopt(device->cfgopt, "NvAcrWprCompare", false); + acr->wpr_prev = nvkm_longopt(device->cfgopt, "NvAcrWprPrevAddr", 0); + return 0; +} + int nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, int index, struct nvkm_acr **pacr) { struct nvkm_acr *acr; + long wprfw; if (!(acr = *pacr = kzalloc(sizeof(*acr), GFP_KERNEL))) return -ENOMEM; nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev); + INIT_LIST_HEAD(&acr->hsfw); INIT_LIST_HEAD(&acr->lsfw); + INIT_LIST_HEAD(&acr->hsf); INIT_LIST_HEAD(&acr->lsf); fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr); @@ -147,5 +394,13 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device, return PTR_ERR(fwif); acr->func = fwif->func; + + wprfw = nvkm_longopt(device->cfgopt, "NvAcrWpr", -1); + if (wprfw >= 0) { + int ret = nvkm_acr_ctor_wpr(acr, wprfw); + if (ret) + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c index d04472de3e64..9a6394085cf0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c @@ -21,11 +21,391 @@ */ #include "priv.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +int +gm200_acr_init(struct nvkm_acr *acr) +{ + return nvkm_acr_hsf_boot(acr, "load"); +} + +void +gm200_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit) +{ + struct nvkm_device *device = acr->subdev.device; + + nvkm_wr32(device, 0x100cd4, 2); + *start = (u64)(nvkm_rd32(device, 0x100cd4) & 0xffffff00) << 8; + nvkm_wr32(device, 0x100cd4, 3); + *limit = (u64)(nvkm_rd32(device, 0x100cd4) & 0xffffff00) << 8; + *limit = *limit + 0x20000; +} + +void +gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct wpr_header hdr; + struct lsb_header lsb; + struct nvkm_acr_lsf *lsfw; + u32 offset = 0; + + do { + nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr)); + wpr_header_dump(subdev, &hdr); + + list_for_each_entry(lsfw, &acr->lsfw, head) { + if (lsfw->id != hdr.falcon_id) + continue; + + nvkm_robj(acr->wpr, hdr.lsb_offset, &lsb, sizeof(lsb)); + lsb_header_dump(subdev, &lsb); + + lsfw->func->bld_patch(acr, lsb.tail.bl_data_off, adjust); + break; + } + offset += sizeof(hdr); + } while (hdr.falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID); +} + +void +gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *lsfw, + struct lsb_header_tail *hdr) +{ + hdr->ucode_off = lsfw->offset.img; + hdr->ucode_size = lsfw->ucode_size; + hdr->data_size = lsfw->data_size; + hdr->bl_code_size = lsfw->bootloader_size; + hdr->bl_imem_off = lsfw->bootloader_imem_offset; + hdr->bl_data_off = lsfw->offset.bld; + hdr->bl_data_size = lsfw->bl_data_size; + hdr->app_code_off = lsfw->app_start_offset + + lsfw->app_resident_code_offset; + hdr->app_code_size = lsfw->app_resident_code_size; + hdr->app_data_off = lsfw->app_start_offset + + lsfw->app_resident_data_offset; + hdr->app_data_size = lsfw->app_resident_data_size; + hdr->flags = lsfw->func->flags; +} + +static int +gm200_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw) +{ + struct lsb_header hdr; + + if (WARN_ON(lsfw->sig->size != sizeof(hdr.signature))) + return -EINVAL; + + memcpy(&hdr.signature, lsfw->sig->data, lsfw->sig->size); + gm200_acr_wpr_build_lsb_tail(lsfw, &hdr.tail); + + nvkm_wobj(acr->wpr, lsfw->offset.lsb, &hdr, sizeof(hdr)); + return 0; +} + +int +gm200_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos) +{ + struct nvkm_acr_lsfw *lsfw; + u32 offset = 0; + int ret; + + /* Fill per-LSF structures. */ + list_for_each_entry(lsfw, &acr->lsfw, head) { + struct wpr_header hdr = { + .falcon_id = lsfw->id, + .lsb_offset = lsfw->offset.lsb, + .bootstrap_owner = NVKM_ACR_LSF_PMU, + .lazy_bootstrap = rtos && lsfw->id != rtos->id, + .status = WPR_HEADER_V0_STATUS_COPY, + }; + + /* Write WPR header. */ + nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr)); + offset += sizeof(hdr); + + /* Write LSB header. */ + ret = gm200_acr_wpr_build_lsb(acr, lsfw); + if (ret) + return ret; + + /* Write ucode image. */ + nvkm_wobj(acr->wpr, lsfw->offset.img, + lsfw->img.data, + lsfw->img.size); + + /* Write bootloader data. */ + lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw); + } + + /* Finalise WPR. */ + nvkm_wo32(acr->wpr, offset, WPR_HEADER_V0_FALCON_ID_INVALID); + return 0; +} + +static int +gm200_acr_wpr_alloc(struct nvkm_acr *acr, u32 wpr_size) +{ + int ret = nvkm_memory_new(acr->subdev.device, NVKM_MEM_TARGET_INST, + ALIGN(wpr_size, 0x40000), 0x40000, true, + &acr->wpr); + if (ret) + return ret; + + acr->wpr_start = nvkm_memory_addr(acr->wpr); + acr->wpr_end = acr->wpr_start + nvkm_memory_size(acr->wpr); + return 0; +} + +u32 +gm200_acr_wpr_layout(struct nvkm_acr *acr) +{ + struct nvkm_acr_lsfw *lsfw; + u32 wpr = 0; + + wpr += 11 /* MAX_LSF */ * sizeof(struct wpr_header); + + list_for_each_entry(lsfw, &acr->lsfw, head) { + wpr = ALIGN(wpr, 256); + lsfw->offset.lsb = wpr; + wpr += sizeof(struct lsb_header); + + wpr = ALIGN(wpr, 4096); + lsfw->offset.img = wpr; + wpr += lsfw->img.size; + + wpr = ALIGN(wpr, 256); + lsfw->offset.bld = wpr; + lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256); + wpr += lsfw->bl_data_size; + } + + return wpr; +} + +int +gm200_acr_wpr_parse(struct nvkm_acr *acr) +{ + const struct wpr_header *hdr = (void *)acr->wpr_fw->data; + + while (hdr->falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID) { + wpr_header_dump(&acr->subdev, hdr); + if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) + return -ENOMEM; + } + + return 0; +} + +void +gm200_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + struct flcn_bl_dmem_desc_v1 hsdesc = { + .ctx_dma = FALCON_DMAIDX_VIRT, + .code_dma_base = hsf->vma->addr, + .non_sec_code_off = hsf->non_sec_addr, + .non_sec_code_size = hsf->non_sec_size, + .sec_code_off = hsf->sec_addr, + .sec_code_size = hsf->sec_size, + .code_entry_point = 0, + .data_dma_base = hsf->vma->addr + hsf->data_addr, + .data_size = hsf->data_size, + }; + + flcn_bl_dmem_desc_v1_dump(&acr->subdev, &hsdesc); + + nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); +} + +int +gm200_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf, + u32 intr_clear, u32 mbox0_ok) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_device *device = subdev->device; + struct nvkm_falcon *falcon = hsf->falcon; + u32 mbox0, mbox1; + int ret; + + /* Reset falcon. */ + nvkm_falcon_reset(falcon); + nvkm_falcon_bind_context(falcon, acr->inst); + + /* Load bootloader into IMEM. */ + nvkm_falcon_load_imem(falcon, hsf->imem, + falcon->code.limit - hsf->imem_size, + hsf->imem_size, + hsf->imem_tag, + 0, false); + + /* Load bootloader data into DMEM. */ + hsf->func->bld(acr, hsf); + + /* Boot the falcon. */ + nvkm_mc_intr_mask(device, falcon->owner->index, false); + + nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5); + nvkm_falcon_set_start_addr(falcon, hsf->imem_tag << 8); + nvkm_falcon_start(falcon); + ret = nvkm_falcon_wait_for_halt(falcon, 100); + if (ret) + return ret; + + /* Check for successful completion. */ + mbox0 = nvkm_falcon_rd32(falcon, 0x040); + mbox1 = nvkm_falcon_rd32(falcon, 0x044); + nvkm_debug(subdev, "mailbox %08x %08x\n", mbox0, mbox1); + if (mbox0 && mbox0 != mbox0_ok) + return -EIO; + + nvkm_falcon_clear_interrupt(falcon, intr_clear); + nvkm_mc_intr_mask(device, falcon->owner->index, true); + return ret; +} + +int +gm200_acr_hsfw_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw, + struct nvkm_falcon *falcon) +{ + struct nvkm_subdev *subdev = &acr->subdev; + struct nvkm_acr_hsf *hsf; + int ret; + + /* Patch the appropriate signature (production/debug) into the FW + * image, as determined by the mode the falcon is in. + */ + ret = nvkm_falcon_get(falcon, subdev); + if (ret) + return ret; + + if (hsfw->sig.patch_loc) { + if (!falcon->debug) { + nvkm_debug(subdev, "patching production signature\n"); + memcpy(hsfw->image + hsfw->sig.patch_loc, + hsfw->sig.prod.data, + hsfw->sig.prod.size); + } else { + nvkm_debug(subdev, "patching debug signature\n"); + memcpy(hsfw->image + hsfw->sig.patch_loc, + hsfw->sig.dbg.data, + hsfw->sig.dbg.size); + } + } + + nvkm_falcon_put(falcon, subdev); + + if (!(hsf = kzalloc(sizeof(*hsf), GFP_KERNEL))) + return -ENOMEM; + hsf->func = hsfw->func; + hsf->name = hsfw->name; + list_add_tail(&hsf->head, &acr->hsf); + + hsf->imem_size = hsfw->imem_size; + hsf->imem_tag = hsfw->imem_tag; + hsf->imem = kmemdup(hsfw->imem, hsfw->imem_size, GFP_KERNEL); + if (!hsf->imem) + return -ENOMEM; + + hsf->non_sec_addr = hsfw->non_sec_addr; + hsf->non_sec_size = hsfw->non_sec_size; + hsf->sec_addr = hsfw->sec_addr; + hsf->sec_size = hsfw->sec_size; + hsf->data_addr = hsfw->data_addr; + hsf->data_size = hsfw->data_size; + + /* Make the FW image accessible to the HS bootloader. */ + ret = nvkm_memory_new(subdev->device, NVKM_MEM_TARGET_INST, + hsfw->image_size, 0x1000, false, &hsf->ucode); + if (ret) + return ret; + + nvkm_kmap(hsf->ucode); + nvkm_wobj(hsf->ucode, 0, hsfw->image, hsfw->image_size); + nvkm_done(hsf->ucode); + + ret = nvkm_vmm_get(acr->vmm, 12, nvkm_memory_size(hsf->ucode), + &hsf->vma); + if (ret) + return ret; + + ret = nvkm_memory_map(hsf->ucode, 0, acr->vmm, hsf->vma, NULL, 0); + if (ret) + return ret; + + hsf->falcon = falcon; + return 0; +} + +int +gm200_acr_unload_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + return gm200_acr_hsfw_boot(acr, hsf, 0, 0x1d); +} + +int +gm200_acr_unload_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +{ + return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); +} + +const struct nvkm_acr_hsf_func +gm200_acr_unload_0 = { + .load = gm200_acr_unload_load, + .boot = gm200_acr_unload_boot, + .bld = gm200_acr_hsfw_bld, +}; + MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gm204/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gm206/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin"); +static const struct nvkm_acr_hsf_fwif +gm200_acr_unload_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 }, + {} +}; + +int +gm200_acr_load_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + return gm200_acr_hsfw_boot(acr, hsf, 0x10, 0); +} + +static int +gm200_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +{ + struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr]; + + desc->wpr_region_id = 1; + desc->regions.no_regions = 2; + desc->regions.region_props[0].start_addr = acr->wpr_start >> 8; + desc->regions.region_props[0].end_addr = acr->wpr_end >> 8; + desc->regions.region_props[0].region_id = 1; + desc->regions.region_props[0].read_mask = 0xf; + desc->regions.region_props[0].write_mask = 0xc; + desc->regions.region_props[0].client_mask = 0x2; + flcn_acr_desc_dump(&acr->subdev, desc); + + return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); +} + +static const struct nvkm_acr_hsf_func +gm200_acr_load_0 = { + .load = gm200_acr_load_load, + .boot = gm200_acr_load_boot, + .bld = gm200_acr_hsfw_bld, +}; + MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gm200/acr/ucode_load.bin"); @@ -38,13 +418,42 @@ MODULE_FIRMWARE("nvidia/gm206/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gp100/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin"); +static const struct nvkm_acr_hsf_fwif +gm200_acr_load_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gm200_acr_load_0 }, + {} +}; + static const struct nvkm_acr_func gm200_acr = { + .load = gm200_acr_load_fwif, + .unload = gm200_acr_unload_fwif, + .wpr_parse = gm200_acr_wpr_parse, + .wpr_layout = gm200_acr_wpr_layout, + .wpr_alloc = gm200_acr_wpr_alloc, + .wpr_build = gm200_acr_wpr_build, + .wpr_patch = gm200_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, }; static int gm200_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) { + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvkm_acr_hsf_fwif *hsfwif; + + hsfwif = nvkm_firmware_load(subdev, fwif->func->load, "AcrLoad", + acr, "acr/bl", "acr/ucode_load", "load"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload", + acr, "acr/bl", "acr/ucode_unload", + "unload"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c index 2e56b90c25da..034a6ede70c7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c @@ -21,18 +21,103 @@ */ #include "priv.h" +#include +#include +#include +#include + +#include +#include + +int +gm20b_acr_wpr_alloc(struct nvkm_acr *acr, u32 wpr_size) +{ + struct nvkm_subdev *subdev = &acr->subdev; + + acr->func->wpr_check(acr, &acr->wpr_start, &acr->wpr_end); + + if ((acr->wpr_end - acr->wpr_start) < wpr_size) { + nvkm_error(subdev, "WPR image too big for WPR!\n"); + return -ENOSPC; + } + + return nvkm_memory_new(subdev->device, NVKM_MEM_TARGET_INST, + wpr_size, 0, true, &acr->wpr); +} + +static void +gm20b_acr_load_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + struct flcn_bl_dmem_desc hsdesc = { + .ctx_dma = FALCON_DMAIDX_VIRT, + .code_dma_base = hsf->vma->addr >> 8, + .non_sec_code_off = hsf->non_sec_addr, + .non_sec_code_size = hsf->non_sec_size, + .sec_code_off = hsf->sec_addr, + .sec_code_size = hsf->sec_size, + .code_entry_point = 0, + .data_dma_base = (hsf->vma->addr + hsf->data_addr) >> 8, + .data_size = hsf->data_size, + }; + + flcn_bl_dmem_desc_dump(&acr->subdev, &hsdesc); + + nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); +} + +static int +gm20b_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +{ + struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr]; + + desc->ucode_blob_base = nvkm_memory_addr(acr->wpr); + desc->ucode_blob_size = nvkm_memory_size(acr->wpr); + flcn_acr_desc_dump(&acr->subdev, desc); + + return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon); +} + +const struct nvkm_acr_hsf_func +gm20b_acr_load_0 = { + .load = gm20b_acr_load_load, + .boot = gm200_acr_load_boot, + .bld = gm20b_acr_load_bld, +}; + #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) MODULE_FIRMWARE("nvidia/gm20b/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin"); #endif +static const struct nvkm_acr_hsf_fwif +gm20b_acr_load_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 }, + {} +}; + static const struct nvkm_acr_func gm20b_acr = { + .load = gm20b_acr_load_fwif, + .wpr_parse = gm200_acr_wpr_parse, + .wpr_layout = gm200_acr_wpr_layout, + .wpr_alloc = gm20b_acr_wpr_alloc, + .wpr_build = gm200_acr_wpr_build, + .wpr_patch = gm200_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, }; int gm20b_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) { + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvkm_acr_hsf_fwif *hsfwif; + + hsfwif = nvkm_firmware_load(subdev, fwif->func->load, "AcrLoad", + acr, "acr/bl", "acr/ucode_load", "load"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c index d85dc19546a6..49e11c46d525 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c @@ -21,6 +21,156 @@ */ #include "priv.h" +#include +#include +#include +#include + +#include +#include + +void +gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust) +{ + struct wpr_header_v1 hdr; + struct lsb_header_v1 lsb; + struct nvkm_acr_lsfw *lsfw; + u32 offset = 0; + + do { + nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr)); + wpr_header_v1_dump(&acr->subdev, &hdr); + + list_for_each_entry(lsfw, &acr->lsfw, head) { + if (lsfw->id != hdr.falcon_id) + continue; + + nvkm_robj(acr->wpr, hdr.lsb_offset, &lsb, sizeof(lsb)); + lsb_header_v1_dump(&acr->subdev, &lsb); + + lsfw->func->bld_patch(acr, lsb.tail.bl_data_off, adjust); + break; + } + + offset += sizeof(hdr); + } while (hdr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID); +} + +int +gp102_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw) +{ + struct lsb_header_v1 hdr; + + if (WARN_ON(lsfw->sig->size != sizeof(hdr.signature))) + return -EINVAL; + + memcpy(&hdr.signature, lsfw->sig->data, lsfw->sig->size); + gm200_acr_wpr_build_lsb_tail(lsfw, &hdr.tail); + + nvkm_wobj(acr->wpr, lsfw->offset.lsb, &hdr, sizeof(hdr)); + return 0; +} + +int +gp102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos) +{ + struct nvkm_acr_lsfw *lsfw; + u32 offset = 0; + int ret; + + /* Fill per-LSF structures. */ + list_for_each_entry(lsfw, &acr->lsfw, head) { + struct lsf_signature_v1 *sig = (void *)lsfw->sig->data; + struct wpr_header_v1 hdr = { + .falcon_id = lsfw->id, + .lsb_offset = lsfw->offset.lsb, + .bootstrap_owner = NVKM_ACR_LSF_SEC2, + .lazy_bootstrap = rtos && lsfw->id != rtos->id, + .bin_version = sig->version, + .status = WPR_HEADER_V1_STATUS_COPY, + }; + + /* Write WPR header. */ + nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr)); + offset += sizeof(hdr); + + /* Write LSB header. */ + ret = gp102_acr_wpr_build_lsb(acr, lsfw); + if (ret) + return ret; + + /* Write ucode image. */ + nvkm_wobj(acr->wpr, lsfw->offset.img, + lsfw->img.data, + lsfw->img.size); + + /* Write bootloader data. */ + lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw); + } + + /* Finalise WPR. */ + nvkm_wo32(acr->wpr, offset, WPR_HEADER_V1_FALCON_ID_INVALID); + return 0; +} + +int +gp102_acr_wpr_alloc(struct nvkm_acr *acr, u32 wpr_size) +{ + int ret = nvkm_memory_new(acr->subdev.device, NVKM_MEM_TARGET_INST, + ALIGN(wpr_size, 0x40000) << 1, 0x40000, true, + &acr->wpr); + if (ret) + return ret; + + acr->shadow_start = nvkm_memory_addr(acr->wpr); + acr->wpr_start = acr->shadow_start + (nvkm_memory_size(acr->wpr) >> 1); + acr->wpr_end = acr->wpr_start + (nvkm_memory_size(acr->wpr) >> 1); + return 0; +} + +u32 +gp102_acr_wpr_layout(struct nvkm_acr *acr) +{ + struct nvkm_acr_lsfw *lsfw; + u32 wpr = 0; + + wpr += 11 /* MAX_LSF */ * sizeof(struct wpr_header_v1); + wpr = ALIGN(wpr, 256); + + wpr += 0x100; /* Shared sub-WPR headers. */ + + list_for_each_entry(lsfw, &acr->lsfw, head) { + wpr = ALIGN(wpr, 256); + lsfw->offset.lsb = wpr; + wpr += sizeof(struct lsb_header_v1); + + wpr = ALIGN(wpr, 4096); + lsfw->offset.img = wpr; + wpr += lsfw->img.size; + + wpr = ALIGN(wpr, 256); + lsfw->offset.bld = wpr; + lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256); + wpr += lsfw->bl_data_size; + } + + return wpr; +} + +int +gp102_acr_wpr_parse(struct nvkm_acr *acr) +{ + const struct wpr_header_v1 *hdr = (void *)acr->wpr_fw->data; + + while (hdr->falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) { + wpr_header_v1_dump(&acr->subdev, hdr); + if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->falcon_id)) + return -ENOMEM; + } + + return 0; +} + MODULE_FIRMWARE("nvidia/gp102/acr/unload_bl.bin"); MODULE_FIRMWARE("nvidia/gp102/acr/ucode_unload.bin"); @@ -33,6 +183,40 @@ MODULE_FIRMWARE("nvidia/gp106/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gp107/acr/unload_bl.bin"); MODULE_FIRMWARE("nvidia/gp107/acr/ucode_unload.bin"); +static const struct nvkm_acr_hsf_fwif +gp102_acr_unload_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 }, + {} +}; + +int +gp102_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +{ + struct flcn_acr_desc_v1 *desc = (void *)&hsfw->image[hsfw->data_addr]; + + desc->wpr_region_id = 1; + desc->regions.no_regions = 2; + desc->regions.region_props[0].start_addr = acr->wpr_start >> 8; + desc->regions.region_props[0].end_addr = acr->wpr_end >> 8; + desc->regions.region_props[0].region_id = 1; + desc->regions.region_props[0].read_mask = 0xf; + desc->regions.region_props[0].write_mask = 0xc; + desc->regions.region_props[0].client_mask = 0x2; + desc->regions.region_props[0].shadow_mem_start_addr = + acr->shadow_start >> 8; + flcn_acr_desc_v1_dump(&acr->subdev, desc); + + return gm200_acr_hsfw_load(acr, hsfw, + &acr->subdev.device->sec2->falcon); +} + +static const struct nvkm_acr_hsf_func +gp102_acr_load_0 = { + .load = gp102_acr_load_load, + .boot = gm200_acr_load_boot, + .bld = gm200_acr_hsfw_bld, +}; + MODULE_FIRMWARE("nvidia/gp102/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp102/acr/ucode_load.bin"); @@ -45,13 +229,42 @@ MODULE_FIRMWARE("nvidia/gp106/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gp107/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin"); +static const struct nvkm_acr_hsf_fwif +gp102_acr_load_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gp102_acr_load_0 }, + {} +}; + static const struct nvkm_acr_func gp102_acr = { + .load = gp102_acr_load_fwif, + .unload = gp102_acr_unload_fwif, + .wpr_parse = gp102_acr_wpr_parse, + .wpr_layout = gp102_acr_wpr_layout, + .wpr_alloc = gp102_acr_wpr_alloc, + .wpr_build = gp102_acr_wpr_build, + .wpr_patch = gp102_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, }; int gp102_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) { + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvkm_acr_hsf_fwif *hsfwif; + + hsfwif = nvkm_firmware_load(subdev, fwif->func->load, "AcrLoad", + acr, "acr/bl", "acr/ucode_load", "load"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload", + acr, "acr/unload_bl", "acr/ucode_unload", + "unload"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c index 7c9e0375cafd..f10dc9112678 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c @@ -21,20 +21,81 @@ */ #include "priv.h" +#include + +#include + +void +gp108_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + struct flcn_bl_dmem_desc_v2 hsdesc = { + .ctx_dma = FALCON_DMAIDX_VIRT, + .code_dma_base = hsf->vma->addr, + .non_sec_code_off = hsf->non_sec_addr, + .non_sec_code_size = hsf->non_sec_size, + .sec_code_off = hsf->sec_addr, + .sec_code_size = hsf->sec_size, + .code_entry_point = 0, + .data_dma_base = hsf->vma->addr + hsf->data_addr, + .data_size = hsf->data_size, + .argc = 0, + .argv = 0, + }; + + flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hsdesc); + + nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0); +} + +const struct nvkm_acr_hsf_func +gp108_acr_unload_0 = { + .load = gm200_acr_unload_load, + .boot = gm200_acr_unload_boot, + .bld = gp108_acr_hsfw_bld, +}; + MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin"); MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin"); MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin"); MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin"); +static const struct nvkm_acr_hsf_fwif +gp108_acr_unload_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 }, + {} +}; + +static const struct nvkm_acr_hsf_func +gp108_acr_load_0 = { + .load = gp102_acr_load_load, + .boot = gm200_acr_load_boot, + .bld = gp108_acr_hsfw_bld, +}; + MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin"); +static const struct nvkm_acr_hsf_fwif +gp108_acr_load_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gp108_acr_load_0 }, + {} +}; + static const struct nvkm_acr_func gp108_acr = { + .load = gp108_acr_load_fwif, + .unload = gp108_acr_unload_fwif, + .wpr_parse = gp102_acr_wpr_parse, + .wpr_layout = gp102_acr_wpr_layout, + .wpr_alloc = gp102_acr_wpr_alloc, + .wpr_build = gp102_acr_wpr_build, + .wpr_patch = gp102_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, }; static const struct nvkm_acr_fwif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c index 6ee27829d588..39de64292a41 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c @@ -26,8 +26,22 @@ MODULE_FIRMWARE("nvidia/gp10b/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin"); #endif +static const struct nvkm_acr_hsf_fwif +gp10b_acr_load_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 }, + {} +}; + static const struct nvkm_acr_func gp10b_acr = { + .load = gp10b_acr_load_fwif, + .wpr_parse = gm200_acr_wpr_parse, + .wpr_layout = gm200_acr_wpr_layout, + .wpr_alloc = gm20b_acr_wpr_alloc, + .wpr_build = gm200_acr_wpr_build, + .wpr_patch = gm200_acr_wpr_patch, + .wpr_check = gm200_acr_wpr_check, + .init = gm200_acr_init, }; static const struct nvkm_acr_fwif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c new file mode 100644 index 000000000000..7204bfa3877d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c @@ -0,0 +1,180 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#include + +#include +#include + +static void +nvkm_acr_hsfw_del(struct nvkm_acr_hsfw *hsfw) +{ + list_del(&hsfw->head); + kfree(hsfw->imem); + kfree(hsfw->image); + kfree(hsfw->sig.prod.data); + kfree(hsfw->sig.dbg.data); + kfree(hsfw); +} + +void +nvkm_acr_hsfw_del_all(struct nvkm_acr *acr) +{ + struct nvkm_acr_hsfw *hsfw, *hsft; + list_for_each_entry_safe(hsfw, hsft, &acr->hsfw, head) { + nvkm_acr_hsfw_del(hsfw); + } +} + +static int +nvkm_acr_hsfw_load_image(struct nvkm_acr *acr, const char *name, int ver, + struct nvkm_acr_hsfw *hsfw) +{ + struct nvkm_subdev *subdev = &acr->subdev; + const struct firmware *fw; + const struct nvfw_bin_hdr *hdr; + const struct nvfw_hs_header *fwhdr; + const struct nvfw_hs_load_header *lhdr; + u32 loc, sig; + int ret; + + ret = nvkm_firmware_get_version(subdev, name, ver, ver, &fw); + if (ret < 0) + return ret; + + hdr = nvfw_bin_hdr(subdev, fw->data); + fwhdr = nvfw_hs_header(subdev, fw->data + hdr->header_offset); + + /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's + * standard format, and don't have the indirection seen in the 0x10de + * case. + */ + switch (hdr->bin_magic) { + case 0x000010de: + loc = *(u32 *)(fw->data + fwhdr->patch_loc); + sig = *(u32 *)(fw->data + fwhdr->patch_sig); + break; + case 0x3b1d14f0: + loc = fwhdr->patch_loc; + sig = fwhdr->patch_sig; + break; + default: + ret = -EINVAL; + goto done; + } + + lhdr = nvfw_hs_load_header(subdev, fw->data + fwhdr->hdr_offset); + + if (!(hsfw->image = kmalloc(hdr->data_size, GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + memcpy(hsfw->image, fw->data + hdr->data_offset, hdr->data_size); + hsfw->image_size = hdr->data_size; + hsfw->non_sec_addr = lhdr->non_sec_code_off; + hsfw->non_sec_size = lhdr->non_sec_code_size; + hsfw->sec_addr = lhdr->apps[0]; + hsfw->sec_size = lhdr->apps[lhdr->num_apps]; + hsfw->data_addr = lhdr->data_dma_base; + hsfw->data_size = lhdr->data_size; + + hsfw->sig.prod.size = fwhdr->sig_prod_size; + hsfw->sig.prod.data = kmalloc(hsfw->sig.prod.size, GFP_KERNEL); + if (!hsfw->sig.prod.data) { + ret = -ENOMEM; + goto done; + } + + memcpy(hsfw->sig.prod.data, fw->data + fwhdr->sig_prod_offset + sig, + hsfw->sig.prod.size); + + hsfw->sig.dbg.size = fwhdr->sig_dbg_size; + hsfw->sig.dbg.data = kmalloc(hsfw->sig.dbg.size, GFP_KERNEL); + if (!hsfw->sig.dbg.data) { + ret = -ENOMEM; + goto done; + } + + memcpy(hsfw->sig.dbg.data, fw->data + fwhdr->sig_dbg_offset + sig, + hsfw->sig.dbg.size); + + hsfw->sig.patch_loc = loc; +done: + nvkm_firmware_put(fw); + return ret; +} + +static int +nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver, + struct nvkm_acr_hsfw *hsfw) +{ + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvfw_bin_hdr *hdr; + const struct nvfw_bl_desc *desc; + const struct firmware *fw; + u8 *data; + int ret; + + ret = nvkm_firmware_get_version(subdev, name, ver, ver, &fw); + if (ret) + return ret; + + hdr = nvfw_bin_hdr(subdev, fw->data); + desc = nvfw_bl_desc(subdev, fw->data + hdr->header_offset); + data = (void *)fw->data + hdr->data_offset; + + hsfw->imem_size = desc->code_size; + hsfw->imem_tag = desc->start_tag; + hsfw->imem = kmalloc(desc->code_size, GFP_KERNEL); + memcpy(hsfw->imem, data + desc->code_off, desc->code_size); + + nvkm_firmware_put(fw); + return 0; +} + +int +nvkm_acr_hsfw_load(struct nvkm_acr *acr, const char *bl, const char *fw, + const char *name, int version, + const struct nvkm_acr_hsf_fwif *fwif) +{ + struct nvkm_acr_hsfw *hsfw; + int ret; + + if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL))) + return -ENOMEM; + + hsfw->func = fwif->func; + hsfw->name = name; + list_add_tail(&hsfw->head, &acr->hsfw); + + ret = nvkm_acr_hsfw_load_bl(acr, bl, version, hsfw); + if (ret) + goto done; + + ret = nvkm_acr_hsfw_load_image(acr, fw, version, hsfw); +done: + if (ret) + nvkm_acr_hsfw_del(hsfw); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index 808ba7f191b4..d8ba72806d39 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -1,6 +1,7 @@ #ifndef __NVKM_ACR_PRIV_H__ #define __NVKM_ACR_PRIV_H__ #include +struct lsb_header_tail; struct nvkm_acr_fwif { int version; @@ -12,11 +13,128 @@ struct nvkm_acr_fwif { int gm20b_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); int gp102_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); +struct nvkm_acr_lsf; struct nvkm_acr_func { + const struct nvkm_acr_hsf_fwif *load; + const struct nvkm_acr_hsf_fwif *ahesasc; + const struct nvkm_acr_hsf_fwif *asb; + const struct nvkm_acr_hsf_fwif *unload; + int (*wpr_parse)(struct nvkm_acr *); + u32 (*wpr_layout)(struct nvkm_acr *); + int (*wpr_alloc)(struct nvkm_acr *, u32 wpr_size); + int (*wpr_build)(struct nvkm_acr *, struct nvkm_acr_lsf *rtos); + void (*wpr_patch)(struct nvkm_acr *, s64 adjust); + void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit); + int (*init)(struct nvkm_acr *); + void (*fini)(struct nvkm_acr *); }; +int gm200_acr_wpr_parse(struct nvkm_acr *); +u32 gm200_acr_wpr_layout(struct nvkm_acr *); +int gm200_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *); +void gm200_acr_wpr_patch(struct nvkm_acr *, s64); +void gm200_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *); +void gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *, + struct lsb_header_tail *); +int gm200_acr_init(struct nvkm_acr *); + +int gm20b_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size); + +int gp102_acr_wpr_parse(struct nvkm_acr *); +u32 gp102_acr_wpr_layout(struct nvkm_acr *); +int gp102_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size); +int gp102_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *); +int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *); +void gp102_acr_wpr_patch(struct nvkm_acr *, s64); + +struct nvkm_acr_hsfw { + const struct nvkm_acr_hsf_func *func; + const char *name; + struct list_head head; + + u32 imem_size; + u32 imem_tag; + u32 *imem; + + u8 *image; + u32 image_size; + u32 non_sec_addr; + u32 non_sec_size; + u32 sec_addr; + u32 sec_size; + u32 data_addr; + u32 data_size; + + struct { + struct { + void *data; + u32 size; + } prod, dbg; + u32 patch_loc; + } sig; +}; + +struct nvkm_acr_hsf_fwif { + int version; + int (*load)(struct nvkm_acr *, const char *bl, const char *fw, + const char *name, int version, + const struct nvkm_acr_hsf_fwif *); + const struct nvkm_acr_hsf_func *func; +}; + +int nvkm_acr_hsfw_load(struct nvkm_acr *, const char *, const char *, + const char *, int, const struct nvkm_acr_hsf_fwif *); +void nvkm_acr_hsfw_del_all(struct nvkm_acr *); + +struct nvkm_acr_hsf { + const struct nvkm_acr_hsf_func *func; + const char *name; + struct list_head head; + + u32 imem_size; + u32 imem_tag; + u32 *imem; + + u32 non_sec_addr; + u32 non_sec_size; + u32 sec_addr; + u32 sec_size; + u32 data_addr; + u32 data_size; + + struct nvkm_memory *ucode; + struct nvkm_vma *vma; + struct nvkm_falcon *falcon; +}; + +struct nvkm_acr_hsf_func { + int (*load)(struct nvkm_acr *, struct nvkm_acr_hsfw *); + int (*boot)(struct nvkm_acr *, struct nvkm_acr_hsf *); + void (*bld)(struct nvkm_acr *, struct nvkm_acr_hsf *); +}; + +int gm200_acr_hsfw_load(struct nvkm_acr *, struct nvkm_acr_hsfw *, + struct nvkm_falcon *); +int gm200_acr_hsfw_boot(struct nvkm_acr *, struct nvkm_acr_hsf *, + u32 clear_intr, u32 mbox0_ok); + +int gm200_acr_load_boot(struct nvkm_acr *, struct nvkm_acr_hsf *); + +extern const struct nvkm_acr_hsf_func gm200_acr_unload_0; +int gm200_acr_unload_load(struct nvkm_acr *, struct nvkm_acr_hsfw *); +int gm200_acr_unload_boot(struct nvkm_acr *, struct nvkm_acr_hsf *); +void gm200_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *); + +extern const struct nvkm_acr_hsf_func gm20b_acr_load_0; + +int gp102_acr_load_load(struct nvkm_acr *, struct nvkm_acr_hsfw *); + +extern const struct nvkm_acr_hsf_func gp108_acr_unload_0; +void gp108_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *); + int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int, struct nvkm_acr **); +int nvkm_acr_hsf_boot(struct nvkm_acr *, const char *name); struct nvkm_acr_lsf { const struct nvkm_acr_lsf_func *func; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index ef22678d041a..6d5a13e4a857 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -21,9 +21,10 @@ */ #include "priv.h" -#include +#include #include +#include #include static int @@ -60,14 +61,65 @@ int gm20b_pmu_acr_boot(struct nvkm_falcon *falcon) { struct nv_pmu_args args = { .secure_mode = true }; - const u32 addr_args = falcon->data.limit - NVKM_MSGQUEUE_CMDLINE_SIZE; /*XXX*/ + const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args); nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0); nvkm_falcon_start(falcon); return 0; } +void +gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust) +{ + struct loader_config hdr; + u64 addr; + + nvkm_robj(acr->wpr, bld, &hdr, sizeof(hdr)); + addr = ((u64)hdr.code_dma_base1 << 40 | hdr.code_dma_base << 8); + hdr.code_dma_base = lower_32_bits((addr + adjust) >> 8); + hdr.code_dma_base1 = upper_32_bits((addr + adjust) >> 8); + addr = ((u64)hdr.data_dma_base1 << 40 | hdr.data_dma_base << 8); + hdr.data_dma_base = lower_32_bits((addr + adjust) >> 8); + hdr.data_dma_base1 = upper_32_bits((addr + adjust) >> 8); + addr = ((u64)hdr.overlay_dma_base1 << 40 | hdr.overlay_dma_base << 8); + hdr.overlay_dma_base = lower_32_bits((addr + adjust) << 8); + hdr.overlay_dma_base1 = upper_32_bits((addr + adjust) << 8); + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); + + loader_config_dump(&acr->subdev, &hdr); +} + +void +gm20b_pmu_acr_bld_write(struct nvkm_acr *acr, u32 bld, + struct nvkm_acr_lsfw *lsfw) +{ + const u64 base = lsfw->offset.img + lsfw->app_start_offset; + const u64 code = (base + lsfw->app_resident_code_offset) >> 8; + const u64 data = (base + lsfw->app_resident_data_offset) >> 8; + const struct loader_config hdr = { + .dma_idx = FALCON_DMAIDX_UCODE, + .code_dma_base = lower_32_bits(code), + .code_size_total = lsfw->app_size, + .code_size_to_load = lsfw->app_resident_code_size, + .code_entry_point = lsfw->app_imem_entry, + .data_dma_base = lower_32_bits(data), + .data_size = lsfw->app_resident_data_size, + .overlay_dma_base = lower_32_bits(code), + .argc = 1, + .argv = lsfw->falcon->data.limit - sizeof(struct nv_pmu_args), + .code_dma_base1 = upper_32_bits(code), + .data_dma_base1 = upper_32_bits(data), + .overlay_dma_base1 = upper_32_bits(code), + }; + + nvkm_wobj(acr->wpr, bld, &hdr, sizeof(hdr)); +} + static const struct nvkm_acr_lsf_func gm20b_pmu_acr = { + .flags = NVKM_ACR_LSF_DMACTL_REQ_CTX, + .bld_size = sizeof(struct loader_config), + .bld_write = gm20b_pmu_acr_bld_write, + .bld_patch = gm20b_pmu_acr_bld_patch, .boot = gm20b_pmu_acr_boot, .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 0e0ebd6857da..39c86bc56310 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -23,6 +23,7 @@ #include +#include #include static int @@ -58,6 +59,11 @@ gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask) static const struct nvkm_acr_lsf_func gp10b_pmu_acr = { + .flags = NVKM_ACR_LSF_DMACTL_REQ_CTX, + .bld_size = sizeof(struct loader_config), + .bld_write = gm20b_pmu_acr_bld_write, + .bld_patch = gm20b_pmu_acr_bld_patch, + .boot = gm20b_pmu_acr_boot, .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon, .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h index 21ca224fc186..f470859244de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h @@ -5,6 +5,7 @@ #include #include enum nvkm_acr_lsf_id; +struct nvkm_acr_lsfw; struct nvkm_pmu_func { const struct nvkm_falcon_func *flcn; @@ -43,6 +44,9 @@ void gf100_pmu_reset(struct nvkm_pmu *); void gk110_pmu_pgob(struct nvkm_pmu *, bool); +void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64); +void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *); +int gm20b_pmu_acr_boot(struct nvkm_falcon *); int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id); void gm20b_pmu_recv(struct nvkm_pmu *); int gm20b_pmu_initmsg(struct nvkm_pmu *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c index 74e00d470ac3..7184120133dc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c @@ -900,8 +900,6 @@ acr_r352_wpr_is_set(const struct acr_r352 *acr, const struct nvkm_secboot *sb) wpr_hi > wpr_range_lo && wpr_hi <= wpr_range_hi); } -int nvkm_acr_boot_ls_falcons(struct nvkm_device *); - static int acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) { @@ -934,7 +932,7 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) return -EINVAL; } - return nvkm_acr_boot_ls_falcons(subdev->device); + return 0; } /** diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h index 2efed6f995ad..855f75b6d5c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h @@ -22,7 +22,6 @@ #ifndef __NVKM_SECBOOT_ACR_R370_H__ #define __NVKM_SECBOOT_ACR_R370_H__ - #include "priv.h" struct hsf_load_header; -- cgit v1.2.3 From 9d350c5e5156792ba7c87b3b1e897656dc2a88e5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/secboot: remove Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/core/device.h | 3 - .../gpu/drm/nouveau/include/nvkm/core/msgqueue.h | 28 - drivers/gpu/drm/nouveau/nvkm/core/subdev.c | 1 - drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 - drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h | 1 - drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild | 1 - drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild | 17 - drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c | 54 - drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h | 70 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 1217 -------------------- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h | 165 --- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c | 227 ---- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.h | 71 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r364.c | 117 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c | 417 ------- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.h | 36 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c | 167 --- .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h | 49 - .../gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c | 93 -- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c | 213 ---- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c | 197 ---- .../gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h | 46 - .../gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c | 150 --- .../gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c | 61 - .../gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c | 46 - .../gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c | 73 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.c | 97 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.h | 81 -- .../gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h | 161 --- .../drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c | 160 --- .../nvkm/subdev/secboot/ls_ucode_msgqueue.c | 102 -- drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h | 65 -- 33 files changed, 1 insertion(+), 4189 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r364.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c delete mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 5598a36f11ec..5c007ce62fc3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -30,7 +30,6 @@ enum nvkm_devidx { NVKM_SUBDEV_THERM, NVKM_SUBDEV_CLK, NVKM_SUBDEV_GSP, - NVKM_SUBDEV_SECBOOT, NVKM_ENGINE_BSP, @@ -151,7 +150,6 @@ struct nvkm_device { struct nvkm_subdev *mxm; struct nvkm_pci *pci; struct nvkm_pmu *pmu; - struct nvkm_secboot *secboot; struct nvkm_therm *therm; struct nvkm_timer *timer; struct nvkm_top *top; @@ -225,7 +223,6 @@ struct nvkm_device_chip { int (*mxm )(struct nvkm_device *, int idx, struct nvkm_subdev **); int (*pci )(struct nvkm_device *, int idx, struct nvkm_pci **); int (*pmu )(struct nvkm_device *, int idx, struct nvkm_pmu **); - int (*secboot )(struct nvkm_device *, int idx, struct nvkm_secboot **); int (*therm )(struct nvkm_device *, int idx, struct nvkm_therm **); int (*timer )(struct nvkm_device *, int idx, struct nvkm_timer **); int (*top )(struct nvkm_device *, int idx, struct nvkm_top **); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h deleted file mode 100644 index bd0476bf6253..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_CORE_MSGQUEUE_H -#define __NVKM_CORE_MSGQUEUE_H - -/* Hopefully we will never have firmware arguments larger than that... */ -#define NVKM_MSGQUEUE_CMDLINE_SIZE 0x100 -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c index aecb48434947..79a8f9d305c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c @@ -51,7 +51,6 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = { [NVKM_SUBDEV_MXM ] = "mxm", [NVKM_SUBDEV_PCI ] = "pci", [NVKM_SUBDEV_PMU ] = "pmu", - [NVKM_SUBDEV_SECBOOT ] = "secboot", [NVKM_SUBDEV_THERM ] = "therm", [NVKM_SUBDEV_TIMER ] = "tmr", [NVKM_SUBDEV_TOP ] = "top", diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index b452ef2cd27d..c81507b11a5e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2691,7 +2691,6 @@ nvkm_device_subdev(struct nvkm_device *device, int index) _(MXM , device->mxm , device->mxm); _(PCI , device->pci , &device->pci->subdev); _(PMU , device->pmu , &device->pmu->subdev); - _(SECBOOT , device->secboot , &device->secboot->subdev); _(THERM , device->therm , &device->therm->subdev); _(TIMER , device->timer , &device->timer->subdev); _(TOP , device->top , &device->top->subdev); @@ -3198,7 +3197,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func, _(NVKM_SUBDEV_MXM , mxm); _(NVKM_SUBDEV_PCI , pci); _(NVKM_SUBDEV_PMU , pmu); - _(NVKM_SUBDEV_SECBOOT , secboot); _(NVKM_SUBDEV_THERM , therm); _(NVKM_SUBDEV_TIMER , timer); _(NVKM_SUBDEV_TOP , top); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h index 0f83ca3166af..54eab5e04230 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c index b45e8f10ec73..09d8c5d5b000 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c @@ -84,7 +84,7 @@ gm20b_gr_init_gpc_mmu(struct gf100_gr *gr) u32 val; /* Bypass MMU check for non-secure boot */ - if (!device->secboot) { + if (!device->acr) { nvkm_wr32(device, 0x100ce4, 0xffffffff); if (nvkm_rd32(device, 0x100ce4) != 0xffffffff) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild index bb3e53f891c5..fb4fff1222af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild @@ -20,7 +20,6 @@ include $(src)/nvkm/subdev/mmu/Kbuild include $(src)/nvkm/subdev/mxm/Kbuild include $(src)/nvkm/subdev/pci/Kbuild include $(src)/nvkm/subdev/pmu/Kbuild -include $(src)/nvkm/subdev/secboot/Kbuild include $(src)/nvkm/subdev/therm/Kbuild include $(src)/nvkm/subdev/timer/Kbuild include $(src)/nvkm/subdev/top/Kbuild diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild deleted file mode 100644 index f3dee2693c79..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: MIT -nvkm-y += nvkm/subdev/secboot/base.o -nvkm-y += nvkm/subdev/secboot/hs_ucode.o -nvkm-y += nvkm/subdev/secboot/ls_ucode_gr.o -nvkm-y += nvkm/subdev/secboot/ls_ucode_msgqueue.o -nvkm-y += nvkm/subdev/secboot/acr.o -nvkm-y += nvkm/subdev/secboot/acr_r352.o -nvkm-y += nvkm/subdev/secboot/acr_r361.o -nvkm-y += nvkm/subdev/secboot/acr_r364.o -nvkm-y += nvkm/subdev/secboot/acr_r367.o -nvkm-y += nvkm/subdev/secboot/acr_r370.o -nvkm-y += nvkm/subdev/secboot/acr_r375.o -nvkm-y += nvkm/subdev/secboot/gm200.o -nvkm-y += nvkm/subdev/secboot/gm20b.o -nvkm-y += nvkm/subdev/secboot/gp102.o -nvkm-y += nvkm/subdev/secboot/gp108.o -nvkm-y += nvkm/subdev/secboot/gp10b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c deleted file mode 100644 index dc80985cf093..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr.h" - -#include - -/** - * Convenience function to duplicate a firmware file in memory and check that - * it has the required minimum size. - */ -void * -nvkm_acr_load_firmware(const struct nvkm_subdev *subdev, const char *name, - size_t min_size) -{ - const struct firmware *fw; - void *blob; - int ret; - - ret = nvkm_firmware_get(subdev, name, &fw); - if (ret) - return ERR_PTR(ret); - if (fw->size < min_size) { - nvkm_error(subdev, "%s is smaller than expected size %zu\n", - name, min_size); - nvkm_firmware_put(fw); - return ERR_PTR(-EINVAL); - } - blob = kmemdup(fw->data, fw->size, GFP_KERNEL); - nvkm_firmware_put(fw); - if (!blob) - return ERR_PTR(-ENOMEM); - - return blob; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h deleted file mode 100644 index 73a2ac81ac69..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_ACR_H__ -#define __NVKM_SECBOOT_ACR_H__ - -#include "priv.h" - -struct nvkm_acr; - -/** - * struct nvkm_acr_func - properties and functions specific to an ACR - * - * @load: make the ACR ready to run on the given secboot device - * @reset: reset the specified falcon - * @start: start the specified falcon (assumed to have been reset) - */ -struct nvkm_acr_func { - void (*dtor)(struct nvkm_acr *); - int (*oneinit)(struct nvkm_acr *, struct nvkm_secboot *); - int (*fini)(struct nvkm_acr *, struct nvkm_secboot *, bool); - int (*load)(struct nvkm_acr *, struct nvkm_falcon *, - struct nvkm_gpuobj *, u64); - int (*reset)(struct nvkm_acr *, struct nvkm_secboot *, unsigned long); -}; - -/** - * struct nvkm_acr - instance of an ACR - * - * @boot_falcon: ID of the falcon that will perform secure boot - * @managed_falcons: bitfield of falcons managed by this ACR - * @optional_falcons: bitfield of falcons we can live without - */ -struct nvkm_acr { - const struct nvkm_acr_func *func; - const struct nvkm_subdev *subdev; - - enum nvkm_secboot_falcon boot_falcon; - unsigned long managed_falcons; - unsigned long optional_falcons; -}; - -void *nvkm_acr_load_firmware(const struct nvkm_subdev *, const char *, size_t); - -struct nvkm_acr *acr_r352_new(unsigned long); -struct nvkm_acr *acr_r361_new(unsigned long); -struct nvkm_acr *acr_r364_new(unsigned long); -struct nvkm_acr *acr_r367_new(enum nvkm_secboot_falcon, unsigned long); -struct nvkm_acr *acr_r370_new(enum nvkm_secboot_falcon, unsigned long); -struct nvkm_acr *acr_r375_new(enum nvkm_secboot_falcon, unsigned long); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c deleted file mode 100644 index 7184120133dc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r352.h" -#include "hs_ucode.h" - -#include -#include -#include -#include -#include -#include - -/** - * struct acr_r352_flcn_bl_desc - DMEM bootloader descriptor - * @signature: 16B signature for secure code. 0s if no secure code - * @ctx_dma: DMA context to be used by BL while loading code/data - * @code_dma_base: 256B-aligned Physical FB Address where code is located - * (falcon's $xcbase register) - * @non_sec_code_off: offset from code_dma_base where the non-secure code is - * located. The offset must be multiple of 256 to help perf - * @non_sec_code_size: the size of the nonSecure code part. - * @sec_code_off: offset from code_dma_base where the secure code is - * located. The offset must be multiple of 256 to help perf - * @sec_code_size: offset from code_dma_base where the secure code is - * located. The offset must be multiple of 256 to help perf - * @code_entry_point: code entry point which will be invoked by BL after - * code is loaded. - * @data_dma_base: 256B aligned Physical FB Address where data is located. - * (falcon's $xdbase register) - * @data_size: size of data block. Should be multiple of 256B - * - * Structure used by the bootloader to load the rest of the code. This has - * to be filled by host and copied into DMEM at offset provided in the - * hsflcn_bl_desc.bl_desc_dmem_load_off. - */ -struct acr_r352_flcn_bl_desc { - u32 reserved[4]; - u32 signature[4]; - u32 ctx_dma; - u32 code_dma_base; - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 sec_code_off; - u32 sec_code_size; - u32 code_entry_point; - u32 data_dma_base; - u32 data_size; - u32 code_dma_base1; - u32 data_dma_base1; -}; - -/** - * acr_r352_generate_flcn_bl_desc - generate generic BL descriptor for LS image - */ -static void -acr_r352_generate_flcn_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - struct acr_r352_flcn_bl_desc *desc = _desc; - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - u64 base, addr_code, addr_data; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = (base + pdesc->app_resident_code_offset) >> 8; - addr_data = (base + pdesc->app_resident_data_offset) >> 8; - - desc->ctx_dma = FALCON_DMAIDX_UCODE; - desc->code_dma_base = lower_32_bits(addr_code); - desc->code_dma_base1 = upper_32_bits(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = lower_32_bits(addr_data); - desc->data_dma_base1 = upper_32_bits(addr_data); - desc->data_size = pdesc->app_resident_data_size; -} - - -/** - * struct hsflcn_acr_desc - data section of the HS firmware - * - * This header is to be copied at the beginning of DMEM by the HS bootloader. - * - * @signature: signature of ACR ucode - * @wpr_region_id: region ID holding the WPR header and its details - * @wpr_offset: offset from the WPR region holding the wpr header - * @regions: region descriptors - * @nonwpr_ucode_blob_size: size of LS blob - * @nonwpr_ucode_blob_start: FB location of LS blob is - */ -struct hsflcn_acr_desc { - union { - u8 reserved_dmem[0x200]; - u32 signatures[4]; - } ucode_reserved_space; - u32 wpr_region_id; - u32 wpr_offset; - u32 mmu_mem_range; -#define FLCN_ACR_MAX_REGIONS 2 - struct { - u32 no_regions; - struct { - u32 start_addr; - u32 end_addr; - u32 region_id; - u32 read_mask; - u32 write_mask; - u32 client_mask; - } region_props[FLCN_ACR_MAX_REGIONS]; - } regions; - u32 ucode_blob_size; - u64 ucode_blob_base __aligned(8); - struct { - u32 vpr_enabled; - u32 vpr_start; - u32 vpr_end; - u32 hdcp_policies; - } vpr_desc; -}; - - -/* - * Low-secure blob creation - */ - -/** - * struct acr_r352_lsf_lsb_header - LS firmware header - * @signature: signature to verify the firmware against - * @ucode_off: offset of the ucode blob in the WPR region. The ucode - * blob contains the bootloader, code and data of the - * LS falcon - * @ucode_size: size of the ucode blob, including bootloader - * @data_size: size of the ucode blob data - * @bl_code_size: size of the bootloader code - * @bl_imem_off: offset in imem of the bootloader - * @bl_data_off: offset of the bootloader data in WPR region - * @bl_data_size: size of the bootloader data - * @app_code_off: offset of the app code relative to ucode_off - * @app_code_size: size of the app code - * @app_data_off: offset of the app data relative to ucode_off - * @app_data_size: size of the app data - * @flags: flags for the secure bootloader - * - * This structure is written into the WPR region for each managed falcon. Each - * instance is referenced by the lsb_offset member of the corresponding - * lsf_wpr_header. - */ -struct acr_r352_lsf_lsb_header { - /** - * LS falcon signatures - * @prd_keys: signature to use in production mode - * @dgb_keys: signature to use in debug mode - * @b_prd_present: whether the production key is present - * @b_dgb_present: whether the debug key is present - * @falcon_id: ID of the falcon the ucode applies to - */ - struct { - u8 prd_keys[2][16]; - u8 dbg_keys[2][16]; - u32 b_prd_present; - u32 b_dbg_present; - u32 falcon_id; - } signature; - u32 ucode_off; - u32 ucode_size; - u32 data_size; - u32 bl_code_size; - u32 bl_imem_off; - u32 bl_data_off; - u32 bl_data_size; - u32 app_code_off; - u32 app_code_size; - u32 app_data_off; - u32 app_data_size; - u32 flags; -}; - -/** - * struct acr_r352_lsf_wpr_header - LS blob WPR Header - * @falcon_id: LS falcon ID - * @lsb_offset: offset of the lsb_lsf_header in the WPR region - * @bootstrap_owner: secure falcon reponsible for bootstrapping the LS falcon - * @lazy_bootstrap: skip bootstrapping by ACR - * @status: bootstrapping status - * - * An array of these is written at the beginning of the WPR region, one for - * each managed falcon. The array is terminated by an instance which falcon_id - * is LSF_FALCON_ID_INVALID. - */ -struct acr_r352_lsf_wpr_header { - u32 falcon_id; - u32 lsb_offset; - u32 bootstrap_owner; - u32 lazy_bootstrap; - u32 status; -#define LSF_IMAGE_STATUS_NONE 0 -#define LSF_IMAGE_STATUS_COPY 1 -#define LSF_IMAGE_STATUS_VALIDATION_CODE_FAILED 2 -#define LSF_IMAGE_STATUS_VALIDATION_DATA_FAILED 3 -#define LSF_IMAGE_STATUS_VALIDATION_DONE 4 -#define LSF_IMAGE_STATUS_VALIDATION_SKIPPED 5 -#define LSF_IMAGE_STATUS_BOOTSTRAP_READY 6 -}; - -/** - * struct ls_ucode_img_r352 - ucode image augmented with r352 headers - */ -struct ls_ucode_img_r352 { - struct ls_ucode_img base; - - const struct acr_r352_lsf_func *func; - - struct acr_r352_lsf_wpr_header wpr_header; - struct acr_r352_lsf_lsb_header lsb_header; -}; -#define ls_ucode_img_r352(i) container_of(i, struct ls_ucode_img_r352, base) - -/** - * ls_ucode_img_load() - create a lsf_ucode_img and load it - */ -struct ls_ucode_img * -acr_r352_ls_ucode_img_load(const struct acr_r352 *acr, - const struct nvkm_secboot *sb, - enum nvkm_secboot_falcon falcon_id) -{ - const struct nvkm_subdev *subdev = acr->base.subdev; - const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id]; - struct ls_ucode_img_r352 *img; - int ret; - - img = kzalloc(sizeof(*img), GFP_KERNEL); - if (!img) - return ERR_PTR(-ENOMEM); - - img->base.falcon_id = falcon_id; - - ret = func->load(sb, func->version_max, &img->base); - if (ret < 0) { - kfree(img->base.ucode_data); - kfree(img->base.sig); - kfree(img); - return ERR_PTR(ret); - } - - img->func = func->version[ret]; - - /* Check that the signature size matches our expectations... */ - if (img->base.sig_size != sizeof(img->lsb_header.signature)) { - nvkm_error(subdev, "invalid signature size for %s falcon!\n", - nvkm_secboot_falcon_name[falcon_id]); - return ERR_PTR(-EINVAL); - } - - /* Copy signature to the right place */ - memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size); - - /* not needed? the signature should already have the right value */ - img->lsb_header.signature.falcon_id = falcon_id; - - return &img->base; -} - -#define LSF_LSB_HEADER_ALIGN 256 -#define LSF_BL_DATA_ALIGN 256 -#define LSF_BL_DATA_SIZE_ALIGN 256 -#define LSF_BL_CODE_SIZE_ALIGN 256 -#define LSF_UCODE_DATA_ALIGN 4096 - -/** - * acr_r352_ls_img_fill_headers - fill the WPR and LSB headers of an image - * @acr: ACR to use - * @img: image to generate for - * @offset: offset in the WPR region where this image starts - * - * Allocate space in the WPR area from offset and write the WPR and LSB headers - * accordingly. - * - * Return: offset at the end of this image. - */ -static u32 -acr_r352_ls_img_fill_headers(struct acr_r352 *acr, - struct ls_ucode_img_r352 *img, u32 offset) -{ - struct ls_ucode_img *_img = &img->base; - struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header; - struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header; - struct ls_ucode_img_desc *desc = &_img->ucode_desc; - const struct acr_r352_lsf_func *func = img->func; - - /* Fill WPR header */ - whdr->falcon_id = _img->falcon_id; - whdr->bootstrap_owner = acr->base.boot_falcon; - whdr->status = LSF_IMAGE_STATUS_COPY; - - /* Skip bootstrapping falcons started by someone else than ACR */ - if (acr->lazy_bootstrap & BIT(_img->falcon_id)) - whdr->lazy_bootstrap = 1; - - /* Align, save off, and include an LSB header size */ - offset = ALIGN(offset, LSF_LSB_HEADER_ALIGN); - whdr->lsb_offset = offset; - offset += sizeof(*lhdr); - - /* - * Align, save off, and include the original (static) ucode - * image size - */ - offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN); - _img->ucode_off = lhdr->ucode_off = offset; - offset += _img->ucode_size; - - /* - * For falcons that use a boot loader (BL), we append a loader - * desc structure on the end of the ucode image and consider - * this the boot loader data. The host will then copy the loader - * desc args to this space within the WPR region (before locking - * down) and the HS bin will then copy them to DMEM 0 for the - * loader. - */ - lhdr->bl_code_size = ALIGN(desc->bootloader_size, - LSF_BL_CODE_SIZE_ALIGN); - lhdr->ucode_size = ALIGN(desc->app_resident_data_offset, - LSF_BL_CODE_SIZE_ALIGN) + lhdr->bl_code_size; - lhdr->data_size = ALIGN(desc->app_size, LSF_BL_CODE_SIZE_ALIGN) + - lhdr->bl_code_size - lhdr->ucode_size; - /* - * Though the BL is located at 0th offset of the image, the VA - * is different to make sure that it doesn't collide the actual - * OS VA range - */ - lhdr->bl_imem_off = desc->bootloader_imem_offset; - lhdr->app_code_off = desc->app_start_offset + - desc->app_resident_code_offset; - lhdr->app_code_size = desc->app_resident_code_size; - lhdr->app_data_off = desc->app_start_offset + - desc->app_resident_data_offset; - lhdr->app_data_size = desc->app_resident_data_size; - - lhdr->flags = func->lhdr_flags; - if (_img->falcon_id == acr->base.boot_falcon) - lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX; - - /* Align and save off BL descriptor size */ - lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN); - - /* - * Align, save off, and include the additional BL data - */ - offset = ALIGN(offset, LSF_BL_DATA_ALIGN); - lhdr->bl_data_off = offset; - offset += lhdr->bl_data_size; - - return offset; -} - -/** - * acr_r352_ls_fill_headers - fill WPR and LSB headers of all managed images - */ -int -acr_r352_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs) -{ - struct ls_ucode_img_r352 *img; - struct list_head *l; - u32 count = 0; - u32 offset; - - /* Count the number of images to manage */ - list_for_each(l, imgs) - count++; - - /* - * Start with an array of WPR headers at the base of the WPR. - * The expectation here is that the secure falcon will do a single DMA - * read of this array and cache it internally so it's ok to pack these. - * Also, we add 1 to the falcon count to indicate the end of the array. - */ - offset = sizeof(img->wpr_header) * (count + 1); - - /* - * Walk the managed falcons, accounting for the LSB structs - * as well as the ucode images. - */ - list_for_each_entry(img, imgs, base.node) { - offset = acr_r352_ls_img_fill_headers(acr, img, offset); - } - - return offset; -} - -/** - * acr_r352_ls_write_wpr - write the WPR blob contents - */ -int -acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, - struct nvkm_gpuobj *wpr_blob, u64 wpr_addr) -{ - struct ls_ucode_img *_img; - u32 pos = 0; - u32 max_desc_size = 0; - u8 *gdesc; - - /* Figure out how large we need gdesc to be. */ - list_for_each_entry(_img, imgs, node) { - struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img); - const struct acr_r352_lsf_func *ls_func = img->func; - - max_desc_size = max(max_desc_size, ls_func->bl_desc_size); - } - - gdesc = kmalloc(max_desc_size, GFP_KERNEL); - if (!gdesc) - return -ENOMEM; - - nvkm_kmap(wpr_blob); - - list_for_each_entry(_img, imgs, node) { - struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img); - const struct acr_r352_lsf_func *ls_func = img->func; - - nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, - sizeof(img->wpr_header)); - - nvkm_gpuobj_memcpy_to(wpr_blob, img->wpr_header.lsb_offset, - &img->lsb_header, sizeof(img->lsb_header)); - - /* Generate and write BL descriptor */ - memset(gdesc, 0, ls_func->bl_desc_size); - ls_func->generate_bl_desc(&acr->base, _img, wpr_addr, gdesc); - - nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off, - gdesc, ls_func->bl_desc_size); - - /* Copy ucode */ - nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off, - _img->ucode_data, _img->ucode_size); - - pos += sizeof(img->wpr_header); - } - - nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID); - - nvkm_done(wpr_blob); - - kfree(gdesc); - - return 0; -} - -/* Both size and address of WPR need to be 256K-aligned */ -#define WPR_ALIGNMENT 0x40000 -/** - * acr_r352_prepare_ls_blob() - prepare the LS blob - * - * For each securely managed falcon, load the FW, signatures and bootloaders and - * prepare a ucode blob. Then, compute the offsets in the WPR region for each - * blob, and finally write the headers and ucode blobs into a GPU object that - * will be copied into the WPR region by the HS firmware. - */ -static int -acr_r352_prepare_ls_blob(struct acr_r352 *acr, struct nvkm_secboot *sb) -{ - const struct nvkm_subdev *subdev = acr->base.subdev; - struct list_head imgs; - struct ls_ucode_img *img, *t; - unsigned long managed_falcons = acr->base.managed_falcons; - u64 wpr_addr = sb->wpr_addr; - u32 wpr_size = sb->wpr_size; - int managed_count = 0; - u32 image_wpr_size, ls_blob_size; - int falcon_id; - int ret; - - INIT_LIST_HEAD(&imgs); - - /* Load all LS blobs */ - for_each_set_bit(falcon_id, &managed_falcons, NVKM_SECBOOT_FALCON_END) { - struct ls_ucode_img *img; - - img = acr->func->ls_ucode_img_load(acr, sb, falcon_id); - if (IS_ERR(img)) { - if (acr->base.optional_falcons & BIT(falcon_id)) { - managed_falcons &= ~BIT(falcon_id); - nvkm_info(subdev, "skipping %s falcon...\n", - nvkm_secboot_falcon_name[falcon_id]); - continue; - } - ret = PTR_ERR(img); - goto cleanup; - } - - list_add_tail(&img->node, &imgs); - managed_count++; - } - - /* Commit the actual list of falcons we will manage from now on */ - acr->base.managed_falcons = managed_falcons; - - /* - * If the boot falcon has a firmare, let it manage the bootstrap of other - * falcons. - */ - if (acr->func->ls_func[acr->base.boot_falcon] && - (managed_falcons & BIT(acr->base.boot_falcon))) { - for_each_set_bit(falcon_id, &managed_falcons, - NVKM_SECBOOT_FALCON_END) { - if (falcon_id == acr->base.boot_falcon) - continue; - - acr->lazy_bootstrap |= BIT(falcon_id); - } - } - - /* - * Fill the WPR and LSF headers with the right offsets and compute - * required WPR size - */ - image_wpr_size = acr->func->ls_fill_headers(acr, &imgs); - image_wpr_size = ALIGN(image_wpr_size, WPR_ALIGNMENT); - - ls_blob_size = image_wpr_size; - - /* - * If we need a shadow area, allocate twice the size and use the - * upper half as WPR - */ - if (wpr_size == 0 && acr->func->shadow_blob) - ls_blob_size *= 2; - - /* Allocate GPU object that will contain the WPR region */ - ret = nvkm_gpuobj_new(subdev->device, ls_blob_size, WPR_ALIGNMENT, - false, NULL, &acr->ls_blob); - if (ret) - goto cleanup; - - nvkm_debug(subdev, "%d managed LS falcons, WPR size is %d bytes\n", - managed_count, image_wpr_size); - - /* If WPR address and size are not fixed, set them to fit the LS blob */ - if (wpr_size == 0) { - wpr_addr = acr->ls_blob->addr; - if (acr->func->shadow_blob) - wpr_addr += acr->ls_blob->size / 2; - - wpr_size = image_wpr_size; - /* - * But if the WPR region is set by the bootloader, it is illegal for - * the HS blob to be larger than this region. - */ - } else if (image_wpr_size > wpr_size) { - nvkm_error(subdev, "WPR region too small for FW blob!\n"); - nvkm_error(subdev, "required: %dB\n", image_wpr_size); - nvkm_error(subdev, "available: %dB\n", wpr_size); - ret = -ENOSPC; - goto cleanup; - } - - /* Write LS blob */ - ret = acr->func->ls_write_wpr(acr, &imgs, acr->ls_blob, wpr_addr); - if (ret) - nvkm_gpuobj_del(&acr->ls_blob); - -cleanup: - list_for_each_entry_safe(img, t, &imgs, node) { - kfree(img->ucode_data); - kfree(img->sig); - kfree(img); - } - - return ret; -} - - - - -void -acr_r352_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb, - void *_desc) -{ - struct hsflcn_acr_desc *desc = _desc; - struct nvkm_gpuobj *ls_blob = acr->ls_blob; - - /* WPR region information if WPR is not fixed */ - if (sb->wpr_size == 0) { - u64 wpr_start = ls_blob->addr; - u64 wpr_end = wpr_start + ls_blob->size; - - desc->wpr_region_id = 1; - desc->regions.no_regions = 2; - desc->regions.region_props[0].start_addr = wpr_start >> 8; - desc->regions.region_props[0].end_addr = wpr_end >> 8; - desc->regions.region_props[0].region_id = 1; - desc->regions.region_props[0].read_mask = 0xf; - desc->regions.region_props[0].write_mask = 0xc; - desc->regions.region_props[0].client_mask = 0x2; - } else { - desc->ucode_blob_base = ls_blob->addr; - desc->ucode_blob_size = ls_blob->size; - } -} - -static void -acr_r352_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, - u64 offset) -{ - struct acr_r352_flcn_bl_desc *bl_desc = _bl_desc; - u64 addr_code, addr_data; - - addr_code = offset >> 8; - addr_data = (offset + hdr->data_dma_base) >> 8; - - bl_desc->ctx_dma = FALCON_DMAIDX_VIRT; - bl_desc->code_dma_base = lower_32_bits(addr_code); - bl_desc->non_sec_code_off = hdr->non_sec_code_off; - bl_desc->non_sec_code_size = hdr->non_sec_code_size; - bl_desc->sec_code_off = hsf_load_header_app_off(hdr, 0); - bl_desc->sec_code_size = hsf_load_header_app_size(hdr, 0); - bl_desc->code_entry_point = 0; - bl_desc->data_dma_base = lower_32_bits(addr_data); - bl_desc->data_size = hdr->data_size; -} - -/** - * acr_r352_prepare_hs_blob - load and prepare a HS blob and BL descriptor - * - * @sb secure boot instance to prepare for - * @fw name of the HS firmware to load - * @blob pointer to gpuobj that will be allocated to receive the HS FW payload - * @bl_desc pointer to the BL descriptor to write for this firmware - * @patch whether we should patch the HS descriptor (only for HS loaders) - */ -static int -acr_r352_prepare_hs_blob(struct acr_r352 *acr, struct nvkm_secboot *sb, - const char *fw, struct nvkm_gpuobj **blob, - struct hsf_load_header *load_header, bool patch) -{ - struct nvkm_subdev *subdev = &sb->subdev; - void *acr_image; - struct fw_bin_header *hsbin_hdr; - struct hsf_fw_header *fw_hdr; - struct hsf_load_header *load_hdr; - void *acr_data; - int ret; - - acr_image = hs_ucode_load_blob(subdev, sb->boot_falcon, fw); - if (IS_ERR(acr_image)) - return PTR_ERR(acr_image); - - hsbin_hdr = acr_image; - fw_hdr = acr_image + hsbin_hdr->header_offset; - load_hdr = acr_image + fw_hdr->hdr_offset; - acr_data = acr_image + hsbin_hdr->data_offset; - - /* Patch descriptor with WPR information? */ - if (patch) { - struct hsflcn_acr_desc *desc; - - desc = acr_data + load_hdr->data_dma_base; - acr->func->fixup_hs_desc(acr, sb, desc); - } - - if (load_hdr->num_apps > ACR_R352_MAX_APPS) { - nvkm_error(subdev, "more apps (%d) than supported (%d)!", - load_hdr->num_apps, ACR_R352_MAX_APPS); - ret = -EINVAL; - goto cleanup; - } - memcpy(load_header, load_hdr, sizeof(*load_header) + - (sizeof(load_hdr->apps[0]) * 2 * load_hdr->num_apps)); - - /* Create ACR blob and copy HS data to it */ - ret = nvkm_gpuobj_new(subdev->device, ALIGN(hsbin_hdr->data_size, 256), - 0x1000, false, NULL, blob); - if (ret) - goto cleanup; - - nvkm_kmap(*blob); - nvkm_gpuobj_memcpy_to(*blob, 0, acr_data, hsbin_hdr->data_size); - nvkm_done(*blob); - -cleanup: - kfree(acr_image); - - return ret; -} - -/** - * acr_r352_load_blobs - load blobs common to all ACR V1 versions. - * - * This includes the LS blob, HS ucode loading blob, and HS bootloader. - * - * The HS ucode unload blob is only used on dGPU if the WPR region is variable. - */ -int -acr_r352_load_blobs(struct acr_r352 *acr, struct nvkm_secboot *sb) -{ - struct nvkm_subdev *subdev = &sb->subdev; - int ret; - - /* Firmware already loaded? */ - if (acr->firmware_ok) - return 0; - - /* Load and prepare the managed falcon's firmwares */ - ret = acr_r352_prepare_ls_blob(acr, sb); - if (ret) - return ret; - - /* Load the HS firmware that will load the LS firmwares */ - if (!acr->load_blob) { - ret = acr_r352_prepare_hs_blob(acr, sb, "acr/ucode_load", - &acr->load_blob, - &acr->load_bl_header, true); - if (ret) - return ret; - } - - /* If the ACR region is dynamically programmed, we need an unload FW */ - if (sb->wpr_size == 0) { - ret = acr_r352_prepare_hs_blob(acr, sb, "acr/ucode_unload", - &acr->unload_blob, - &acr->unload_bl_header, false); - if (ret) - return ret; - } - - /* Load the HS firmware bootloader */ - if (!acr->hsbl_blob) { - acr->hsbl_blob = nvkm_acr_load_firmware(subdev, "acr/bl", 0); - if (IS_ERR(acr->hsbl_blob)) { - ret = PTR_ERR(acr->hsbl_blob); - acr->hsbl_blob = NULL; - return ret; - } - - if (acr->base.boot_falcon != NVKM_SECBOOT_FALCON_PMU) { - acr->hsbl_unload_blob = nvkm_acr_load_firmware(subdev, - "acr/unload_bl", 0); - if (IS_ERR(acr->hsbl_unload_blob)) { - ret = PTR_ERR(acr->hsbl_unload_blob); - acr->hsbl_unload_blob = NULL; - return ret; - } - } else { - acr->hsbl_unload_blob = acr->hsbl_blob; - } - } - - acr->firmware_ok = true; - nvkm_debug(&sb->subdev, "LS blob successfully created\n"); - - return 0; -} - -/** - * acr_r352_load() - prepare HS falcon to run the specified blob, mapped. - * - * Returns the start address to use, or a negative error value. - */ -static int -acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon, - struct nvkm_gpuobj *blob, u64 offset) -{ - struct acr_r352 *acr = acr_r352(_acr); - const u32 bl_desc_size = acr->func->hs_bl_desc_size; - const struct hsf_load_header *load_hdr; - struct fw_bin_header *bl_hdr; - struct fw_bl_desc *hsbl_desc; - void *bl, *blob_data, *hsbl_code, *hsbl_data; - u32 code_size; - u8 *bl_desc; - - bl_desc = kzalloc(bl_desc_size, GFP_KERNEL); - if (!bl_desc) - return -ENOMEM; - - /* Find the bootloader descriptor for our blob and copy it */ - if (blob == acr->load_blob) { - load_hdr = &acr->load_bl_header; - bl = acr->hsbl_blob; - } else if (blob == acr->unload_blob) { - load_hdr = &acr->unload_bl_header; - bl = acr->hsbl_unload_blob; - } else { - nvkm_error(_acr->subdev, "invalid secure boot blob!\n"); - kfree(bl_desc); - return -EINVAL; - } - - bl_hdr = bl; - hsbl_desc = bl + bl_hdr->header_offset; - blob_data = bl + bl_hdr->data_offset; - hsbl_code = blob_data + hsbl_desc->code_off; - hsbl_data = blob_data + hsbl_desc->data_off; - code_size = ALIGN(hsbl_desc->code_size, 256); - - /* - * Copy HS bootloader data - */ - nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0); - - /* Copy HS bootloader code to end of IMEM */ - nvkm_falcon_load_imem(falcon, hsbl_code, falcon->code.limit - code_size, - code_size, hsbl_desc->start_tag, 0, false); - - /* Generate the BL header */ - acr->func->generate_hs_bl_desc(load_hdr, bl_desc, offset); - - /* - * Copy HS BL header where the HS descriptor expects it to be - */ - nvkm_falcon_load_dmem(falcon, bl_desc, hsbl_desc->dmem_load_off, - bl_desc_size, 0); - - kfree(bl_desc); - return hsbl_desc->start_tag << 8; -} - -static int -acr_r352_shutdown(struct acr_r352 *acr, struct nvkm_secboot *sb) -{ - struct nvkm_subdev *subdev = &sb->subdev; - int i; - - /* Run the unload blob to unprotect the WPR region */ - if (acr->unload_blob && sb->wpr_set) { - int ret; - - nvkm_debug(subdev, "running HS unload blob\n"); - ret = sb->func->run_blob(sb, acr->unload_blob, sb->halt_falcon); - if (ret < 0) - return ret; - /* - * Unload blob will return this error code - it is not an error - * and the expected behavior on RM as well - */ - if (ret && ret != 0x1d) { - nvkm_error(subdev, "HS unload failed, ret 0x%08x\n", ret); - return -EINVAL; - } - nvkm_debug(subdev, "HS unload blob completed\n"); - } - - for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++) - acr->falcon_state[i] = NON_SECURE; - - sb->wpr_set = false; - - return 0; -} - -/** - * Check if the WPR region has been indeed set by the ACR firmware, and - * matches where it should be. - */ -static bool -acr_r352_wpr_is_set(const struct acr_r352 *acr, const struct nvkm_secboot *sb) -{ - const struct nvkm_subdev *subdev = &sb->subdev; - const struct nvkm_device *device = subdev->device; - u64 wpr_lo, wpr_hi; - u64 wpr_range_lo, wpr_range_hi; - - nvkm_wr32(device, 0x100cd4, 0x2); - wpr_lo = (nvkm_rd32(device, 0x100cd4) & ~0xff); - wpr_lo <<= 8; - nvkm_wr32(device, 0x100cd4, 0x3); - wpr_hi = (nvkm_rd32(device, 0x100cd4) & ~0xff); - wpr_hi <<= 8; - - if (sb->wpr_size != 0) { - wpr_range_lo = sb->wpr_addr; - wpr_range_hi = wpr_range_lo + sb->wpr_size; - } else { - wpr_range_lo = acr->ls_blob->addr; - wpr_range_hi = wpr_range_lo + acr->ls_blob->size; - } - - return (wpr_lo >= wpr_range_lo && wpr_lo < wpr_range_hi && - wpr_hi > wpr_range_lo && wpr_hi <= wpr_range_hi); -} - -static int -acr_r352_bootstrap(struct acr_r352 *acr, struct nvkm_secboot *sb) -{ - const struct nvkm_subdev *subdev = &sb->subdev; - int ret; - - if (sb->wpr_set) - return 0; - - /* Make sure all blobs are ready */ - ret = acr_r352_load_blobs(acr, sb); - if (ret) - return ret; - - nvkm_debug(subdev, "running HS load blob\n"); - ret = sb->func->run_blob(sb, acr->load_blob, sb->boot_falcon); - /* clear halt interrupt */ - nvkm_falcon_clear_interrupt(sb->boot_falcon, 0x10); - sb->wpr_set = acr_r352_wpr_is_set(acr, sb); - if (ret < 0) { - return ret; - } else if (ret > 0) { - nvkm_error(subdev, "HS load failed, ret 0x%08x\n", ret); - return -EINVAL; - } - nvkm_debug(subdev, "HS load blob completed\n"); - /* WPR must be set at this point */ - if (!sb->wpr_set) { - nvkm_error(subdev, "ACR blob completed but WPR not set!\n"); - return -EINVAL; - } - - return 0; -} - -/** - * acr_r352_reset_nopmu - dummy reset method when no PMU firmware is loaded - * - * Reset is done by re-executing secure boot from scratch, with lazy bootstrap - * disabled. This has the effect of making all managed falcons ready-to-run. - */ -static int -acr_r352_reset_nopmu(struct acr_r352 *acr, struct nvkm_secboot *sb, - unsigned long falcon_mask) -{ - int falcon; - int ret; - - /* - * Perform secure boot each time we are called on FECS. Since only FECS - * and GPCCS are managed and started together, this ought to be safe. - */ - if (!(falcon_mask & BIT(NVKM_SECBOOT_FALCON_FECS))) - goto end; - - ret = acr_r352_shutdown(acr, sb); - if (ret) - return ret; - - ret = acr_r352_bootstrap(acr, sb); - if (ret) - return ret; - -end: - for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) { - acr->falcon_state[falcon] = RESET; - } - return 0; -} - -/* - * acr_r352_reset() - execute secure boot from the prepared state - * - * Load the HS bootloader and ask the falcon to run it. This will in turn - * load the HS firmware and run it, so once the falcon stops all the managed - * falcons should have their LS firmware loaded and be ready to run. - */ -int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long); - -static int -acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb, - unsigned long falcon_mask) -{ - struct acr_r352 *acr = acr_r352(_acr); - int falcon; - bool wpr_already_set = sb->wpr_set; - int ret; - - /* Make sure secure boot is performed */ - ret = acr_r352_bootstrap(acr, sb); - if (ret) - return ret; - - /* No PMU interface? */ - if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon)) { - /* Redo secure boot entirely if it was already done */ - if (wpr_already_set) - return acr_r352_reset_nopmu(acr, sb, falcon_mask); - /* Else return the result of the initial invokation */ - else - return ret; - } - - /* Otherwise just ask the LS firmware to reset the falcon */ - for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) - nvkm_debug(&sb->subdev, "resetting %s falcon\n", - nvkm_secboot_falcon_name[falcon]); - - ret = nvkm_acr_bootstrap_falcons(sb->subdev.device, falcon_mask); - if (ret) { - nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret); - return ret; - } - nvkm_debug(&sb->subdev, "falcon reset done\n"); - - return 0; -} - -static int -acr_r352_fini(struct nvkm_acr *_acr, struct nvkm_secboot *sb, bool suspend) -{ - struct acr_r352 *acr = acr_r352(_acr); - - return acr_r352_shutdown(acr, sb); -} - -static void -acr_r352_dtor(struct nvkm_acr *_acr) -{ - struct acr_r352 *acr = acr_r352(_acr); - - nvkm_gpuobj_del(&acr->unload_blob); - - if (_acr->boot_falcon != NVKM_SECBOOT_FALCON_PMU) - kfree(acr->hsbl_unload_blob); - kfree(acr->hsbl_blob); - nvkm_gpuobj_del(&acr->load_blob); - nvkm_gpuobj_del(&acr->ls_blob); - - kfree(acr); -} - -static const struct acr_r352_lsf_func -acr_r352_ls_fecs_func_0 = { - .generate_bl_desc = acr_r352_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r352_ls_fecs_func = { - .load = acr_ls_ucode_load_fecs, - .version_max = 0, - .version = { - &acr_r352_ls_fecs_func_0, - } -}; - -static const struct acr_r352_lsf_func -acr_r352_ls_gpccs_func_0 = { - .generate_bl_desc = acr_r352_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc), - /* GPCCS will be loaded using PRI */ - .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, -}; - -static const struct acr_r352_ls_func -acr_r352_ls_gpccs_func = { - .load = acr_ls_ucode_load_gpccs, - .version_max = 0, - .version = { - &acr_r352_ls_gpccs_func_0, - } -}; - - - -/** - * struct acr_r352_pmu_bl_desc - PMU DMEM bootloader descriptor - * @dma_idx: DMA context to be used by BL while loading code/data - * @code_dma_base: 256B-aligned Physical FB Address where code is located - * @total_code_size: total size of the code part in the ucode - * @code_size_to_load: size of the code part to load in PMU IMEM. - * @code_entry_point: entry point in the code. - * @data_dma_base: Physical FB address where data part of ucode is located - * @data_size: Total size of the data portion. - * @overlay_dma_base: Physical Fb address for resident code present in ucode - * @argc: Total number of args - * @argv: offset where args are copied into PMU's DMEM. - * - * Structure used by the PMU bootloader to load the rest of the code - */ -struct acr_r352_pmu_bl_desc { - u32 dma_idx; - u32 code_dma_base; - u32 code_size_total; - u32 code_size_to_load; - u32 code_entry_point; - u32 data_dma_base; - u32 data_size; - u32 overlay_dma_base; - u32 argc; - u32 argv; - u16 code_dma_base1; - u16 data_dma_base1; - u16 overlay_dma_base1; -}; - -/** - * acr_r352_generate_pmu_bl_desc() - populate a DMEM BL descriptor for PMU LS image - * - */ -static void -acr_r352_generate_pmu_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - const struct nvkm_pmu *pmu = acr->subdev->device->pmu; - struct acr_r352_pmu_bl_desc *desc = _desc; - u64 base; - u64 addr_code; - u64 addr_data; - u32 addr_args; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = (base + pdesc->app_resident_code_offset) >> 8; - addr_data = (base + pdesc->app_resident_data_offset) >> 8; - addr_args = pmu->falcon.data.limit; - addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; - - desc->dma_idx = FALCON_DMAIDX_UCODE; - desc->code_dma_base = lower_32_bits(addr_code); - desc->code_dma_base1 = upper_32_bits(addr_code); - desc->code_size_total = pdesc->app_size; - desc->code_size_to_load = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = lower_32_bits(addr_data); - desc->data_dma_base1 = upper_32_bits(addr_data); - desc->data_size = pdesc->app_resident_data_size; - desc->overlay_dma_base = lower_32_bits(addr_code); - desc->overlay_dma_base1 = upper_32_bits(addr_code); - desc->argc = 1; - desc->argv = addr_args; -} - -static const struct acr_r352_lsf_func -acr_r352_ls_pmu_func_0 = { - .generate_bl_desc = acr_r352_generate_pmu_bl_desc, - .bl_desc_size = sizeof(struct acr_r352_pmu_bl_desc), -}; - -static const struct acr_r352_ls_func -acr_r352_ls_pmu_func = { - .load = acr_ls_ucode_load_pmu, - .version_max = 0, - .version = { - &acr_r352_ls_pmu_func_0, - } -}; - -const struct acr_r352_func -acr_r352_func = { - .fixup_hs_desc = acr_r352_fixup_hs_desc, - .generate_hs_bl_desc = acr_r352_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc), - .ls_ucode_img_load = acr_r352_ls_ucode_img_load, - .ls_fill_headers = acr_r352_ls_fill_headers, - .ls_write_wpr = acr_r352_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r352_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r352_ls_gpccs_func, - [NVKM_SECBOOT_FALCON_PMU] = &acr_r352_ls_pmu_func, - }, -}; - -static const struct nvkm_acr_func -acr_r352_base_func = { - .dtor = acr_r352_dtor, - .fini = acr_r352_fini, - .load = acr_r352_load, - .reset = acr_r352_reset, -}; - -struct nvkm_acr * -acr_r352_new_(const struct acr_r352_func *func, - enum nvkm_secboot_falcon boot_falcon, - unsigned long managed_falcons) -{ - struct acr_r352 *acr; - int i; - - /* Check that all requested falcons are supported */ - for_each_set_bit(i, &managed_falcons, NVKM_SECBOOT_FALCON_END) { - if (!func->ls_func[i]) - return ERR_PTR(-ENOTSUPP); - } - - acr = kzalloc(sizeof(*acr), GFP_KERNEL); - if (!acr) - return ERR_PTR(-ENOMEM); - - acr->base.boot_falcon = boot_falcon; - acr->base.managed_falcons = managed_falcons; - acr->base.func = &acr_r352_base_func; - acr->func = func; - - return &acr->base; -} - -struct nvkm_acr * -acr_r352_new(unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r352_func, NVKM_SECBOOT_FALCON_PMU, - managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h deleted file mode 100644 index 3197cb83bc27..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_ACR_R352_H__ -#define __NVKM_SECBOOT_ACR_R352_H__ - -#include "acr.h" -#include "ls_ucode.h" -#include "hs_ucode.h" - -struct ls_ucode_img; - -#define ACR_R352_MAX_APPS 8 - -#define LSF_FLAG_LOAD_CODE_AT_0 1 -#define LSF_FLAG_DMACTL_REQ_CTX 4 -#define LSF_FLAG_FORCE_PRIV_LOAD 8 - -static inline u32 -hsf_load_header_app_off(const struct hsf_load_header *hdr, u32 app) -{ - return hdr->apps[app]; -} - -static inline u32 -hsf_load_header_app_size(const struct hsf_load_header *hdr, u32 app) -{ - return hdr->apps[hdr->num_apps + app]; -} - -/** - * struct acr_r352_lsf_func - manages a specific LS firmware version - * - * @generate_bl_desc: function called on a block of bl_desc_size to generate the - * proper bootloader descriptor for this LS firmware - * @bl_desc_size: size of the bootloader descriptor - * @lhdr_flags: LS flags - */ -struct acr_r352_lsf_func { - void (*generate_bl_desc)(const struct nvkm_acr *, - const struct ls_ucode_img *, u64, void *); - u32 bl_desc_size; - u32 lhdr_flags; -}; - -/** - * struct acr_r352_ls_func - manages a single LS falcon - * - * @load: load the external firmware into a ls_ucode_img - */ -struct acr_r352_ls_func { - int (*load)(const struct nvkm_secboot *, int maxver, - struct ls_ucode_img *); - int version_max; - const struct acr_r352_lsf_func *version[]; -}; - -struct acr_r352; - -/** - * struct acr_r352_func - manages nuances between ACR versions - * - * @generate_hs_bl_desc: function called on a block of bl_desc_size to generate - * the proper HS bootloader descriptor - * @hs_bl_desc_size: size of the HS bootloader descriptor - */ -struct acr_r352_func { - void (*generate_hs_bl_desc)(const struct hsf_load_header *, void *, - u64); - void (*fixup_hs_desc)(struct acr_r352 *, struct nvkm_secboot *, void *); - u32 hs_bl_desc_size; - bool shadow_blob; - - struct ls_ucode_img *(*ls_ucode_img_load)(const struct acr_r352 *, - const struct nvkm_secboot *, - enum nvkm_secboot_falcon); - int (*ls_fill_headers)(struct acr_r352 *, struct list_head *); - int (*ls_write_wpr)(struct acr_r352 *, struct list_head *, - struct nvkm_gpuobj *, u64); - - const struct acr_r352_ls_func *ls_func[NVKM_SECBOOT_FALCON_END]; -}; - -/** - * struct acr_r352 - ACR data for driver release 352 (and beyond) - */ -struct acr_r352 { - struct nvkm_acr base; - const struct acr_r352_func *func; - - /* - * HS FW - lock WPR region (dGPU only) and load LS FWs - * on Tegra the HS FW copies the LS blob into the fixed WPR instead - */ - struct nvkm_gpuobj *load_blob; - struct { - struct hsf_load_header load_bl_header; - u32 __load_apps[ACR_R352_MAX_APPS * 2]; - }; - - /* HS FW - unlock WPR region (dGPU only) */ - struct nvkm_gpuobj *unload_blob; - struct { - struct hsf_load_header unload_bl_header; - u32 __unload_apps[ACR_R352_MAX_APPS * 2]; - }; - - /* HS bootloader */ - void *hsbl_blob; - - /* HS bootloader for unload blob, if using a different falcon */ - void *hsbl_unload_blob; - - /* LS FWs, to be loaded by the HS ACR */ - struct nvkm_gpuobj *ls_blob; - - /* Firmware already loaded? */ - bool firmware_ok; - - /* Falcons to lazy-bootstrap */ - u32 lazy_bootstrap; - - /* To keep track of the state of all managed falcons */ - enum { - /* In non-secure state, no firmware loaded, no privileges*/ - NON_SECURE = 0, - /* In low-secure mode and ready to be started */ - RESET, - /* In low-secure mode and running */ - RUNNING, - } falcon_state[NVKM_SECBOOT_FALCON_END]; -}; -#define acr_r352(acr) container_of(acr, struct acr_r352, base) - -struct nvkm_acr *acr_r352_new_(const struct acr_r352_func *, - enum nvkm_secboot_falcon, unsigned long); - -struct ls_ucode_img *acr_r352_ls_ucode_img_load(const struct acr_r352 *, - const struct nvkm_secboot *, - enum nvkm_secboot_falcon); -int acr_r352_ls_fill_headers(struct acr_r352 *, struct list_head *); -int acr_r352_ls_write_wpr(struct acr_r352 *, struct list_head *, - struct nvkm_gpuobj *, u64); - -void acr_r352_fixup_hs_desc(struct acr_r352 *, struct nvkm_secboot *, void *); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c deleted file mode 100644 index 86d3864c7717..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r361.h" - -#include -#include -#include -#include - -static void -acr_r361_generate_flcn_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - struct acr_r361_flcn_bl_desc *desc = _desc; - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - u64 base, addr_code, addr_data; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = base + pdesc->app_resident_code_offset; - addr_data = base + pdesc->app_resident_data_offset; - - desc->ctx_dma = FALCON_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; -} - -void -acr_r361_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, - u64 offset) -{ - struct acr_r361_flcn_bl_desc *bl_desc = _bl_desc; - - bl_desc->ctx_dma = FALCON_DMAIDX_VIRT; - bl_desc->code_dma_base = u64_to_flcn64(offset); - bl_desc->non_sec_code_off = hdr->non_sec_code_off; - bl_desc->non_sec_code_size = hdr->non_sec_code_size; - bl_desc->sec_code_off = hsf_load_header_app_off(hdr, 0); - bl_desc->sec_code_size = hsf_load_header_app_size(hdr, 0); - bl_desc->code_entry_point = 0; - bl_desc->data_dma_base = u64_to_flcn64(offset + hdr->data_dma_base); - bl_desc->data_size = hdr->data_size; -} - -static const struct acr_r352_lsf_func -acr_r361_ls_fecs_func_0 = { - .generate_bl_desc = acr_r361_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r361_ls_fecs_func = { - .load = acr_ls_ucode_load_fecs, - .version_max = 0, - .version = { - &acr_r361_ls_fecs_func_0, - } -}; - -static const struct acr_r352_lsf_func -acr_r361_ls_gpccs_func_0 = { - .generate_bl_desc = acr_r361_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), - /* GPCCS will be loaded using PRI */ - .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, -}; - -const struct acr_r352_ls_func -acr_r361_ls_gpccs_func = { - .load = acr_ls_ucode_load_gpccs, - .version_max = 0, - .version = { - &acr_r361_ls_gpccs_func_0, - } -}; - -struct acr_r361_pmu_bl_desc { - u32 reserved; - u32 dma_idx; - struct flcn_u64 code_dma_base; - u32 total_code_size; - u32 code_size_to_load; - u32 code_entry_point; - struct flcn_u64 data_dma_base; - u32 data_size; - struct flcn_u64 overlay_dma_base; - u32 argc; - u32 argv; -}; - -static void -acr_r361_generate_pmu_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - const struct nvkm_pmu *pmu = acr->subdev->device->pmu; - struct acr_r361_pmu_bl_desc *desc = _desc; - u64 base, addr_code, addr_data; - u32 addr_args; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = base + pdesc->app_resident_code_offset; - addr_data = base + pdesc->app_resident_data_offset; - addr_args = pmu->falcon.data.limit; - addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; - - desc->dma_idx = FALCON_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->total_code_size = pdesc->app_size; - desc->code_size_to_load = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; - desc->overlay_dma_base = u64_to_flcn64(addr_code); - desc->argc = 1; - desc->argv = addr_args; -} - -static const struct acr_r352_lsf_func -acr_r361_ls_pmu_func_0 = { - .generate_bl_desc = acr_r361_generate_pmu_bl_desc, - .bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r361_ls_pmu_func = { - .load = acr_ls_ucode_load_pmu, - .version_max = 0, - .version = { - &acr_r361_ls_pmu_func_0, - } -}; - -static void -acr_r361_generate_sec2_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - const struct nvkm_sec2 *sec = acr->subdev->device->sec2; - struct acr_r361_pmu_bl_desc *desc = _desc; - u64 base, addr_code, addr_data; - u32 addr_args; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - /* For some reason we should not add app_resident_code_offset here */ - addr_code = base; - addr_data = base + pdesc->app_resident_data_offset; - addr_args = sec->falcon.data.limit; - addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; - - desc->dma_idx = FALCON_SEC2_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->total_code_size = pdesc->app_size; - desc->code_size_to_load = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; - desc->overlay_dma_base = u64_to_flcn64(addr_code); - desc->argc = 1; - /* args are stored at the beginning of EMEM */ - desc->argv = 0x01000000; -} - -const struct acr_r352_lsf_func -acr_r361_ls_sec2_func_0 = { - .generate_bl_desc = acr_r361_generate_sec2_bl_desc, - .bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc), -}; - -static const struct acr_r352_ls_func -acr_r361_ls_sec2_func = { - .load = acr_ls_ucode_load_sec2, - .version_max = 0, - .version = { - &acr_r361_ls_sec2_func_0, - } -}; - - -const struct acr_r352_func -acr_r361_func = { - .fixup_hs_desc = acr_r352_fixup_hs_desc, - .generate_hs_bl_desc = acr_r361_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), - .ls_ucode_img_load = acr_r352_ls_ucode_img_load, - .ls_fill_headers = acr_r352_ls_fill_headers, - .ls_write_wpr = acr_r352_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func, - [NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func, - [NVKM_SECBOOT_FALCON_SEC2] = &acr_r361_ls_sec2_func, - }, -}; - -struct nvkm_acr * -acr_r361_new(unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r361_func, NVKM_SECBOOT_FALCON_PMU, - managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.h deleted file mode 100644 index 38dec93779c8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r361.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_ACR_R361_H__ -#define __NVKM_SECBOOT_ACR_R361_H__ - -#include "acr_r352.h" - -/** - * struct acr_r361_flcn_bl_desc - DMEM bootloader descriptor - * @signature: 16B signature for secure code. 0s if no secure code - * @ctx_dma: DMA context to be used by BL while loading code/data - * @code_dma_base: 256B-aligned Physical FB Address where code is located - * (falcon's $xcbase register) - * @non_sec_code_off: offset from code_dma_base where the non-secure code is - * located. The offset must be multiple of 256 to help perf - * @non_sec_code_size: the size of the nonSecure code part. - * @sec_code_off: offset from code_dma_base where the secure code is - * located. The offset must be multiple of 256 to help perf - * @sec_code_size: offset from code_dma_base where the secure code is - * located. The offset must be multiple of 256 to help perf - * @code_entry_point: code entry point which will be invoked by BL after - * code is loaded. - * @data_dma_base: 256B aligned Physical FB Address where data is located. - * (falcon's $xdbase register) - * @data_size: size of data block. Should be multiple of 256B - * - * Structure used by the bootloader to load the rest of the code. This has - * to be filled by host and copied into DMEM at offset provided in the - * hsflcn_bl_desc.bl_desc_dmem_load_off. - */ -struct acr_r361_flcn_bl_desc { - u32 reserved[4]; - u32 signature[4]; - u32 ctx_dma; - struct flcn_u64 code_dma_base; - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 sec_code_off; - u32 sec_code_size; - u32 code_entry_point; - struct flcn_u64 data_dma_base; - u32 data_size; -}; - -void acr_r361_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64); - -extern const struct acr_r352_ls_func acr_r361_ls_fecs_func; -extern const struct acr_r352_ls_func acr_r361_ls_gpccs_func; -extern const struct acr_r352_ls_func acr_r361_ls_pmu_func; -extern const struct acr_r352_lsf_func acr_r361_ls_sec2_func_0; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r364.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r364.c deleted file mode 100644 index 30cf04109991..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r364.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r361.h" - -#include - -/* - * r364 ACR: hsflcn_desc structure has changed to introduce the shadow_mem - * parameter. - */ - -struct acr_r364_hsflcn_desc { - union { - u8 reserved_dmem[0x200]; - u32 signatures[4]; - } ucode_reserved_space; - u32 wpr_region_id; - u32 wpr_offset; - u32 mmu_memory_range; - struct { - u32 no_regions; - struct { - u32 start_addr; - u32 end_addr; - u32 region_id; - u32 read_mask; - u32 write_mask; - u32 client_mask; - u32 shadow_mem_start_addr; - } region_props[2]; - } regions; - u32 ucode_blob_size; - u64 ucode_blob_base __aligned(8); - struct { - u32 vpr_enabled; - u32 vpr_start; - u32 vpr_end; - u32 hdcp_policies; - } vpr_desc; -}; - -static void -acr_r364_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb, - void *_desc) -{ - struct acr_r364_hsflcn_desc *desc = _desc; - struct nvkm_gpuobj *ls_blob = acr->ls_blob; - - /* WPR region information if WPR is not fixed */ - if (sb->wpr_size == 0) { - u64 wpr_start = ls_blob->addr; - u64 wpr_end = ls_blob->addr + ls_blob->size; - - if (acr->func->shadow_blob) - wpr_start += ls_blob->size / 2; - - desc->wpr_region_id = 1; - desc->regions.no_regions = 2; - desc->regions.region_props[0].start_addr = wpr_start >> 8; - desc->regions.region_props[0].end_addr = wpr_end >> 8; - desc->regions.region_props[0].region_id = 1; - desc->regions.region_props[0].read_mask = 0xf; - desc->regions.region_props[0].write_mask = 0xc; - desc->regions.region_props[0].client_mask = 0x2; - if (acr->func->shadow_blob) - desc->regions.region_props[0].shadow_mem_start_addr = - ls_blob->addr >> 8; - else - desc->regions.region_props[0].shadow_mem_start_addr = 0; - } else { - desc->ucode_blob_base = ls_blob->addr; - desc->ucode_blob_size = ls_blob->size; - } -} - -const struct acr_r352_func -acr_r364_func = { - .fixup_hs_desc = acr_r364_fixup_hs_desc, - .generate_hs_bl_desc = acr_r361_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), - .ls_ucode_img_load = acr_r352_ls_ucode_img_load, - .ls_fill_headers = acr_r352_ls_fill_headers, - .ls_write_wpr = acr_r352_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func, - [NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func, - }, -}; - - -struct nvkm_acr * -acr_r364_new(unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r364_func, NVKM_SECBOOT_FALCON_PMU, - managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c deleted file mode 100644 index f75abbe12ecc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r367.h" -#include "acr_r361.h" -#include "acr_r370.h" - -#include - -/* - * r367 ACR: new LS signature format requires a rewrite of LS firmware and - * blob creation functions. Also the hsflcn_desc layout has changed slightly. - */ - -#define LSF_LSB_DEPMAP_SIZE 11 - -/** - * struct acr_r367_lsf_lsb_header - LS firmware header - * - * See also struct acr_r352_lsf_lsb_header for documentation. - */ -struct acr_r367_lsf_lsb_header { - /** - * LS falcon signatures - * @prd_keys: signature to use in production mode - * @dgb_keys: signature to use in debug mode - * @b_prd_present: whether the production key is present - * @b_dgb_present: whether the debug key is present - * @falcon_id: ID of the falcon the ucode applies to - */ - struct { - u8 prd_keys[2][16]; - u8 dbg_keys[2][16]; - u32 b_prd_present; - u32 b_dbg_present; - u32 falcon_id; - u32 supports_versioning; - u32 version; - u32 depmap_count; - u8 depmap[LSF_LSB_DEPMAP_SIZE * 2 * 4]; - u8 kdf[16]; - } signature; - u32 ucode_off; - u32 ucode_size; - u32 data_size; - u32 bl_code_size; - u32 bl_imem_off; - u32 bl_data_off; - u32 bl_data_size; - u32 app_code_off; - u32 app_code_size; - u32 app_data_off; - u32 app_data_size; - u32 flags; -}; - -/** - * struct acr_r367_lsf_wpr_header - LS blob WPR Header - * - * See also struct acr_r352_lsf_wpr_header for documentation. - */ -struct acr_r367_lsf_wpr_header { - u32 falcon_id; - u32 lsb_offset; - u32 bootstrap_owner; - u32 lazy_bootstrap; - u32 bin_version; - u32 status; -#define LSF_IMAGE_STATUS_NONE 0 -#define LSF_IMAGE_STATUS_COPY 1 -#define LSF_IMAGE_STATUS_VALIDATION_CODE_FAILED 2 -#define LSF_IMAGE_STATUS_VALIDATION_DATA_FAILED 3 -#define LSF_IMAGE_STATUS_VALIDATION_DONE 4 -#define LSF_IMAGE_STATUS_VALIDATION_SKIPPED 5 -#define LSF_IMAGE_STATUS_BOOTSTRAP_READY 6 -#define LSF_IMAGE_STATUS_REVOCATION_CHECK_FAILED 7 -}; - -/** - * struct ls_ucode_img_r367 - ucode image augmented with r367 headers - */ -struct ls_ucode_img_r367 { - struct ls_ucode_img base; - - const struct acr_r352_lsf_func *func; - - struct acr_r367_lsf_wpr_header wpr_header; - struct acr_r367_lsf_lsb_header lsb_header; -}; -#define ls_ucode_img_r367(i) container_of(i, struct ls_ucode_img_r367, base) - -struct ls_ucode_img * -acr_r367_ls_ucode_img_load(const struct acr_r352 *acr, - const struct nvkm_secboot *sb, - enum nvkm_secboot_falcon falcon_id) -{ - const struct nvkm_subdev *subdev = acr->base.subdev; - const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id]; - struct ls_ucode_img_r367 *img; - int ret; - - img = kzalloc(sizeof(*img), GFP_KERNEL); - if (!img) - return ERR_PTR(-ENOMEM); - - img->base.falcon_id = falcon_id; - - ret = func->load(sb, func->version_max, &img->base); - if (ret < 0) { - kfree(img->base.ucode_data); - kfree(img->base.sig); - kfree(img); - return ERR_PTR(ret); - } - - img->func = func->version[ret]; - - /* Check that the signature size matches our expectations... */ - if (img->base.sig_size != sizeof(img->lsb_header.signature)) { - nvkm_error(subdev, "invalid signature size for %s falcon!\n", - nvkm_secboot_falcon_name[falcon_id]); - return ERR_PTR(-EINVAL); - } - - /* Copy signature to the right place */ - memcpy(&img->lsb_header.signature, img->base.sig, img->base.sig_size); - - /* not needed? the signature should already have the right value */ - img->lsb_header.signature.falcon_id = falcon_id; - - return &img->base; -} - -#define LSF_LSB_HEADER_ALIGN 256 -#define LSF_BL_DATA_ALIGN 256 -#define LSF_BL_DATA_SIZE_ALIGN 256 -#define LSF_BL_CODE_SIZE_ALIGN 256 -#define LSF_UCODE_DATA_ALIGN 4096 - -static u32 -acr_r367_ls_img_fill_headers(struct acr_r352 *acr, - struct ls_ucode_img_r367 *img, u32 offset) -{ - struct ls_ucode_img *_img = &img->base; - struct acr_r367_lsf_wpr_header *whdr = &img->wpr_header; - struct acr_r367_lsf_lsb_header *lhdr = &img->lsb_header; - struct ls_ucode_img_desc *desc = &_img->ucode_desc; - const struct acr_r352_lsf_func *func = img->func; - - /* Fill WPR header */ - whdr->falcon_id = _img->falcon_id; - whdr->bootstrap_owner = acr->base.boot_falcon; - whdr->bin_version = lhdr->signature.version; - whdr->status = LSF_IMAGE_STATUS_COPY; - - /* Skip bootstrapping falcons started by someone else than ACR */ - if (acr->lazy_bootstrap & BIT(_img->falcon_id)) - whdr->lazy_bootstrap = 1; - - /* Align, save off, and include an LSB header size */ - offset = ALIGN(offset, LSF_LSB_HEADER_ALIGN); - whdr->lsb_offset = offset; - offset += sizeof(*lhdr); - - /* - * Align, save off, and include the original (static) ucode - * image size - */ - offset = ALIGN(offset, LSF_UCODE_DATA_ALIGN); - _img->ucode_off = lhdr->ucode_off = offset; - offset += _img->ucode_size; - - /* - * For falcons that use a boot loader (BL), we append a loader - * desc structure on the end of the ucode image and consider - * this the boot loader data. The host will then copy the loader - * desc args to this space within the WPR region (before locking - * down) and the HS bin will then copy them to DMEM 0 for the - * loader. - */ - lhdr->bl_code_size = ALIGN(desc->bootloader_size, - LSF_BL_CODE_SIZE_ALIGN); - lhdr->ucode_size = ALIGN(desc->app_resident_data_offset, - LSF_BL_CODE_SIZE_ALIGN) + lhdr->bl_code_size; - lhdr->data_size = ALIGN(desc->app_size, LSF_BL_CODE_SIZE_ALIGN) + - lhdr->bl_code_size - lhdr->ucode_size; - /* - * Though the BL is located at 0th offset of the image, the VA - * is different to make sure that it doesn't collide the actual - * OS VA range - */ - lhdr->bl_imem_off = desc->bootloader_imem_offset; - lhdr->app_code_off = desc->app_start_offset + - desc->app_resident_code_offset; - lhdr->app_code_size = desc->app_resident_code_size; - lhdr->app_data_off = desc->app_start_offset + - desc->app_resident_data_offset; - lhdr->app_data_size = desc->app_resident_data_size; - - lhdr->flags = func->lhdr_flags; - if (_img->falcon_id == acr->base.boot_falcon) - lhdr->flags |= LSF_FLAG_DMACTL_REQ_CTX; - - /* Align and save off BL descriptor size */ - lhdr->bl_data_size = ALIGN(func->bl_desc_size, LSF_BL_DATA_SIZE_ALIGN); - - /* - * Align, save off, and include the additional BL data - */ - offset = ALIGN(offset, LSF_BL_DATA_ALIGN); - lhdr->bl_data_off = offset; - offset += lhdr->bl_data_size; - - return offset; -} - -int -acr_r367_ls_fill_headers(struct acr_r352 *acr, struct list_head *imgs) -{ - struct ls_ucode_img_r367 *img; - struct list_head *l; - u32 count = 0; - u32 offset; - - /* Count the number of images to manage */ - list_for_each(l, imgs) - count++; - - /* - * Start with an array of WPR headers at the base of the WPR. - * The expectation here is that the secure falcon will do a single DMA - * read of this array and cache it internally so it's ok to pack these. - * Also, we add 1 to the falcon count to indicate the end of the array. - */ - offset = sizeof(img->wpr_header) * (count + 1); - - /* - * Walk the managed falcons, accounting for the LSB structs - * as well as the ucode images. - */ - list_for_each_entry(img, imgs, base.node) { - offset = acr_r367_ls_img_fill_headers(acr, img, offset); - } - - return offset; -} - -int -acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, - struct nvkm_gpuobj *wpr_blob, u64 wpr_addr) -{ - struct ls_ucode_img *_img; - u32 pos = 0; - u32 max_desc_size = 0; - u8 *gdesc; - - list_for_each_entry(_img, imgs, node) { - struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img); - const struct acr_r352_lsf_func *ls_func = img->func; - - max_desc_size = max(max_desc_size, ls_func->bl_desc_size); - } - - gdesc = kmalloc(max_desc_size, GFP_KERNEL); - if (!gdesc) - return -ENOMEM; - - nvkm_kmap(wpr_blob); - - list_for_each_entry(_img, imgs, node) { - struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img); - const struct acr_r352_lsf_func *ls_func = img->func; - - nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, - sizeof(img->wpr_header)); - - nvkm_gpuobj_memcpy_to(wpr_blob, img->wpr_header.lsb_offset, - &img->lsb_header, sizeof(img->lsb_header)); - - /* Generate and write BL descriptor */ - memset(gdesc, 0, ls_func->bl_desc_size); - ls_func->generate_bl_desc(&acr->base, _img, wpr_addr, gdesc); - - nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.bl_data_off, - gdesc, ls_func->bl_desc_size); - - /* Copy ucode */ - nvkm_gpuobj_memcpy_to(wpr_blob, img->lsb_header.ucode_off, - _img->ucode_data, _img->ucode_size); - - pos += sizeof(img->wpr_header); - } - - nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID); - - nvkm_done(wpr_blob); - - kfree(gdesc); - - return 0; -} - -struct acr_r367_hsflcn_desc { - u8 reserved_dmem[0x200]; - u32 signatures[4]; - u32 wpr_region_id; - u32 wpr_offset; - u32 mmu_memory_range; -#define FLCN_ACR_MAX_REGIONS 2 - struct { - u32 no_regions; - struct { - u32 start_addr; - u32 end_addr; - u32 region_id; - u32 read_mask; - u32 write_mask; - u32 client_mask; - u32 shadow_mem_start_addr; - } region_props[FLCN_ACR_MAX_REGIONS]; - } regions; - u32 ucode_blob_size; - u64 ucode_blob_base __aligned(8); - struct { - u32 vpr_enabled; - u32 vpr_start; - u32 vpr_end; - u32 hdcp_policies; - } vpr_desc; -}; - -void -acr_r367_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb, - void *_desc) -{ - struct acr_r367_hsflcn_desc *desc = _desc; - struct nvkm_gpuobj *ls_blob = acr->ls_blob; - - /* WPR region information if WPR is not fixed */ - if (sb->wpr_size == 0) { - u64 wpr_start = ls_blob->addr; - u64 wpr_end = ls_blob->addr + ls_blob->size; - - if (acr->func->shadow_blob) - wpr_start += ls_blob->size / 2; - - desc->wpr_region_id = 1; - desc->regions.no_regions = 2; - desc->regions.region_props[0].start_addr = wpr_start >> 8; - desc->regions.region_props[0].end_addr = wpr_end >> 8; - desc->regions.region_props[0].region_id = 1; - desc->regions.region_props[0].read_mask = 0xf; - desc->regions.region_props[0].write_mask = 0xc; - desc->regions.region_props[0].client_mask = 0x2; - if (acr->func->shadow_blob) - desc->regions.region_props[0].shadow_mem_start_addr = - ls_blob->addr >> 8; - else - desc->regions.region_props[0].shadow_mem_start_addr = 0; - } else { - desc->ucode_blob_base = ls_blob->addr; - desc->ucode_blob_size = ls_blob->size; - } -} - -static const struct acr_r352_ls_func -acr_r367_ls_sec2_func = { - .load = acr_ls_ucode_load_sec2, - .version_max = 1, - .version = { - &acr_r361_ls_sec2_func_0, - &acr_r370_ls_sec2_func_0, - } -}; - -const struct acr_r352_func -acr_r367_func = { - .fixup_hs_desc = acr_r367_fixup_hs_desc, - .generate_hs_bl_desc = acr_r361_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), - .shadow_blob = true, - .ls_ucode_img_load = acr_r367_ls_ucode_img_load, - .ls_fill_headers = acr_r367_ls_fill_headers, - .ls_write_wpr = acr_r367_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func, - [NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func, - [NVKM_SECBOOT_FALCON_SEC2] = &acr_r367_ls_sec2_func, - }, -}; - -struct nvkm_acr * -acr_r367_new(enum nvkm_secboot_falcon boot_falcon, - unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r367_func, boot_falcon, managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.h deleted file mode 100644 index 8bdfb3e5cd1c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_ACR_R367_H__ -#define __NVKM_SECBOOT_ACR_R367_H__ - -#include "acr_r352.h" - -void acr_r367_fixup_hs_desc(struct acr_r352 *, struct nvkm_secboot *, void *); - -struct ls_ucode_img *acr_r367_ls_ucode_img_load(const struct acr_r352 *, - const struct nvkm_secboot *, - enum nvkm_secboot_falcon); -int acr_r367_ls_fill_headers(struct acr_r352 *, struct list_head *); -int acr_r367_ls_write_wpr(struct acr_r352 *, struct list_head *, - struct nvkm_gpuobj *, u64); -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c deleted file mode 100644 index 3d80e508445f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r370.h" -#include "acr_r367.h" - -#include -#include -#include - -static void -acr_r370_generate_flcn_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - struct acr_r370_flcn_bl_desc *desc = _desc; - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - u64 base, addr_code, addr_data; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = base + pdesc->app_resident_code_offset; - addr_data = base + pdesc->app_resident_data_offset; - - desc->ctx_dma = FALCON_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; -} - -static const struct acr_r352_lsf_func -acr_r370_ls_fecs_func_0 = { - .generate_bl_desc = acr_r370_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r370_ls_fecs_func = { - .load = acr_ls_ucode_load_fecs, - .version_max = 0, - .version = { - &acr_r370_ls_fecs_func_0, - } -}; - -static const struct acr_r352_lsf_func -acr_r370_ls_gpccs_func_0 = { - .generate_bl_desc = acr_r370_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), - /* GPCCS will be loaded using PRI */ - .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, -}; - -const struct acr_r352_ls_func -acr_r370_ls_gpccs_func = { - .load = acr_ls_ucode_load_gpccs, - .version_max = 0, - .version = { - &acr_r370_ls_gpccs_func_0, - } -}; - -static void -acr_r370_generate_sec2_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - const struct nvkm_sec2 *sec = acr->subdev->device->sec2; - struct acr_r370_flcn_bl_desc *desc = _desc; - u64 base, addr_code, addr_data; - u32 addr_args; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - /* For some reason we should not add app_resident_code_offset here */ - addr_code = base; - addr_data = base + pdesc->app_resident_data_offset; - addr_args = sec->falcon.data.limit; - addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; - - desc->ctx_dma = FALCON_SEC2_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; - desc->argc = 1; - /* args are stored at the beginning of EMEM */ - desc->argv = 0x01000000; -} - -const struct acr_r352_lsf_func -acr_r370_ls_sec2_func_0 = { - .generate_bl_desc = acr_r370_generate_sec2_bl_desc, - .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r370_ls_sec2_func = { - .load = acr_ls_ucode_load_sec2, - .version_max = 0, - .version = { - &acr_r370_ls_sec2_func_0, - } -}; - -void -acr_r370_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, - u64 offset) -{ - struct acr_r370_flcn_bl_desc *bl_desc = _bl_desc; - - bl_desc->ctx_dma = FALCON_DMAIDX_VIRT; - bl_desc->non_sec_code_off = hdr->non_sec_code_off; - bl_desc->non_sec_code_size = hdr->non_sec_code_size; - bl_desc->sec_code_off = hsf_load_header_app_off(hdr, 0); - bl_desc->sec_code_size = hsf_load_header_app_size(hdr, 0); - bl_desc->code_entry_point = 0; - bl_desc->code_dma_base = u64_to_flcn64(offset); - bl_desc->data_dma_base = u64_to_flcn64(offset + hdr->data_dma_base); - bl_desc->data_size = hdr->data_size; -} - -const struct acr_r352_func -acr_r370_func = { - .fixup_hs_desc = acr_r367_fixup_hs_desc, - .generate_hs_bl_desc = acr_r370_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), - .shadow_blob = true, - .ls_ucode_img_load = acr_r367_ls_ucode_img_load, - .ls_fill_headers = acr_r367_ls_fill_headers, - .ls_write_wpr = acr_r367_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_SEC2] = &acr_r370_ls_sec2_func, - [NVKM_SECBOOT_FALCON_FECS] = &acr_r370_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r370_ls_gpccs_func, - }, -}; - -struct nvkm_acr * -acr_r370_new(enum nvkm_secboot_falcon boot_falcon, - unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r370_func, boot_falcon, managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h deleted file mode 100644 index 855f75b6d5c6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_ACR_R370_H__ -#define __NVKM_SECBOOT_ACR_R370_H__ -#include "priv.h" -struct hsf_load_header; - -/* Same as acr_r361_flcn_bl_desc, plus argc/argv */ -struct acr_r370_flcn_bl_desc { - u32 reserved[4]; - u32 signature[4]; - u32 ctx_dma; - struct flcn_u64 code_dma_base; - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 sec_code_off; - u32 sec_code_size; - u32 code_entry_point; - struct flcn_u64 data_dma_base; - u32 data_size; - u32 argc; - u32 argv; -}; - -void acr_r370_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64); -extern const struct acr_r352_ls_func acr_r370_ls_fecs_func; -extern const struct acr_r352_ls_func acr_r370_ls_gpccs_func; -extern const struct acr_r352_lsf_func acr_r370_ls_sec2_func_0; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c deleted file mode 100644 index 06cb2f867b80..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr_r370.h" -#include "acr_r367.h" - -#include -#include - -static void -acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - const struct nvkm_pmu *pmu = acr->subdev->device->pmu; - struct acr_r370_flcn_bl_desc *desc = _desc; - u64 base, addr_code, addr_data; - u32 addr_args; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = base + pdesc->app_resident_code_offset; - addr_data = base + pdesc->app_resident_data_offset; - addr_args = pmu->falcon.data.limit; - addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; - - desc->ctx_dma = FALCON_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; - desc->argc = 1; - desc->argv = addr_args; -} - -static const struct acr_r352_lsf_func -acr_r375_ls_pmu_func_0 = { - .generate_bl_desc = acr_r375_generate_pmu_bl_desc, - .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r375_ls_pmu_func = { - .load = acr_ls_ucode_load_pmu, - .version_max = 0, - .version = { - &acr_r375_ls_pmu_func_0, - } -}; - -const struct acr_r352_func -acr_r375_func = { - .fixup_hs_desc = acr_r367_fixup_hs_desc, - .generate_hs_bl_desc = acr_r370_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), - .shadow_blob = true, - .ls_ucode_img_load = acr_r367_ls_ucode_img_load, - .ls_fill_headers = acr_r367_ls_fill_headers, - .ls_write_wpr = acr_r367_ls_write_wpr, - .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r370_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r370_ls_gpccs_func, - [NVKM_SECBOOT_FALCON_PMU] = &acr_r375_ls_pmu_func, - }, -}; - -struct nvkm_acr * -acr_r375_new(enum nvkm_secboot_falcon boot_falcon, - unsigned long managed_falcons) -{ - return acr_r352_new_(&acr_r375_func, boot_falcon, managed_falcons); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c deleted file mode 100644 index 993f01b1d155..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -/* - * Secure boot is the process by which NVIDIA-signed firmware is loaded into - * some of the falcons of a GPU. For production devices this is the only way - * for the firmware to access useful (but sensitive) registers. - * - * A Falcon microprocessor supporting advanced security modes can run in one of - * three modes: - * - * - Non-secure (NS). In this mode, functionality is similar to Falcon - * architectures before security modes were introduced (pre-Maxwell), but - * capability is restricted. In particular, certain registers may be - * inaccessible for reads and/or writes, and physical memory access may be - * disabled (on certain Falcon instances). This is the only possible mode that - * can be used if you don't have microcode cryptographically signed by NVIDIA. - * - * - Heavy Secure (HS). In this mode, the microprocessor is a black box - it's - * not possible to read or write any Falcon internal state or Falcon registers - * from outside the Falcon (for example, from the host system). The only way - * to enable this mode is by loading microcode that has been signed by NVIDIA. - * (The loading process involves tagging the IMEM block as secure, writing the - * signature into a Falcon register, and starting execution. The hardware will - * validate the signature, and if valid, grant HS privileges.) - * - * - Light Secure (LS). In this mode, the microprocessor has more privileges - * than NS but fewer than HS. Some of the microprocessor state is visible to - * host software to ease debugging. The only way to enable this mode is by HS - * microcode enabling LS mode. Some privileges available to HS mode are not - * available here. LS mode is introduced in GM20x. - * - * Secure boot consists in temporarily switching a HS-capable falcon (typically - * PMU) into HS mode in order to validate the LS firmwares of managed falcons, - * load them, and switch managed falcons into LS mode. Once secure boot - * completes, no falcon remains in HS mode. - * - * Secure boot requires a write-protected memory region (WPR) which can only be - * written by the secure falcon. On dGPU, the driver sets up the WPR region in - * video memory. On Tegra, it is set up by the bootloader and its location and - * size written into memory controller registers. - * - * The secure boot process takes place as follows: - * - * 1) A LS blob is constructed that contains all the LS firmwares we want to - * load, along with their signatures and bootloaders. - * - * 2) A HS blob (also called ACR) is created that contains the signed HS - * firmware in charge of loading the LS firmwares into their respective - * falcons. - * - * 3) The HS blob is loaded (via its own bootloader) and executed on the - * HS-capable falcon. It authenticates itself, switches the secure falcon to - * HS mode and setup the WPR region around the LS blob (dGPU) or copies the - * LS blob into the WPR region (Tegra). - * - * 4) The LS blob is now secure from all external tampering. The HS falcon - * checks the signatures of the LS firmwares and, if valid, switches the - * managed falcons to LS mode and makes them ready to run the LS firmware. - * - * 5) The managed falcons remain in LS mode and can be started. - * - */ - -#include "priv.h" -#include "acr.h" - -#include -#include -#include -#include - -const char * -nvkm_secboot_falcon_name[] = { - [NVKM_SECBOOT_FALCON_PMU] = "PMU", - [NVKM_SECBOOT_FALCON_RESERVED] = "", - [NVKM_SECBOOT_FALCON_FECS] = "FECS", - [NVKM_SECBOOT_FALCON_GPCCS] = "GPCCS", - [NVKM_SECBOOT_FALCON_SEC2] = "SEC2", - [NVKM_SECBOOT_FALCON_END] = "", -}; -/** - * nvkm_secboot_reset() - reset specified falcon - */ -int -nvkm_secboot_reset(struct nvkm_secboot *sb, unsigned long falcon_mask) -{ - /* Unmanaged falcon? */ - if ((falcon_mask | sb->acr->managed_falcons) != sb->acr->managed_falcons) { - nvkm_error(&sb->subdev, "cannot reset unmanaged falcon!\n"); - return -EINVAL; - } - - return sb->acr->func->reset(sb->acr, sb, falcon_mask); -} - -/** - * nvkm_secboot_is_managed() - check whether a given falcon is securely-managed - */ -bool -nvkm_secboot_is_managed(struct nvkm_secboot *sb, enum nvkm_secboot_falcon fid) -{ - if (!sb) - return false; - - return sb->acr->managed_falcons & BIT(fid); -} - -static int -nvkm_secboot_oneinit(struct nvkm_subdev *subdev) -{ - struct nvkm_secboot *sb = nvkm_secboot(subdev); - int ret = 0; - - switch (sb->acr->boot_falcon) { - case NVKM_SECBOOT_FALCON_PMU: - sb->halt_falcon = sb->boot_falcon = &subdev->device->pmu->falcon; - break; - case NVKM_SECBOOT_FALCON_SEC2: - /* we must keep SEC2 alive forever since ACR will run on it */ - nvkm_engine_ref(&subdev->device->sec2->engine); - sb->boot_falcon = &subdev->device->sec2->falcon; - sb->halt_falcon = &subdev->device->pmu->falcon; - break; - default: - nvkm_error(subdev, "Unmanaged boot falcon %s!\n", - nvkm_secboot_falcon_name[sb->acr->boot_falcon]); - return -EINVAL; - } - nvkm_debug(subdev, "using %s falcon for ACR\n", sb->boot_falcon->name); - - /* Call chip-specific init function */ - if (sb->func->oneinit) - ret = sb->func->oneinit(sb); - if (ret) { - nvkm_error(subdev, "Secure Boot initialization failed: %d\n", - ret); - return ret; - } - - return 0; -} - -static int -nvkm_secboot_fini(struct nvkm_subdev *subdev, bool suspend) -{ - struct nvkm_secboot *sb = nvkm_secboot(subdev); - int ret = 0; - - if (sb->func->fini) - ret = sb->func->fini(sb, suspend); - - return ret; -} - -static void * -nvkm_secboot_dtor(struct nvkm_subdev *subdev) -{ - struct nvkm_secboot *sb = nvkm_secboot(subdev); - void *ret = NULL; - - if (sb->func->dtor) - ret = sb->func->dtor(sb); - - return ret; -} - -static const struct nvkm_subdev_func -nvkm_secboot = { - .oneinit = nvkm_secboot_oneinit, - .fini = nvkm_secboot_fini, - .dtor = nvkm_secboot_dtor, -}; - -int -nvkm_secboot_ctor(const struct nvkm_secboot_func *func, struct nvkm_acr *acr, - struct nvkm_device *device, int index, - struct nvkm_secboot *sb) -{ - unsigned long fid; - - nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev); - sb->func = func; - sb->acr = acr; - acr->subdev = &sb->subdev; - - nvkm_debug(&sb->subdev, "securely managed falcons:\n"); - for_each_set_bit(fid, &sb->acr->managed_falcons, - NVKM_SECBOOT_FALCON_END) - nvkm_debug(&sb->subdev, "- %s\n", - nvkm_secboot_falcon_name[fid]); - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c deleted file mode 100644 index d6f8b904af65..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - - -#include "acr.h" -#include "gm200.h" - -#include -#include -#include -#include - -/** - * gm200_secboot_run_blob() - run the given high-secure blob - * - */ -int -gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, - struct nvkm_falcon *falcon) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - struct nvkm_subdev *subdev = &gsb->base.subdev; - struct nvkm_vma *vma = NULL; - u32 start_address; - int ret; - - ret = nvkm_falcon_get(falcon, subdev); - if (ret) - return ret; - - /* Map the HS firmware so the HS bootloader can see it */ - ret = nvkm_vmm_get(gsb->vmm, 12, blob->size, &vma); - if (ret) { - nvkm_falcon_put(falcon, subdev); - return ret; - } - - ret = nvkm_memory_map(blob, 0, gsb->vmm, vma, NULL, 0); - if (ret) - goto end; - - /* Reset and set the falcon up */ - ret = nvkm_falcon_reset(falcon); - if (ret) - goto end; - nvkm_falcon_bind_context(falcon, gsb->inst); - - /* Load the HS bootloader into the falcon's IMEM/DMEM */ - ret = sb->acr->func->load(sb->acr, falcon, blob, vma->addr); - if (ret < 0) - goto end; - - start_address = ret; - - /* Disable interrupts as we will poll for the HALT bit */ - nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, false); - - /* Set default error value in mailbox register */ - nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5); - - /* Start the HS bootloader */ - nvkm_falcon_set_start_addr(falcon, start_address); - nvkm_falcon_start(falcon); - ret = nvkm_falcon_wait_for_halt(falcon, 100); - if (ret) - goto end; - - /* - * The mailbox register contains the (positive) error code - return this - * to the caller - */ - ret = nvkm_falcon_rd32(falcon, 0x040); - -end: - /* Reenable interrupts */ - nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true); - - /* We don't need the ACR firmware anymore */ - nvkm_vmm_put(gsb->vmm, &vma); - nvkm_falcon_put(falcon, subdev); - - return ret; -} - -int -gm200_secboot_oneinit(struct nvkm_secboot *sb) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - struct nvkm_device *device = sb->subdev.device; - int ret; - - /* Allocate instance block and VM */ - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true, - &gsb->inst); - if (ret) - return ret; - - ret = nvkm_vmm_new(device, 0, 600 * 1024, NULL, 0, NULL, "acr", - &gsb->vmm); - if (ret) - return ret; - - atomic_inc(&gsb->vmm->engref[NVKM_SUBDEV_PMU]); - gsb->vmm->debug = gsb->base.subdev.debug; - - ret = nvkm_vmm_join(gsb->vmm, gsb->inst); - if (ret) - return ret; - - if (sb->acr->func->oneinit) { - ret = sb->acr->func->oneinit(sb->acr, sb); - if (ret) - return ret; - } - - return 0; -} - -int -gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend) -{ - int ret = 0; - - if (sb->acr->func->fini) - ret = sb->acr->func->fini(sb->acr, sb, suspend); - - return ret; -} - -void * -gm200_secboot_dtor(struct nvkm_secboot *sb) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - - sb->acr->func->dtor(sb->acr); - - nvkm_vmm_part(gsb->vmm, gsb->inst); - nvkm_vmm_unref(&gsb->vmm); - nvkm_memory_unref(&gsb->inst); - - return gsb; -} - - -static const struct nvkm_secboot_func -gm200_secboot = { - .dtor = gm200_secboot_dtor, - .oneinit = gm200_secboot_oneinit, - .fini = gm200_secboot_fini, - .run_blob = gm200_secboot_run_blob, -}; - -int -gm200_secboot_new(struct nvkm_device *device, int index, - struct nvkm_secboot **psb) -{ - int ret; - struct gm200_secboot *gsb; - struct nvkm_acr *acr; - - acr = acr_r361_new(BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_GPCCS)); - if (IS_ERR(acr)) - return PTR_ERR(acr); - - gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); - if (!gsb) { - psb = NULL; - return -ENOMEM; - } - *psb = &gsb->base; - - ret = nvkm_secboot_ctor(&gm200_secboot, acr, device, index, &gsb->base); - if (ret) - return ret; - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h deleted file mode 100644 index 280b1448df88..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_GM200_H__ -#define __NVKM_SECBOOT_GM200_H__ - -#include "priv.h" - -struct gm200_secboot { - struct nvkm_secboot base; - - /* Instance block & address space used for HS FW execution */ - struct nvkm_memory *inst; - struct nvkm_vmm *vmm; -}; -#define gm200_secboot(sb) container_of(sb, struct gm200_secboot, base) - -int gm200_secboot_oneinit(struct nvkm_secboot *); -int gm200_secboot_fini(struct nvkm_secboot *, bool); -void *gm200_secboot_dtor(struct nvkm_secboot *); -int gm200_secboot_run_blob(struct nvkm_secboot *, struct nvkm_gpuobj *, - struct nvkm_falcon *); - -/* Tegra-only */ -int gm20b_secboot_tegra_read_wpr(struct gm200_secboot *); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c deleted file mode 100644 index d047bfeaf5d4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr.h" -#include "gm200.h" - -#ifdef CONFIG_ARCH_TEGRA -/** - * gm20b_secboot_tegra_read_wpr() - read the WPR registers on Tegra - * - * On dGPU, we can manage the WPR region ourselves, but on Tegra this region - * is allocated from system memory by the secure firmware. The region is then - * marked as a "secure carveout" and irreversibly locked. Furthermore, the WPR - * secure carveout is also configured to be sent to the GPU via a dedicated - * serial bus between the memory controller and the GPU. The GPU requests this - * information upon leaving reset and exposes it through a FIFO register at - * offset 0x100cd4. - * - * The FIFO register's lower 4 bits can be used to set the read index into the - * FIFO. After each read of the FIFO register, the read index is incremented. - * - * Indices 2 and 3 contain the lower and upper addresses of the WPR. These are - * stored in units of 256 B. The WPR is inclusive of both addresses. - * - * Unfortunately, for some reason the WPR info register doesn't contain the - * correct values for the secure carveout. It seems like the upper address is - * always too small by 128 KiB - 1. Given that the secure carvout size in the - * memory controller configuration is specified in units of 128 KiB, it's - * possible that the computation of the upper address of the WPR is wrong and - * causes this difference. - */ -int -gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb) -{ - struct nvkm_device *device = gsb->base.subdev.device; - struct nvkm_secboot *sb = &gsb->base; - u64 base, limit; - u32 value; - - /* set WPR info register to point at WPR base address register */ - value = nvkm_rd32(device, 0x100cd4); - value &= ~0xf; - value |= 0x2; - nvkm_wr32(device, 0x100cd4, value); - - /* read base address */ - value = nvkm_rd32(device, 0x100cd4); - base = (u64)(value >> 4) << 12; - - /* read limit */ - value = nvkm_rd32(device, 0x100cd4); - limit = (u64)(value >> 4) << 12; - - /* - * The upper address of the WPR seems to be computed wrongly and is - * actually SZ_128K - 1 bytes lower than it should be. Adjust the - * value accordingly. - */ - limit += SZ_128K - 1; - - sb->wpr_size = limit - base + 1; - sb->wpr_addr = base; - - nvkm_info(&sb->subdev, "WPR: %016llx-%016llx\n", sb->wpr_addr, - sb->wpr_addr + sb->wpr_size - 1); - - /* Check that WPR settings are valid */ - if (sb->wpr_size == 0) { - nvkm_error(&sb->subdev, "WPR region is empty\n"); - return -EINVAL; - } - - return 0; -} -#else -int -gm20b_secboot_tegra_read_wpr(struct gm200_secboot *gsb) -{ - nvkm_error(&gsb->base.subdev, "Tegra support not compiled in\n"); - return -EINVAL; -} -#endif - -static int -gm20b_secboot_oneinit(struct nvkm_secboot *sb) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - int ret; - - ret = gm20b_secboot_tegra_read_wpr(gsb); - if (ret) - return ret; - - return gm200_secboot_oneinit(sb); -} - -static const struct nvkm_secboot_func -gm20b_secboot = { - .dtor = gm200_secboot_dtor, - .oneinit = gm20b_secboot_oneinit, - .fini = gm200_secboot_fini, - .run_blob = gm200_secboot_run_blob, -}; - -int -gm20b_secboot_new(struct nvkm_device *device, int index, - struct nvkm_secboot **psb) -{ - int ret; - struct gm200_secboot *gsb; - struct nvkm_acr *acr; - - *psb = NULL; - acr = acr_r352_new(BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_PMU)); - if (IS_ERR(acr)) - return PTR_ERR(acr); - /* Support the initial GM20B firmware release without PMU */ - acr->optional_falcons = BIT(NVKM_SECBOOT_FALCON_PMU); - - gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); - if (!gsb) - return -ENOMEM; - *psb = &gsb->base; - - ret = nvkm_secboot_ctor(&gm20b_secboot, acr, device, index, &gsb->base); - if (ret) - return ret; - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c deleted file mode 100644 index 49dad16fb3ec..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr.h" -#include "gm200.h" - -const struct nvkm_secboot_func -gp102_secboot = { - .dtor = gm200_secboot_dtor, - .oneinit = gm200_secboot_oneinit, - .fini = gm200_secboot_fini, - .run_blob = gm200_secboot_run_blob, -}; - -int -gp102_secboot_new(struct nvkm_device *device, int index, - struct nvkm_secboot **psb) -{ - int ret; - struct gm200_secboot *gsb; - struct nvkm_acr *acr; - - acr = acr_r367_new(NVKM_SECBOOT_FALCON_SEC2, - BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_GPCCS) | - BIT(NVKM_SECBOOT_FALCON_SEC2)); - if (IS_ERR(acr)) - return PTR_ERR(acr); - - gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); - if (!gsb) { - psb = NULL; - return -ENOMEM; - } - *psb = &gsb->base; - - ret = nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); - if (ret) - return ret; - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c deleted file mode 100644 index 03d0428079fa..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 Red Hat 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. - */ -#include "gm200.h" -#include "acr.h" - -int -gp108_secboot_new(struct nvkm_device *device, int index, - struct nvkm_secboot **psb) -{ - struct gm200_secboot *gsb; - struct nvkm_acr *acr; - - acr = acr_r370_new(NVKM_SECBOOT_FALCON_SEC2, - BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_GPCCS) | - BIT(NVKM_SECBOOT_FALCON_SEC2)); - if (IS_ERR(acr)) - return PTR_ERR(acr); - - if (!(gsb = kzalloc(sizeof(*gsb), GFP_KERNEL))) { - acr->func->dtor(acr); - return -ENOMEM; - } - *psb = &gsb->base; - - return nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c deleted file mode 100644 index b36fcc4f43bf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp10b.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "acr.h" -#include "gm200.h" - -static int -gp10b_secboot_oneinit(struct nvkm_secboot *sb) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - int ret; - - ret = gm20b_secboot_tegra_read_wpr(gsb); - if (ret) - return ret; - - return gm200_secboot_oneinit(sb); -} - -static const struct nvkm_secboot_func -gp10b_secboot = { - .dtor = gm200_secboot_dtor, - .oneinit = gp10b_secboot_oneinit, - .fini = gm200_secboot_fini, - .run_blob = gm200_secboot_run_blob, -}; - -int -gp10b_secboot_new(struct nvkm_device *device, int index, - struct nvkm_secboot **psb) -{ - int ret; - struct gm200_secboot *gsb; - struct nvkm_acr *acr; - - acr = acr_r352_new(BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_GPCCS) | - BIT(NVKM_SECBOOT_FALCON_PMU)); - if (IS_ERR(acr)) - return PTR_ERR(acr); - - gsb = kzalloc(sizeof(*gsb), GFP_KERNEL); - if (!gsb) { - psb = NULL; - return -ENOMEM; - } - *psb = &gsb->base; - - ret = nvkm_secboot_ctor(&gp10b_secboot, acr, device, index, &gsb->base); - if (ret) - return ret; - - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.c deleted file mode 100644 index 6b33182ddc2f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - -#include "hs_ucode.h" -#include "ls_ucode.h" -#include "acr.h" - -#include - -/** - * hs_ucode_patch_signature() - patch HS blob with correct signature for - * specified falcon. - */ -static void -hs_ucode_patch_signature(const struct nvkm_falcon *falcon, void *acr_image, - bool new_format) -{ - struct fw_bin_header *hsbin_hdr = acr_image; - struct hsf_fw_header *fw_hdr = acr_image + hsbin_hdr->header_offset; - void *hs_data = acr_image + hsbin_hdr->data_offset; - void *sig; - u32 sig_size; - u32 patch_loc, patch_sig; - - /* - * I had the brilliant idea to "improve" the binary format by - * removing this useless indirection. However to make NVIDIA files - * directly compatible, let's support both format. - */ - if (new_format) { - patch_loc = fw_hdr->patch_loc; - patch_sig = fw_hdr->patch_sig; - } else { - patch_loc = *(u32 *)(acr_image + fw_hdr->patch_loc); - patch_sig = *(u32 *)(acr_image + fw_hdr->patch_sig); - } - - /* Falcon in debug or production mode? */ - if (falcon->debug) { - sig = acr_image + fw_hdr->sig_dbg_offset; - sig_size = fw_hdr->sig_dbg_size; - } else { - sig = acr_image + fw_hdr->sig_prod_offset; - sig_size = fw_hdr->sig_prod_size; - } - - /* Patch signature */ - memcpy(hs_data + patch_loc, sig + patch_sig, sig_size); -} - -void * -hs_ucode_load_blob(struct nvkm_subdev *subdev, const struct nvkm_falcon *falcon, - const char *fw) -{ - void *acr_image; - bool new_format; - - acr_image = nvkm_acr_load_firmware(subdev, fw, 0); - if (IS_ERR(acr_image)) - return acr_image; - - /* detect the format to define how signature should be patched */ - switch (((u32 *)acr_image)[0]) { - case 0x3b1d14f0: - new_format = true; - break; - case 0x000010de: - new_format = false; - break; - default: - nvkm_error(subdev, "unknown header for HS blob %s\n", fw); - return ERR_PTR(-EINVAL); - } - - hs_ucode_patch_signature(falcon, acr_image, new_format); - - return acr_image; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.h deleted file mode 100644 index d8cfc6f7752a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/hs_ucode.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2017, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_HS_UCODE_H__ -#define __NVKM_SECBOOT_HS_UCODE_H__ - -#include -#include - -struct nvkm_falcon; - -/** - * struct hsf_fw_header - HS firmware descriptor - * @sig_dbg_offset: offset of the debug signature - * @sig_dbg_size: size of the debug signature - * @sig_prod_offset: offset of the production signature - * @sig_prod_size: size of the production signature - * @patch_loc: offset of the offset (sic) of where the signature is - * @patch_sig: offset of the offset (sic) to add to sig_*_offset - * @hdr_offset: offset of the load header (see struct hs_load_header) - * @hdr_size: size of above header - * - * This structure is embedded in the HS firmware image at - * hs_bin_hdr.header_offset. - */ -struct hsf_fw_header { - u32 sig_dbg_offset; - u32 sig_dbg_size; - u32 sig_prod_offset; - u32 sig_prod_size; - u32 patch_loc; - u32 patch_sig; - u32 hdr_offset; - u32 hdr_size; -}; - -/** - * struct hsf_load_header - HS firmware load header - */ -struct hsf_load_header { - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 data_dma_base; - u32 data_size; - u32 num_apps; - /* - * Organized as follows: - * - app0_code_off - * - app1_code_off - * - ... - * - appn_code_off - * - app0_code_size - * - app1_code_size - * - ... - */ - u32 apps[0]; -}; - -void *hs_ucode_load_blob(struct nvkm_subdev *, const struct nvkm_falcon *, - const char *); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h deleted file mode 100644 index d43f906da3a7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_LS_UCODE_H__ -#define __NVKM_SECBOOT_LS_UCODE_H__ - -#include -#include -#include - -struct nvkm_acr; - -/** - * struct ls_ucode_img_desc - descriptor of firmware image - * @descriptor_size: size of this descriptor - * @image_size: size of the whole image - * @bootloader_start_offset: start offset of the bootloader in ucode image - * @bootloader_size: size of the bootloader - * @bootloader_imem_offset: start off set of the bootloader in IMEM - * @bootloader_entry_point: entry point of the bootloader in IMEM - * @app_start_offset: start offset of the LS firmware - * @app_size: size of the LS firmware's code and data - * @app_imem_offset: offset of the app in IMEM - * @app_imem_entry: entry point of the app in IMEM - * @app_dmem_offset: offset of the data in DMEM - * @app_resident_code_offset: offset of app code from app_start_offset - * @app_resident_code_size: size of the code - * @app_resident_data_offset: offset of data from app_start_offset - * @app_resident_data_size: size of data - * - * A firmware image contains the code, data, and bootloader of a given LS - * falcon in a single blob. This structure describes where everything is. - * - * This can be generated from a (bootloader, code, data) set if they have - * been loaded separately, or come directly from a file. - */ -struct ls_ucode_img_desc { - u32 descriptor_size; - u32 image_size; - u32 tools_version; - u32 app_version; - char date[64]; - u32 bootloader_start_offset; - u32 bootloader_size; - u32 bootloader_imem_offset; - u32 bootloader_entry_point; - u32 app_start_offset; - u32 app_size; - u32 app_imem_offset; - u32 app_imem_entry; - u32 app_dmem_offset; - u32 app_resident_code_offset; - u32 app_resident_code_size; - u32 app_resident_data_offset; - u32 app_resident_data_size; - u32 nb_overlays; - struct {u32 start; u32 size; } load_ovl[64]; - u32 compressed; -}; - -/** - * struct ls_ucode_img - temporary storage for loaded LS firmwares - * @node: to link within lsf_ucode_mgr - * @falcon_id: ID of the falcon this LS firmware is for - * @ucode_desc: loaded or generated map of ucode_data - * @ucode_data: firmware payload (code and data) - * @ucode_size: size in bytes of data in ucode_data - * @ucode_off: offset of the ucode in ucode_data - * @sig: signature for this firmware - * @sig:size: size of the signature in bytes - * - * Preparing the WPR LS blob requires information about all the LS firmwares - * (size, etc) to be known. This structure contains all the data of one LS - * firmware. - */ -struct ls_ucode_img { - struct list_head node; - enum nvkm_secboot_falcon falcon_id; - - struct ls_ucode_img_desc ucode_desc; - u8 *ucode_data; - u32 ucode_size; - u32 ucode_off; - - u8 *sig; - u32 sig_size; -}; - -/** - * struct fw_bin_header - header of firmware files - * @bin_magic: always 0x3b1d14f0 - * @bin_ver: version of the bin format - * @bin_size: entire image size including this header - * @header_offset: offset of the firmware/bootloader header in the file - * @data_offset: offset of the firmware/bootloader payload in the file - * @data_size: size of the payload - * - * This header is located at the beginning of the HS firmware and HS bootloader - * files, to describe where the headers and data can be found. - */ -struct fw_bin_header { - u32 bin_magic; - u32 bin_ver; - u32 bin_size; - u32 header_offset; - u32 data_offset; - u32 data_size; -}; - -/** - * struct fw_bl_desc - firmware bootloader descriptor - * @start_tag: starting tag of bootloader - * @desc_dmem_load_off: DMEM offset of flcn_bl_dmem_desc - * @code_off: offset of code section - * @code_size: size of code section - * @data_off: offset of data section - * @data_size: size of data section - * - * This structure is embedded in bootloader firmware files at to describe the - * IMEM and DMEM layout expected by the bootloader. - */ -struct fw_bl_desc { - u32 start_tag; - u32 dmem_load_off; - u32 code_off; - u32 code_size; - u32 data_off; - u32 data_size; -}; - -int acr_ls_ucode_load_fecs(const struct nvkm_secboot *, int, - struct ls_ucode_img *); -int acr_ls_ucode_load_gpccs(const struct nvkm_secboot *, int, - struct ls_ucode_img *); -int acr_ls_ucode_load_pmu(const struct nvkm_secboot *, int, - struct ls_ucode_img *); -int acr_ls_pmu_post_run(const struct nvkm_acr *, const struct nvkm_secboot *); -int acr_ls_ucode_load_sec2(const struct nvkm_secboot *, int, - struct ls_ucode_img *); -int acr_ls_sec2_post_run(const struct nvkm_acr *, const struct nvkm_secboot *); - -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c deleted file mode 100644 index 821d3b2bdb1f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - - -#include "ls_ucode.h" -#include "acr.h" - -#include - -#define BL_DESC_BLK_SIZE 256 -/** - * Build a ucode image and descriptor from provided bootloader, code and data. - * - * @bl: bootloader image, including 16-bytes descriptor - * @code: LS firmware code segment - * @data: LS firmware data segment - * @desc: ucode descriptor to be written - * - * Return: allocated ucode image with corresponding descriptor information. desc - * is also updated to contain the right offsets within returned image. - */ -static void * -ls_ucode_img_build(const struct firmware *bl, const struct firmware *code, - const struct firmware *data, struct ls_ucode_img_desc *desc) -{ - struct fw_bin_header *bin_hdr = (void *)bl->data; - struct fw_bl_desc *bl_desc = (void *)bl->data + bin_hdr->header_offset; - void *bl_data = (void *)bl->data + bin_hdr->data_offset; - u32 pos = 0; - void *image; - - desc->bootloader_start_offset = pos; - desc->bootloader_size = ALIGN(bl_desc->code_size, sizeof(u32)); - desc->bootloader_imem_offset = bl_desc->start_tag * 256; - desc->bootloader_entry_point = bl_desc->start_tag * 256; - - pos = ALIGN(pos + desc->bootloader_size, BL_DESC_BLK_SIZE); - desc->app_start_offset = pos; - desc->app_size = ALIGN(code->size, BL_DESC_BLK_SIZE) + - ALIGN(data->size, BL_DESC_BLK_SIZE); - desc->app_imem_offset = 0; - desc->app_imem_entry = 0; - desc->app_dmem_offset = 0; - desc->app_resident_code_offset = 0; - desc->app_resident_code_size = ALIGN(code->size, BL_DESC_BLK_SIZE); - - pos = ALIGN(pos + desc->app_resident_code_size, BL_DESC_BLK_SIZE); - desc->app_resident_data_offset = pos - desc->app_start_offset; - desc->app_resident_data_size = ALIGN(data->size, BL_DESC_BLK_SIZE); - - desc->image_size = ALIGN(bl_desc->code_size, BL_DESC_BLK_SIZE) + - desc->app_size; - - image = kzalloc(desc->image_size, GFP_KERNEL); - if (!image) - return ERR_PTR(-ENOMEM); - - memcpy(image + desc->bootloader_start_offset, bl_data, - bl_desc->code_size); - memcpy(image + desc->app_start_offset, code->data, code->size); - memcpy(image + desc->app_start_offset + desc->app_resident_data_offset, - data->data, data->size); - - return image; -} - -/** - * ls_ucode_img_load_gr() - load and prepare a LS GR ucode image - * - * Load the LS microcode, bootloader and signature and pack them into a single - * blob. Also generate the corresponding ucode descriptor. - */ -static int -ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, int maxver, - struct ls_ucode_img *img, const char *falcon_name) -{ - const struct firmware *bl, *code, *data, *sig; - char f[64]; - int ret; - - snprintf(f, sizeof(f), "gr/%s_bl", falcon_name); - ret = nvkm_firmware_get(subdev, f, &bl); - if (ret) - goto error; - - snprintf(f, sizeof(f), "gr/%s_inst", falcon_name); - ret = nvkm_firmware_get(subdev, f, &code); - if (ret) - goto free_bl; - - snprintf(f, sizeof(f), "gr/%s_data", falcon_name); - ret = nvkm_firmware_get(subdev, f, &data); - if (ret) - goto free_inst; - - snprintf(f, sizeof(f), "gr/%s_sig", falcon_name); - ret = nvkm_firmware_get(subdev, f, &sig); - if (ret) - goto free_data; - - img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL); - if (!img->sig) { - ret = -ENOMEM; - goto free_sig; - } - img->sig_size = sig->size; - - img->ucode_data = ls_ucode_img_build(bl, code, data, - &img->ucode_desc); - if (IS_ERR(img->ucode_data)) { - kfree(img->sig); - ret = PTR_ERR(img->ucode_data); - goto free_sig; - } - img->ucode_size = img->ucode_desc.image_size; - -free_sig: - nvkm_firmware_put(sig); -free_data: - nvkm_firmware_put(data); -free_inst: - nvkm_firmware_put(code); -free_bl: - nvkm_firmware_put(bl); -error: - return ret; -} - -int -acr_ls_ucode_load_fecs(const struct nvkm_secboot *sb, int maxver, - struct ls_ucode_img *img) -{ - return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "fecs"); -} - -int -acr_ls_ucode_load_gpccs(const struct nvkm_secboot *sb, int maxver, - struct ls_ucode_img *img) -{ - return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "gpccs"); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c deleted file mode 100644 index 7e5282caf00c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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. - */ - - -#include "ls_ucode.h" -#include "acr.h" - -#include -#include -#include -#include -#include -#include - -/** - * acr_ls_ucode_load_msgqueue - load and prepare a ucode img for a msgqueue fw - * - * Load the LS microcode, desc and signature and pack them into a single - * blob. - */ -static int -acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name, - int maxver, struct ls_ucode_img *img) -{ - const struct firmware *image, *desc, *sig; - char f[64]; - int ver, ret; - - snprintf(f, sizeof(f), "%s/image", name); - ver = nvkm_firmware_get_version(subdev, f, 0, maxver, &image); - if (ver < 0) - return ver; - img->ucode_data = kmemdup(image->data, image->size, GFP_KERNEL); - nvkm_firmware_put(image); - if (!img->ucode_data) - return -ENOMEM; - - snprintf(f, sizeof(f), "%s/desc", name); - ret = nvkm_firmware_get_version(subdev, f, ver, ver, &desc); - if (ret < 0) - return ret; - memcpy(&img->ucode_desc, desc->data, sizeof(img->ucode_desc)); - img->ucode_size = ALIGN(img->ucode_desc.app_start_offset + img->ucode_desc.app_size, 256); - nvkm_firmware_put(desc); - - snprintf(f, sizeof(f), "%s/sig", name); - ret = nvkm_firmware_get_version(subdev, f, ver, ver, &sig); - if (ret < 0) - return ret; - img->sig_size = sig->size; - img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL); - nvkm_firmware_put(sig); - if (!img->sig) - return -ENOMEM; - - return ver; -} - -int -acr_ls_ucode_load_pmu(const struct nvkm_secboot *sb, int maxver, - struct ls_ucode_img *img) -{ - int ret; - - ret = acr_ls_ucode_load_msgqueue(&sb->subdev, "pmu", maxver, img); - if (ret) - return ret; - - return 0; -} - -int -acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, int maxver, - struct ls_ucode_img *img) -{ - int ver; - - ver = acr_ls_ucode_load_msgqueue(&sb->subdev, "sec2", maxver, img); - if (ver < 0) - return ver; - - return ver; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h deleted file mode 100644 index 959a7b2dbdc9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2015, NVIDIA CORPORATION. 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, 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 AUTHORS OR COPYRIGHT HOLDERS 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 __NVKM_SECBOOT_PRIV_H__ -#define __NVKM_SECBOOT_PRIV_H__ - -#include -#include -struct nvkm_gpuobj; - -struct nvkm_secboot_func { - int (*oneinit)(struct nvkm_secboot *); - int (*fini)(struct nvkm_secboot *, bool suspend); - void *(*dtor)(struct nvkm_secboot *); - int (*run_blob)(struct nvkm_secboot *, struct nvkm_gpuobj *, - struct nvkm_falcon *); -}; - -int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_acr *, - struct nvkm_device *, int, struct nvkm_secboot *); -int nvkm_secboot_falcon_reset(struct nvkm_secboot *); -int nvkm_secboot_falcon_run(struct nvkm_secboot *); - -extern const struct nvkm_secboot_func gp102_secboot; - -struct flcn_u64 { - u32 lo; - u32 hi; -}; - -static inline u64 flcn64_to_u64(const struct flcn_u64 f) -{ - return ((u64)f.hi) << 32 | f.lo; -} - -static inline struct flcn_u64 u64_to_flcn64(u64 u) -{ - struct flcn_u64 ret; - - ret.hi = upper_32_bits(u); - ret.lo = lower_32_bits(u); - - return ret; -} - -#endif -- cgit v1.2.3 From edec7149cbfae95c35282c19cda20b7bc53873af Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/core: remove previous versioned fw loader Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/core/firmware.h | 5 +-- drivers/gpu/drm/nouveau/nvkm/core/firmware.c | 36 ++++++++-------------- drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 3 +- drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c | 4 +-- 4 files changed, 16 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h index cb8eed19061d..d14b7fb07368 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h @@ -4,10 +4,7 @@ #include #include -int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname, - int min_version, int max_version, - const struct firmware **); -int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, +int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, int ver, const struct firmware **); void nvkm_firmware_put(const struct firmware *); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c index 1c2909566b2a..8b25367917ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c @@ -30,7 +30,7 @@ nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base, int ret; snprintf(path, sizeof(path), "%s%s", base, name); - ret = nvkm_firmware_get_version(subdev, path, ver, ver, pfw); + ret = nvkm_firmware_get(subdev, path, ver, pfw); if (ret < 0) return ret; @@ -66,9 +66,8 @@ nvkm_firmware_load_blob(const struct nvkm_subdev *subdev, const char *base, * Firmware files released by NVIDIA will always follow this format. */ int -nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname, - int min_version, int max_version, - const struct firmware **fw) +nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname, int ver, + const struct firmware **fw) { struct nvkm_device *device = subdev->device; char f[64]; @@ -84,32 +83,21 @@ nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname, cname[i] = tolower(cname[i]); } - for (i = max_version; i >= min_version; i--) { - if (i != 0) - snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, i); - else - snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); - - if (!firmware_request_nowarn(fw, f, device->dev)) { - nvkm_debug(subdev, "firmware \"%s\" loaded - " - "%zu byte(s)\n", f, (*fw)->size); - return i; - } + if (ver != 0) + snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, ver); + else + snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); - nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f); + if (!firmware_request_nowarn(fw, f, device->dev)) { + nvkm_debug(subdev, "firmware \"%s\" loaded - %zu byte(s)\n", + f, (*fw)->size); + return 0; } - nvkm_error(subdev, "failed to load firmware \"%s\"\n", fwname); + nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f); return -ENOENT; } -int -nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname, - const struct firmware **fw) -{ - return nvkm_firmware_get_version(subdev, fwname, 0, 0, fw); -} - /** * nvkm_firmware_put - release firmware loaded with nvkm_firmware_get */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index c154f3b9d536..a713aaa27980 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -357,8 +357,7 @@ nvkm_acr_ctor_wpr(struct nvkm_acr *acr, int ver) struct nvkm_device *device = subdev->device; int ret; - ret = nvkm_firmware_get_version(subdev, "acr/wpr", ver, ver, - &acr->wpr_fw); + ret = nvkm_firmware_get(subdev, "acr/wpr", ver, &acr->wpr_fw); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c index 7204bfa3877d..aecce2dac558 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c @@ -58,7 +58,7 @@ nvkm_acr_hsfw_load_image(struct nvkm_acr *acr, const char *name, int ver, u32 loc, sig; int ret; - ret = nvkm_firmware_get_version(subdev, name, ver, ver, &fw); + ret = nvkm_firmware_get(subdev, name, ver, &fw); if (ret < 0) return ret; @@ -136,7 +136,7 @@ nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver, u8 *data; int ret; - ret = nvkm_firmware_get_version(subdev, name, ver, ver, &fw); + ret = nvkm_firmware_get(subdev, name, ver, &fw); if (ret) return ret; -- cgit v1.2.3 From 3fa8fe1572bc708596318280a22669dfc9eaf805 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/acr/tu10x: initial support Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 3 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 6 + drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c | 215 ++++++++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c | 3 + 6 files changed, 229 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 9e5284f63bd5..5d9c3a966de6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h @@ -62,6 +62,7 @@ int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp108_acr_new(struct nvkm_device *, int, struct nvkm_acr **); int gp10b_acr_new(struct nvkm_device *, int, struct nvkm_acr **); +int tu102_acr_new(struct nvkm_device *, int, struct nvkm_acr **); struct nvkm_acr_lsfw { const struct nvkm_acr_lsf_func *func; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index c81507b11a5e..2ef37d878951 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2462,6 +2462,7 @@ nv140_chipset = { static const struct nvkm_device_chip nv162_chipset = { .name = "TU102", + .acr = tu102_acr_new, .bar = tu102_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2498,6 +2499,7 @@ nv162_chipset = { static const struct nvkm_device_chip nv164_chipset = { .name = "TU104", + .acr = tu102_acr_new, .bar = tu102_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, @@ -2535,6 +2537,7 @@ nv164_chipset = { static const struct nvkm_device_chip nv166_chipset = { .name = "TU106", + .acr = tu102_acr_new, .bar = tu102_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild index 4a77f3a0853f..5b9f64a8957f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild @@ -7,3 +7,4 @@ nvkm-y += nvkm/subdev/acr/gm20b.o nvkm-y += nvkm/subdev/acr/gp102.o nvkm-y += nvkm/subdev/acr/gp108.o nvkm-y += nvkm/subdev/acr/gp10b.o +nvkm-y += nvkm/subdev/acr/tu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index a713aaa27980..8eb2a930a9b5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -215,6 +215,12 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev) u32 wpr_size = 0; int ret, i; + if (list_empty(&acr->hsfw)) { + nvkm_debug(subdev, "No HSFW(s)\n"); + nvkm_acr_cleanup(acr); + return 0; + } + /* Determine layout/size of WPR image up-front, as we need to know * it to allocate memory before we begin constructing it. */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c new file mode 100644 index 000000000000..7f4b89d82d32 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c @@ -0,0 +1,215 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "priv.h" + +#include +#include +#include +#include +#include + +#include + +static int +tu102_acr_init(struct nvkm_acr *acr) +{ + int ret = nvkm_acr_hsf_boot(acr, "AHESASC"); + if (ret) + return ret; + + return nvkm_acr_hsf_boot(acr, "ASB"); +} + +static int +tu102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos) +{ + struct nvkm_acr_lsfw *lsfw; + u32 offset = 0; + int ret; + + /*XXX: shared sub-WPR headers, fill terminator for now. */ + nvkm_wo32(acr->wpr, 0x200, 0xffffffff); + + /* Fill per-LSF structures. */ + list_for_each_entry(lsfw, &acr->lsfw, head) { + struct lsf_signature_v1 *sig = (void *)lsfw->sig->data; + struct wpr_header_v1 hdr = { + .falcon_id = lsfw->id, + .lsb_offset = lsfw->offset.lsb, + .bootstrap_owner = NVKM_ACR_LSF_GSPLITE, + .lazy_bootstrap = 1, + .bin_version = sig->version, + .status = WPR_HEADER_V1_STATUS_COPY, + }; + + /* Write WPR header. */ + nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr)); + offset += sizeof(hdr); + + /* Write LSB header. */ + ret = gp102_acr_wpr_build_lsb(acr, lsfw); + if (ret) + return ret; + + /* Write ucode image. */ + nvkm_wobj(acr->wpr, lsfw->offset.img, + lsfw->img.data, + lsfw->img.size); + + /* Write bootloader data. */ + lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw); + } + + /* Finalise WPR. */ + nvkm_wo32(acr->wpr, offset, WPR_HEADER_V1_FALCON_ID_INVALID); + return 0; +} + +static int +tu102_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf) +{ + return gm200_acr_hsfw_boot(acr, hsf, 0, 0); +} + +static int +tu102_acr_hsfw_nofw(struct nvkm_acr *acr, const char *bl, const char *fw, + const char *name, int version, + const struct nvkm_acr_hsf_fwif *fwif) +{ + return 0; +} + +MODULE_FIRMWARE("nvidia/tu102/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/tu102/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/tu104/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/tu104/acr/ucode_unload.bin"); + +MODULE_FIRMWARE("nvidia/tu106/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/tu106/acr/ucode_unload.bin"); + +static const struct nvkm_acr_hsf_fwif +tu102_acr_unload_fwif[] = { + { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 }, + { -1, tu102_acr_hsfw_nofw }, + {} +}; + +static int +tu102_acr_asb_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw) +{ + return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->gsp->falcon); +} + +static const struct nvkm_acr_hsf_func +tu102_acr_asb_0 = { + .load = tu102_acr_asb_load, + .boot = tu102_acr_hsfw_boot, + .bld = gp108_acr_hsfw_bld, +}; + +MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin"); +MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin"); + +static const struct nvkm_acr_hsf_fwif +tu102_acr_asb_fwif[] = { + { 0, nvkm_acr_hsfw_load, &tu102_acr_asb_0 }, + { -1, tu102_acr_hsfw_nofw }, + {} +}; + +static const struct nvkm_acr_hsf_func +tu102_acr_ahesasc_0 = { + .load = gp102_acr_load_load, + .boot = tu102_acr_hsfw_boot, + .bld = gp108_acr_hsfw_bld, +}; + +MODULE_FIRMWARE("nvidia/tu102/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/tu102/acr/ucode_ahesasc.bin"); + +MODULE_FIRMWARE("nvidia/tu104/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/tu104/acr/ucode_ahesasc.bin"); + +MODULE_FIRMWARE("nvidia/tu106/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/tu106/acr/ucode_ahesasc.bin"); + +static const struct nvkm_acr_hsf_fwif +tu102_acr_ahesasc_fwif[] = { + { 0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 }, + { -1, tu102_acr_hsfw_nofw }, + {} +}; + +static const struct nvkm_acr_func +tu102_acr = { + .ahesasc = tu102_acr_ahesasc_fwif, + .asb = tu102_acr_asb_fwif, + .unload = tu102_acr_unload_fwif, + .wpr_parse = gp102_acr_wpr_parse, + .wpr_layout = gp102_acr_wpr_layout, + .wpr_alloc = gp102_acr_wpr_alloc, + .wpr_patch = gp102_acr_wpr_patch, + .wpr_build = tu102_acr_wpr_build, + .wpr_check = gm200_acr_wpr_check, + .init = tu102_acr_init, +}; + +static int +tu102_acr_load(struct nvkm_acr *acr, int version, + const struct nvkm_acr_fwif *fwif) +{ + struct nvkm_subdev *subdev = &acr->subdev; + const struct nvkm_acr_hsf_fwif *hsfwif; + + hsfwif = nvkm_firmware_load(subdev, fwif->func->ahesasc, "AcrAHESASC", + acr, "acr/bl", "acr/ucode_ahesasc", + "AHESASC"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB", + acr, "acr/bl", "acr/ucode_asb", "ASB"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload", + acr, "acr/unload_bl", "acr/ucode_unload", + "unload"); + if (IS_ERR(hsfwif)) + return PTR_ERR(hsfwif); + + return 0; +} + +static const struct nvkm_acr_fwif +tu102_acr_fwif[] = { + { 0, tu102_acr_load, &tu102_acr }, + {} +}; + +int +tu102_acr_new(struct nvkm_device *device, int index, struct nvkm_acr **pacr) +{ + return nvkm_acr_new_(tu102_acr_fwif, device, index, pacr); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index e4326bf674b8..389bad312bf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -48,3 +48,6 @@ gv100_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) } MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin"); -- cgit v1.2.3 From afa3b96b058d87c2c44d1c83dadb2ba6998d03ce Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Jan 2020 06:34:22 +1000 Subject: drm/nouveau/gr/tu10x: initial support Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/class.h | 3 + drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 3 + drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c | 5 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h | 10 ++ drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c | 12 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c | 95 ++++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | 2 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 6 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c | 8 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c | 177 ++++++++++++++++++++++ 12 files changed, 313 insertions(+), 11 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index f704ae600e94..30659747ffe8 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -166,6 +166,8 @@ #define VOLTA_A /* cl9097.h */ 0x0000c397 +#define TURING_A /* cl9097.h */ 0x0000c597 + #define NV74_BSP 0x000074b0 #define GT212_MSVLD 0x000085b1 @@ -207,6 +209,7 @@ #define PASCAL_COMPUTE_A 0x0000c0c0 #define PASCAL_COMPUTE_B 0x0000c1c0 #define VOLTA_COMPUTE_A 0x0000c3c0 +#define TURING_COMPUTE_A 0x0000c5c0 #define NV74_CIPHER 0x000074c1 #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h index 612383b31ece..1530c81f86a2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h @@ -53,4 +53,5 @@ int gp107_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp108_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gp10b_gr_new(struct nvkm_device *, int, struct nvkm_gr **); int gv100_gr_new(struct nvkm_device *, int, struct nvkm_gr **); +int tu102_gr_new(struct nvkm_device *, int, struct nvkm_gr **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 2ef37d878951..c7d700916eae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2491,6 +2491,7 @@ nv162_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, + .gr = tu102_gr_new, .nvdec[0] = gm107_nvdec_new, .nvenc[0] = gm107_nvenc_new, .sec2 = tu102_sec2_new, @@ -2528,6 +2529,7 @@ nv164_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, + .gr = tu102_gr_new, .nvdec[0] = gm107_nvdec_new, .nvdec[1] = gm107_nvdec_new, .nvenc[0] = gm107_nvenc_new, @@ -2566,6 +2568,7 @@ nv166_chipset = { .disp = tu102_disp_new, .dma = gv100_dma_new, .fifo = tu102_fifo_new, + .gr = tu102_gr_new, .nvdec[0] = gm107_nvdec_new, .nvdec[1] = gm107_nvdec_new, .nvdec[2] = gm107_nvdec_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild index 02a1025d0060..558c86fd8e82 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild @@ -39,6 +39,7 @@ nvkm-y += nvkm/engine/gr/gp107.o nvkm-y += nvkm/engine/gr/gp108.o nvkm-y += nvkm/engine/gr/gp10b.o nvkm-y += nvkm/engine/gr/gv100.o +nvkm-y += nvkm/engine/gr/tu102.o nvkm-y += nvkm/engine/gr/ctxnv40.o nvkm-y += nvkm/engine/gr/ctxnv50.o @@ -61,3 +62,4 @@ nvkm-y += nvkm/engine/gr/ctxgp102.o nvkm-y += nvkm/engine/gr/ctxgp104.o nvkm-y += nvkm/engine/gr/ctxgp107.o nvkm-y += nvkm/engine/gr/ctxgv100.o +nvkm-y += nvkm/engine/gr/ctxtu102.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index 4338e515040d..297915719bf2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -1334,7 +1334,8 @@ gf100_grctx_generate_floorsweep(struct gf100_gr *gr) } gf100_gr_init_num_tpc_per_gpc(gr, false, true); - gf100_gr_init_num_tpc_per_gpc(gr, true, false); + if (!func->skip_pd_num_tpc_per_gpc) + gf100_gr_init_num_tpc_per_gpc(gr, true, false); if (func->r4060a8) func->r4060a8(gr); @@ -1425,6 +1426,8 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) grctx->r419a3c(gr); if (grctx->r408840) grctx->r408840(gr); + if (grctx->r419c0c) + grctx->r419c0c(gr); } #define CB_RESERVED 0x80000 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 478b4723d0f9..32bbddc0993e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -57,6 +57,7 @@ struct gf100_grctx_func { /* floorsweeping */ void (*sm_id)(struct gf100_gr *, int gpc, int tpc, int sm); void (*tpc_nr)(struct gf100_gr *, int gpc); + bool skip_pd_num_tpc_per_gpc; void (*r4060a8)(struct gf100_gr *); void (*rop_mapping)(struct gf100_gr *); void (*alpha_beta_tables)(struct gf100_gr *); @@ -76,6 +77,7 @@ struct gf100_grctx_func { void (*r418e94)(struct gf100_gr *); void (*r419a3c)(struct gf100_gr *); void (*r408840)(struct gf100_gr *); + void (*r419c0c)(struct gf100_gr *); }; extern const struct gf100_grctx_func gf100_grctx; @@ -153,6 +155,14 @@ extern const struct gf100_grctx_func gp107_grctx; extern const struct gf100_grctx_func gv100_grctx; +extern const struct gf100_grctx_func tu102_grctx; +void gv100_grctx_unkn88c(struct gf100_gr *, bool); +void gv100_grctx_generate_unkn(struct gf100_gr *); +extern const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[]; +void gv100_grctx_generate_attrib(struct gf100_grctx *); +void gv100_grctx_generate_rop_mapping(struct gf100_gr *); +void gv100_grctx_generate_r400088(struct gf100_gr *, bool); + /* context init value lists */ extern const struct gf100_gr_pack gf100_grctx_pack_icmd[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c index 313f0080bbdc..39553d55d3f3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c @@ -25,7 +25,7 @@ * PGRAPH context implementation ******************************************************************************/ -static const struct gf100_gr_init +const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[] = { { 0x00001000, 64, 0x00100000, 0x00000008 }, { 0x00000941, 64, 0x00100000, 0x00000000 }, @@ -58,7 +58,7 @@ gv100_grctx_pack_sw_veid_bundle_init[] = { {} }; -static void +void gv100_grctx_generate_attrib(struct gf100_grctx *info) { struct gf100_gr *gr = info->gr; @@ -109,7 +109,7 @@ gv100_grctx_generate_attrib(struct gf100_grctx *info) mmio_wr32(info, 0x41befc, 0x00000100); } -static void +void gv100_grctx_generate_rop_mapping(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -146,7 +146,7 @@ gv100_grctx_generate_rop_mapping(struct gf100_gr *gr) gr->screen_tile_row_offset); } -static void +void gv100_grctx_generate_r400088(struct gf100_gr *gr, bool on) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -162,7 +162,7 @@ gv100_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm); } -static void +void gv100_grctx_generate_unkn(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -173,7 +173,7 @@ gv100_grctx_generate_unkn(struct gf100_gr *gr) nvkm_mask(device, 0x419c00, 0x00000008, 0x00000008); } -static void +void gv100_grctx_unkn88c(struct gf100_gr *gr, bool on) { struct nvkm_device *device = gr->base.engine.subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c new file mode 100644 index 000000000000..2299ca07d04a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "ctxgf100.h" + +static void +tu102_grctx_generate_r419c0c(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_mask(device, 0x419c0c, 0x80000000, 0x80000000); + nvkm_mask(device, 0x40584c, 0x00000008, 0x00000000); + nvkm_mask(device, 0x400080, 0x00000000, 0x00000000); +} + +static void +tu102_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm); + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm); +} + +static const struct gf100_gr_init +tu102_grctx_init_unknown_bundle_init_0[] = { + { 0x00001000, 1, 0x00000001, 0x00000004 }, + { 0x00002020, 64, 0x00000001, 0x00000000 }, + { 0x0001e100, 1, 0x00000001, 0x00000001 }, + {} +}; + +static const struct gf100_gr_pack +tu102_grctx_pack_sw_veid_bundle_init[] = { + { gv100_grctx_init_sw_veid_bundle_init_0 }, + { tu102_grctx_init_unknown_bundle_init_0 }, + {} +}; + +static void +tu102_grctx_generate_attrib(struct gf100_grctx *info) +{ + const u64 size = 0x80000; /*XXX: educated guess */ + const int s = 8; + const int b = mmio_vram(info, size, (1 << s), true); + + gv100_grctx_generate_attrib(info); + + mmio_refn(info, 0x408070, 0x00000000, s, b); + mmio_wr32(info, 0x408074, size >> s); /*XXX: guess */ + mmio_refn(info, 0x419034, 0x00000000, s, b); + mmio_wr32(info, 0x408078, 0x00000000); +} + +const struct gf100_grctx_func +tu102_grctx = { + .unkn88c = gv100_grctx_unkn88c, + .main = gf100_grctx_generate_main, + .unkn = gv100_grctx_generate_unkn, + .sw_veid_bundle_init = tu102_grctx_pack_sw_veid_bundle_init, + .bundle = gm107_grctx_generate_bundle, + .bundle_size = 0x3000, + .bundle_min_gpm_fifo_depth = 0x180, + .bundle_token_limit = 0xa80, + .pagepool = gp100_grctx_generate_pagepool, + .pagepool_size = 0x20000, + .attrib = tu102_grctx_generate_attrib, + .attrib_nr_max = 0x800, + .attrib_nr = 0x700, + .alpha_nr_max = 0xc00, + .alpha_nr = 0x800, + .gfxp_nr = 0xfa8, + .sm_id = tu102_grctx_generate_sm_id, + .skip_pd_num_tpc_per_gpc = true, + .rop_mapping = gv100_grctx_generate_rop_mapping, + .r406500 = gm200_grctx_generate_r406500, + .r400088 = gv100_grctx_generate_r400088, + .r419c0c = tu102_grctx_generate_r419c0c, +}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 6c1a1e074721..dd8f85b8b3a7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -2262,6 +2262,8 @@ gf100_gr_init(struct gf100_gr *gr) gr->func->init_bios_2(gr); if (gr->func->init_swdx_pes_mask) gr->func->init_swdx_pes_mask(gr); + if (gr->func->init_fs) + gr->func->init_fs(gr); nvkm_wr32(device, 0x400500, 0x00010001); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 67286bb57e55..4c67b254c413 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -162,6 +162,7 @@ struct gf100_gr_func { void (*init_rop_active_fbps)(struct gf100_gr *); void (*init_bios_2)(struct gf100_gr *); void (*init_swdx_pes_mask)(struct gf100_gr *); + void (*init_fs)(struct gf100_gr *); void (*init_fecs_exceptions)(struct gf100_gr *); void (*init_ds_hww_esr_2)(struct gf100_gr *); void (*init_40601c)(struct gf100_gr *); @@ -243,6 +244,11 @@ extern const struct gf100_gr_func_zbc gp102_gr_zbc; extern const struct gf100_gr_func gp107_gr; +void gv100_gr_init_419bd8(struct gf100_gr *); +void gv100_gr_init_504430(struct gf100_gr *, int, int); +void gv100_gr_init_shader_exceptions(struct gf100_gr *, int, int); +void gv100_gr_trap_mp(struct gf100_gr *, int, int); + #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) #include diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c index b2cab983a11c..70639d88b8e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c @@ -45,7 +45,7 @@ gv100_gr_trap_sm(struct gf100_gr *gr, int gpc, int tpc, int sm) nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x734 + sm * 0x80), gerr); } -static void +void gv100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc) { gv100_gr_trap_sm(gr, gpc, tpc, 0); @@ -59,7 +59,7 @@ gv100_gr_init_4188a4(struct gf100_gr *gr) nvkm_mask(device, 0x4188a4, 0x03000000, 0x03000000); } -static void +void gv100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc) { struct nvkm_device *device = gr->base.engine.subdev.device; @@ -71,14 +71,14 @@ gv100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc) } } -static void +void gv100_gr_init_504430(struct gf100_gr *gr, int gpc, int tpc) { struct nvkm_device *device = gr->base.engine.subdev.device; nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x430), 0x403f0000); } -static void +void gv100_gr_init_419bd8(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c new file mode 100644 index 000000000000..454668b1cf54 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -0,0 +1,177 @@ +/* + * Copyright 2019 Red Hat 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. + */ +#include "gf100.h" +#include "ctxgf100.h" + +#include + +static void +tu102_gr_init_fecs_exceptions(struct gf100_gr *gr) +{ + nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006f0002); +} + +static void +tu102_gr_init_fs(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + int sm; + + gp100_grctx_generate_smid_config(gr); + gk104_grctx_generate_gpc_tpc_nr(gr); + + for (sm = 0; sm < gr->sm_nr; sm++) { + nvkm_wr32(device, GPC_UNIT(gr->sm[sm].gpc, 0x0c10 + + gr->sm[sm].tpc * 4), sm); + } + + gm200_grctx_generate_dist_skip_table(gr); + gf100_gr_init_num_tpc_per_gpc(gr, true, true); +} + +static void +tu102_gr_init_zcull(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); + const u8 tile_nr = ALIGN(gr->tpc_total, 64); + u8 bank[GPC_MAX] = {}, gpc, i, j; + u32 data; + + for (i = 0; i < tile_nr; i += 8) { + for (data = 0, j = 0; j < 8 && i + j < gr->tpc_total; j++) { + data |= bank[gr->tile[i + j]] << (j * 4); + bank[gr->tile[i + j]]++; + } + nvkm_wr32(device, GPC_BCAST(0x0980 + ((i / 8) * 4)), data); + } + + for (gpc = 0; gpc < gr->gpc_nr; gpc++) { + nvkm_wr32(device, GPC_UNIT(gpc, 0x0914), + gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 | + gr->tpc_total); + nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918); + } + + nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918); +} + +static void +tu102_gr_init_gpc_mmu(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0xf8001fff); + nvkm_wr32(device, 0x418890, 0x00000000); + nvkm_wr32(device, 0x418894, 0x00000000); + + nvkm_wr32(device, 0x4188b4, nvkm_rd32(device, 0x100cc8)); + nvkm_wr32(device, 0x4188b8, nvkm_rd32(device, 0x100ccc)); + nvkm_wr32(device, 0x4188b0, nvkm_rd32(device, 0x100cc4)); +} + +static const struct gf100_gr_func +tu102_gr = { + .oneinit_tiles = gm200_gr_oneinit_tiles, + .oneinit_sm_id = gm200_gr_oneinit_sm_id, + .init = gf100_gr_init, + .init_419bd8 = gv100_gr_init_419bd8, + .init_gpc_mmu = tu102_gr_init_gpc_mmu, + .init_vsc_stream_master = gk104_gr_init_vsc_stream_master, + .init_zcull = tu102_gr_init_zcull, + .init_num_active_ltcs = gf100_gr_init_num_active_ltcs, + .init_rop_active_fbps = gp100_gr_init_rop_active_fbps, + .init_swdx_pes_mask = gp102_gr_init_swdx_pes_mask, + .init_fs = tu102_gr_init_fs, + .init_fecs_exceptions = tu102_gr_init_fecs_exceptions, + .init_ds_hww_esr_2 = gm200_gr_init_ds_hww_esr_2, + .init_sked_hww_esr = gk104_gr_init_sked_hww_esr, + .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, + .init_504430 = gv100_gr_init_504430, + .init_shader_exceptions = gv100_gr_init_shader_exceptions, + .trap_mp = gv100_gr_trap_mp, + .rops = gm200_gr_rops, + .gpc_nr = 6, + .tpc_nr = 5, + .ppc_nr = 3, + .grctx = &tu102_grctx, + .zbc = &gp102_gr_zbc, + .sclass = { + { -1, -1, FERMI_TWOD_A }, + { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, + { -1, -1, TURING_A, &gf100_fermi }, + { -1, -1, TURING_COMPUTE_A }, + {} + } +}; + +MODULE_FIRMWARE("nvidia/tu102/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/tu102/gr/sw_method_init.bin"); + +MODULE_FIRMWARE("nvidia/tu104/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/tu104/gr/sw_method_init.bin"); + +MODULE_FIRMWARE("nvidia/tu106/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/tu106/gr/sw_method_init.bin"); + +static const struct gf100_gr_fwif +tu102_gr_fwif[] = { + { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, + {} +}; + +int +tu102_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) +{ + return gf100_gr_new_(tu102_gr_fwif, device, index, pgr); +} -- cgit v1.2.3 From 89b34254bb61d0ad5c701413572cf3d993c9bff8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 15 Jan 2020 15:06:13 +0100 Subject: drm/nouveau/pmu/gm20b,gp10b: Fix Falcon bootstrapping The low-level Falcon bootstrapping callbacks are expected to return 0 on success or a negative error code on failure. However, the implementation on Tegra returns the ID or mask of the Falcons that were bootstrapped on success, thus breaking the calling code, which treats this as failure. Fix this by making sure we only return 0 or a negative error code, just like the code for discrete GPUs does. Fixes: 86ce2a71539c ("drm/nouveau/flcn/cmdq: move command generation to subdevs") Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 9 +++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c index 6d5a13e4a857..82571032a07d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c @@ -52,8 +52,13 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon, ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr, gm20b_pmu_acr_bootstrap_falcon_cb, &pmu->subdev, msecs_to_jiffies(1000)); - if (ret >= 0 && ret != cmd.falcon_id) - ret = -EIO; + if (ret >= 0) { + if (ret != cmd.falcon_id) + ret = -EIO; + else + ret = 0; + } + return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c index 39c86bc56310..5b81c7320479 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c @@ -52,8 +52,13 @@ gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask) ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr, gp10b_pmu_acr_bootstrap_multiple_falcons_cb, &pmu->subdev, msecs_to_jiffies(1000)); - if (ret >= 0 && ret != cmd.falcon_mask) - ret = -EIO; + if (ret >= 0) { + if (ret != cmd.falcon_mask) + ret = -EIO; + else + ret = 0; + } + return ret; } -- cgit v1.2.3 From 90e2e96ea37745ae18a1ff7b322e3321731828e4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 15 Jan 2020 15:07:56 +0100 Subject: drm/nouveau/gr/gp10b: Use gp100_grctx and gp100_gr_zbc gp10b doesn't have all the registers that gp102_gr_zbc wants to access, which causes IBUS MMIO faults to occur. Avoid this by using the gp100 variants of grctx and gr_zbc. Signed-off-by: Thierry Reding Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c | 2 +- drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index 4c67b254c413..88bcb57c2e07 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -238,6 +238,7 @@ void gp100_gr_init_fecs_exceptions(struct gf100_gr *); void gp100_gr_init_shader_exceptions(struct gf100_gr *, int, int); void gp100_gr_zbc_clear_color(struct gf100_gr *, int); void gp100_gr_zbc_clear_depth(struct gf100_gr *, int); +extern const struct gf100_gr_func_zbc gp100_gr_zbc; void gp102_gr_init_swdx_pes_mask(struct gf100_gr *); extern const struct gf100_gr_func_zbc gp102_gr_zbc; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c index bd5d8cc66987..33c8634ae567 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c @@ -62,7 +62,7 @@ gp100_gr_zbc_clear_depth(struct gf100_gr *gr, int zbc) gr->zbc_depth[zbc].format << ((znum % 4) * 7)); } -static const struct gf100_gr_func_zbc +const struct gf100_gr_func_zbc gp100_gr_zbc = { .clear_color = gp100_gr_zbc_clear_color, .clear_depth = gp100_gr_zbc_clear_depth, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c index a3db2a95ff9a..eaf913eb5aa3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c @@ -60,8 +60,8 @@ gp10b_gr = { .gpc_nr = 1, .tpc_nr = 2, .ppc_nr = 1, - .grctx = &gp102_grctx, - .zbc = &gp102_gr_zbc, + .grctx = &gp100_grctx, + .zbc = &gp100_gr_zbc, .sclass = { { -1, -1, FERMI_TWOD_A }, { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, -- cgit v1.2.3 From 35e4909b6a2b4005ced3c4238da60d926b78fdea Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 08:23:06 +1000 Subject: drm/nouveau/mmu: fix comptag memory leak Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/core/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/core/memory.c b/drivers/gpu/drm/nouveau/nvkm/core/memory.c index e85a08ecd9da..4cc186262d34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/memory.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/memory.c @@ -91,8 +91,8 @@ nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device, } refcount_set(&tags->refcount, 1); + *ptags = memory->tags = tags; mutex_unlock(&fb->subdev.mutex); - *ptags = tags; return 0; } -- cgit v1.2.3 From 39496368ba96b40b1dca07315418e473998eef15 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 17 Jan 2020 11:36:42 +0800 Subject: drm/nouveau/kms/nv50: remove set but not unused variable 'nv_connector' drivers/gpu/drm/nouveau/dispnv50/disp.c: In function nv50_pior_enable: drivers/gpu/drm/nouveau/dispnv50/disp.c:1672:28: warning: variable nv_connector set but not used [-Wunused-but-set-variable] commit ac2d9275f371 ("drm/nouveau/kms/nv50-: Store the bpc we're using in nv50_head_atom") left behind this. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Lyude Paul Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 5fabe2b88eca..a82b354e5a8c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1669,7 +1669,6 @@ nv50_pior_enable(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); - struct nouveau_connector *nv_connector; struct nv50_head_atom *asyh = nv50_head_atom(nv_crtc->base.state); struct nv50_core *core = nv50_disp(encoder->dev)->core; u8 owner = 1 << nv_crtc->index; @@ -1677,7 +1676,6 @@ nv50_pior_enable(struct drm_encoder *encoder) nv50_outp_acquire(nv_encoder); - nv_connector = nouveau_encoder_connector_get(nv_encoder); switch (asyh->or.bpc) { case 10: asyh->or.depth = 0x6; break; case 8: asyh->or.depth = 0x5; break; -- cgit v1.2.3 From 67d52f0f1379e93d1052c459b5e56ad50e98e74d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 17 Jan 2020 10:01:02 +0800 Subject: drm/nouveau/kms/nv04: remove set but not used variable 'width' drivers/gpu/drm/nouveau/dispnv04/arb.c: In function nv04_calc_arb: drivers/gpu/drm/nouveau/dispnv04/arb.c:56:21: warning: variable width set but not used [-Wunused-but-set-variable] 'width' is never used, so remove it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv04/arb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c index f607a04d262d..9d4a2d97507e 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/arb.c +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -53,7 +53,7 @@ struct nv_sim_state { static void nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) { - int pagemiss, cas, width, bpp; + int pagemiss, cas, bpp; int nvclks, mclks, crtpagemiss; int found, mclk_extra, mclk_loop, cbs, m1, p1; int mclk_freq, pclk_freq, nvclk_freq; @@ -65,7 +65,6 @@ nv04_calc_arb(struct nv_fifo_info *fifo, struct nv_sim_state *arb) nvclk_freq = arb->nvclk_khz; pagemiss = arb->mem_page_miss; cas = arb->mem_latency; - width = arb->memory_width >> 6; bpp = arb->bpp; cbs = 128; -- cgit v1.2.3 From ee8642162a9edd40daafd3fb894e3fd3f909e361 Mon Sep 17 00:00:00 2001 From: Chen Zhou Date: Thu, 16 Jan 2020 20:50:10 +0800 Subject: drm/nouveau: fix build error without CONFIG_IOMMU_API If CONFIG_IOMMU_API is n, build fails: vers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c:37:9: error: implicit declaration of function dev_iommu_fwspec_get; did you mean iommu_fwspec_free? [-Werror=implicit-function-declaration] spec = dev_iommu_fwspec_get(device->dev); ^~~~~~~~~~~~~~~~~~~~ iommu_fwspec_free drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c:37:7: warning: assignment makes pointer from integer without a cast [-Wint-conversion] spec = dev_iommu_fwspec_get(device->dev); ^ drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c:39:17: error: struct iommu_fwspec has no member named ids u32 sid = spec->ids[0] & 0xffff; Seletc IOMMU_API under config DRM_NOUVEAU to fix this. Reported-by: Hulk Robot Signed-off-by: Chen Zhou Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 9c990266e876..ce03693698ef 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -2,6 +2,7 @@ config DRM_NOUVEAU tristate "Nouveau (NVIDIA) cards" depends on DRM && PCI && MMU + select IOMMU_API select FW_LOADER select DRM_KMS_HELPER select DRM_TTM -- cgit v1.2.3 From 742db30c4ee6cd28142e83e154b5271f95a2c67a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 13 Jan 2020 15:17:21 +0100 Subject: drm/nouveau: Add HD-audio component notifier support This patch adds the support for the notification of HD-audio hotplug via the already existing drm_audio_component framework. This allows us more reliable hotplug notification and ELD transfer without accessing HD-audio bus; it's more efficient, and more importantly, it works without waking up the runtime PM. The implementation is rather simplistic: nouveau driver provides the get_eld ops for HD-audio, and it notifies the audio hotplug via pin_eld_notify callback upon each nv50_audio_enable() and _disable() call. As the HD-audio pin assignment seems corresponding to the CRTC, the crtc->index number is passed directly as the zero-based port number. The bind and unbind callbacks handle the device-link so that it assures the PM call order. Link: https://lore.kernel.org/r/20190722143815.7339-3-tiwai@suse.de Reviewed-by: Lyude Paul Cc: Jaroslav Kysela Signed-off-by: Takashi Iwai Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Kconfig | 1 + drivers/gpu/drm/nouveau/dispnv50/disp.c | 111 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 7 ++ 3 files changed, 119 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ce03693698ef..d6e4ae1ef705 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -17,6 +17,7 @@ config DRM_NOUVEAU select INPUT if ACPI && X86 select THERMAL if ACPI && X86 select ACPI_VIDEO if ACPI && X86 + select SND_HDA_COMPONENT if SND_HDA_CORE help Choose this option for open-source NVIDIA support. diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index a82b354e5a8c..2f123082c85d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -476,12 +477,113 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) return 0; } +/* + * audio component binding for ELD notification + */ +static void +nv50_audio_component_eld_notify(struct drm_audio_component *acomp, int port) +{ + if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) + acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, + port, -1); +} + +static int +nv50_audio_component_get_eld(struct device *kdev, int port, int pipe, + bool *enabled, unsigned char *buf, int max_bytes) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_encoder *encoder; + struct nouveau_encoder *nv_encoder; + struct nouveau_connector *nv_connector; + struct nouveau_crtc *nv_crtc; + int ret = 0; + + *enabled = false; + drm_for_each_encoder(encoder, drm->dev) { + nv_encoder = nouveau_encoder(encoder); + nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_crtc = nouveau_crtc(encoder->crtc); + if (!nv_connector || !nv_crtc || nv_crtc->index != port) + continue; + *enabled = drm_detect_monitor_audio(nv_connector->edid); + if (*enabled) { + ret = drm_eld_size(nv_connector->base.eld); + memcpy(buf, nv_connector->base.eld, + min(max_bytes, ret)); + } + break; + } + return ret; +} + +static const struct drm_audio_component_ops nv50_audio_component_ops = { + .get_eld = nv50_audio_component_get_eld, +}; + +static int +nv50_audio_component_bind(struct device *kdev, struct device *hda_kdev, + void *data) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_audio_component *acomp = data; + + if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS))) + return -ENOMEM; + + drm_modeset_lock_all(drm_dev); + acomp->ops = &nv50_audio_component_ops; + acomp->dev = kdev; + drm->audio.component = acomp; + drm_modeset_unlock_all(drm_dev); + return 0; +} + +static void +nv50_audio_component_unbind(struct device *kdev, struct device *hda_kdev, + void *data) +{ + struct drm_device *drm_dev = dev_get_drvdata(kdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); + struct drm_audio_component *acomp = data; + + drm_modeset_lock_all(drm_dev); + drm->audio.component = NULL; + acomp->ops = NULL; + acomp->dev = NULL; + drm_modeset_unlock_all(drm_dev); +} + +static const struct component_ops nv50_audio_component_bind_ops = { + .bind = nv50_audio_component_bind, + .unbind = nv50_audio_component_unbind, +}; + +static void +nv50_audio_component_init(struct nouveau_drm *drm) +{ + if (!component_add(drm->dev->dev, &nv50_audio_component_bind_ops)) + drm->audio.component_registered = true; +} + +static void +nv50_audio_component_fini(struct nouveau_drm *drm) +{ + if (drm->audio.component_registered) { + component_del(drm->dev->dev, &nv50_audio_component_bind_ops); + drm->audio.component_registered = false; + } +} + /****************************************************************************** * Audio *****************************************************************************/ static void nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nv50_disp *disp = nv50_disp(encoder->dev); struct { @@ -496,11 +598,14 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) }; nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); + + nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); } static void nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) { + struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; @@ -527,6 +632,8 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) nvif_mthd(&disp->disp->object, 0, &args, sizeof(args.base) + drm_eld_size(args.data)); + + nv50_audio_component_eld_notify(drm->audio.component, nv_crtc->index); } /****************************************************************************** @@ -2296,6 +2403,8 @@ nv50_display_destroy(struct drm_device *dev) { struct nv50_disp *disp = nv50_disp(dev); + nv50_audio_component_fini(nouveau_drm(dev)); + nv50_core_del(&disp->core); nouveau_bo_unmap(disp->sync); @@ -2444,6 +2553,8 @@ nv50_display_create(struct drm_device *dev) /* Disable vblank irqs aggressively for power-saving, safe on nv50+ */ dev->vblank_disable_immediate = true; + nv50_audio_component_init(drm); + out: if (ret) nv50_display_destroy(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index da8c46e09943..c2c332fbde97 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -58,6 +58,8 @@ #include #include +#include + #include "uapi/drm/nouveau_drm.h" struct nouveau_channel; @@ -211,6 +213,11 @@ struct nouveau_drm { struct nouveau_svm *svm; struct nouveau_dmem *dmem; + + struct { + struct drm_audio_component *component; + bool component_registered; + } audio; }; static inline struct nouveau_drm * -- cgit v1.2.3 From 4c9ee1bfca820b93f107957f5322845c862ea368 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 13:55:19 +1000 Subject: drm/nouveau: zero vma pointer even if we only unreference it rather than free I'm not sure this affects anything, but best be safe. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_vmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c index 77061182a1cf..b28c7dc13ad6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c @@ -69,8 +69,8 @@ nouveau_vma_del(struct nouveau_vma **pvma) } list_del(&vma->head); kfree(*pvma); - *pvma = NULL; } + *pvma = NULL; } int -- cgit v1.2.3 From 0181f4bfbdcdfdf8474946bf14fd644727fb8363 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 13:47:12 +1000 Subject: drm/nouveau: reject attempts to submit to dead channels Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 05ec8edd6a8b..8f97534e996c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -702,6 +702,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (!chan) return nouveau_abi16_put(abi16, -ENOENT); + if (unlikely(atomic_read(&chan->killed))) + return nouveau_abi16_put(abi16, -ENODEV); req->vram_available = drm->gem.vram_available; req->gart_available = drm->gem.gart_available; -- cgit v1.2.3 From ea13e5abf807ea912ce84eef6a1946b9a38c6508 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 15:39:27 +1000 Subject: drm/nouveau: signal pending fences when channel has been killed Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_chan.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_fence.c | 10 +++++++++- drivers/gpu/drm/nouveau/nouveau_fence.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 282fd90b65e1..d9381a053169 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -55,6 +55,8 @@ nouveau_channel_killed(struct nvif_notify *ntfy) struct nouveau_cli *cli = (void *)chan->user.client; NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid); atomic_set(&chan->killed, 1); + if (chan->fence) + nouveau_fence_context_kill(chan->fence, -ENODEV); return NVIF_NOTIFY_DROP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 70bb6bb97af8..666f2090d92b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -87,7 +87,7 @@ nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) } void -nouveau_fence_context_del(struct nouveau_fence_chan *fctx) +nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) { struct nouveau_fence *fence; @@ -95,11 +95,19 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx) while (!list_empty(&fctx->pending)) { fence = list_entry(fctx->pending.next, typeof(*fence), head); + if (error) + dma_fence_set_error(&fence->base, error); + if (nouveau_fence_signal(fence)) nvif_notify_put(&fctx->notify); } spin_unlock_irq(&fctx->lock); +} +void +nouveau_fence_context_del(struct nouveau_fence_chan *fctx) +{ + nouveau_fence_context_kill(fctx, 0); nvif_notify_fini(&fctx->notify); fctx->dead = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index c9e24baaaa4f..4887caa69c65 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -63,6 +63,7 @@ struct nouveau_fence_priv { void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *); void nouveau_fence_context_del(struct nouveau_fence_chan *); void nouveau_fence_context_free(struct nouveau_fence_chan *); +void nouveau_fence_context_kill(struct nouveau_fence_chan *, int error); int nv04_fence_create(struct nouveau_drm *); int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32); -- cgit v1.2.3 From 0352029ed83ff4d3f99e6bcf31bed5a97b07e3cf Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 23 Jan 2020 15:52:12 +1000 Subject: drm/nouveau: support synchronous pushbuf submission This is useful for debugging GPU hangs. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 11 ++++++++++- include/uapi/drm/nouveau_drm.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 8f97534e996c..f5ece1f94973 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -688,7 +688,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct validate_op op; struct nouveau_fence *fence = NULL; int i, j, ret = 0; - bool do_reloc = false; + bool do_reloc = false, sync = false; if (unlikely(!abi16)) return -ENOMEM; @@ -705,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (unlikely(atomic_read(&chan->killed))) return nouveau_abi16_put(abi16, -ENODEV); + sync = req->vram_available & NOUVEAU_GEM_PUSHBUF_SYNC; + req->vram_available = drm->gem.vram_available; req->gart_available = drm->gem.gart_available; if (unlikely(req->nr_push == 0)) @@ -852,6 +854,13 @@ revalidate: goto out; } + if (sync) { + if (!(ret = nouveau_fence_wait(fence, false, false))) { + if ((ret = dma_fence_get_status(&fence->base)) == 1) + ret = 0; + } + } + out: validate_fini(&op, chan, fence, bo); nouveau_fence_unref(&fence); diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h index 9459a6e3bc1f..853a327433d3 100644 --- a/include/uapi/drm/nouveau_drm.h +++ b/include/uapi/drm/nouveau_drm.h @@ -110,6 +110,7 @@ struct drm_nouveau_gem_pushbuf { __u64 push; __u32 suffix0; __u32 suffix1; +#define NOUVEAU_GEM_PUSHBUF_SYNC (1ULL << 0) __u64 vram_available; __u64 gart_available; }; -- cgit v1.2.3 From 0e6176c6d286316e9431b4f695940cfac4ffe6c2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 28 Jan 2020 14:39:26 +1000 Subject: drm/nouveau/disp/nv50-: prevent oops when no channel method map provided The implementations for most channel types contains a map of methods to priv registers in order to provide debugging info when a disp exception has been raised. This info is missing from the implementation of PIO channels as they're rather simplistic already, however, if an exception is raised by one of them, we'd end up triggering a NULL-pointer deref. Not ideal... Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=206299 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c index bcf32d92ee5a..50e3539f33d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -74,6 +74,8 @@ nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) if (debug > subdev->debug) return; + if (!mthd) + return; for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { u32 base = chan->head * mthd->addr; -- cgit v1.2.3 From 86e18ebd87072ed1ba6ecd86271e7a712115d579 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 28 Jan 2020 15:03:25 +1000 Subject: drm/nouveau/disp/gv100-: not all channel types support reporting error codes Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 892be6c9b76c..3aa2cc3af1e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -101,15 +101,26 @@ gv100_disp_exception(struct nv50_disp *disp, int chid) u32 stat = nvkm_rd32(device, 0x611020 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; u32 mthd = (stat & 0x00000fff) << 2; - u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); - u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); const struct nvkm_enum *reason = nvkm_enum_find(nv50_disp_intr_error_type, type); - nvkm_error(subdev, "chid %d stat %08x reason %d [%s] mthd %04x " - "data %08x code %08x\n", - chid, stat, type, reason ? reason->name : "", - mthd, data, code); + /*TODO: Suspect 33->41 are for WRBK channel exceptions, but we + * don't support those currently. + * + * CORE+WIN CHIDs map directly to the FE_EXCEPT() slots. + */ + if (chid <= 32) { + u32 data = nvkm_rd32(device, 0x611024 + (chid * 12)); + u32 code = nvkm_rd32(device, 0x611028 + (chid * 12)); + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] " + "mthd %04x data %08x code %08x\n", + chid, stat, type, reason ? reason->name : "", + mthd, data, code); + } else { + nvkm_error(subdev, "chid %d stat %08x reason %d [%s] " + "mthd %04x\n", + chid, stat, type, reason ? reason->name : "", mthd); + } if (chid < ARRAY_SIZE(disp->chan) && disp->chan[chid]) { switch (mthd) { -- cgit v1.2.3 From 1c338ed5e52b62737a9d45f37f085bdbb367821b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 29 Jan 2020 11:20:34 +1000 Subject: drm/nouveau/acr: return error when registering LSF if ACR not supported This fixes an oops on TU11x GPUs where SEC2 attempts to register its falcon, and triggers a NULL-pointer deref because ACR isn't yet supported. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index 9896462960ea..07d1830126ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -58,8 +58,12 @@ struct nvkm_acr_lsfw * nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *func, struct nvkm_acr *acr, struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id) { - struct nvkm_acr_lsfw *lsfw = nvkm_acr_lsfw_get(acr, id); + struct nvkm_acr_lsfw *lsfw; + + if (!acr) + return ERR_PTR(-ENOSYS); + lsfw = nvkm_acr_lsfw_get(acr, id); if (lsfw && lsfw->func) { nvkm_error(&acr->subdev, "LSFW %d redefined\n", id); return ERR_PTR(-EEXIST); -- cgit v1.2.3 From c3463aed05abf06bd5ebaac12f2c015db298b98f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 29 Jan 2020 11:29:05 +1000 Subject: drm/nouveau/fb/gp102-: allow module to load even when scrubber binary is missing Without relaxing this requirement, TU10x boards will fail to load without an updated linux-firmware, and TU11x will completely fail to load because FW isn't available yet. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c | 39 +++++++++++++++++++------- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c | 5 ++-- 2 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index d09db7c6b7ee..5940e0dea2f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -125,6 +125,34 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev) return nvkm_mm_init(&fb->tags, 0, 0, tags, 1); } +static int +nvkm_fb_init_scrub_vpr(struct nvkm_fb *fb) +{ + struct nvkm_subdev *subdev = &fb->subdev; + int ret; + + nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); + + if (!fb->vpr_scrubber.size) { + nvkm_warn(subdev, "VPR locked, but no scrubber binary!\n"); + return 0; + } + + ret = fb->func->vpr.scrub(fb); + if (ret) { + nvkm_error(subdev, "VPR scrubber binary failed\n"); + return ret; + } + + if (fb->func->vpr.scrub_required(fb)) { + nvkm_error(subdev, "VPR still locked after scrub!\n"); + return -EIO; + } + + nvkm_debug(subdev, "VPR scrubber binary successful\n"); + return 0; +} + static int nvkm_fb_init(struct nvkm_subdev *subdev) { @@ -157,18 +185,9 @@ nvkm_fb_init(struct nvkm_subdev *subdev) if (fb->func->vpr.scrub_required && fb->func->vpr.scrub_required(fb)) { - nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); - - ret = fb->func->vpr.scrub(fb); + ret = nvkm_fb_init_scrub_vpr(fb); if (ret) return ret; - - if (fb->func->vpr.scrub_required(fb)) { - nvkm_error(subdev, "VPR still locked after scrub!\n"); - return -EIO; - } - - nvkm_debug(subdev, "VPR scrubber binary successful\n"); } return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 9be7316c6642..fc8c93aa3da5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -120,8 +120,9 @@ gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, if (ret) return ret; - return nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, - &(*pfb)->vpr_scrubber); + nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, + &(*pfb)->vpr_scrubber); + return 0; } int -- cgit v1.2.3 From 58ae5284f663f0856a13bc6caad93a0fe49d7cb4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 3 Feb 2020 01:58:45 -0500 Subject: drm/nouveau/disp/gv100-: halt NV_PDISP_FE_RM_INTR_STAT_CTRL_DISP_ERROR storms Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 3aa2cc3af1e2..c1032527f791 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -155,6 +155,12 @@ gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) if (stat & 0x00000008) stat &= ~0x00000008; + if (stat & 0x00000080) { + u32 error = nvkm_mask(device, 0x611848, 0x00000000, 0x00000000); + nvkm_warn(subdev, "error %08x\n", error); + stat &= ~0x00000080; + } + if (stat & 0x00000100) { unsigned long wndws = nvkm_rd32(device, 0x611858); unsigned long other = nvkm_rd32(device, 0x61185c); -- cgit v1.2.3 From 5bb88d07948b6779cb783ec0f08b4c1474d592dd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 3 Feb 2020 03:36:30 -0500 Subject: drm/nouveau/kms/gv100-: move window ownership setup into modesetting path For various complicated reasons, we need to avoid sending a core update method during display init. Something, which we've been required to do on GV100 and up because we've been assigning windows to heads there and the HW is rather picky about when that's allowed. This moves window assignment into the modesetting path at a point where it's much safer to send our first update methods to NVDisplay. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/core.h | 6 ++++++ drivers/gpu/drm/nouveau/dispnv50/corec37d.c | 21 ++++++++++++++++++--- drivers/gpu/drm/nouveau/dispnv50/corec57d.c | 7 ++++--- drivers/gpu/drm/nouveau/dispnv50/disp.c | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/core.h b/drivers/gpu/drm/nouveau/dispnv50/core.h index df8336b593f7..ff94f3f6f264 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core.h +++ b/drivers/gpu/drm/nouveau/dispnv50/core.h @@ -6,6 +6,7 @@ struct nv50_core { const struct nv50_core_func *func; struct nv50_dmac chan; + bool assign_windows; }; int nv50_core_new(struct nouveau_drm *, struct nv50_core **); @@ -18,6 +19,10 @@ struct nv50_core_func { struct nvif_device *); void (*update)(struct nv50_core *, u32 *interlock, bool ntfy); + struct { + void (*owner)(struct nv50_core *); + } wndw; + const struct nv50_head_func *head; const struct nv50_outp_func { void (*ctrl)(struct nv50_core *, int or, u32 ctrl, @@ -48,6 +53,7 @@ int core917d_new(struct nouveau_drm *, s32, struct nv50_core **); int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **); int corec37d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *); void corec37d_update(struct nv50_core *, u32 *, bool); +void corec37d_wndw_owner(struct nv50_core *); extern const struct nv50_outp_func sorc37d; int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **); diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c index 40d9b654ab8c..f414171e40b4 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c @@ -24,6 +24,20 @@ #include +void +corec37d_wndw_owner(struct nv50_core *core) +{ + const u32 windows = 8; /*XXX*/ + u32 *push, i; + if ((push = evo_wait(&core->chan, 2 * windows))) { + for (i = 0; i < windows; i++) { + evo_mthd(push, 0x1000 + (i * 0x080), 1); + evo_data(push, i >> 1); + } + evo_kick(push, &core->chan); + } +} + void corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy) { @@ -76,12 +90,11 @@ corec37d_init(struct nv50_core *core) { const u32 windows = 8; /*XXX*/ u32 *push, i; - if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) { + if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) { evo_mthd(push, 0x0208, 1); evo_data(push, core->chan.sync.handle); for (i = 0; i < windows; i++) { - evo_mthd(push, 0x1000 + (i * 0x080), 3); - evo_data(push, i >> 1); + evo_mthd(push, 0x1004 + (i * 0x080), 2); evo_data(push, 0x0000001f); evo_data(push, 0x00000000); evo_mthd(push, 0x1010 + (i * 0x080), 1); @@ -90,6 +103,7 @@ corec37d_init(struct nv50_core *core) evo_mthd(push, 0x0200, 1); evo_data(push, 0x00000001); evo_kick(push, &core->chan); + core->assign_windows = true; } } @@ -99,6 +113,7 @@ corec37d = { .ntfy_init = corec37d_ntfy_init, .ntfy_wait_done = corec37d_ntfy_wait_done, .update = corec37d_update, + .wndw.owner = corec37d_wndw_owner, .head = &headc37d, .sor = &sorc37d, }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c index b606d68cda10..b540606ac052 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c @@ -27,12 +27,11 @@ corec57d_init(struct nv50_core *core) { const u32 windows = 8; /*XXX*/ u32 *push, i; - if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) { + if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) { evo_mthd(push, 0x0208, 1); evo_data(push, core->chan.sync.handle); for (i = 0; i < windows; i++) { - evo_mthd(push, 0x1000 + (i * 0x080), 3); - evo_data(push, i >> 1); + evo_mthd(push, 0x1004 + (i * 0x080), 2); evo_data(push, 0x0000000f); evo_data(push, 0x00000000); evo_mthd(push, 0x1010 + (i * 0x080), 1); @@ -41,6 +40,7 @@ corec57d_init(struct nv50_core *core) evo_mthd(push, 0x0200, 1); evo_data(push, 0x00000001); evo_kick(push, &core->chan); + core->assign_windows = true; } } @@ -50,6 +50,7 @@ corec57d = { .ntfy_init = corec37d_ntfy_init, .ntfy_wait_done = corec37d_ntfy_wait_done, .update = corec37d_update, + .wndw.owner = corec37d_wndw_owner, .head = &headc57d, .sor = &sorc37d, }; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 2f123082c85d..a3dc2ba19fb2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1933,6 +1933,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) struct nouveau_drm *drm = nouveau_drm(dev); struct nv50_disp *disp = nv50_disp(dev); struct nv50_atom *atom = nv50_atom(state); + struct nv50_core *core = disp->core; struct nv50_outp_atom *outp, *outt; u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {}; int i; @@ -2051,6 +2052,21 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) } } + /* Update window->head assignment. + * + * This has to happen in an update that's not interlocked with + * any window channels to avoid hitting HW error checks. + * + *TODO: Proper handling of window ownership (Turing apparently + * supports non-fixed mappings). + */ + if (core->assign_windows) { + core->func->wndw.owner(core); + core->func->update(core, interlock, false); + core->assign_windows = false; + interlock[NV50_DISP_INTERLOCK_CORE] = 0; + } + /* Update plane(s). */ for_each_new_plane_in_state(state, plane, new_plane_state, i) { struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state); -- cgit v1.2.3 From 137c4ba7163ad9d5696b9fde78b1c0898a9c115b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 3 Feb 2020 03:37:07 -0500 Subject: drm/nouveau/kms/gv100-: avoid sending a core update until the first modeset The OR routing logic in NVKM does not expect to receive supervisor interrupts until the DD has provided consistent information on the ORs it's using and the EVO/NVD assembly state to match. The combination of changing window ownership + core channel update during display init triggered a situation where we'd disconnect an OR from the pad it was meant to still be driving on some systems. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/corec37d.c | 4 +--- drivers/gpu/drm/nouveau/dispnv50/corec57d.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/nouveau') diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c index f414171e40b4..3b36dc8d36b2 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec37d.c @@ -90,7 +90,7 @@ corec37d_init(struct nv50_core *core) { const u32 windows = 8; /*XXX*/ u32 *push, i; - if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) { + if ((push = evo_wait(&core->chan, 2 + 5 * windows))) { evo_mthd(push, 0x0208, 1); evo_data(push, core->chan.sync.handle); for (i = 0; i < windows; i++) { @@ -100,8 +100,6 @@ corec37d_init(struct nv50_core *core) evo_mthd(push, 0x1010 + (i * 0x080), 1); evo_data(push, 0x00127fff); } - evo_mthd(push, 0x0200, 1); - evo_data(push, 0x00000001); evo_kick(push, &core->chan); core->assign_windows = true; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c index b540606ac052..147adcd60937 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/corec57d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/corec57d.c @@ -27,7 +27,7 @@ corec57d_init(struct nv50_core *core) { const u32 windows = 8; /*XXX*/ u32 *push, i; - if ((push = evo_wait(&core->chan, 2 + 5 * windows + 2))) { + if ((push = evo_wait(&core->chan, 2 + 5 * windows))) { evo_mthd(push, 0x0208, 1); evo_data(push, core->chan.sync.handle); for (i = 0; i < windows; i++) { @@ -37,8 +37,6 @@ corec57d_init(struct nv50_core *core) evo_mthd(push, 0x1010 + (i * 0x080), 1); evo_data(push, 0x00117fff); } - evo_mthd(push, 0x0200, 1); - evo_data(push, 0x00000001); evo_kick(push, &core->chan); core->assign_windows = true; } -- cgit v1.2.3