Skip to content

Commit f2e18c9

Browse files
Timur Kristófalexdeucher
authored andcommitted
drm/amdgpu/vce: Move firmware load to amdgpu_vce_early_init
Try to load the VCE firmware at early_init. When the correct firmware is not found, return -ENOENT. This way, the driver initialization will complete even without VCE, and the GPU will be functional, albeit without video encoding capabilities. This is necessary because we are planning to add support for the VCE1, and AMD hasn't yet publised the correct firmware for this version. So we need to anticipate that users will try to boot amdgpu on SI GPUs without the correct VCE1 firmware present on their system. Signed-off-by: Timur Kristóf <timur.kristof@gmail.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 43a0ca3 commit f2e18c9

5 files changed

Lines changed: 91 additions & 46 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c

Lines changed: 75 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -88,82 +88,87 @@ static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
8888
bool direct, struct dma_fence **fence);
8989

9090
/**
91-
* amdgpu_vce_sw_init - allocate memory, load vce firmware
91+
* amdgpu_vce_firmware_name() - determine the firmware file name for VCE
9292
*
9393
* @adev: amdgpu_device pointer
94-
* @size: size for the new BO
9594
*
96-
* First step to get VCE online, allocate memory and load the firmware
95+
* Each chip that has VCE IP may need a different firmware.
96+
* This function returns the name of the VCE firmware file
97+
* appropriate for the current chip.
9798
*/
98-
int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
99+
static const char *amdgpu_vce_firmware_name(struct amdgpu_device *adev)
99100
{
100-
const char *fw_name;
101-
const struct common_firmware_header *hdr;
102-
unsigned int ucode_version, version_major, version_minor, binary_id;
103-
int i, r;
104-
105101
switch (adev->asic_type) {
106102
#ifdef CONFIG_DRM_AMDGPU_CIK
107103
case CHIP_BONAIRE:
108-
fw_name = FIRMWARE_BONAIRE;
109-
break;
104+
return FIRMWARE_BONAIRE;
110105
case CHIP_KAVERI:
111-
fw_name = FIRMWARE_KAVERI;
112-
break;
106+
return FIRMWARE_KAVERI;
113107
case CHIP_KABINI:
114-
fw_name = FIRMWARE_KABINI;
115-
break;
108+
return FIRMWARE_KABINI;
116109
case CHIP_HAWAII:
117-
fw_name = FIRMWARE_HAWAII;
118-
break;
110+
return FIRMWARE_HAWAII;
119111
case CHIP_MULLINS:
120-
fw_name = FIRMWARE_MULLINS;
121-
break;
112+
return FIRMWARE_MULLINS;
122113
#endif
123114
case CHIP_TONGA:
124-
fw_name = FIRMWARE_TONGA;
125-
break;
115+
return FIRMWARE_TONGA;
126116
case CHIP_CARRIZO:
127-
fw_name = FIRMWARE_CARRIZO;
128-
break;
117+
return FIRMWARE_CARRIZO;
129118
case CHIP_FIJI:
130-
fw_name = FIRMWARE_FIJI;
131-
break;
119+
return FIRMWARE_FIJI;
132120
case CHIP_STONEY:
133-
fw_name = FIRMWARE_STONEY;
134-
break;
121+
return FIRMWARE_STONEY;
135122
case CHIP_POLARIS10:
136-
fw_name = FIRMWARE_POLARIS10;
137-
break;
123+
return FIRMWARE_POLARIS10;
138124
case CHIP_POLARIS11:
139-
fw_name = FIRMWARE_POLARIS11;
140-
break;
125+
return FIRMWARE_POLARIS11;
141126
case CHIP_POLARIS12:
142-
fw_name = FIRMWARE_POLARIS12;
143-
break;
127+
return FIRMWARE_POLARIS12;
144128
case CHIP_VEGAM:
145-
fw_name = FIRMWARE_VEGAM;
146-
break;
129+
return FIRMWARE_VEGAM;
147130
case CHIP_VEGA10:
148-
fw_name = FIRMWARE_VEGA10;
149-
break;
131+
return FIRMWARE_VEGA10;
150132
case CHIP_VEGA12:
151-
fw_name = FIRMWARE_VEGA12;
152-
break;
133+
return FIRMWARE_VEGA12;
153134
case CHIP_VEGA20:
154-
fw_name = FIRMWARE_VEGA20;
155-
break;
135+
return FIRMWARE_VEGA20;
156136

157137
default:
158-
return -EINVAL;
138+
return NULL;
159139
}
140+
}
141+
142+
/**
143+
* amdgpu_vce_early_init() - try to load VCE firmware
144+
*
145+
* @adev: amdgpu_device pointer
146+
*
147+
* Tries to load the VCE firmware.
148+
*
149+
* When not found, returns ENOENT so that the driver can
150+
* still load and initialize the rest of the IP blocks.
151+
* The GPU can function just fine without VCE, they will just
152+
* not support video encoding.
153+
*/
154+
int amdgpu_vce_early_init(struct amdgpu_device *adev)
155+
{
156+
const char *fw_name = amdgpu_vce_firmware_name(adev);
157+
const struct common_firmware_header *hdr;
158+
unsigned int ucode_version, version_major, version_minor, binary_id;
159+
int r;
160+
161+
if (!fw_name)
162+
return -ENOENT;
160163

161164
r = amdgpu_ucode_request(adev, &adev->vce.fw, AMDGPU_UCODE_REQUIRED, "%s", fw_name);
162165
if (r) {
163-
dev_err(adev->dev, "amdgpu_vce: Can't validate firmware \"%s\"\n",
164-
fw_name);
166+
dev_err(adev->dev,
167+
"amdgpu_vce: Firmware \"%s\" not found or failed to validate (%d)\n",
168+
fw_name, r);
169+
165170
amdgpu_ucode_release(&adev->vce.fw);
166-
return r;
171+
return -ENOENT;
167172
}
168173

169174
hdr = (const struct common_firmware_header *)adev->vce.fw->data;
@@ -172,11 +177,35 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
172177
version_major = (ucode_version >> 20) & 0xfff;
173178
version_minor = (ucode_version >> 8) & 0xfff;
174179
binary_id = ucode_version & 0xff;
175-
DRM_INFO("Found VCE firmware Version: %d.%d Binary ID: %d\n",
180+
dev_info(adev->dev, "Found VCE firmware Version: %d.%d Binary ID: %d\n",
176181
version_major, version_minor, binary_id);
177182
adev->vce.fw_version = ((version_major << 24) | (version_minor << 16) |
178183
(binary_id << 8));
179184

185+
return 0;
186+
}
187+
188+
/**
189+
* amdgpu_vce_sw_init() - allocate memory for VCE BO
190+
*
191+
* @adev: amdgpu_device pointer
192+
* @size: size for the new BO
193+
*
194+
* First step to get VCE online: allocate memory for VCE BO.
195+
* The VCE firmware binary is copied into the VCE BO later,
196+
* in amdgpu_vce_resume. The VCE executes its code from the
197+
* VCE BO and also uses the space in this BO for its stack and data.
198+
*
199+
* Ideally this BO should be placed in VRAM for optimal performance,
200+
* although technically it also runs from system RAM (albeit slowly).
201+
*/
202+
int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
203+
{
204+
int i, r;
205+
206+
if (!adev->vce.fw)
207+
return -ENOENT;
208+
180209
r = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE,
181210
AMDGPU_GEM_DOMAIN_VRAM |
182211
AMDGPU_GEM_DOMAIN_GTT,

drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ struct amdgpu_vce {
5353
unsigned num_rings;
5454
};
5555

56+
int amdgpu_vce_early_init(struct amdgpu_device *adev);
5657
int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size);
5758
int amdgpu_vce_sw_fini(struct amdgpu_device *adev);
5859
int amdgpu_vce_entity_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);

drivers/gpu/drm/amd/amdgpu/vce_v2_0.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable,
407407
static int vce_v2_0_early_init(struct amdgpu_ip_block *ip_block)
408408
{
409409
struct amdgpu_device *adev = ip_block->adev;
410+
int r;
411+
412+
r = amdgpu_vce_early_init(adev);
413+
if (r)
414+
return r;
410415

411416
adev->vce.num_rings = 2;
412417

drivers/gpu/drm/amd/amdgpu/vce_v3_0.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
399399
static int vce_v3_0_early_init(struct amdgpu_ip_block *ip_block)
400400
{
401401
struct amdgpu_device *adev = ip_block->adev;
402+
int r;
402403

403404
adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
404405

@@ -407,6 +408,10 @@ static int vce_v3_0_early_init(struct amdgpu_ip_block *ip_block)
407408
(AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
408409
return -ENOENT;
409410

411+
r = amdgpu_vce_early_init(adev);
412+
if (r)
413+
return r;
414+
410415
adev->vce.num_rings = 3;
411416

412417
vce_v3_0_set_ring_funcs(adev);

drivers/gpu/drm/amd/amdgpu/vce_v4_0.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,11 @@ static int vce_v4_0_stop(struct amdgpu_device *adev)
410410
static int vce_v4_0_early_init(struct amdgpu_ip_block *ip_block)
411411
{
412412
struct amdgpu_device *adev = ip_block->adev;
413+
int r;
414+
415+
r = amdgpu_vce_early_init(adev);
416+
if (r)
417+
return r;
413418

414419
if (amdgpu_sriov_vf(adev)) /* currently only VCN0 support SRIOV */
415420
adev->vce.num_rings = 1;

0 commit comments

Comments
 (0)