diff options
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_encoders.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/cik.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/cik_sdma.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600_dma.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kfd.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kfd.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_vce.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/uvd_v1_0.c | 10 |
16 files changed, 132 insertions, 50 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 01b20e14a247..1603751b1164 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -2623,16 +2623,8 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) } -static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { .dpms = radeon_atom_ext_dpms, - .mode_fixup = radeon_atom_ext_mode_fixup, .prepare = radeon_atom_ext_prepare, .mode_set = radeon_atom_ext_mode_set, .commit = radeon_atom_ext_commit, diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4c30d8c65558..06001400ce8b 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -4219,13 +4219,20 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); return r; } - r = radeon_fence_wait(ib.fence, false); - if (r) { + r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); radeon_scratch_free(rdev, scratch); radeon_ib_free(rdev, &ib); return r; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + radeon_scratch_free(rdev, scratch); + radeon_ib_free(rdev, &ib); + return -ETIMEDOUT; } + r = 0; for (i = 0; i < rdev->usec_timeout; i++) { tmp = RREG32(scratch); if (tmp == 0xDEADBEEF) diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index d16f2eebd95e..9c351dc8a9e0 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -737,11 +737,16 @@ int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); return r; } - r = radeon_fence_wait(ib.fence, false); - if (r) { + r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); return r; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + return -ETIMEDOUT; } + r = 0; for (i = 0; i < rdev->usec_timeout; i++) { tmp = le32_to_cpu(rdev->wb.wb[index/4]); if (tmp == 0xDEADBEEF) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 5eae0a88dd3e..6e478a248628 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3732,11 +3732,17 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); goto free_ib; } - r = radeon_fence_wait(ib.fence, false); - if (r) { + r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); goto free_ib; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + r = -ETIMEDOUT; + goto free_ib; } + r = 0; for (i = 0; i < rdev->usec_timeout; i++) { tmp = RREG32(scratch); if (tmp == 0xDEADBEEF) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index cc2fdf0be37a..ed121042247f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3381,11 +3381,17 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); goto free_ib; } - r = radeon_fence_wait(ib.fence, false); - if (r) { + r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); goto free_ib; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + r = -ETIMEDOUT; + goto free_ib; } + r = 0; for (i = 0; i < rdev->usec_timeout; i++) { tmp = RREG32(scratch); if (tmp == 0xDEADBEEF) diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index d2dd29ab24fa..fb65e6fb5c4f 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -368,11 +368,16 @@ int r600_dma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); return r; } - r = radeon_fence_wait(ib.fence, false); - if (r) { + r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); return r; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + return -ETIMEDOUT; } + r = 0; for (i = 0; i < rdev->usec_timeout; i++) { tmp = le32_to_cpu(rdev->wb.wb[index/4]); if (tmp == 0xDEADBEEF) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 78a51b3eda10..007be29a0020 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -120,6 +120,7 @@ extern int radeon_mst; */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define RADEON_FENCE_JIFFIES_TIMEOUT (HZ / 2) +#define RADEON_USEC_IB_TEST_TIMEOUT 1000000 /* 1s */ /* RADEON_IB_POOL_SIZE must be a power of 2 */ #define RADEON_IB_POOL_SIZE 16 #define RADEON_DEBUGFS_MAX_COMPONENTS 32 @@ -382,6 +383,7 @@ void radeon_fence_driver_force_completion(struct radeon_device *rdev, int ring); int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); void radeon_fence_process(struct radeon_device *rdev, int ring); bool radeon_fence_signaled(struct radeon_fence *fence); +long radeon_fence_wait_timeout(struct radeon_fence *fence, bool interruptible, long timeout); int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); int radeon_fence_wait_next(struct radeon_device *rdev, int ring); int radeon_fence_wait_empty(struct radeon_device *rdev, int ring); diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index c4b4f298a283..56482e35d43e 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -551,13 +551,14 @@ static bool radeon_atpx_detect(void) void radeon_register_atpx_handler(void) { bool r; + enum vga_switcheroo_handler_flags_t handler_flags = 0; /* detect if we have any ATPX + 2 VGA in the system */ r = radeon_atpx_detect(); if (!r) return; - vga_switcheroo_register_handler(&radeon_atpx_handler); + vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags); } /** diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 340f3f549f29..cfcc099c537d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -34,6 +34,7 @@ #include "atom.h" #include <linux/pm_runtime.h> +#include <linux/vga_switcheroo.h> static int radeon_dp_handle_hpd(struct drm_connector *connector) { @@ -344,6 +345,11 @@ static void radeon_connector_get_edid(struct drm_connector *connector) else if (radeon_connector->ddc_bus) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); + } else if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC && + connector->connector_type == DRM_MODE_CONNECTOR_LVDS && + radeon_connector->ddc_bus) { + radeon_connector->edid = drm_get_edid_switcheroo(&radeon_connector->base, + &radeon_connector->ddc_bus->adapter); } else if (radeon_connector->ddc_bus) { radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 298ea1c453c3..a4674bfd979a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1686,6 +1686,9 @@ void radeon_modeset_fini(struct radeon_device *rdev) radeon_fbdev_fini(rdev); kfree(rdev->mode_info.bios_hardcoded_edid); + /* free i2c buses */ + radeon_i2c_fini(rdev); + if (rdev->mode_info.mode_config_initialized) { radeon_afmt_fini(rdev); drm_kms_helper_poll_fini(rdev->ddev); @@ -1693,8 +1696,6 @@ void radeon_modeset_fini(struct radeon_device *rdev) drm_mode_config_cleanup(rdev->ddev); rdev->mode_info.mode_config_initialized = false; } - /* free i2c buses */ - radeon_i2c_fini(rdev); } static bool is_hdtv_mode(const struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index e266ffc520d2..ccd4ad4ee592 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -34,9 +34,11 @@ #include "radeon_drv.h" #include <drm/drm_pciids.h> +#include <linux/apple-gmux.h> #include <linux/console.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> #include <drm/drm_gem.h> @@ -319,6 +321,23 @@ static int radeon_pci_probe(struct pci_dev *pdev, { int ret; + /* + * Initialize amdkfd before starting radeon. If it was not loaded yet, + * defer radeon probing + */ + ret = radeon_kfd_init(); + if (ret == -EPROBE_DEFER) + return ret; + + /* + * apple-gmux is needed on dual GPU MacBook Pro + * to probe the panel if we're the inactive GPU. + */ + if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && + apple_gmux_present() && pdev != vga_default_device() && + !vga_switcheroo_handler_flags()) + return -EPROBE_DEFER; + /* Get rid of things like offb */ ret = radeon_kick_out_firmware_fb(pdev); if (ret) @@ -570,8 +589,6 @@ static int __init radeon_init(void) return -EINVAL; } - radeon_kfd_init(); - /* let modprobe override vga console setting */ return drm_pci_init(driver, pdriver); } diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 05815c47b246..7ef075acde9c 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -527,7 +527,7 @@ static long radeon_fence_wait_seq_timeout(struct radeon_device *rdev, } /** - * radeon_fence_wait - wait for a fence to signal + * radeon_fence_wait_timeout - wait for a fence to signal with timeout * * @fence: radeon fence object * @intr: use interruptible sleep @@ -535,12 +535,15 @@ static long radeon_fence_wait_seq_timeout(struct radeon_device *rdev, * Wait for the requested fence to signal (all asics). * @intr selects whether to use interruptable (true) or non-interruptable * (false) sleep when waiting for the fence. - * Returns 0 if the fence has passed, error for all other cases. + * @timeout: maximum time to wait, or MAX_SCHEDULE_TIMEOUT for infinite wait + * Returns remaining time if the sequence number has passed, 0 when + * the wait timeout, or an error for all other cases. */ -int radeon_fence_wait(struct radeon_fence *fence, bool intr) +long radeon_fence_wait_timeout(struct radeon_fence *fence, bool intr, long timeout) { uint64_t seq[RADEON_NUM_RINGS] = {}; long r; + int r_sig; /* * This function should not be called on !radeon fences. @@ -552,15 +555,36 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr) return fence_wait(&fence->base, intr); seq[fence->ring] = fence->seq; - r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, MAX_SCHEDULE_TIMEOUT); - if (r < 0) { + r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, timeout); + if (r <= 0) { return r; } - r = fence_signal(&fence->base); - if (!r) + r_sig = fence_signal(&fence->base); + if (!r_sig) FENCE_TRACE(&fence->base, "signaled from fence_wait\n"); - return 0; + return r; +} + +/** + * radeon_fence_wait - wait for a fence to signal + * + * @fence: radeon fence object + * @intr: use interruptible sleep + * + * Wait for the requested fence to signal (all asics). + * @intr selects whether to use interruptable (true) or non-interruptable + * (false) sleep when waiting for the fence. + * Returns 0 if the fence has passed, error for all other cases. + */ +int radeon_fence_wait(struct radeon_fence *fence, bool intr) +{ + long r = radeon_fence_wait_timeout(fence, intr, MAX_SCHEDULE_TIMEOUT); + if (r > 0) { + return 0; + } else { + return r; + } } /** diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 9a4d69e59401..87a9ebb5f58f 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c @@ -132,35 +132,34 @@ static const struct kfd2kgd_calls kfd2kgd = { static const struct kgd2kfd_calls *kgd2kfd; -bool radeon_kfd_init(void) +int radeon_kfd_init(void) { + int ret; + #if defined(CONFIG_HSA_AMD_MODULE) - bool (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**); + int (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**); kgd2kfd_init_p = symbol_request(kgd2kfd_init); if (kgd2kfd_init_p == NULL) - return false; + return -ENOENT; - if (!kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd)) { + ret = kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd); + if (ret) { symbol_put(kgd2kfd_init); kgd2kfd = NULL; - - return false; } - return true; #elif defined(CONFIG_HSA_AMD) - if (!kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd)) { + ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); + if (ret) kgd2kfd = NULL; - return false; - } - - return true; #else - return false; + ret = -ENOENT; #endif + + return ret; } void radeon_kfd_fini(void) diff --git a/drivers/gpu/drm/radeon/radeon_kfd.h b/drivers/gpu/drm/radeon/radeon_kfd.h index 1103f9082f6b..9df1fea8e971 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.h +++ b/drivers/gpu/drm/radeon/radeon_kfd.h @@ -33,7 +33,7 @@ struct radeon_device; -bool radeon_kfd_init(void); +int radeon_kfd_init(void); void radeon_kfd_fini(void); void radeon_kfd_suspend(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 7eb1ae758906..566a1a01f6d1 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -810,11 +810,16 @@ int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) goto error; } - r = radeon_fence_wait(fence, false); - if (r) { + r = radeon_fence_wait_timeout(fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + r = -ETIMEDOUT; } else { - DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + r = 0; } error: radeon_fence_unref(&fence); diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index c6b1cbca47fc..12ddcfa82e20 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -522,11 +522,17 @@ int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) goto error; } - r = radeon_fence_wait(fence, false); - if (r) { + r = radeon_fence_wait_timeout(fence, false, usecs_to_jiffies( + RADEON_USEC_IB_TEST_TIMEOUT)); + if (r < 0) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); goto error; + } else if (r == 0) { + DRM_ERROR("radeon: fence wait timed out.\n"); + r = -ETIMEDOUT; + goto error; } + r = 0; DRM_INFO("ib test on ring %d succeeded\n", ring->idx); error: radeon_fence_unref(&fence); |