mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	drm/amdgpu: Place NPS mode request on unload
If a user has requested NPS mode switch, place the request through PSP during unload of the driver. For devices which are part of a hive, all requests are placed together. If one of them fails, revert back to the current NPS mode. Signed-off-by: Lijo Lazar <lijo.lazar@amd.com> Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com> Reviewed-by: Feifei Xu <Feifei.Xu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
		
							parent
							
								
									01b64bc063
								
							
						
					
					
						commit
						ee52489d12
					
				
					 5 changed files with 92 additions and 0 deletions
				
			
		| 
						 | 
					@ -2429,6 +2429,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
 | 
				
			||||||
	struct amdgpu_device *adev = drm_to_adev(dev);
 | 
						struct amdgpu_device *adev = drm_to_adev(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	amdgpu_xcp_dev_unplug(adev);
 | 
						amdgpu_xcp_dev_unplug(adev);
 | 
				
			||||||
 | 
						amdgpu_gmc_prepare_nps_mode_change(adev);
 | 
				
			||||||
	drm_dev_unplug(dev);
 | 
						drm_dev_unplug(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
 | 
						if (adev->pm.rpm_mode != AMDGPU_RUNPM_NONE) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1333,3 +1333,50 @@ int amdgpu_gmc_request_memory_partition(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return psp_memory_partition(&adev->psp, nps_mode);
 | 
						return psp_memory_partition(&adev->psp, nps_mode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool amdgpu_gmc_need_nps_switch_req(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
											  int req_nps_mode,
 | 
				
			||||||
 | 
											  int cur_nps_mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (((BIT(req_nps_mode) & adev->gmc.supported_nps_modes) ==
 | 
				
			||||||
 | 
								BIT(req_nps_mode)) &&
 | 
				
			||||||
 | 
							req_nps_mode != cur_nps_mode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void amdgpu_gmc_prepare_nps_mode_change(struct amdgpu_device *adev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int req_nps_mode, cur_nps_mode, r;
 | 
				
			||||||
 | 
						struct amdgpu_hive_info *hive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (amdgpu_sriov_vf(adev) || !adev->gmc.supported_nps_modes ||
 | 
				
			||||||
 | 
						    !adev->gmc.gmc_funcs->request_mem_partition_mode)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cur_nps_mode = adev->gmc.gmc_funcs->query_mem_partition_mode(adev);
 | 
				
			||||||
 | 
						hive = amdgpu_get_xgmi_hive(adev);
 | 
				
			||||||
 | 
						if (hive) {
 | 
				
			||||||
 | 
							req_nps_mode = atomic_read(&hive->requested_nps_mode);
 | 
				
			||||||
 | 
							if (!amdgpu_gmc_need_nps_switch_req(adev, req_nps_mode,
 | 
				
			||||||
 | 
											    cur_nps_mode)) {
 | 
				
			||||||
 | 
								amdgpu_put_xgmi_hive(hive);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							r = amdgpu_xgmi_request_nps_change(adev, hive, req_nps_mode);
 | 
				
			||||||
 | 
							amdgpu_put_xgmi_hive(hive);
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req_nps_mode = adev->gmc.requested_nps_mode;
 | 
				
			||||||
 | 
						if (!amdgpu_gmc_need_nps_switch_req(adev, req_nps_mode, cur_nps_mode))
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* even if this fails, we should let driver unload w/o blocking */
 | 
				
			||||||
 | 
						r = adev->gmc.gmc_funcs->request_mem_partition_mode(adev, req_nps_mode);
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						if (r)
 | 
				
			||||||
 | 
							dev_err(adev->dev, "NPS mode change request failed\n");
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							dev_info(
 | 
				
			||||||
 | 
								adev->dev,
 | 
				
			||||||
 | 
								"NPS mode change request done, reload driver to complete the change\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -466,4 +466,6 @@ int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int amdgpu_gmc_request_memory_partition(struct amdgpu_device *adev,
 | 
					int amdgpu_gmc_request_memory_partition(struct amdgpu_device *adev,
 | 
				
			||||||
					int nps_mode);
 | 
										int nps_mode);
 | 
				
			||||||
 | 
					void amdgpu_gmc_prepare_nps_mode_change(struct amdgpu_device *adev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1564,3 +1564,41 @@ int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
									   struct amdgpu_hive_info *hive,
 | 
				
			||||||
 | 
									   int req_nps_mode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct amdgpu_device *tmp_adev;
 | 
				
			||||||
 | 
						int cur_nps_mode, r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This is expected to be called only during unload of driver. The
 | 
				
			||||||
 | 
						 * request needs to be placed only once for all devices in the hive. If
 | 
				
			||||||
 | 
						 * one of them fail, revert the request for previous successful devices.
 | 
				
			||||||
 | 
						 * After placing the request, make hive mode as UNKNOWN so that other
 | 
				
			||||||
 | 
						 * devices don't request anymore.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						mutex_lock(&hive->hive_lock);
 | 
				
			||||||
 | 
						list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
 | 
				
			||||||
 | 
							r = adev->gmc.gmc_funcs->request_mem_partition_mode(
 | 
				
			||||||
 | 
								tmp_adev, req_nps_mode);
 | 
				
			||||||
 | 
							if (r)
 | 
				
			||||||
 | 
								goto err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* Set to UNKNOWN so that other devices don't request anymore */
 | 
				
			||||||
 | 
						atomic_set(&hive->requested_nps_mode, UNKNOWN_MEMORY_PARTITION_MODE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_unlock(&hive->hive_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					err:
 | 
				
			||||||
 | 
						/* Request back current mode if one of the requests failed */
 | 
				
			||||||
 | 
						cur_nps_mode = adev->gmc.gmc_funcs->query_mem_partition_mode(tmp_adev);
 | 
				
			||||||
 | 
						list_for_each_entry_continue_reverse(tmp_adev, &hive->device_list,
 | 
				
			||||||
 | 
										     gmc.xgmi.head)
 | 
				
			||||||
 | 
							adev->gmc.gmc_funcs->request_mem_partition_mode(tmp_adev,
 | 
				
			||||||
 | 
													cur_nps_mode);
 | 
				
			||||||
 | 
						mutex_lock(&hive->hive_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,4 +79,8 @@ static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
 | 
				
			||||||
int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev);
 | 
					int amdgpu_xgmi_ras_sw_init(struct amdgpu_device *adev);
 | 
				
			||||||
int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
 | 
					int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
 | 
				
			||||||
 | 
									   struct amdgpu_hive_info *hive,
 | 
				
			||||||
 | 
									   int req_nps_mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue