[PATCH 75/95] drm/amdgpu: Separate out ualink init sequences
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Lijo Lazar <[email protected]> Separate out sw_init and hw_init part of ualink. ualink init errors are ignored temporarily. Keep ualink sysfs init together with sysfs init sequence of other IPs. Signed-off-by: Lijo Lazar <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 + drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 300 +++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h | 16 +- drivers/gpu/drm/amd/amdgpu/soc_v1_0.c | 23 -- 4 files changed, 188 insertions(+), 161 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2c3180dfd26d5..715cc2e85105c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2456,6 +2456,8 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) } } + amdgpu_ualink_mgr_sw_init(adev); + if (amdgpu_sriov_vf(adev)) amdgpu_virt_init_data_exchange(adev); @@ -2482,6 +2484,8 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) if (r) goto init_failed; + amdgpu_ualink_mgr_hw_init(adev); + /* * retired pages will be loaded from eeprom and reserved here, * it should be called after amdgpu_device_ip_hw_init_phase2 since @@ -2765,6 +2769,8 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev) adev->ip_blocks[i].status.late_initialized = true; } + amdgpu_ualink_mgr_late_init(adev); + r = amdgpu_ras_late_init(adev); if (r) { dev_err(adev->dev, "amdgpu_ras_late_init failed %d", r); @@ -2957,6 +2963,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) amdgpu_amdkfd_device_fini_sw(adev); + amdgpu_ualink_mgr_sw_fini(adev); + for (i = adev->num_ip_blocks - 1; i >= 0; i--) { if (!adev->ip_blocks[i].status.sw) continue; @@ -3726,6 +3734,7 @@ static int amdgpu_device_sys_interface_init(struct amdgpu_device *adev) amdgpu_xcp_sysfs_init(adev); amdgpu_uma_sysfs_init(adev); amdgpu_ptl_sysfs_init(adev); + amdgpu_ualink_sysfs_init(adev); return r; } @@ -3747,6 +3756,7 @@ static void amdgpu_device_sys_interface_fini(struct amdgpu_device *adev) amdgpu_xcp_sysfs_fini(adev); amdgpu_uma_sysfs_fini(adev); amdgpu_ptl_sysfs_fini(adev); + amdgpu_ualink_sysfs_fini(adev); } static bool diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c index f45edc882b2f2..bc53d37534222 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c @@ -80,57 +80,90 @@ static int amdgpu_ualink_drm_client_create(struct amdgpu_device *adev) return 0; } -int amdgpu_ualink_init(struct amdgpu_device *adev) +static bool amdgpu_ualink_supported(struct amdgpu_device *adev) +{ + if (!amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) + return false; + + if (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(15, 0, 8)) + return false; + + return true; +} + +static void amdgpu_ualink_object_fini(struct amdgpu_device *adev) +{ + if (!adev->ualink.info) + return; + + kobject_put(&adev->ualink.stations->kobj); + kobject_put(&adev->ualink.config->kobj); + kobject_put(&adev->ualink.setup->kobj); + kobject_put(&adev->ualink.info->kobj); + adev->ualink.stations = NULL; + adev->ualink.config = NULL; + adev->ualink.setup = NULL; + adev->ualink.info = NULL; +} + +int amdgpu_ualink_mgr_hw_init(struct amdgpu_device *adev) { int r; - /* UALink relies on PSP services. If the PSP IP block is not present - * just skip UALink initialization. - */ - if (!amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) { - adev->ualink.psp_if_ver = 0xffffffff; + if (!adev->ualink.info) return 0; - } r = psp_ual_get_interface_version(&adev->psp, &adev->ualink.psp_if_ver); if (r) { adev->ualink.psp_if_ver = 0xffffffff; - dev_err(adev->dev, - "UALink interface version detection failed: %d", r); - return r; + dev_info(adev->dev, + "UALink disabled, PSP interface version detection failed: %d\n", + r); + goto disable; } dev_info(adev->dev, "Found UALink interface version 0x%x\n", adev->ualink.psp_if_ver); - /* Query initial configuration from ASP */ r = psp_ual_query_info(&adev->psp, adev->ualink.psp_if_ver, adev->ualink.info); if (r) { - dev_err(adev->dev, - "Failed to query initial UALink config: %d\n", r); - return r; + dev_info(adev->dev, + "UALink disabled, failed to query initial config: %d\n", + r); + goto disable; } + adev->ualink.mgr_state = AMDGPU_UALINK_INIT_HW; + + return 0; + +disable: + adev->ualink.mgr_state = AMDGPU_UALINK_INIT_ERROR; + return 0; +} + +int amdgpu_ualink_mgr_late_init(struct amdgpu_device *adev) +{ + int r; + + if (adev->ualink.mgr_state != AMDGPU_UALINK_INIT_HW) + return 0; + r = amdgpu_ualink_drm_client_create(adev); if (r) { dev_err(adev->dev, "Failed to create UALink DRM client: %d\n", r); - return r; + goto error; } - r = amdgpu_ualink_init_interrupt(adev); - if (r) { - dev_err(adev->dev, - "Failed to enable UALink irq: %d\n", r); - return r; - } + /* Consider UALink initialized only at this stage */ + adev->ualink.mgr_state = AMDGPU_UALINK_INIT_COMPLETE; return 0; -} -void amdgpu_ualink_fini(struct amdgpu_device *adev) -{ - /* empty */ +error: + adev->ualink.mgr_state = AMDGPU_UALINK_INIT_ERROR; + return r; } /**************************************************************************** @@ -430,9 +463,7 @@ static const struct attribute *ualink_info_attrs[] = { static void ualink_info_release(struct kobject *kobj) { - struct amdgpu_ualink_info *info = to_ualink_info(kobj); - - kfree(info); + kfree(to_ualink_info(kobj)); } static const struct kobj_type ualink_info_ktype = { @@ -537,9 +568,7 @@ static const struct attribute *ualink_ppod_setup_attrs[] = { static void ualink_ppod_setup_release(struct kobject *kobj) { - struct amdgpu_ualink_ppod_setup *setup = to_ualink_ppod_setup(kobj); - - kfree(setup); + kfree(to_ualink_ppod_setup(kobj)); } static const struct kobj_type ualink_ppod_setup_ktype = { @@ -875,9 +904,7 @@ static const struct attribute *ualink_vpod_config_attrs[] = { static void ualink_vpod_config_release(struct kobject *kobj) { - struct amdgpu_ualink_vpod_config *config = to_ualink_vpod_config(kobj); - - kfree(config); + kfree(to_ualink_vpod_config(kobj)); } static const struct kobj_type ualink_vpod_config_ktype = { @@ -995,9 +1022,7 @@ static const struct attribute *ualink_station_config_attrs[] = { static void ualink_station_config_release(struct kobject *kobj) { - struct amdgpu_ualink_station_config *stations = to_ualink_station_config(kobj); - - kfree(stations); + kfree(to_ualink_station_config(kobj)); } static const struct kobj_type ualink_station_config_ktype = { @@ -1005,20 +1030,29 @@ static const struct kobj_type ualink_station_config_ktype = { .sysfs_ops = &kobj_sysfs_ops }; -int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) +int amdgpu_ualink_mgr_sw_init(struct amdgpu_device *adev) { - struct amdgpu_ualink_station_config *stations = NULL; - struct amdgpu_ualink_vpod_config *vpod_config = NULL; - struct amdgpu_ualink_ppod_setup *ppod_setup = NULL; - struct amdgpu_ualink_info *info = NULL; int r; - if (!amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_PSP)) + struct amdgpu_ualink_station_config *stations; + struct amdgpu_ualink_vpod_config *vpod_config; + struct amdgpu_ualink_ppod_setup *ppod_setup; + struct amdgpu_ualink_info *info; + + if (!amdgpu_ualink_supported(adev)) return 0; info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + ppod_setup = kzalloc(sizeof(*ppod_setup), GFP_KERNEL); + vpod_config = kzalloc(sizeof(*vpod_config), GFP_KERNEL); + stations = kzalloc(sizeof(*stations), GFP_KERNEL); + if (!info || !ppod_setup || !vpod_config || !stations) { + kfree(info); + kfree(ppod_setup); + kfree(vpod_config); + kfree(stations); return -ENOMEM; + } info->ppod.accel_id = 0xffffffff; info->ppod.bandwidth = 0xffffffff; @@ -1026,115 +1060,103 @@ int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) info->vpod.id = 0xffffffff; info->vpod.addr_mode = AMDGPU_UALINK_ADDR_MODE_MAX; - r = kobject_init_and_add(&info->kobj, &ualink_info_ktype, - &adev->dev->kobj, "ualink"); - if (r) - goto err_put_info; - r = sysfs_create_files(&info->kobj, ualink_info_attrs); - if (r) - goto err_del_info; + /* + * Initialize the kobjects here so their lifetime is tied to the UALink + * manager software state. amdgpu_ualink_object_fini() drops the final + * reference via kobject_put(). + */ + kobject_init(&info->kobj, &ualink_info_ktype); + kobject_init(&ppod_setup->kobj, &ualink_ppod_setup_ktype); + kobject_init(&vpod_config->kobj, &ualink_vpod_config_ktype); + kobject_init(&stations->kobj, &ualink_station_config_ktype); - ppod_setup = kzalloc(sizeof(*ppod_setup), GFP_KERNEL); - if (!ppod_setup) { - r = -ENOMEM; - goto err_remove_info_files; + adev->ualink.info = info; + adev->ualink.setup = ppod_setup; + adev->ualink.config = vpod_config; + adev->ualink.stations = stations; + + r = amdgpu_ualink_init_interrupt(adev); + if (r) { + dev_err(adev->dev, "Failed to add UALink irq: %d\n", r); + return r; } - r = kobject_init_and_add(&ppod_setup->kobj, &ualink_ppod_setup_ktype, - &info->kobj, "setup"); + + return 0; +} + +void amdgpu_ualink_mgr_sw_fini(struct amdgpu_device *adev) +{ + amdgpu_ualink_object_fini(adev); +} + +static int ualink_kobj_add(struct kobject *kobj, struct kobject *parent, + const char *name, const struct attribute **attrs) +{ + int r; + + r = kobject_add(kobj, parent, "%s", name); if (r) - goto err_put_ppod_setup; - r = sysfs_create_files(&ppod_setup->kobj, ualink_ppod_setup_attrs); + return r; + r = sysfs_create_files(kobj, attrs); if (r) - goto err_del_ppod_setup; + kobject_del(kobj); - vpod_config = kzalloc(sizeof(*vpod_config), GFP_KERNEL); - if (!vpod_config) { - r = -ENOMEM; - goto err_remove_ppod_setup_files; - } - r = kobject_init_and_add(&vpod_config->kobj, &ualink_vpod_config_ktype, - &info->kobj, "config"); - if (r) - goto err_put_vpod_config; - r = sysfs_create_files(&vpod_config->kobj, ualink_vpod_config_attrs); + return r; +} + +int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) +{ + struct amdgpu_ualink_info *info = adev->ualink.info; + int r; + + if (adev->ualink.mgr_state != AMDGPU_UALINK_INIT_COMPLETE) + return 0; + + /* ualink parent node */ + r = ualink_kobj_add(&info->kobj, &adev->dev->kobj, "ualink", + ualink_info_attrs); if (r) - goto err_del_vpod_config; + goto err; - stations = kzalloc(sizeof(*stations), GFP_KERNEL); - if (!stations) { - r = -ENOMEM; - goto err_remove_vpod_config_files; - } - r = kobject_init_and_add(&stations->kobj, &ualink_station_config_ktype, - &info->kobj, "stations"); + r = ualink_kobj_add(&adev->ualink.setup->kobj, &info->kobj, "setup", + ualink_ppod_setup_attrs); if (r) - goto err_put_stations; - r = sysfs_create_files(&stations->kobj, ualink_station_config_attrs); + goto err_info; + + r = ualink_kobj_add(&adev->ualink.config->kobj, &info->kobj, "config", + ualink_vpod_config_attrs); if (r) - goto err_del_stations; + goto err_setup; - adev->ualink.stations = stations; - adev->ualink.config = vpod_config; - adev->ualink.setup = ppod_setup; - adev->ualink.info = info; + r = ualink_kobj_add(&adev->ualink.stations->kobj, &info->kobj, + "stations", ualink_station_config_attrs); + if (r) + goto err_config; - return r; + adev->ualink.sysfs_init = true; + return 0; -err_del_stations: - kobject_del(&stations->kobj); -err_put_stations: - kobject_put(&stations->kobj); -err_remove_vpod_config_files: - sysfs_remove_files(&vpod_config->kobj, ualink_vpod_config_attrs); -err_del_vpod_config: - kobject_del(&vpod_config->kobj); -err_put_vpod_config: - kobject_put(&vpod_config->kobj); -err_remove_ppod_setup_files: - sysfs_remove_files(&ppod_setup->kobj, ualink_ppod_setup_attrs); -err_del_ppod_setup: - kobject_del(&ppod_setup->kobj); -err_put_ppod_setup: - kobject_put(&ppod_setup->kobj); -err_remove_info_files: - sysfs_remove_files(&info->kobj, ualink_info_attrs); -err_del_info: +err_config: + kobject_del(&adev->ualink.config->kobj); +err_setup: + kobject_del(&adev->ualink.setup->kobj); +err_info: kobject_del(&info->kobj); -err_put_info: - kobject_put(&info->kobj); - return r; +err: + dev_warn(adev->dev, "Failed to create UALink sysfs: %d\n", r); + return 0; } void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev) { - if (adev->ualink.stations) { - sysfs_remove_files(&adev->ualink.stations->kobj, - ualink_station_config_attrs); - kobject_del(&adev->ualink.stations->kobj); - kobject_put(&adev->ualink.stations->kobj); - adev->ualink.stations = NULL; - } - if (adev->ualink.config) { - sysfs_remove_files(&adev->ualink.config->kobj, - ualink_vpod_config_attrs); - kobject_del(&adev->ualink.config->kobj); - kobject_put(&adev->ualink.config->kobj); - adev->ualink.config = NULL; - } - if (adev->ualink.setup) { - sysfs_remove_files(&adev->ualink.setup->kobj, - ualink_ppod_setup_attrs); - kobject_del(&adev->ualink.setup->kobj); - kobject_put(&adev->ualink.setup->kobj); - adev->ualink.setup = NULL; - } - if (adev->ualink.info) { - sysfs_remove_files(&adev->ualink.info->kobj, - ualink_info_attrs); - kobject_del(&adev->ualink.info->kobj); - kobject_put(&adev->ualink.info->kobj); - adev->ualink.info = NULL; - } + if (!adev->ualink.sysfs_init) + return; + + kobject_del(&adev->ualink.stations->kobj); + kobject_del(&adev->ualink.config->kobj); + kobject_del(&adev->ualink.setup->kobj); + kobject_del(&adev->ualink.info->kobj); + adev->ualink.sysfs_init = false; } static int amdgpu_ualink_npa_alloc_va(struct amdgpu_device *adev, @@ -5356,6 +5378,12 @@ static int amdgpu_ualink_process_irq(struct amdgpu_device *adev, u32 local_acc_id; int handled = 1; + if (unlikely(adev->ualink.mgr_state != AMDGPU_UALINK_INIT_COMPLETE)) { + dev_dbg(adev->dev, + "UALink manager not initialized, dropping irq\n"); + return handled; + } + dev_dbg(adev->dev, "%s client_id 0x%x src_id 0x%x ih\n", entry->ih == &adev->irq.ih ? "ring" : "ualink soft ring", entry->client_id, entry->src_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h index 407220710d9b4..3c5bfdd3af5bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h @@ -109,6 +109,13 @@ enum amdgpu_ualink_addr_mode { AMDGPU_UALINK_ADDR_MODE_MAX }; +enum amdgpu_ualink_mgr_state { + AMDGPU_UALINK_INIT_NONE = 0, + AMDGPU_UALINK_INIT_HW, + AMDGPU_UALINK_INIT_COMPLETE, + AMDGPU_UALINK_INIT_ERROR +}; + /* Physical pod info shared between query and setup API */ struct amdgpu_ualink_ppod_info { u32 accel_id; @@ -295,6 +302,8 @@ struct amdgpu_ualink_mgr { struct amdgpu_ualink_ppod_setup *setup; struct amdgpu_ualink_vpod_config *config; struct amdgpu_ualink_station_config *stations; + bool sysfs_init; + enum amdgpu_ualink_mgr_state mgr_state; /* For remote interrupt and shootdown */ struct amdgpu_ualink_remote *remote; @@ -362,10 +371,13 @@ void amdgpu_ualink_sw_fini(struct amdgpu_device *adev); int ualink_send_hello(struct amdgpu_device *adev, u32 remote_accel_id); +int amdgpu_ualink_mgr_sw_init(struct amdgpu_device *adev); +void amdgpu_ualink_mgr_sw_fini(struct amdgpu_device *adev); +int amdgpu_ualink_mgr_hw_init(struct amdgpu_device *adev); +int amdgpu_ualink_mgr_late_init(struct amdgpu_device *adev); + int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev); void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev); -int amdgpu_ualink_init(struct amdgpu_device *adev); -void amdgpu_ualink_fini(struct amdgpu_device *adev); int amdgpu_ualink_manager_start(struct amdgpu_device *adev); void amdgpu_ualink_manager_stop(struct amdgpu_device *adev); int amdgpu_ualink_export_handle(struct drm_device *dev, struct drm_file *filp, diff --git a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c index 84cdb09f731e5..757da0a30fdc4 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c @@ -439,25 +439,6 @@ static int soc_v1_0_common_late_init(struct amdgpu_ip_block *ip_block) */ adev->nbio.funcs->enable_doorbell_selfring_aperture(adev, true); - /* Depends on PSP being initialized */ - amdgpu_ualink_init(adev); - - return 0; -} - -static int soc_v1_0_common_sw_init(struct amdgpu_ip_block *ip_block) -{ - struct amdgpu_device *adev = ip_block->adev; - - return amdgpu_ualink_sysfs_init(adev); -} - -static int soc_v1_0_common_sw_fini(struct amdgpu_ip_block *ip_block) -{ - struct amdgpu_device *adev = ip_block->adev; - - amdgpu_ualink_sysfs_fini(adev); - return 0; } @@ -475,8 +456,6 @@ static int soc_v1_0_common_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; - amdgpu_ualink_fini(adev); - adev->nbio.funcs->enable_doorbell_aperture(adev, false); adev->nbio.funcs->enable_doorbell_selfring_aperture(adev, false); @@ -515,8 +494,6 @@ static const struct amd_ip_funcs soc_v1_0_common_ip_funcs = { .name = "soc_v1_0_common", .early_init = soc_v1_0_common_early_init, .late_init = soc_v1_0_common_late_init, - .sw_init = soc_v1_0_common_sw_init, - .sw_fini = soc_v1_0_common_sw_fini, .hw_init = soc_v1_0_common_hw_init, .hw_fini = soc_v1_0_common_hw_fini, .suspend = soc_v1_0_common_suspend, -- 2.55.0