diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 44 | 
1 files changed, 37 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..5ed4227f304b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -55,6 +55,7 @@  #include "amdgpu_connectors.h"  #include "amdgpu_trace.h"  #include "amdgpu_amdkfd.h" +#include "amdgpu_ras.h"  #include <linux/pm_runtime.h> @@ -87,10 +88,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 +157,22 @@ 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 (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) { +		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 +248,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 +283,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 +314,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 +399,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.   */  | 
