drm/radeon: Use PCI Express Capability accessors
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / radeon / evergreen.c
index 7fb3d2e0434c71d52725633573bc3f17a34a010d..b106c56c9af14357c0110ab16bf0ad843d4c84d4 100644 (file)
@@ -77,13 +77,9 @@ void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
        u16 ctl, v;
-       int cap, err;
+       int err;
 
-       cap = pci_pcie_cap(rdev->pdev);
-       if (!cap)
-               return;
-
-       err = pci_read_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, &ctl);
+       err = pcie_capability_read_word(rdev->pdev, PCI_EXP_DEVCTL, &ctl);
        if (err)
                return;
 
@@ -95,10 +91,18 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
        if ((v == 0) || (v == 6) || (v == 7)) {
                ctl &= ~PCI_EXP_DEVCTL_READRQ;
                ctl |= (2 << 12);
-               pci_write_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, ctl);
+               pcie_capability_write_word(rdev->pdev, PCI_EXP_DEVCTL, ctl);
        }
 }
 
+/**
+ * dce4_wait_for_vblank - vblank wait asic callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc: crtc to wait for vblank on
+ *
+ * Wait for vblank on the requested crtc (evergreen+).
+ */
 void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
@@ -118,18 +122,49 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
        }
 }
 
+/**
+ * radeon_irq_kms_pflip_irq_get - pre-pageflip callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc: crtc to prepare for pageflip on
+ *
+ * Pre-pageflip callback (evergreen+).
+ * Enables the pageflip irq (vblank irq).
+ */
 void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
        /* enable the pflip int */
        radeon_irq_kms_pflip_irq_get(rdev, crtc);
 }
 
+/**
+ * evergreen_post_page_flip - pos-pageflip callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc: crtc to cleanup pageflip on
+ *
+ * Post-pageflip callback (evergreen+).
+ * Disables the pageflip irq (vblank irq).
+ */
 void evergreen_post_page_flip(struct radeon_device *rdev, int crtc)
 {
        /* disable the pflip int */
        radeon_irq_kms_pflip_irq_put(rdev, crtc);
 }
 
+/**
+ * evergreen_page_flip - pageflip callback.
+ *
+ * @rdev: radeon_device pointer
+ * @crtc_id: crtc to cleanup pageflip on
+ * @crtc_base: new address of the crtc (GPU MC address)
+ *
+ * Does the actual pageflip (evergreen+).
+ * During vblank we take the crtc lock and wait for the update_pending
+ * bit to go high, when it does, we release the lock, and allow the
+ * double buffered update to take place.
+ * Returns the current update pending status.
+ */
 u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 {
        struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
@@ -214,6 +249,15 @@ int sumo_get_temp(struct radeon_device *rdev)
        return actual_temp * 1000;
 }
 
+/**
+ * sumo_pm_init_profile - Initialize power profiles callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the power states used in profile mode
+ * (sumo, trinity, SI).
+ * Used for profile mode only.
+ */
 void sumo_pm_init_profile(struct radeon_device *rdev)
 {
        int idx;
@@ -265,6 +309,14 @@ void sumo_pm_init_profile(struct radeon_device *rdev)
                rdev->pm.power_state[idx].num_clock_modes - 1;
 }
 
+/**
+ * evergreen_pm_misc - set additional pm hw parameters callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Set non-clock parameters associated with a power state
+ * (voltage, etc.) (evergreen+).
+ */
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
        int req_ps_idx = rdev->pm.requested_power_state_index;
@@ -292,6 +344,13 @@ void evergreen_pm_misc(struct radeon_device *rdev)
        }
 }
 
+/**
+ * evergreen_pm_prepare - pre-power state change callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Prepare for a power state change (evergreen+).
+ */
 void evergreen_pm_prepare(struct radeon_device *rdev)
 {
        struct drm_device *ddev = rdev->ddev;
@@ -310,6 +369,13 @@ void evergreen_pm_prepare(struct radeon_device *rdev)
        }
 }
 
+/**
+ * evergreen_pm_finish - post-power state change callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Clean up after a power state change (evergreen+).
+ */
 void evergreen_pm_finish(struct radeon_device *rdev)
 {
        struct drm_device *ddev = rdev->ddev;
@@ -328,6 +394,15 @@ void evergreen_pm_finish(struct radeon_device *rdev)
        }
 }
 
+/**
+ * evergreen_hpd_sense - hpd sense callback.
+ *
+ * @rdev: radeon_device pointer
+ * @hpd: hpd (hotplug detect) pin
+ *
+ * Checks if a digital monitor is connected (evergreen+).
+ * Returns true if connected, false if not connected.
+ */
 bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
 {
        bool connected = false;
@@ -364,6 +439,14 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
        return connected;
 }
 
+/**
+ * evergreen_hpd_set_polarity - hpd set polarity callback.
+ *
+ * @rdev: radeon_device pointer
+ * @hpd: hpd (hotplug detect) pin
+ *
+ * Set the polarity of the hpd pin (evergreen+).
+ */
 void evergreen_hpd_set_polarity(struct radeon_device *rdev,
                                enum radeon_hpd_id hpd)
 {
@@ -424,10 +507,19 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
        }
 }
 
+/**
+ * evergreen_hpd_init - hpd setup callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Setup the hpd pins used by the card (evergreen+).
+ * Enable the pin, set the polarity, and enable the hpd interrupts.
+ */
 void evergreen_hpd_init(struct radeon_device *rdev)
 {
        struct drm_device *dev = rdev->ddev;
        struct drm_connector *connector;
+       unsigned enabled = 0;
        u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
                DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;
 
@@ -436,73 +528,72 @@ void evergreen_hpd_init(struct radeon_device *rdev)
                switch (radeon_connector->hpd.hpd) {
                case RADEON_HPD_1:
                        WREG32(DC_HPD1_CONTROL, tmp);
-                       rdev->irq.hpd[0] = true;
                        break;
                case RADEON_HPD_2:
                        WREG32(DC_HPD2_CONTROL, tmp);
-                       rdev->irq.hpd[1] = true;
                        break;
                case RADEON_HPD_3:
                        WREG32(DC_HPD3_CONTROL, tmp);
-                       rdev->irq.hpd[2] = true;
                        break;
                case RADEON_HPD_4:
                        WREG32(DC_HPD4_CONTROL, tmp);
-                       rdev->irq.hpd[3] = true;
                        break;
                case RADEON_HPD_5:
                        WREG32(DC_HPD5_CONTROL, tmp);
-                       rdev->irq.hpd[4] = true;
                        break;
                case RADEON_HPD_6:
                        WREG32(DC_HPD6_CONTROL, tmp);
-                       rdev->irq.hpd[5] = true;
                        break;
                default:
                        break;
                }
                radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
+               enabled |= 1 << radeon_connector->hpd.hpd;
        }
-       if (rdev->irq.installed)
-               evergreen_irq_set(rdev);
+       radeon_irq_kms_enable_hpd(rdev, enabled);
 }
 
+/**
+ * evergreen_hpd_fini - hpd tear down callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Tear down the hpd pins used by the card (evergreen+).
+ * Disable the hpd interrupts.
+ */
 void evergreen_hpd_fini(struct radeon_device *rdev)
 {
        struct drm_device *dev = rdev->ddev;
        struct drm_connector *connector;
+       unsigned disabled = 0;
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                switch (radeon_connector->hpd.hpd) {
                case RADEON_HPD_1:
                        WREG32(DC_HPD1_CONTROL, 0);
-                       rdev->irq.hpd[0] = false;
                        break;
                case RADEON_HPD_2:
                        WREG32(DC_HPD2_CONTROL, 0);
-                       rdev->irq.hpd[1] = false;
                        break;
                case RADEON_HPD_3:
                        WREG32(DC_HPD3_CONTROL, 0);
-                       rdev->irq.hpd[2] = false;
                        break;
                case RADEON_HPD_4:
                        WREG32(DC_HPD4_CONTROL, 0);
-                       rdev->irq.hpd[3] = false;
                        break;
                case RADEON_HPD_5:
                        WREG32(DC_HPD5_CONTROL, 0);
-                       rdev->irq.hpd[4] = false;
                        break;
                case RADEON_HPD_6:
                        WREG32(DC_HPD6_CONTROL, 0);
-                       rdev->irq.hpd[5] = false;
                        break;
                default:
                        break;
                }
+               disabled |= 1 << radeon_connector->hpd.hpd;
        }
+       radeon_irq_kms_disable_hpd(rdev, disabled);
 }
 
 /* watermark setup */
@@ -933,6 +1024,14 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
 
 }
 
+/**
+ * evergreen_bandwidth_update - update display watermarks callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Update the display watermarks based on the requested mode(s)
+ * (evergreen+).
+ */
 void evergreen_bandwidth_update(struct radeon_device *rdev)
 {
        struct drm_display_mode *mode0 = NULL;
@@ -956,6 +1055,15 @@ void evergreen_bandwidth_update(struct radeon_device *rdev)
        }
 }
 
+/**
+ * evergreen_mc_wait_for_idle - wait for MC idle callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Wait for the MC (memory controller) to be idle.
+ * (evergreen+).
+ * Returns 0 if the MC is idle, -1 if not.
+ */
 int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
 {
        unsigned i;
@@ -1371,12 +1479,28 @@ void evergreen_mc_program(struct radeon_device *rdev)
  */
 void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
-       struct radeon_ring *ring = &rdev->ring[ib->fence->ring];
+       struct radeon_ring *ring = &rdev->ring[ib->ring];
+       u32 next_rptr;
 
        /* set to DX10/11 mode */
        radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
        radeon_ring_write(ring, 1);
-       /* FIXME: implement */
+
+       if (ring->rptr_save_reg) {
+               next_rptr = ring->wptr + 3 + 4;
+               radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+               radeon_ring_write(ring, ((ring->rptr_save_reg - 
+                                         PACKET3_SET_CONFIG_REG_START) >> 2));
+               radeon_ring_write(ring, next_rptr);
+       } else if (rdev->wb.enabled) {
+               next_rptr = ring->wptr + 5 + 4;
+               radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3));
+               radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
+               radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18));
+               radeon_ring_write(ring, next_rptr);
+               radeon_ring_write(ring, 0);
+       }
+
        radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
        radeon_ring_write(ring,
 #ifdef __BIG_ENDIAN
@@ -2188,6 +2312,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
                RREG32(SRBM_STATUS));
+       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
+               RREG32(CP_STALLED_STAT1));
+       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
+               RREG32(CP_STALLED_STAT2));
+       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
+               RREG32(CP_BUSY_STAT));
+       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
+               RREG32(CP_STAT));
        evergreen_mc_stop(rdev, &save);
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
@@ -2225,6 +2357,14 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
                RREG32(SRBM_STATUS));
+       dev_info(rdev->dev, "  R_008674_CP_STALLED_STAT1 = 0x%08X\n",
+               RREG32(CP_STALLED_STAT1));
+       dev_info(rdev->dev, "  R_008678_CP_STALLED_STAT2 = 0x%08X\n",
+               RREG32(CP_STALLED_STAT2));
+       dev_info(rdev->dev, "  R_00867C_CP_BUSY_STAT     = 0x%08X\n",
+               RREG32(CP_BUSY_STAT));
+       dev_info(rdev->dev, "  R_008680_CP_STAT          = 0x%08X\n",
+               RREG32(CP_STAT));
        evergreen_mc_resume(rdev, &save);
        return 0;
 }
@@ -2348,20 +2488,20 @@ int evergreen_irq_set(struct radeon_device *rdev)
 
        if (rdev->family >= CHIP_CAYMAN) {
                /* enable CP interrupts on all rings */
-               if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
+               if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
                        DRM_DEBUG("evergreen_irq_set: sw int gfx\n");
                        cp_int_cntl |= TIME_STAMP_INT_ENABLE;
                }
-               if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP1_INDEX]) {
+               if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP1_INDEX])) {
                        DRM_DEBUG("evergreen_irq_set: sw int cp1\n");
                        cp_int_cntl1 |= TIME_STAMP_INT_ENABLE;
                }
-               if (rdev->irq.sw_int[CAYMAN_RING_TYPE_CP2_INDEX]) {
+               if (atomic_read(&rdev->irq.ring_int[CAYMAN_RING_TYPE_CP2_INDEX])) {
                        DRM_DEBUG("evergreen_irq_set: sw int cp2\n");
                        cp_int_cntl2 |= TIME_STAMP_INT_ENABLE;
                }
        } else {
-               if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) {
+               if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {
                        DRM_DEBUG("evergreen_irq_set: sw int gfx\n");
                        cp_int_cntl |= RB_INT_ENABLE;
                        cp_int_cntl |= TIME_STAMP_INT_ENABLE;
@@ -2369,32 +2509,32 @@ int evergreen_irq_set(struct radeon_device *rdev)
        }
 
        if (rdev->irq.crtc_vblank_int[0] ||
-           rdev->irq.pflip[0]) {
+           atomic_read(&rdev->irq.pflip[0])) {
                DRM_DEBUG("evergreen_irq_set: vblank 0\n");
                crtc1 |= VBLANK_INT_MASK;
        }
        if (rdev->irq.crtc_vblank_int[1] ||
-           rdev->irq.pflip[1]) {
+           atomic_read(&rdev->irq.pflip[1])) {
                DRM_DEBUG("evergreen_irq_set: vblank 1\n");
                crtc2 |= VBLANK_INT_MASK;
        }
        if (rdev->irq.crtc_vblank_int[2] ||
-           rdev->irq.pflip[2]) {
+           atomic_read(&rdev->irq.pflip[2])) {
                DRM_DEBUG("evergreen_irq_set: vblank 2\n");
                crtc3 |= VBLANK_INT_MASK;
        }
        if (rdev->irq.crtc_vblank_int[3] ||
-           rdev->irq.pflip[3]) {
+           atomic_read(&rdev->irq.pflip[3])) {
                DRM_DEBUG("evergreen_irq_set: vblank 3\n");
                crtc4 |= VBLANK_INT_MASK;
        }
        if (rdev->irq.crtc_vblank_int[4] ||
-           rdev->irq.pflip[4]) {
+           atomic_read(&rdev->irq.pflip[4])) {
                DRM_DEBUG("evergreen_irq_set: vblank 4\n");
                crtc5 |= VBLANK_INT_MASK;
        }
        if (rdev->irq.crtc_vblank_int[5] ||
-           rdev->irq.pflip[5]) {
+           atomic_read(&rdev->irq.pflip[5])) {
                DRM_DEBUG("evergreen_irq_set: vblank 5\n");
                crtc6 |= VBLANK_INT_MASK;
        }
@@ -2676,7 +2816,6 @@ int evergreen_irq_process(struct radeon_device *rdev)
        u32 rptr;
        u32 src_id, src_data;
        u32 ring_index;
-       unsigned long flags;
        bool queue_hotplug = false;
        bool queue_hdmi = false;
 
@@ -2684,22 +2823,21 @@ int evergreen_irq_process(struct radeon_device *rdev)
                return IRQ_NONE;
 
        wptr = evergreen_get_ih_wptr(rdev);
+
+restart_ih:
+       /* is somebody else already processing irqs? */
+       if (atomic_xchg(&rdev->ih.lock, 1))
+               return IRQ_NONE;
+
        rptr = rdev->ih.rptr;
        DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
 
-       spin_lock_irqsave(&rdev->ih.lock, flags);
-       if (rptr == wptr) {
-               spin_unlock_irqrestore(&rdev->ih.lock, flags);
-               return IRQ_NONE;
-       }
-restart_ih:
        /* Order reading of wptr vs. reading of IH ring data */
        rmb();
 
        /* display interrupts */
        evergreen_irq_ack(rdev);
 
-       rdev->ih.wptr = wptr;
        while (rptr != wptr) {
                /* wptr/rptr are in bytes! */
                ring_index = rptr / 4;
@@ -2716,7 +2854,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[0])
+                                       if (atomic_read(&rdev->irq.pflip[0]))
                                                radeon_crtc_handle_flip(rdev, 0);
                                        rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D1 vblank\n");
@@ -2742,7 +2880,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[1])
+                                       if (atomic_read(&rdev->irq.pflip[1]))
                                                radeon_crtc_handle_flip(rdev, 1);
                                        rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D2 vblank\n");
@@ -2768,7 +2906,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[2])
+                                       if (atomic_read(&rdev->irq.pflip[2]))
                                                radeon_crtc_handle_flip(rdev, 2);
                                        rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D3 vblank\n");
@@ -2794,7 +2932,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[3])
+                                       if (atomic_read(&rdev->irq.pflip[3]))
                                                radeon_crtc_handle_flip(rdev, 3);
                                        rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D4 vblank\n");
@@ -2820,7 +2958,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[4])
+                                       if (atomic_read(&rdev->irq.pflip[4]))
                                                radeon_crtc_handle_flip(rdev, 4);
                                        rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D5 vblank\n");
@@ -2846,7 +2984,7 @@ restart_ih:
                                                rdev->pm.vblank_sync = true;
                                                wake_up(&rdev->irq.vblank_queue);
                                        }
-                                       if (rdev->irq.pflip[5])
+                                       if (atomic_read(&rdev->irq.pflip[5]))
                                                radeon_crtc_handle_flip(rdev, 5);
                                        rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT;
                                        DRM_DEBUG("IH: D6 vblank\n");
@@ -2986,7 +3124,6 @@ restart_ih:
                        break;
                case 233: /* GUI IDLE */
                        DRM_DEBUG("IH: GUI idle\n");
-                       rdev->pm.gui_idle = true;
                        wake_up(&rdev->irq.idle_queue);
                        break;
                default:
@@ -2998,17 +3135,19 @@ restart_ih:
                rptr += 16;
                rptr &= rdev->ih.ptr_mask;
        }
-       /* make sure wptr hasn't changed while processing */
-       wptr = evergreen_get_ih_wptr(rdev);
-       if (wptr != rdev->ih.wptr)
-               goto restart_ih;
        if (queue_hotplug)
                schedule_work(&rdev->hotplug_work);
        if (queue_hdmi)
                schedule_work(&rdev->audio_work);
        rdev->ih.rptr = rptr;
        WREG32(IH_RB_RPTR, rdev->ih.rptr);
-       spin_unlock_irqrestore(&rdev->ih.lock, flags);
+       atomic_set(&rdev->ih.lock, 0);
+
+       /* make sure wptr hasn't changed while processing */
+       wptr = evergreen_get_ih_wptr(rdev);
+       if (wptr != rptr)
+               goto restart_ih;
+
        return IRQ_HANDLED;
 }
 
@@ -3096,13 +3235,11 @@ static int evergreen_startup(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_pool_start(rdev);
-       if (r)
-               return r;
-
-       r = radeon_ib_ring_tests(rdev);
-       if (r)
+       r = radeon_ib_pool_init(rdev);
+       if (r) {
+               dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
                return r;
+       }
 
        r = r600_audio_init(rdev);
        if (r) {
@@ -3146,9 +3283,6 @@ int evergreen_suspend(struct radeon_device *rdev)
        struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 
        r600_audio_fini(rdev);
-       /* FIXME: we should wait for ring to be empty */
-       radeon_ib_pool_suspend(rdev);
-       r600_blit_suspend(rdev);
        r700_cp_stop(rdev);
        ring->ready = false;
        evergreen_irq_suspend(rdev);
@@ -3234,20 +3368,14 @@ int evergreen_init(struct radeon_device *rdev)
        if (r)
                return r;
 
-       r = radeon_ib_pool_init(rdev);
        rdev->accel_working = true;
-       if (r) {
-               dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
-               rdev->accel_working = false;
-       }
-
        r = evergreen_startup(rdev);
        if (r) {
                dev_err(rdev->dev, "disabling GPU acceleration\n");
                r700_cp_fini(rdev);
                r600_irq_fini(rdev);
                radeon_wb_fini(rdev);
-               r100_ib_fini(rdev);
+               radeon_ib_pool_fini(rdev);
                radeon_irq_kms_fini(rdev);
                evergreen_pcie_gart_fini(rdev);
                rdev->accel_working = false;
@@ -3274,7 +3402,7 @@ void evergreen_fini(struct radeon_device *rdev)
        r700_cp_fini(rdev);
        r600_irq_fini(rdev);
        radeon_wb_fini(rdev);
-       r100_ib_fini(rdev);
+       radeon_ib_pool_fini(rdev);
        radeon_irq_kms_fini(rdev);
        evergreen_pcie_gart_fini(rdev);
        r600_vram_scratch_fini(rdev);
@@ -3289,7 +3417,8 @@ void evergreen_fini(struct radeon_device *rdev)
 
 void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
 {
-       u32 link_width_cntl, speed_cntl;
+       u32 link_width_cntl, speed_cntl, mask;
+       int ret;
 
        if (radeon_pcie_gen2 == 0)
                return;
@@ -3304,6 +3433,15 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
        if (ASIC_IS_X2(rdev))
                return;
 
+       ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
+       if (ret != 0)
+               return;
+
+       if (!(mask & DRM_PCIE_SPEED_50))
+               return;
+
+       DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
+
        speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
        if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
            (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {