diff options
Diffstat (limited to 'drivers/gpu')
63 files changed, 1027 insertions, 312 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index dc3c6b3a00e5..d356e329e6f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -758,7 +758,7 @@ enum amd_hw_ip_block_type {  	MAX_HWIP  }; -#define HWIP_MAX_INSTANCE	8 +#define HWIP_MAX_INSTANCE	10  struct amd_powerplay {  	void *pp_handle; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 3003ee1c9487..1d41c2c00623 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -192,6 +192,16 @@ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm)  		kgd2kfd_suspend(adev->kfd.dev, run_pm);  } +int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev) +{ +	int r = 0; + +	if (adev->kfd.dev) +		r = kgd2kfd_resume_iommu(adev->kfd.dev); + +	return r; +} +  int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm)  {  	int r = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index ec028cf963f5..3bc52b2c604f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -137,6 +137,7 @@ int amdgpu_amdkfd_init(void);  void amdgpu_amdkfd_fini(void);  void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); +int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev);  int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm);  void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev,  			const void *ih_ring_entry); @@ -327,6 +328,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,  			 const struct kgd2kfd_shared_resources *gpu_resources);  void kgd2kfd_device_exit(struct kfd_dev *kfd);  void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); +int kgd2kfd_resume_iommu(struct kfd_dev *kfd);  int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm);  int kgd2kfd_pre_reset(struct kfd_dev *kfd);  int kgd2kfd_post_reset(struct kfd_dev *kfd); @@ -365,6 +367,11 @@ static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)  {  } +static int __maybe_unused kgd2kfd_resume_iommu(struct kfd_dev *kfd) +{ +	return 0; +} +  static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)  {  	return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 277128846dd1..463b9c0283f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1544,20 +1544,18 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)  	struct dentry *ent;  	int r, i; - -  	ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev,  				  &fops_ib_preempt); -	if (!ent) { +	if (IS_ERR(ent)) {  		DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); -		return -EIO; +		return PTR_ERR(ent);  	}  	ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev,  				  &fops_sclk_set); -	if (!ent) { +	if (IS_ERR(ent)) {  		DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); -		return -EIO; +		return PTR_ERR(ent);  	}  	/* Register debugfs entries for amdgpu_ttm */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 41c6b3aacd37..ab3794c42d36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)  	if (r)  		goto init_failed; +	r = amdgpu_amdkfd_resume_iommu(adev); +	if (r) +		goto init_failed; +  	r = amdgpu_device_ip_hw_init_phase1(adev);  	if (r)  		goto init_failed; @@ -3148,6 +3152,10 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)  {  	int r; +	r = amdgpu_amdkfd_resume_iommu(adev); +	if (r) +		return r; +  	r = amdgpu_device_ip_resume_phase1(adev);  	if (r)  		return r; @@ -4601,6 +4609,10 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle,  				dev_warn(tmp_adev->dev, "asic atom init failed!");  			} else {  				dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); +				r = amdgpu_amdkfd_resume_iommu(tmp_adev); +				if (r) +					goto out; +  				r = amdgpu_device_ip_resume_phase1(tmp_adev);  				if (r)  					goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index c7797eac83c3..9ff600a38559 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -598,7 +598,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)  		break;  	default:  		adev->gmc.tmz_enabled = false; -		dev_warn(adev->dev, +		dev_info(adev->dev,  			 "Trusted Memory Zone (TMZ) feature not supported\n");  		break;  	} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index dc44c946a244..98732518543e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -757,7 +757,7 @@ Out:  	return res;  } -inline uint32_t amdgpu_ras_eeprom_max_record_count(void) +uint32_t amdgpu_ras_eeprom_max_record_count(void)  {  	return RAS_MAX_RECORD_COUNT;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index f95fc61b3021..6bb00578bfbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -120,7 +120,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control,  int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control,  			     struct eeprom_table_record *records, const u32 num); -inline uint32_t amdgpu_ras_eeprom_max_record_count(void); +uint32_t amdgpu_ras_eeprom_max_record_count(void);  void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 7b634a1517f9..0554576d3695 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -428,8 +428,8 @@ int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,  	ent = debugfs_create_file(name,  				  S_IFREG | S_IRUGO, root,  				  ring, &amdgpu_debugfs_ring_fops); -	if (!ent) -		return -ENOMEM; +	if (IS_ERR(ent)) +		return PTR_ERR(ent);  	i_size_write(ent->d_inode, ring->ring_size + 12);  	ring->ent = ent; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 38dade421d46..94126dc39688 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,  		goto out;  	} +	if (bo->type == ttm_bo_type_device && +	    new_mem->mem_type == TTM_PL_VRAM && +	    old_mem->mem_type != TTM_PL_VRAM) { +		/* amdgpu_bo_fault_reserve_notify will re-set this if the CPU +		 * accesses the BO after it's moved. +		 */ +		abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; +	} +  	if (adev->mman.buffer_funcs_enabled) {  		if (((old_mem->mem_type == TTM_PL_SYSTEM &&  		      new_mem->mem_type == TTM_PL_VRAM) || @@ -545,15 +554,6 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,  			return r;  	} -	if (bo->type == ttm_bo_type_device && -	    new_mem->mem_type == TTM_PL_VRAM && -	    old_mem->mem_type != TTM_PL_VRAM) { -		/* amdgpu_bo_fault_reserve_notify will re-set this if the CPU -		 * accesses the BO after it's moved. -		 */ -		abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; -	} -  out:  	/* update statistics */  	atomic64_add(bo->base.size, &adev->num_bytes_moved); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 16a57b70cc1a..c2a4d920da40 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -468,6 +468,7 @@ static const struct kfd_device_info navi10_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 145,  	.num_sdma_engines = 2,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -487,6 +488,7 @@ static const struct kfd_device_info navi12_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 145,  	.num_sdma_engines = 2,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -506,6 +508,7 @@ static const struct kfd_device_info navi14_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 145,  	.num_sdma_engines = 2,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -525,6 +528,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 4,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -544,6 +548,7 @@ static const struct kfd_device_info navy_flounder_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 2,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -562,7 +567,8 @@ static const struct kfd_device_info vangogh_device_info = {  	.mqd_size_aligned = MQD_SIZE_ALIGNED,  	.needs_iommu_device = false,  	.supports_cwsr = true, -	.needs_pci_atomics = false, +	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 1,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 2, @@ -582,6 +588,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 2,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -601,6 +608,7 @@ static const struct kfd_device_info beige_goby_device_info = {  	.needs_iommu_device = false,  	.supports_cwsr = true,  	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 1,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 8, @@ -619,7 +627,8 @@ static const struct kfd_device_info yellow_carp_device_info = {  	.mqd_size_aligned = MQD_SIZE_ALIGNED,  	.needs_iommu_device = false,  	.supports_cwsr = true, -	.needs_pci_atomics = false, +	.needs_pci_atomics = true, +	.no_atomic_fw_version = 92,  	.num_sdma_engines = 1,  	.num_xgmi_sdma_engines = 0,  	.num_sdma_queues_per_engine = 2, @@ -708,20 +717,6 @@ struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd,  	if (!kfd)  		return NULL; -	/* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. -	 * 32 and 64-bit requests are possible and must be -	 * supported. -	 */ -	kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kgd); -	if (device_info->needs_pci_atomics && -	    !kfd->pci_atomic_requested) { -		dev_info(kfd_device, -			 "skipped device %x:%x, PCI rejects atomics\n", -			 pdev->vendor, pdev->device); -		kfree(kfd); -		return NULL; -	} -  	kfd->kgd = kgd;  	kfd->device_info = device_info;  	kfd->pdev = pdev; @@ -821,6 +816,23 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,  	kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd  			- kfd->vm_info.first_vmid_kfd + 1; +	/* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. +	 * 32 and 64-bit requests are possible and must be +	 * supported. +	 */ +	kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kfd->kgd); +	if (!kfd->pci_atomic_requested && +	    kfd->device_info->needs_pci_atomics && +	    (!kfd->device_info->no_atomic_fw_version || +	     kfd->mec_fw_version < kfd->device_info->no_atomic_fw_version)) { +		dev_info(kfd_device, +			 "skipped device %x:%x, PCI rejects atomics %d<%d\n", +			 kfd->pdev->vendor, kfd->pdev->device, +			 kfd->mec_fw_version, +			 kfd->device_info->no_atomic_fw_version); +		return false; +	} +  	/* Verify module parameters regarding mapped process number*/  	if ((hws_max_conc_proc < 0)  			|| (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) { @@ -959,7 +971,6 @@ out:  void kgd2kfd_device_exit(struct kfd_dev *kfd)  {  	if (kfd->init_complete) { -		svm_migrate_fini((struct amdgpu_device *)kfd->kgd);  		device_queue_manager_uninit(kfd->dqm);  		kfd_interrupt_exit(kfd);  		kfd_topology_remove_device(kfd); @@ -1057,17 +1068,21 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)  	return ret;  } -static int kfd_resume(struct kfd_dev *kfd) +int kgd2kfd_resume_iommu(struct kfd_dev *kfd)  {  	int err = 0;  	err = kfd_iommu_resume(kfd); -	if (err) { +	if (err)  		dev_err(kfd_device,  			"Failed to resume IOMMU for device %x:%x\n",  			kfd->pdev->vendor, kfd->pdev->device); -		return err; -	} +	return err; +} + +static int kfd_resume(struct kfd_dev *kfd) +{ +	int err = 0;  	err = kfd->dqm->ops.start(kfd->dqm);  	if (err) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index dab290a4d19d..4a16e3c257b9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -891,9 +891,16 @@ int svm_migrate_init(struct amdgpu_device *adev)  	pgmap->ops = &svm_migrate_pgmap_ops;  	pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev);  	pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE; + +	/* Device manager releases device-specific resources, memory region and +	 * pgmap when driver disconnects from device. +	 */  	r = devm_memremap_pages(adev->dev, pgmap);  	if (IS_ERR(r)) {  		pr_err("failed to register HMM device memory\n"); + +		/* Disable SVM support capability */ +		pgmap->type = 0;  		devm_release_mem_region(adev->dev, res->start,  					res->end - res->start + 1);  		return PTR_ERR(r); @@ -908,12 +915,3 @@ int svm_migrate_init(struct amdgpu_device *adev)  	return 0;  } - -void svm_migrate_fini(struct amdgpu_device *adev) -{ -	struct dev_pagemap *pgmap = &adev->kfd.dev->pgmap; - -	devm_memunmap_pages(adev->dev, pgmap); -	devm_release_mem_region(adev->dev, pgmap->range.start, -				pgmap->range.end - pgmap->range.start + 1); -} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h index 0de76b5d4973..2f5b3394c9ed 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h @@ -47,7 +47,6 @@ unsigned long  svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr);  int svm_migrate_init(struct amdgpu_device *adev); -void svm_migrate_fini(struct amdgpu_device *adev);  #else @@ -55,10 +54,6 @@ static inline int svm_migrate_init(struct amdgpu_device *adev)  {  	return 0;  } -static inline void svm_migrate_fini(struct amdgpu_device *adev) -{ -	/* empty */ -}  #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index ab83b0de6b22..6d8f9bb2d905 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -207,6 +207,7 @@ struct kfd_device_info {  	bool supports_cwsr;  	bool needs_iommu_device;  	bool needs_pci_atomics; +	uint32_t no_atomic_fw_version;  	unsigned int num_sdma_engines;  	unsigned int num_xgmi_sdma_engines;  	unsigned int num_sdma_queues_per_engine; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 9fc8021bb0ab..9d0f65a90002 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -118,6 +118,13 @@ static void svm_range_remove_notifier(struct svm_range *prange)  		mmu_interval_notifier_remove(&prange->notifier);  } +static bool +svm_is_valid_dma_mapping_addr(struct device *dev, dma_addr_t dma_addr) +{ +	return dma_addr && !dma_mapping_error(dev, dma_addr) && +	       !(dma_addr & SVM_RANGE_VRAM_DOMAIN); +} +  static int  svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,  		      unsigned long offset, unsigned long npages, @@ -139,8 +146,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,  	addr += offset;  	for (i = 0; i < npages; i++) { -		if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), -			      "leaking dma mapping\n")) +		if (svm_is_valid_dma_mapping_addr(dev, addr[i]))  			dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);  		page = hmm_pfn_to_page(hmm_pfns[i]); @@ -209,7 +215,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,  		return;  	for (i = offset; i < offset + npages; i++) { -		if (!dma_addr[i] || dma_mapping_error(dev, dma_addr[i])) +		if (!svm_is_valid_dma_mapping_addr(dev, dma_addr[i]))  			continue;  		pr_debug("dma unmapping 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);  		dma_unmap_page(dev, dma_addr[i], PAGE_SIZE, dir); @@ -1165,7 +1171,7 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	unsigned long last_start;  	int last_domain;  	int r = 0; -	int64_t i; +	int64_t i, j;  	last_start = prange->start + offset; @@ -1178,7 +1184,11 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	for (i = offset; i < offset + npages; i++) {  		last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN;  		dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; -		if ((prange->start + i) < prange->last && + +		/* Collect all pages in the same address range and memory domain +		 * that can be mapped with a single call to update mapping. +		 */ +		if (i < offset + npages - 1 &&  		    last_domain == (dma_addr[i + 1] & SVM_RANGE_VRAM_DOMAIN))  			continue; @@ -1201,6 +1211,10 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,  						NULL, dma_addr,  						&vm->last_update,  						&table_freed); + +		for (j = last_start - prange->start; j <= i; j++) +			dma_addr[j] |= last_domain; +  		if (r) {  			pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start);  			goto out; 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 9b1fc54555ee..66c799f5c7cf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -998,6 +998,8 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_  	uint32_t agp_base, agp_bot, agp_top;  	PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base; +	memset(pa_config, 0, sizeof(*pa_config)); +  	logical_addr_low  = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18;  	pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); @@ -6024,21 +6026,23 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)  		return 0;  #if defined(CONFIG_DRM_AMD_DC_DCN) -	work = kzalloc(sizeof(*work), GFP_ATOMIC); -	if (!work) -		return -ENOMEM; +	if (dm->vblank_control_workqueue) { +		work = kzalloc(sizeof(*work), GFP_ATOMIC); +		if (!work) +			return -ENOMEM; -	INIT_WORK(&work->work, vblank_control_worker); -	work->dm = dm; -	work->acrtc = acrtc; -	work->enable = enable; +		INIT_WORK(&work->work, vblank_control_worker); +		work->dm = dm; +		work->acrtc = acrtc; +		work->enable = enable; -	if (acrtc_state->stream) { -		dc_stream_retain(acrtc_state->stream); -		work->stream = acrtc_state->stream; -	} +		if (acrtc_state->stream) { +			dc_stream_retain(acrtc_state->stream); +			work->stream = acrtc_state->stream; +		} -	queue_work(dm->vblank_control_workqueue, &work->work); +		queue_work(dm->vblank_control_workqueue, &work->work); +	}  #endif  	return 0; @@ -6792,14 +6796,15 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = {  #if defined(CONFIG_DRM_AMD_DC_DCN)  static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, -					    struct dc_state *dc_state) +					    struct dc_state *dc_state, +					    struct dsc_mst_fairness_vars *vars)  {  	struct dc_stream_state *stream = NULL;  	struct drm_connector *connector;  	struct drm_connector_state *new_con_state;  	struct amdgpu_dm_connector *aconnector;  	struct dm_connector_state *dm_conn_state; -	int i, j, clock, bpp; +	int i, j, clock;  	int vcpi, pbn_div, pbn = 0;  	for_each_new_connector_in_state(state, connector, new_con_state, i) { @@ -6838,9 +6843,15 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state,  		}  		pbn_div = dm_mst_get_pbn_divider(stream->link); -		bpp = stream->timing.dsc_cfg.bits_per_pixel;  		clock = stream->timing.pix_clk_100hz / 10; -		pbn = drm_dp_calc_pbn_mode(clock, bpp, true); +		/* pbn is calculated by compute_mst_dsc_configs_for_state*/ +		for (j = 0; j < dc_state->stream_count; j++) { +			if (vars[j].aconnector == aconnector) { +				pbn = vars[j].pbn; +				break; +			} +		} +  		vcpi = drm_dp_mst_atomic_enable_dsc(state,  						    aconnector->port,  						    pbn, pbn_div, @@ -7519,6 +7530,32 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,  	}  } +static void amdgpu_set_panel_orientation(struct drm_connector *connector) +{ +	struct drm_encoder *encoder; +	struct amdgpu_encoder *amdgpu_encoder; +	const struct drm_display_mode *native_mode; + +	if (connector->connector_type != DRM_MODE_CONNECTOR_eDP && +	    connector->connector_type != DRM_MODE_CONNECTOR_LVDS) +		return; + +	encoder = amdgpu_dm_connector_to_encoder(connector); +	if (!encoder) +		return; + +	amdgpu_encoder = to_amdgpu_encoder(encoder); + +	native_mode = &amdgpu_encoder->native_mode; +	if (native_mode->hdisplay == 0 || native_mode->vdisplay == 0) +		return; + +	drm_connector_set_panel_orientation_with_quirk(connector, +						       DRM_MODE_PANEL_ORIENTATION_UNKNOWN, +						       native_mode->hdisplay, +						       native_mode->vdisplay); +} +  static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,  					      struct edid *edid)  { @@ -7547,6 +7584,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,  		 * restored here.  		 */  		amdgpu_dm_update_freesync_caps(connector, edid); + +		amdgpu_set_panel_orientation(connector);  	} else {  		amdgpu_dm_connector->num_modes = 0;  	} @@ -8058,8 +8097,26 @@ static bool is_content_protection_different(struct drm_connector_state *state,  	    state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED)  		state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; -	/* Check if something is connected/enabled, otherwise we start hdcp but nothing is connected/enabled -	 * hot-plug, headless s3, dpms +	/* Stream removed and re-enabled +	 * +	 * Can sometimes overlap with the HPD case, +	 * thus set update_hdcp to false to avoid +	 * setting HDCP multiple times. +	 * +	 * Handles:	DESIRED -> DESIRED (Special case) +	 */ +	if (!(old_state->crtc && old_state->crtc->enabled) && +		state->crtc && state->crtc->enabled && +		connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) { +		dm_con_state->update_hdcp = false; +		return true; +	} + +	/* Hot-plug, headless s3, dpms +	 * +	 * Only start HDCP if the display is connected/enabled. +	 * update_hdcp flag will be set to false until the next +	 * HPD comes in.  	 *  	 * Handles:	DESIRED -> DESIRED (Special case)  	 */ @@ -8648,7 +8705,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,  		 * If PSR or idle optimizations are enabled then flush out  		 * any pending work before hardware programming.  		 */ -		flush_workqueue(dm->vblank_control_workqueue); +		if (dm->vblank_control_workqueue) +			flush_workqueue(dm->vblank_control_workqueue);  #endif  		bundle->stream_update.stream = acrtc_state->stream; @@ -8983,7 +9041,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)  		/* if there mode set or reset, disable eDP PSR */  		if (mode_set_reset_required) {  #if defined(CONFIG_DRM_AMD_DC_DCN) -			flush_workqueue(dm->vblank_control_workqueue); +			if (dm->vblank_control_workqueue) +				flush_workqueue(dm->vblank_control_workqueue);  #endif  			amdgpu_dm_psr_disable_all(dm);  		} @@ -10243,6 +10302,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  	int ret, i;  	bool lock_and_validation_needed = false;  	struct dm_crtc_state *dm_old_crtc_state; +#if defined(CONFIG_DRM_AMD_DC_DCN) +	struct dsc_mst_fairness_vars vars[MAX_PIPES]; +#endif  	trace_amdgpu_dm_atomic_check_begin(state); @@ -10473,10 +10535,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  			goto fail;  #if defined(CONFIG_DRM_AMD_DC_DCN) -		if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) +		if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars))  			goto fail; -		ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context); +		ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars);  		if (ret)  			goto fail;  #endif @@ -10492,7 +10554,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  			goto fail;  		status = dc_validate_global_state(dc, dm_state->context, false);  		if (status != DC_OK) { -			DC_LOG_WARNING("DC global validation failure: %s (%d)", +			drm_dbg_atomic(dev, +				       "DC global validation failure: %s (%d)",  				       dc_status_to_str(status), status);  			ret = -EINVAL;  			goto fail; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 1bcba6943fd7..7af0d58c231b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -518,12 +518,7 @@ struct dsc_mst_fairness_params {  	uint32_t num_slices_h;  	uint32_t num_slices_v;  	uint32_t bpp_overwrite; -}; - -struct dsc_mst_fairness_vars { -	int pbn; -	bool dsc_enabled; -	int bpp_x16; +	struct amdgpu_dm_connector *aconnector;  };  static int kbps_to_peak_pbn(int kbps) @@ -750,12 +745,12 @@ static void try_disable_dsc(struct drm_atomic_state *state,  static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  					     struct dc_state *dc_state, -					     struct dc_link *dc_link) +					     struct dc_link *dc_link, +					     struct dsc_mst_fairness_vars *vars)  {  	int i;  	struct dc_stream_state *stream;  	struct dsc_mst_fairness_params params[MAX_PIPES]; -	struct dsc_mst_fairness_vars vars[MAX_PIPES];  	struct amdgpu_dm_connector *aconnector;  	int count = 0;  	bool debugfs_overwrite = false; @@ -776,6 +771,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  		params[count].timing = &stream->timing;  		params[count].sink = stream->sink;  		aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; +		params[count].aconnector = aconnector;  		params[count].port = aconnector->port;  		params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable;  		if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) @@ -798,6 +794,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  	}  	/* Try no compression */  	for (i = 0; i < count; i++) { +		vars[i].aconnector = params[i].aconnector;  		vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);  		vars[i].dsc_enabled = false;  		vars[i].bpp_x16 = 0; @@ -851,7 +848,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  }  bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, -				       struct dc_state *dc_state) +				       struct dc_state *dc_state, +				       struct dsc_mst_fairness_vars *vars)  {  	int i, j;  	struct dc_stream_state *stream; @@ -882,7 +880,7 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,  			return false;  		mutex_lock(&aconnector->mst_mgr.lock); -		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link)) { +		if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars)) {  			mutex_unlock(&aconnector->mst_mgr.lock);  			return false;  		} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index b38bd68121ce..900d3f7a8498 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -39,8 +39,17 @@ void  dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);  #if defined(CONFIG_DRM_AMD_DC_DCN) + +struct dsc_mst_fairness_vars { +	int pbn; +	bool dsc_enabled; +	int bpp_x16; +	struct amdgpu_dm_connector *aconnector; +}; +  bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, -				       struct dc_state *dc_state); +				       struct dc_state *dc_state, +				       struct dsc_mst_fairness_vars *vars);  #endif  #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c index c9f47d167472..b1bf80da3a55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -62,7 +62,7 @@ inline void dc_assert_fp_enabled(void)  	depth = *pcpu;  	put_cpu_ptr(&fpu_recursion_depth); -	ASSERT(depth > 1); +	ASSERT(depth >= 1);  }  /** diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8bd7f42a8053..1e44b13c1c7d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2586,13 +2586,21 @@ static struct abm *get_abm_from_stream_res(const struct dc_link *link)  int dc_link_get_backlight_level(const struct dc_link *link)  { -  	struct abm *abm = get_abm_from_stream_res(link); +	struct panel_cntl *panel_cntl = link->panel_cntl; +	struct dc  *dc = link->ctx->dc; +	struct dmcu *dmcu = dc->res_pool->dmcu; +	bool fw_set_brightness = true; -	if (abm == NULL || abm->funcs->get_current_backlight == NULL) -		return DC_ERROR_UNEXPECTED; +	if (dmcu) +		fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); -	return (int) abm->funcs->get_current_backlight(abm); +	if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight) +		return panel_cntl->funcs->get_current_backlight(panel_cntl); +	else if (abm != NULL && abm->funcs->get_current_backlight != NULL) +		return (int) abm->funcs->get_current_backlight(abm); +	else +		return DC_ERROR_UNEXPECTED;  }  int dc_link_get_target_backlight_pwm(const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 330edd666b7d..f6dbc5a74757 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1,4 +1,26 @@ -/* Copyright 2015 Advanced Micro Devices, Inc. */ +/* + * Copyright 2015 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */  #include "dm_services.h"  #include "dc.h"  #include "dc_link_dp.h" @@ -1840,9 +1862,13 @@ bool perform_link_training_with_retries(  		dp_disable_link_phy(link, signal);  		/* Abort link training if failure due to sink being unplugged. */ -		if (status == LINK_TRAINING_ABORT) -			break; -		else if (do_fallback) { +		if (status == LINK_TRAINING_ABORT) { +			enum dc_connection_type type = dc_connection_none; + +			dc_link_detect_sink(link, &type); +			if (type == dc_connection_none) +				break; +		} else if (do_fallback) {  			decide_fallback_link_setting(*link_setting, ¤t_setting, status);  			/* Fail link training if reduced link bandwidth no longer meets  			 * stream requirements. diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index e14f99b4b0c3..3c3347341103 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -42,7 +42,7 @@  #define DC_LOGGER \  	engine->ctx->logger -#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ +#define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)  #define IS_DC_I2CAUX_LOGGING_ENABLED() (false)  #define LOG_FLAG_Error_I2cAux LOG_ERROR  #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX @@ -76,7 +76,7 @@ enum {  #define DEFAULT_AUX_ENGINE_MULT   0  #define DEFAULT_AUX_ENGINE_LENGTH 69 -#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ +#define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)  static void release_engine(  	struct dce_aux *engine) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index e92339235863..e8570060d007 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -49,7 +49,6 @@  static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl)  {  	uint64_t current_backlight; -	uint32_t round_result;  	uint32_t bl_period, bl_int_count;  	uint32_t bl_pwm, fractional_duty_cycle_en;  	uint32_t bl_period_mask, bl_pwm_mask; @@ -84,15 +83,6 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_c  	current_backlight = div_u64(current_backlight, bl_period);  	current_backlight = (current_backlight + 1) >> 1; -	current_backlight = (uint64_t)(current_backlight) * bl_period; - -	round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); - -	round_result = (round_result >> (bl_int_count-1)) & 1; - -	current_backlight >>= bl_int_count; -	current_backlight += round_result; -  	return (uint32_t)(current_backlight);  } diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h index 8a08ecc34c69..4884a4e1f261 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h @@ -33,63 +33,47 @@  #define TABLE_PMSTATUSLOG        3 // Called by Tools for Agm logging  #define TABLE_DPMCLOCKS          4 // Called by Driver; defined here, but not used, for backward compatible  #define TABLE_MOMENTARY_PM       5 // Called by Tools; defined here, but not used, for backward compatible -#define TABLE_COUNT              6 +#define TABLE_SMU_METRICS        6 // Called by Driver +#define TABLE_COUNT              7 -#define NUM_DSPCLK_LEVELS		8 -#define NUM_SOCCLK_DPM_LEVELS	8 -#define NUM_DCEFCLK_DPM_LEVELS	4 -#define NUM_FCLK_DPM_LEVELS		4 -#define NUM_MEMCLK_DPM_LEVELS	4 +typedef struct SmuMetricsTable_t { +	//CPU status +	uint16_t CoreFrequency[6];              //[MHz] +	uint32_t CorePower[6];                  //[mW] +	uint16_t CoreTemperature[6];            //[centi-Celsius] +	uint16_t L3Frequency[2];                //[MHz] +	uint16_t L3Temperature[2];              //[centi-Celsius] +	uint16_t C0Residency[6];                //Percentage -#define NUMBER_OF_PSTATES		8 -#define NUMBER_OF_CORES			8 +	// GFX status +	uint16_t GfxclkFrequency;               //[MHz] +	uint16_t GfxTemperature;                //[centi-Celsius] -typedef enum { -	S3_TYPE_ENTRY, -	S5_TYPE_ENTRY, -} Sleep_Type_e; +	// SOC IP info +	uint16_t SocclkFrequency;               //[MHz] +	uint16_t VclkFrequency;                 //[MHz] +	uint16_t DclkFrequency;                 //[MHz] +	uint16_t MemclkFrequency;               //[MHz] -typedef enum { -	GFX_OFF = 0, -	GFX_ON  = 1, -} GFX_Mode_e; +	// power, VF info for CPU/GFX telemetry rails, and then socket power total +	uint32_t Voltage[2];                    //[mV] indices: VDDCR_VDD, VDDCR_GFX +	uint32_t Current[2];                    //[mA] indices: VDDCR_VDD, VDDCR_GFX +	uint32_t Power[2];                      //[mW] indices: VDDCR_VDD, VDDCR_GFX +	uint32_t CurrentSocketPower;            //[mW] -typedef enum { -	CPU_P0 = 0, -	CPU_P1, -	CPU_P2, -	CPU_P3, -	CPU_P4, -	CPU_P5, -	CPU_P6, -	CPU_P7 -} CPU_PState_e; +	uint16_t SocTemperature;                //[centi-Celsius] +	uint16_t EdgeTemperature; +	uint16_t ThrottlerStatus; +	uint16_t Spare; -typedef enum { -	CPU_CORE0 = 0, -	CPU_CORE1, -	CPU_CORE2, -	CPU_CORE3, -	CPU_CORE4, -	CPU_CORE5, -	CPU_CORE6, -	CPU_CORE7 -} CORE_ID_e; +} SmuMetricsTable_t; -typedef enum { -	DF_DPM0 = 0, -	DF_DPM1, -	DF_DPM2, -	DF_DPM3, -	DF_PState_Count -} DF_PState_e; - -typedef enum { -	GFX_DPM0 = 0, -	GFX_DPM1, -	GFX_DPM2, -	GFX_DPM3, -	GFX_PState_Count -} GFX_PState_e; +typedef struct SmuMetrics_t { +	SmuMetricsTable_t Current; +	SmuMetricsTable_t Average; +	uint32_t SampleStartTime; +	uint32_t SampleStopTime; +	uint32_t Accnt; +} SmuMetrics_t;  #endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h index 6f1b1b50d527..18b862a90fbe 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h @@ -226,7 +226,10 @@  	__SMU_DUMMY_MAP(SetUclkDpmMode),		\  	__SMU_DUMMY_MAP(LightSBR),			\  	__SMU_DUMMY_MAP(GfxDriverResetRecovery),	\ -	__SMU_DUMMY_MAP(BoardPowerCalibration), +	__SMU_DUMMY_MAP(BoardPowerCalibration),   \ +	__SMU_DUMMY_MAP(RequestGfxclk),           \ +	__SMU_DUMMY_MAP(ForceGfxVid),             \ +	__SMU_DUMMY_MAP(UnforceGfxVid),  #undef __SMU_DUMMY_MAP  #define __SMU_DUMMY_MAP(type)	SMU_MSG_##type diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h index 6e6088760b18..909a86aa60f3 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h @@ -65,6 +65,13 @@  #define PPSMC_MSG_SetDriverTableVMID                    0x34  #define PPSMC_MSG_SetSoftMinCclk                        0x35  #define PPSMC_MSG_SetSoftMaxCclk                        0x36 -#define PPSMC_Message_Count                             0x37 +#define PPSMC_MSG_GetGfxFrequency                       0x37 +#define PPSMC_MSG_GetGfxVid                             0x38 +#define PPSMC_MSG_ForceGfxFreq                          0x39 +#define PPSMC_MSG_UnForceGfxFreq                        0x3A +#define PPSMC_MSG_ForceGfxVid                           0x3B +#define PPSMC_MSG_UnforceGfxVid                         0x3C +#define PPSMC_MSG_GetEnabledSmuFeatures                 0x3D +#define PPSMC_Message_Count                             0x3E  #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index bdbbeb959c68..81f82aa05ec2 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -6867,6 +6867,8 @@ static int si_dpm_enable(struct amdgpu_device *adev)  	si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true);  	si_thermal_start_thermal_controller(adev); +	ni_update_current_ps(adev, boot_ps); +  	return 0;  } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3ab1ce4d3419..04863a797115 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1404,7 +1404,7 @@ static int smu_disable_dpms(struct smu_context *smu)  	 */  	if (smu->uploading_custom_pp_table &&  	    (adev->asic_type >= CHIP_NAVI10) && -	    (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) +	    (adev->asic_type <= CHIP_BEIGE_GOBY))  		return smu_disable_all_features_with_exception(smu,  							       true,  							       SMU_FEATURE_COUNT); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index e343cc218990..082f01893f3d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -771,8 +771,12 @@ static int arcturus_print_clk_levels(struct smu_context *smu,  	struct smu_11_0_dpm_context *dpm_context = NULL;  	uint32_t gen_speed, lane_width; -	if (amdgpu_ras_intr_triggered()) -		return sysfs_emit(buf, "unavailable\n"); +	smu_cmn_get_sysfs_buf(&buf, &size); + +	if (amdgpu_ras_intr_triggered()) { +		size += sysfs_emit_at(buf, size, "unavailable\n"); +		return size; +	}  	dpm_context = smu_dpm->dpm_context; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index b05f9541accc..3d4c65bc29dc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -44,6 +44,27 @@  #undef pr_info  #undef pr_debug +/* unit: MHz */ +#define CYAN_SKILLFISH_SCLK_MIN			1000 +#define CYAN_SKILLFISH_SCLK_MAX			2000 +#define CYAN_SKILLFISH_SCLK_DEFAULT			1800 + +/* unit: mV */ +#define CYAN_SKILLFISH_VDDC_MIN			700 +#define CYAN_SKILLFISH_VDDC_MAX			1129 +#define CYAN_SKILLFISH_VDDC_MAGIC			5118 // 0x13fe + +static struct gfx_user_settings { +	uint32_t sclk; +	uint32_t vddc; +} cyan_skillfish_user_settings; + +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ +	FEATURE_MASK(FEATURE_FCLK_DPM_BIT)	|	\ +	FEATURE_MASK(FEATURE_SOC_DPM_BIT)	|	\ +	FEATURE_MASK(FEATURE_GFX_DPM_BIT)) +  static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {  	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,			0),  	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,		0), @@ -52,14 +73,473 @@ static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT]  	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverTableDramAddrLow,	0),  	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,	0),  	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,	0), +	MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,	0), +	MSG_MAP(RequestGfxclk,                  PPSMC_MSG_RequestGfxclk,		0), +	MSG_MAP(ForceGfxVid,                    PPSMC_MSG_ForceGfxVid,			0), +	MSG_MAP(UnforceGfxVid,                  PPSMC_MSG_UnforceGfxVid,		0), +}; + +static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { +	TAB_MAP_VALID(SMU_METRICS),  }; +static int cyan_skillfish_tables_init(struct smu_context *smu) +{ +	struct smu_table_context *smu_table = &smu->smu_table; +	struct smu_table *tables = smu_table->tables; + +	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, +				sizeof(SmuMetrics_t), +				PAGE_SIZE, +				AMDGPU_GEM_DOMAIN_VRAM); + +	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); +	if (!smu_table->metrics_table) +		goto err0_out; + +	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); +	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); +	if (!smu_table->gpu_metrics_table) +		goto err1_out; + +	smu_table->metrics_time = 0; + +	return 0; + +err1_out: +	smu_table->gpu_metrics_table_size = 0; +	kfree(smu_table->metrics_table); +err0_out: +	return -ENOMEM; +} + +static int cyan_skillfish_init_smc_tables(struct smu_context *smu) +{ +	int ret = 0; + +	ret = cyan_skillfish_tables_init(smu); +	if (ret) +		return ret; + +	return smu_v11_0_init_smc_tables(smu); +} + +static int cyan_skillfish_finit_smc_tables(struct smu_context *smu) +{ +	struct smu_table_context *smu_table = &smu->smu_table; + +	kfree(smu_table->metrics_table); +	smu_table->metrics_table = NULL; + +	kfree(smu_table->gpu_metrics_table); +	smu_table->gpu_metrics_table = NULL; +	smu_table->gpu_metrics_table_size = 0; + +	smu_table->metrics_time = 0; + +	return 0; +} + +static int +cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, +					MetricsMember_t member, +					uint32_t *value) +{ +	struct smu_table_context *smu_table = &smu->smu_table; +	SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; +	int ret = 0; + +	mutex_lock(&smu->metrics_lock); + +	ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); +	if (ret) { +		mutex_unlock(&smu->metrics_lock); +		return ret; +	} + +	switch (member) { +	case METRICS_CURR_GFXCLK: +		*value = metrics->Current.GfxclkFrequency; +		break; +	case METRICS_CURR_SOCCLK: +		*value = metrics->Current.SocclkFrequency; +		break; +	case METRICS_CURR_VCLK: +		*value = metrics->Current.VclkFrequency; +		break; +	case METRICS_CURR_DCLK: +		*value = metrics->Current.DclkFrequency; +		break; +	case METRICS_CURR_UCLK: +		*value = metrics->Current.MemclkFrequency; +		break; +	case METRICS_AVERAGE_SOCKETPOWER: +		*value = (metrics->Current.CurrentSocketPower << 8) / +				1000; +		break; +	case METRICS_TEMPERATURE_EDGE: +		*value = metrics->Current.GfxTemperature / 100 * +				SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; +		break; +	case METRICS_TEMPERATURE_HOTSPOT: +		*value = metrics->Current.SocTemperature / 100 * +				SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; +		break; +	case METRICS_VOLTAGE_VDDSOC: +		*value = metrics->Current.Voltage[0]; +		break; +	case METRICS_VOLTAGE_VDDGFX: +		*value = metrics->Current.Voltage[1]; +		break; +	case METRICS_THROTTLER_STATUS: +		*value = metrics->Current.ThrottlerStatus; +		break; +	default: +		*value = UINT_MAX; +		break; +	} + +	mutex_unlock(&smu->metrics_lock); + +	return ret; +} + +static int cyan_skillfish_read_sensor(struct smu_context *smu, +					enum amd_pp_sensors sensor, +					void *data, +					uint32_t *size) +{ +	int ret = 0; + +	if (!data || !size) +		return -EINVAL; + +	mutex_lock(&smu->sensor_lock); + +	switch (sensor) { +	case AMDGPU_PP_SENSOR_GFX_SCLK: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_CURR_GFXCLK, +						   (uint32_t *)data); +		*(uint32_t *)data *= 100; +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_GFX_MCLK: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_CURR_UCLK, +						   (uint32_t *)data); +		*(uint32_t *)data *= 100; +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_GPU_POWER: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_AVERAGE_SOCKETPOWER, +						   (uint32_t *)data); +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_TEMPERATURE_HOTSPOT, +						   (uint32_t *)data); +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_EDGE_TEMP: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_TEMPERATURE_EDGE, +						   (uint32_t *)data); +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_VDDNB: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_VOLTAGE_VDDSOC, +						   (uint32_t *)data); +		*size = 4; +		break; +	case AMDGPU_PP_SENSOR_VDDGFX: +		ret = cyan_skillfish_get_smu_metrics_data(smu, +						   METRICS_VOLTAGE_VDDGFX, +						   (uint32_t *)data); +		*size = 4; +		break; +	default: +		ret = -EOPNOTSUPP; +		break; +	} + +	mutex_unlock(&smu->sensor_lock); + +	return ret; +} + +static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, +						enum smu_clk_type clk_type, +						uint32_t *value) +{ +	MetricsMember_t member_type; + +	switch (clk_type) { +	case SMU_GFXCLK: +	case SMU_SCLK: +		member_type = METRICS_CURR_GFXCLK; +		break; +	case SMU_FCLK: +	case SMU_MCLK: +		member_type = METRICS_CURR_UCLK; +		break; +	case SMU_SOCCLK: +		member_type = METRICS_CURR_SOCCLK; +		break; +	case SMU_VCLK: +		member_type = METRICS_CURR_VCLK; +		break; +	case SMU_DCLK: +		member_type = METRICS_CURR_DCLK; +		break; +	default: +		return -EINVAL; +	} + +	return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); +} + +static int cyan_skillfish_print_clk_levels(struct smu_context *smu, +					enum smu_clk_type clk_type, +					char *buf) +{ +	int ret = 0, size = 0; +	uint32_t cur_value = 0; + +	smu_cmn_get_sysfs_buf(&buf, &size); + +	switch (clk_type) { +	case SMU_OD_SCLK: +		ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); +		if (ret) +			return ret; +		size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); +		size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); +		break; +	case SMU_OD_VDDC_CURVE: +		ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); +		if (ret) +			return ret; +		size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); +		size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); +		break; +	case SMU_OD_RANGE: +		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); +		size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", +						CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); +		size += sysfs_emit_at(buf, size, "VDDC: %7umV  %10umV\n", +						CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); +		break; +	case SMU_GFXCLK: +	case SMU_SCLK: +	case SMU_FCLK: +	case SMU_MCLK: +	case SMU_SOCCLK: +	case SMU_VCLK: +	case SMU_DCLK: +		ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); +		if (ret) +			return ret; +		size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); +		break; +	default: +		dev_warn(smu->adev->dev, "Unsupported clock type\n"); +		return ret; +	} + +	return size; +} + +static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) +{ +	struct amdgpu_device *adev = smu->adev; +	int ret = 0; +	uint32_t feature_mask[2]; +	uint64_t feature_enabled; + +	/* we need to re-init after suspend so return false */ +	if (adev->in_suspend) +		return false; + +	ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + +	if (ret) +		return false; + +	feature_enabled = (uint64_t)feature_mask[0] | +				((uint64_t)feature_mask[1] << 32); + +	return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, +						void **table) +{ +	struct smu_table_context *smu_table = &smu->smu_table; +	struct gpu_metrics_v2_2 *gpu_metrics = +		(struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; +	SmuMetrics_t metrics; +	int i, ret = 0; + +	ret = smu_cmn_get_metrics_table(smu, &metrics, true); +	if (ret) +		return ret; + +	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); + +	gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; +	gpu_metrics->temperature_soc = metrics.Current.SocTemperature; + +	gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; +	gpu_metrics->average_soc_power = metrics.Current.Power[0]; +	gpu_metrics->average_gfx_power = metrics.Current.Power[1]; + +	gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; +	gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; +	gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; +	gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; +	gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; +	gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; + +	gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; +	gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; +	gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; +	gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; +	gpu_metrics->current_vclk = metrics.Current.VclkFrequency; +	gpu_metrics->current_dclk = metrics.Current.DclkFrequency; + +	for (i = 0; i < 6; i++) { +		gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; +		gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; +		gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; +	} + +	for (i = 0; i < 2; i++) { +		gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; +		gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; +	} + +	gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; +	gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); + +	*table = (void *)gpu_metrics; + +	return sizeof(struct gpu_metrics_v2_2); +} + +static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, +					enum PP_OD_DPM_TABLE_COMMAND type, +					long input[], uint32_t size) +{ +	int ret = 0; +	uint32_t vid; + +	switch (type) { +	case PP_OD_EDIT_VDDC_CURVE: +		if (size != 3 || input[0] != 0) { +			dev_err(smu->adev->dev, "Invalid parameter!\n"); +			return -EINVAL; +		} + +		if (input[1] <= CYAN_SKILLFISH_SCLK_MIN || +			input[1] > CYAN_SKILLFISH_SCLK_MAX) { +			dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", +					CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); +			return -EINVAL; +		} + +		if (input[2] <= CYAN_SKILLFISH_VDDC_MIN || +			input[2] > CYAN_SKILLFISH_VDDC_MAX) { +			dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", +					CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); +			return -EINVAL; +		} + +		cyan_skillfish_user_settings.sclk = input[1]; +		cyan_skillfish_user_settings.vddc = input[2]; + +		break; +	case PP_OD_RESTORE_DEFAULT_TABLE: +		if (size != 0) { +			dev_err(smu->adev->dev, "Invalid parameter!\n"); +			return -EINVAL; +		} + +		cyan_skillfish_user_settings.sclk = CYAN_SKILLFISH_SCLK_DEFAULT; +		cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; + +		break; +	case PP_OD_COMMIT_DPM_TABLE: +		if (size != 0) { +			dev_err(smu->adev->dev, "Invalid parameter!\n"); +			return -EINVAL; +		} + +		if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || +		    cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { +			dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", +					CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); +			return -EINVAL; +		} + +		if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && +			(cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || +			cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { +			dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", +					CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); +			return -EINVAL; +		} + +		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, +					cyan_skillfish_user_settings.sclk, NULL); +		if (ret) { +			dev_err(smu->adev->dev, "Set sclk failed!\n"); +			return ret; +		} + +		if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { +			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); +			if (ret) { +				dev_err(smu->adev->dev, "Unforce vddc failed!\n"); +				return ret; +			} +		} else { +			/* +			 * PMFW accepts SVI2 VID code, convert voltage to VID: +			 * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) +			 */ +			vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; +			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); +			if (ret) { +				dev_err(smu->adev->dev, "Force vddc failed!\n"); +				return ret; +			} +		} + +		break; +	default: +		return -EOPNOTSUPP; +	} + +	return ret; +} +  static const struct pptable_funcs cyan_skillfish_ppt_funcs = {  	.check_fw_status = smu_v11_0_check_fw_status,  	.check_fw_version = smu_v11_0_check_fw_version,  	.init_power = smu_v11_0_init_power,  	.fini_power = smu_v11_0_fini_power, +	.init_smc_tables = cyan_skillfish_init_smc_tables, +	.fini_smc_tables = cyan_skillfish_finit_smc_tables, +	.read_sensor = cyan_skillfish_read_sensor, +	.print_clk_levels = cyan_skillfish_print_clk_levels, +	.is_dpm_running = cyan_skillfish_is_dpm_running, +	.get_gpu_metrics = cyan_skillfish_get_gpu_metrics, +	.od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table,  	.register_irq_handler = smu_v11_0_register_irq_handler,  	.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,  	.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, @@ -72,5 +552,6 @@ void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)  {  	smu->ppt_funcs = &cyan_skillfish_ppt_funcs;  	smu->message_map = cyan_skillfish_message_map; +	smu->table_map = cyan_skillfish_table_map;  	smu->is_apu = true;  } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index a5fc5d7cb6c7..b1ad451af06b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1279,6 +1279,8 @@ static int navi10_print_clk_levels(struct smu_context *smu,  	struct smu_11_0_overdrive_table *od_settings = smu->od_settings;  	uint32_t min_value, max_value; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_GFXCLK:  	case SMU_SCLK: @@ -1392,7 +1394,7 @@ static int navi10_print_clk_levels(struct smu_context *smu,  	case SMU_OD_RANGE:  		if (!smu->od_enabled || !od_table || !od_settings)  			break; -		size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");  		if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) {  			navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, @@ -2272,7 +2274,27 @@ static int navi10_baco_enter(struct smu_context *smu)  {  	struct amdgpu_device *adev = smu->adev; -	if (adev->in_runpm) +	/* +	 * This aims the case below: +	 *   amdgpu driver loaded -> runpm suspend kicked -> sound driver loaded +	 * +	 * For NAVI10 and later ASICs, we rely on PMFW to handle the runpm. To +	 * make that possible, PMFW needs to acknowledge the dstate transition +	 * process for both gfx(function 0) and audio(function 1) function of +	 * the ASIC. +	 * +	 * The PCI device's initial runpm status is RUNPM_SUSPENDED. So as the +	 * device representing the audio function of the ASIC. And that means +	 * even if the sound driver(snd_hda_intel) was not loaded yet, it's still +	 * possible runpm suspend kicked on the ASIC. However without the dstate +	 * transition notification from audio function, pmfw cannot handle the +	 * BACO in/exit correctly. And that will cause driver hang on runpm +	 * resuming. +	 * +	 * To address this, we revert to legacy message way(driver masters the +	 * timing for BACO in/exit) on sound driver missing. +	 */ +	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev))  		return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO);  	else  		return smu_v11_0_baco_enter(smu); @@ -2282,7 +2304,7 @@ static int navi10_baco_exit(struct smu_context *smu)  {  	struct amdgpu_device *adev = smu->adev; -	if (adev->in_runpm) { +	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {  		/* Wait for PMFW handling for the Dstate change */  		msleep(10);  		return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 5e292c3f5050..ca57221e3962 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1058,6 +1058,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,  	uint32_t min_value, max_value;  	uint32_t smu_version; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_GFXCLK:  	case SMU_SCLK: @@ -1180,7 +1182,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu,  		if (!smu->od_enabled || !od_table || !od_settings)  			break; -		size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");  		if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) {  			sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMIN, @@ -2187,7 +2189,7 @@ static int sienna_cichlid_baco_enter(struct smu_context *smu)  {  	struct amdgpu_device *adev = smu->adev; -	if (adev->in_runpm) +	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev))  		return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO);  	else  		return smu_v11_0_baco_enter(smu); @@ -2197,7 +2199,7 @@ static int sienna_cichlid_baco_exit(struct smu_context *smu)  {  	struct amdgpu_device *adev = smu->adev; -	if (adev->in_runpm) { +	if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) {  		/* Wait for PMFW handling for the Dstate change */  		msleep(10);  		return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 3a3421452e57..f6ef0ce6e9e2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -589,10 +589,12 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,  	if (ret)  		return ret; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_OD_SCLK:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); +			size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");  			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",  			(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);  			size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -601,7 +603,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,  		break;  	case SMU_OD_CCLK:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select); +			size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);  			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",  			(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);  			size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -610,7 +612,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu,  		break;  	case SMU_OD_RANGE:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +			size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");  			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",  				smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);  			size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", @@ -688,10 +690,12 @@ static int vangogh_print_clk_levels(struct smu_context *smu,  	if (ret)  		return ret; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_OD_SCLK:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); +			size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");  			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",  			(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);  			size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -700,7 +704,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu,  		break;  	case SMU_OD_CCLK:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select); +			size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n",  smu->cpu_core_id_select);  			size += sysfs_emit_at(buf, size, "0: %10uMhz\n",  			(smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq);  			size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -709,7 +713,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu,  		break;  	case SMU_OD_RANGE:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -			size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +			size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");  			size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",  				smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);  			size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 5aa175e12a78..145f13b8c977 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -497,6 +497,8 @@ static int renoir_print_clk_levels(struct smu_context *smu,  	if (ret)  		return ret; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_OD_RANGE:  		if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index ab652028e003..5019903db492 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -733,15 +733,19 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,  	uint32_t freq_values[3] = {0};  	uint32_t min_clk, max_clk; -	if (amdgpu_ras_intr_triggered()) -		return sysfs_emit(buf, "unavailable\n"); +	smu_cmn_get_sysfs_buf(&buf, &size); + +	if (amdgpu_ras_intr_triggered()) { +		size += sysfs_emit_at(buf, size, "unavailable\n"); +		return size; +	}  	dpm_context = smu_dpm->dpm_context;  	switch (type) {  	case SMU_OD_SCLK: -		size = sysfs_emit(buf, "%s:\n", "GFXCLK"); +		size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK");  		fallthrough;  	case SMU_SCLK:  		ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); @@ -795,7 +799,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,  		break;  	case SMU_OD_MCLK: -		size = sysfs_emit(buf, "%s:\n", "MCLK"); +		size += sysfs_emit_at(buf, size, "%s:\n", "MCLK");  		fallthrough;  	case SMU_MCLK:  		ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 627ba2eec7fd..a403657151ba 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -1052,16 +1052,18 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu,  	int i, size = 0, ret = 0;  	uint32_t cur_value = 0, value = 0, count = 0; +	smu_cmn_get_sysfs_buf(&buf, &size); +  	switch (clk_type) {  	case SMU_OD_SCLK: -		size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); +		size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");  		size += sysfs_emit_at(buf, size, "0: %10uMhz\n",  		(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);  		size += sysfs_emit_at(buf, size, "1: %10uMhz\n",  		(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);  		break;  	case SMU_OD_RANGE: -		size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); +		size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");  		size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",  						smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);  		break; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 66711ab24c15..843d2cbfc71d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -1053,3 +1053,24 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,  	return ret;  } + +bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev) +{ +	struct pci_dev *p = NULL; +	bool snd_driver_loaded; + +	/* +	 * If the ASIC comes with no audio function, we always assume +	 * it is "enabled". +	 */ +	p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), +			adev->pdev->bus->number, 1); +	if (!p) +		return true; + +	snd_driver_loaded = pci_is_enabled(p) ? true : false; + +	pci_dev_put(p); + +	return snd_driver_loaded; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 16993daa2ae0..beea03810bca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -110,5 +110,20 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);  int smu_cmn_set_mp1_state(struct smu_context *smu,  			  enum pp_mp1_state mp1_state); +/* + * Helper function to make sysfs_emit_at() happy. Align buf to + * the current page boundary and record the offset. + */ +static inline void smu_cmn_get_sysfs_buf(char **buf, int *offset) +{ +	if (!*buf || !offset) +		return; + +	*offset = offset_in_page(*buf); +	*buf -= *offset; +} + +bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev); +  #endif  #endif diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 76d38561c910..cf741c5c82d2 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -397,8 +397,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,  		if (switch_mmu_context) {  			struct etnaviv_iommu_context *old_context = gpu->mmu_context; -			etnaviv_iommu_context_get(mmu_context); -			gpu->mmu_context = mmu_context; +			gpu->mmu_context = etnaviv_iommu_context_get(mmu_context);  			etnaviv_iommu_context_put(old_context);  		} diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 8f1b5af47dd6..f0b2540e60e4 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -294,8 +294,7 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(  		list_del(&mapping->obj_node);  	} -	etnaviv_iommu_context_get(mmu_context); -	mapping->context = mmu_context; +	mapping->context = etnaviv_iommu_context_get(mmu_context);  	mapping->use = 1;  	ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 4dd7d9d541c0..486259e154af 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -532,8 +532,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,  		goto err_submit_objects;  	submit->ctx = file->driver_priv; -	etnaviv_iommu_context_get(submit->ctx->mmu); -	submit->mmu_context = submit->ctx->mmu; +	submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu);  	submit->exec_state = args->exec_state;  	submit->flags = args->flags; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index c297fffe06eb..cc5b07f86346 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -569,6 +569,12 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)  	/* We rely on the GPU running, so program the clock */  	etnaviv_gpu_update_clock(gpu); +	gpu->fe_running = false; +	gpu->exec_state = -1; +	if (gpu->mmu_context) +		etnaviv_iommu_context_put(gpu->mmu_context); +	gpu->mmu_context = NULL; +  	return 0;  } @@ -637,19 +643,23 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)  			  VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE |  			  VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch));  	} + +	gpu->fe_running = true;  } -static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu) +static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu, +					  struct etnaviv_iommu_context *context)  { -	u32 address = etnaviv_cmdbuf_get_va(&gpu->buffer, -				&gpu->mmu_context->cmdbuf_mapping);  	u16 prefetch; +	u32 address;  	/* setup the MMU */ -	etnaviv_iommu_restore(gpu, gpu->mmu_context); +	etnaviv_iommu_restore(gpu, context);  	/* Start command processor */  	prefetch = etnaviv_buffer_init(gpu); +	address = etnaviv_cmdbuf_get_va(&gpu->buffer, +					&gpu->mmu_context->cmdbuf_mapping);  	etnaviv_gpu_start_fe(gpu, address, prefetch);  } @@ -832,7 +842,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)  	/* Now program the hardware */  	mutex_lock(&gpu->lock);  	etnaviv_gpu_hw_init(gpu); -	gpu->exec_state = -1;  	mutex_unlock(&gpu->lock);  	pm_runtime_mark_last_busy(gpu->dev); @@ -1057,8 +1066,6 @@ void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)  	spin_unlock(&gpu->event_spinlock);  	etnaviv_gpu_hw_init(gpu); -	gpu->exec_state = -1; -	gpu->mmu_context = NULL;  	mutex_unlock(&gpu->lock);  	pm_runtime_mark_last_busy(gpu->dev); @@ -1370,14 +1377,12 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit)  		goto out_unlock;  	} -	if (!gpu->mmu_context) { -		etnaviv_iommu_context_get(submit->mmu_context); -		gpu->mmu_context = submit->mmu_context; -		etnaviv_gpu_start_fe_idleloop(gpu); -	} else { -		etnaviv_iommu_context_get(gpu->mmu_context); -		submit->prev_mmu_context = gpu->mmu_context; -	} +	if (!gpu->fe_running) +		etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context); + +	if (submit->prev_mmu_context) +		etnaviv_iommu_context_put(submit->prev_mmu_context); +	submit->prev_mmu_context = etnaviv_iommu_context_get(gpu->mmu_context);  	if (submit->nr_pmrs) {  		gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; @@ -1579,7 +1584,7 @@ int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms)  static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)  { -	if (gpu->initialized && gpu->mmu_context) { +	if (gpu->initialized && gpu->fe_running) {  		/* Replace the last WAIT with END */  		mutex_lock(&gpu->lock);  		etnaviv_buffer_end(gpu); @@ -1592,8 +1597,7 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)  		 */  		etnaviv_gpu_wait_idle(gpu, 100); -		etnaviv_iommu_context_put(gpu->mmu_context); -		gpu->mmu_context = NULL; +		gpu->fe_running = false;  	}  	gpu->exec_state = -1; @@ -1741,6 +1745,9 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,  	etnaviv_gpu_hw_suspend(gpu);  #endif +	if (gpu->mmu_context) +		etnaviv_iommu_context_put(gpu->mmu_context); +  	if (gpu->initialized) {  		etnaviv_cmdbuf_free(&gpu->buffer);  		etnaviv_iommu_global_fini(gpu); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 8ea48697d132..1c75c8ed5bce 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -101,6 +101,7 @@ struct etnaviv_gpu {  	struct workqueue_struct *wq;  	struct drm_gpu_scheduler sched;  	bool initialized; +	bool fe_running;  	/* 'ring'-buffer: */  	struct etnaviv_cmdbuf buffer; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c index 1a7c89a67bea..afe5dd6a9925 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c @@ -92,6 +92,10 @@ static void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu,  	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);  	u32 pgtable; +	if (gpu->mmu_context) +		etnaviv_iommu_context_put(gpu->mmu_context); +	gpu->mmu_context = etnaviv_iommu_context_get(context); +  	/* set base addresses */  	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base);  	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, context->global->memory_base); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c index f8bf488e9d71..d664ae29ae20 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c @@ -172,6 +172,10 @@ static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu,  	if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE)  		return; +	if (gpu->mmu_context) +		etnaviv_iommu_context_put(gpu->mmu_context); +	gpu->mmu_context = etnaviv_iommu_context_get(context); +  	prefetch = etnaviv_buffer_config_mmuv2(gpu,  				(u32)v2_context->mtlb_dma,  				(u32)context->global->bad_page_dma); @@ -192,6 +196,10 @@ static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu,  	if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) & VIVS_MMUv2_SEC_CONTROL_ENABLE)  		return; +	if (gpu->mmu_context) +		etnaviv_iommu_context_put(gpu->mmu_context); +	gpu->mmu_context = etnaviv_iommu_context_get(context); +  	gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_LOW,  		  lower_32_bits(context->global->v2.pta_dma));  	gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_HIGH, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index dab1b58006d8..9fb1a2aadbcb 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -199,6 +199,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,  		 */  		list_for_each_entry_safe(m, n, &list, scan_node) {  			etnaviv_iommu_remove_mapping(context, m); +			etnaviv_iommu_context_put(m->context);  			m->context = NULL;  			list_del_init(&m->mmu_node);  			list_del_init(&m->scan_node); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h index d1d6902fd13b..e4a0b7d09c2e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h @@ -105,9 +105,11 @@ void etnaviv_iommu_dump(struct etnaviv_iommu_context *ctx, void *buf);  struct etnaviv_iommu_context *  etnaviv_iommu_context_init(struct etnaviv_iommu_global *global,  			   struct etnaviv_cmdbuf_suballoc *suballoc); -static inline void etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx) +static inline struct etnaviv_iommu_context * +etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx)  {  	kref_get(&ctx->refcount); +	return ctx;  }  void etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx);  void etnaviv_iommu_restore(struct etnaviv_gpu *gpu, diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 642a5b5a1b81..335ba9f43d8f 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -19,7 +19,6 @@ subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers)  subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)  # clang warnings  subdir-ccflags-y += $(call cc-disable-warning, sign-compare) -subdir-ccflags-y += $(call cc-disable-warning, sometimes-uninitialized)  subdir-ccflags-y += $(call cc-disable-warning, initializer-overrides)  subdir-ccflags-y += $(call cc-disable-warning, frame-address)  subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index e91e0e0191fb..4b94256d7319 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -222,31 +222,42 @@ static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)  struct intel_sa_info {  	u16 displayrtids; -	u8 deburst, deprogbwlimit; +	u8 deburst, deprogbwlimit, derating;  };  static const struct intel_sa_info icl_sa_info = {  	.deburst = 8,  	.deprogbwlimit = 25, /* GB/s */  	.displayrtids = 128, +	.derating = 10,  };  static const struct intel_sa_info tgl_sa_info = {  	.deburst = 16,  	.deprogbwlimit = 34, /* GB/s */  	.displayrtids = 256, +	.derating = 10,  };  static const struct intel_sa_info rkl_sa_info = {  	.deburst = 16,  	.deprogbwlimit = 20, /* GB/s */  	.displayrtids = 128, +	.derating = 10,  };  static const struct intel_sa_info adls_sa_info = {  	.deburst = 16,  	.deprogbwlimit = 38, /* GB/s */  	.displayrtids = 256, +	.derating = 10, +}; + +static const struct intel_sa_info adlp_sa_info = { +	.deburst = 16, +	.deprogbwlimit = 38, /* GB/s */ +	.displayrtids = 256, +	.derating = 20,  };  static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa) @@ -302,7 +313,7 @@ static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel  			bw = icl_calc_bw(sp->dclk, clpchgroup * 32 * num_channels, ct);  			bi->deratedbw[j] = min(maxdebw, -					       bw * 9 / 10); /* 90% */ +					       bw * (100 - sa->derating) / 100);  			drm_dbg_kms(&dev_priv->drm,  				    "BW%d / QGV %d: num_planes=%d deratedbw=%u\n", @@ -400,7 +411,9 @@ void intel_bw_init_hw(struct drm_i915_private *dev_priv)  	if (IS_DG2(dev_priv))  		dg2_get_bw_info(dev_priv); -	else if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) +	else if (IS_ALDERLAKE_P(dev_priv)) +		icl_get_bw_info(dev_priv, &adlp_sa_info); +	else if (IS_ALDERLAKE_S(dev_priv))  		icl_get_bw_info(dev_priv, &adls_sa_info);  	else if (IS_ROCKETLAKE(dev_priv))  		icl_get_bw_info(dev_priv, &rkl_sa_info); diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 3c3c6cb5c0df..b3c8e1c450ef 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -805,11 +805,14 @@ void intel_dmc_ucode_resume(struct drm_i915_private *dev_priv)   */  void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv)  { +	int id; +  	if (!HAS_DMC(dev_priv))  		return;  	intel_dmc_ucode_suspend(dev_priv);  	drm_WARN_ON(&dev_priv->drm, dev_priv->dmc.wakeref); -	kfree(dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload); +	for (id = 0; id < DMC_FW_MAX; id++) +		kfree(dev_priv->dmc.dmc_info[id].payload);  } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 04175f359fd6..abe3d61b6243 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2445,11 +2445,14 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)  	 */  	if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV,  			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == -			     sizeof(intel_dp->edp_dpcd)) +			     sizeof(intel_dp->edp_dpcd)) {  		drm_dbg_kms(&dev_priv->drm, "eDP DPCD: %*ph\n",  			    (int)sizeof(intel_dp->edp_dpcd),  			    intel_dp->edp_dpcd); +		intel_dp->use_max_params = intel_dp->edp_dpcd[0] < DP_EDP_14; +	} +  	/*  	 * This has to be called after intel_dp->edp_dpcd is filled, PSR checks  	 * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1] diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 053a3c2f7267..508a514c5e37 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -848,7 +848,7 @@ intel_dp_link_train_all_phys(struct intel_dp *intel_dp,  	}  	if (ret) -		intel_dp_link_train_phy(intel_dp, crtc_state, DP_PHY_DPRX); +		ret = intel_dp_link_train_phy(intel_dp, crtc_state, DP_PHY_DPRX);  	if (intel_dp->set_idle_link_train)  		intel_dp->set_idle_link_train(intel_dp, crtc_state); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index cff72679ad7c..9ccf4b29b82e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -986,6 +986,9 @@ void i915_gem_context_release(struct kref *ref)  	trace_i915_context_free(ctx);  	GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); +	if (ctx->syncobj) +		drm_syncobj_put(ctx->syncobj); +  	mutex_destroy(&ctx->engines_mutex);  	mutex_destroy(&ctx->lut_mutex); @@ -1205,9 +1208,6 @@ static void context_close(struct i915_gem_context *ctx)  	if (vm)  		i915_vm_close(vm); -	if (ctx->syncobj) -		drm_syncobj_put(ctx->syncobj); -  	ctx->file_priv = ERR_PTR(-EBADF);  	/* diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 35eedc14f522..6ea13159bffc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -356,11 +356,8 @@ static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo)  {  	struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); -	if (likely(obj)) { -		/* This releases all gem object bindings to the backend. */ +	if (likely(obj))  		i915_ttm_free_cached_io_st(obj); -		__i915_gem_free_object(obj); -	}  }  static struct intel_memory_region * @@ -875,8 +872,12 @@ void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)  {  	struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); +	/* This releases all gem object bindings to the backend. */ +	__i915_gem_free_object(obj); +  	i915_gem_object_release_memory_region(obj);  	mutex_destroy(&obj->ttm.get_io_page.lock); +  	if (obj->ttm.created)  		call_rcu(&obj->rcu, __i915_gem_free_object_rcu);  } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index ffae7df5e4d7..4a6bb64c3a35 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -59,13 +59,13 @@ static int igt_dmabuf_import_self(void *arg)  		err = PTR_ERR(import);  		goto out_dmabuf;  	} +	import_obj = to_intel_bo(import);  	if (import != &obj->base) {  		pr_err("i915_gem_prime_import created a new object!\n");  		err = -EINVAL;  		goto out_import;  	} -	import_obj = to_intel_bo(import);  	i915_gem_object_lock(import_obj, NULL);  	err = __i915_gem_object_get_pages(import_obj); @@ -128,6 +128,8 @@ static int igt_dmabuf_import_same_driver_lmem(void *arg)  		pr_err("i915_gem_prime_import failed with the wrong err=%ld\n",  		       PTR_ERR(import));  		err = PTR_ERR(import); +	} else { +		err = 0;  	}  	dma_buf_put(dmabuf); @@ -176,6 +178,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,  		err = PTR_ERR(import);  		goto out_dmabuf;  	} +	import_obj = to_intel_bo(import);  	if (import == &obj->base) {  		pr_err("i915_gem_prime_import reused gem object!\n"); @@ -183,8 +186,6 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,  		goto out_import;  	} -	import_obj = to_intel_bo(import); -  	i915_gem_object_lock(import_obj, NULL);  	err = __i915_gem_object_get_pages(import_obj);  	if (err) { diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index b20f5621f62b..a2c34e5a1c54 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -581,6 +581,20 @@ static enum i915_mmap_type default_mapping(struct drm_i915_private *i915)  	return I915_MMAP_TYPE_GTT;  } +static struct drm_i915_gem_object * +create_sys_or_internal(struct drm_i915_private *i915, +		       unsigned long size) +{ +	if (HAS_LMEM(i915)) { +		struct intel_memory_region *sys_region = +			i915->mm.regions[INTEL_REGION_SMEM]; + +		return __i915_gem_object_create_user(i915, size, &sys_region, 1); +	} + +	return i915_gem_object_create_internal(i915, size); +} +  static bool assert_mmap_offset(struct drm_i915_private *i915,  			       unsigned long size,  			       int expected) @@ -589,7 +603,7 @@ static bool assert_mmap_offset(struct drm_i915_private *i915,  	u64 offset;  	int ret; -	obj = i915_gem_object_create_internal(i915, size); +	obj = create_sys_or_internal(i915, size);  	if (IS_ERR(obj))  		return expected && expected == PTR_ERR(obj); @@ -633,6 +647,7 @@ static int igt_mmap_offset_exhaustion(void *arg)  	struct drm_mm_node *hole, *next;  	int loop, err = 0;  	u64 offset; +	int enospc = HAS_LMEM(i915) ? -ENXIO : -ENOSPC;  	/* Disable background reaper */  	disable_retire_worker(i915); @@ -683,14 +698,14 @@ static int igt_mmap_offset_exhaustion(void *arg)  	}  	/* Too large */ -	if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, -ENOSPC)) { +	if (!assert_mmap_offset(i915, 2 * PAGE_SIZE, enospc)) {  		pr_err("Unexpectedly succeeded in inserting too large object into single page hole\n");  		err = -EINVAL;  		goto out;  	}  	/* Fill the hole, further allocation attempts should then fail */ -	obj = i915_gem_object_create_internal(i915, PAGE_SIZE); +	obj = create_sys_or_internal(i915, PAGE_SIZE);  	if (IS_ERR(obj)) {  		err = PTR_ERR(obj);  		pr_err("Unable to create object for reclaimed hole\n"); @@ -703,7 +718,7 @@ static int igt_mmap_offset_exhaustion(void *arg)  		goto err_obj;  	} -	if (!assert_mmap_offset(i915, PAGE_SIZE, -ENOSPC)) { +	if (!assert_mmap_offset(i915, PAGE_SIZE, enospc)) {  		pr_err("Unexpectedly succeeded in inserting object into no holes!\n");  		err = -EINVAL;  		goto err_obj; @@ -839,10 +854,9 @@ static int wc_check(struct drm_i915_gem_object *obj)  static bool can_mmap(struct drm_i915_gem_object *obj, enum i915_mmap_type type)  { -	struct drm_i915_private *i915 = to_i915(obj->base.dev);  	bool no_map; -	if (HAS_LMEM(i915)) +	if (obj->ops->mmap_offset)  		return type == I915_MMAP_TYPE_FIXED;  	else if (type == I915_MMAP_TYPE_FIXED)  		return false; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index d812b27835f8..591a5224287e 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1973,8 +1973,14 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)  u32 intel_rps_read_punit_req(struct intel_rps *rps)  {  	struct intel_uncore *uncore = rps_to_uncore(rps); +	struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm; +	intel_wakeref_t wakeref; +	u32 freq = 0; -	return intel_uncore_read(uncore, GEN6_RPNSWREQ); +	with_intel_runtime_pm_if_in_use(rpm, wakeref) +		freq = intel_uncore_read(uncore, GEN6_RPNSWREQ); + +	return freq;  }  static u32 intel_rps_get_req(u32 pureq) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index b104fb7607eb..86c318516e14 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -172,11 +172,6 @@ void intel_uc_driver_remove(struct intel_uc *uc)  	__uc_free_load_err_log(uc);  } -static inline bool guc_communication_enabled(struct intel_guc *guc) -{ -	return intel_guc_ct_enabled(&guc->ct); -} -  /*   * Events triggered while CT buffers are disabled are logged in the SCRATCH_15   * register using the same bits used in the CT message payload. Since our @@ -210,7 +205,7 @@ static void guc_get_mmio_msg(struct intel_guc *guc)  static void guc_handle_mmio_msg(struct intel_guc *guc)  {  	/* we need communication to be enabled to reply to GuC */ -	GEM_BUG_ON(!guc_communication_enabled(guc)); +	GEM_BUG_ON(!intel_guc_ct_enabled(&guc->ct));  	spin_lock_irq(&guc->irq_lock);  	if (guc->mmio_msg) { @@ -226,7 +221,7 @@ static int guc_enable_communication(struct intel_guc *guc)  	struct drm_i915_private *i915 = gt->i915;  	int ret; -	GEM_BUG_ON(guc_communication_enabled(guc)); +	GEM_BUG_ON(intel_guc_ct_enabled(&guc->ct));  	ret = i915_inject_probe_error(i915, -ENXIO);  	if (ret) @@ -662,7 +657,7 @@ static int __uc_resume(struct intel_uc *uc, bool enable_communication)  		return 0;  	/* Make sure we enable communication if and only if it's disabled */ -	GEM_BUG_ON(enable_communication == guc_communication_enabled(guc)); +	GEM_BUG_ON(enable_communication == intel_guc_ct_enabled(&guc->ct));  	if (enable_communication)  		guc_enable_communication(guc); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c index b0ece71aefde..ce774579c89d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c @@ -57,7 +57,7 @@ nvkm_control_mthd_pstate_info(struct nvkm_control *ctrl, void *data, u32 size)  		args->v0.count = 0;  		args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;  		args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE; -		args->v0.pwrsrc = -ENOSYS; +		args->v0.pwrsrc = -ENODEV;  		args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;  	} diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0473583dcdac..482fb0ae6cb5 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -119,7 +119,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)  #endif  	if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) -		rdev->agp = radeon_agp_head_init(rdev->ddev); +		rdev->agp = radeon_agp_head_init(dev);  	if (rdev->agp) {  		rdev->agp->agp_mtrr = arch_phys_wc_add(  			rdev->agp->agp_info.aper_base, diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 8ab3247dbc4a..13c6b857158f 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -1123,7 +1123,7 @@ static int cdn_dp_suspend(struct device *dev)  	return ret;  } -static int cdn_dp_resume(struct device *dev) +static __maybe_unused int cdn_dp_resume(struct device *dev)  {  	struct cdn_dp_device *dp = dev_get_drvdata(dev); diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index cb38b1a17b09..82cbb29a05aa 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -383,7 +383,8 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,  	else  		gfp_flags |= GFP_HIGHUSER; -	for (order = min(MAX_ORDER - 1UL, __fls(num_pages)); num_pages; +	for (order = min_t(unsigned int, MAX_ORDER - 1, __fls(num_pages)); +	     num_pages;  	     order = min_t(unsigned int, order, __fls(num_pages))) {  		bool apply_caching = false;  		struct ttm_pool_type *pt; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4a1115043114..b4b4653fe301 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -167,8 +167,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)  	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);  	bool connected = false; -	WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); -  	if (vc4_hdmi->hpd_gpio &&  	    gpiod_get_value_cansleep(vc4_hdmi->hpd_gpio)) {  		connected = true; @@ -189,12 +187,10 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)  			}  		} -		pm_runtime_put(&vc4_hdmi->pdev->dev);  		return connector_status_connected;  	}  	cec_phys_addr_invalidate(vc4_hdmi->cec_adap); -	pm_runtime_put(&vc4_hdmi->pdev->dev);  	return connector_status_disconnected;  } @@ -436,7 +432,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);  	struct drm_connector *connector = &vc4_hdmi->connector;  	struct drm_connector_state *cstate = connector->state; -	struct drm_crtc *crtc = cstate->crtc; +	struct drm_crtc *crtc = encoder->crtc;  	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;  	union hdmi_infoframe frame;  	int ret; @@ -541,11 +537,8 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder,  static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)  { +	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -	struct drm_connector *connector = &vc4_hdmi->connector; -	struct drm_connector_state *cstate = connector->state; -	struct drm_crtc *crtc = cstate->crtc; -	struct drm_display_mode *mode = &crtc->state->adjusted_mode;  	if (!vc4_hdmi_supports_scrambling(encoder, mode))  		return; @@ -566,18 +559,17 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)  static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)  {  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); -	struct drm_connector *connector = &vc4_hdmi->connector; -	struct drm_connector_state *cstate = connector->state; +	struct drm_crtc *crtc = encoder->crtc;  	/* -	 * At boot, connector->state will be NULL. Since we don't know the +	 * At boot, encoder->crtc will be NULL. Since we don't know the  	 * state of the scrambler and in order to avoid any  	 * inconsistency, let's disable it all the time.  	 */ -	if (cstate && !vc4_hdmi_supports_scrambling(encoder, &cstate->crtc->mode)) +	if (crtc && !vc4_hdmi_supports_scrambling(encoder, &crtc->mode))  		return; -	if (cstate && !vc4_hdmi_mode_needs_scrambling(&cstate->crtc->mode)) +	if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode))  		return;  	if (delayed_work_pending(&vc4_hdmi->scrambling_work)) @@ -635,6 +627,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,  		vc4_hdmi->variant->phy_disable(vc4_hdmi);  	clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); +	clk_disable_unprepare(vc4_hdmi->hsm_clock);  	clk_disable_unprepare(vc4_hdmi->pixel_clock);  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev); @@ -898,9 +891,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  		vc4_hdmi_encoder_get_connector_state(encoder, state);  	struct vc4_hdmi_connector_state *vc4_conn_state =  		conn_state_to_vc4_hdmi_conn_state(conn_state); -	struct drm_crtc_state *crtc_state = -		drm_atomic_get_new_crtc_state(state, conn_state->crtc); -	struct drm_display_mode *mode = &crtc_state->adjusted_mode; +	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);  	unsigned long bvb_rate, pixel_rate, hsm_rate;  	int ret; @@ -947,6 +938,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  		return;  	} +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock); +	if (ret) { +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); +		clk_disable_unprepare(vc4_hdmi->pixel_clock); +		return; +	} +  	vc4_hdmi_cec_update_clk_div(vc4_hdmi);  	if (pixel_rate > 297000000) @@ -959,6 +957,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  	ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, bvb_rate);  	if (ret) {  		DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); +		clk_disable_unprepare(vc4_hdmi->hsm_clock);  		clk_disable_unprepare(vc4_hdmi->pixel_clock);  		return;  	} @@ -966,6 +965,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  	ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);  	if (ret) {  		DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); +		clk_disable_unprepare(vc4_hdmi->hsm_clock);  		clk_disable_unprepare(vc4_hdmi->pixel_clock);  		return;  	} @@ -985,11 +985,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,  static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,  					     struct drm_atomic_state *state)  { -	struct drm_connector_state *conn_state = -		vc4_hdmi_encoder_get_connector_state(encoder, state); -	struct drm_crtc_state *crtc_state = -		drm_atomic_get_new_crtc_state(state, conn_state->crtc); -	struct drm_display_mode *mode = &crtc_state->adjusted_mode; +	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); @@ -1012,11 +1008,7 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,  static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,  					      struct drm_atomic_state *state)  { -	struct drm_connector_state *conn_state = -		vc4_hdmi_encoder_get_connector_state(encoder, state); -	struct drm_crtc_state *crtc_state = -		drm_atomic_get_new_crtc_state(state, conn_state->crtc); -	struct drm_display_mode *mode = &crtc_state->adjusted_mode; +	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);  	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; @@ -1204,8 +1196,8 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)  { -	struct drm_connector *connector = &vc4_hdmi->connector; -	struct drm_crtc *crtc = connector->state->crtc; +	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; +	struct drm_crtc *crtc = encoder->crtc;  	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;  	u32 n, cts;  	u64 tmp; @@ -1238,13 +1230,13 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)  static int vc4_hdmi_audio_startup(struct device *dev, void *data)  {  	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -	struct drm_connector *connector = &vc4_hdmi->connector; +	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;  	/*  	 * If the HDMI encoder hasn't probed, or the encoder is  	 * currently in DVI mode, treat the codec dai as missing.  	 */ -	if (!connector->state || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & +	if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &  				VC4_HDMI_RAM_PACKET_ENABLE))  		return -ENODEV; @@ -2114,29 +2106,6 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)  	return 0;  } -#ifdef CONFIG_PM -static int vc4_hdmi_runtime_suspend(struct device *dev) -{ -	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); - -	clk_disable_unprepare(vc4_hdmi->hsm_clock); - -	return 0; -} - -static int vc4_hdmi_runtime_resume(struct device *dev) -{ -	struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); -	int ret; - -	ret = clk_prepare_enable(vc4_hdmi->hsm_clock); -	if (ret) -		return ret; - -	return 0; -} -#endif -  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)  {  	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); @@ -2391,18 +2360,11 @@ static const struct of_device_id vc4_hdmi_dt_match[] = {  	{}  }; -static const struct dev_pm_ops vc4_hdmi_pm_ops = { -	SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend, -			   vc4_hdmi_runtime_resume, -			   NULL) -}; -  struct platform_driver vc4_hdmi_driver = {  	.probe = vc4_hdmi_dev_probe,  	.remove = vc4_hdmi_dev_remove,  	.driver = {  		.name = "vc4_hdmi",  		.of_match_table = vc4_hdmi_dt_match, -		.pm = &vc4_hdmi_pm_ops,  	},  }; | 
