diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 41 | 
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 2a3f5ec298db..30d540d23b77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -87,10 +87,13 @@ static void amdgpu_hotplug_work_func(struct work_struct *work)  	struct drm_device *dev = adev->ddev;  	struct drm_mode_config *mode_config = &dev->mode_config;  	struct drm_connector *connector; +	struct drm_connector_list_iter iter;  	mutex_lock(&mode_config->mutex); -	list_for_each_entry(connector, &mode_config->connector_list, head) +	drm_connector_list_iter_begin(dev, &iter); +	drm_for_each_connector_iter(connector, &iter)  		amdgpu_connector_hotplug(connector); +	drm_connector_list_iter_end(&iter);  	mutex_unlock(&mode_config->mutex);  	/* Just fire off a uevent and let userspace tell us what to do */  	drm_helper_hpd_irq_event(dev); @@ -153,6 +156,20 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)  	ret = amdgpu_ih_process(adev, &adev->irq.ih);  	if (ret == IRQ_HANDLED)  		pm_runtime_mark_last_busy(dev->dev); + +	/* For the hardware that cannot enable bif ring for both ras_controller_irq +         * and ras_err_evnet_athub_irq ih cookies, the driver has to poll status +	 * register to check whether the interrupt is triggered or not, and properly +	 * ack the interrupt if it is there +	 */ +	if (adev->nbio.funcs && +	    adev->nbio.funcs->handle_ras_controller_intr_no_bifring) +		adev->nbio.funcs->handle_ras_controller_intr_no_bifring(adev); + +	if (adev->nbio.funcs && +	    adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring) +		adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring(adev); +  	return ret;  } @@ -228,10 +245,19 @@ int amdgpu_irq_init(struct amdgpu_device *adev)  	adev->irq.msi_enabled = false;  	if (amdgpu_msi_ok(adev)) { -		int ret = pci_enable_msi(adev->pdev); -		if (!ret) { +		int nvec = pci_msix_vec_count(adev->pdev); +		unsigned int flags; + +		if (nvec <= 0) { +			flags = PCI_IRQ_MSI; +		} else { +			flags = PCI_IRQ_MSI | PCI_IRQ_MSIX; +		} +		/* we only need one vector */ +		nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags); +		if (nvec > 0) {  			adev->irq.msi_enabled = true; -			dev_dbg(adev->dev, "amdgpu: using MSI.\n"); +			dev_dbg(adev->dev, "amdgpu: using MSI/MSI-X.\n");  		}  	} @@ -254,7 +280,8 @@ int amdgpu_irq_init(struct amdgpu_device *adev)  	INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);  	adev->irq.installed = true; -	r = drm_irq_install(adev->ddev, adev->ddev->pdev->irq); +	/* Use vector 0 for MSI-X */ +	r = drm_irq_install(adev->ddev, pci_irq_vector(adev->pdev, 0));  	if (r) {  		adev->irq.installed = false;  		if (!amdgpu_device_has_dc_support(adev)) @@ -284,7 +311,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)  		drm_irq_uninstall(adev->ddev);  		adev->irq.installed = false;  		if (adev->irq.msi_enabled) -			pci_disable_msi(adev->pdev); +			pci_free_irq_vectors(adev->pdev);  		if (!amdgpu_device_has_dc_support(adev))  			flush_work(&adev->hotplug_work);  	} @@ -369,7 +396,7 @@ int amdgpu_irq_add_id(struct amdgpu_device *adev,   * amdgpu_irq_dispatch - dispatch IRQ to IP blocks   *   * @adev: amdgpu device pointer - * @entry: interrupt vector pointer + * @ih: interrupt ring instance   *   * Dispatches IRQ to IP blocks.   */  |