diff options
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/ast/ast_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 76 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_encoders.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_i2c.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreend.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/rs400.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/si.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_tt.c | 2 |
17 files changed, 263 insertions, 97 deletions
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 02e52d543e4..b6b7d70f283 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -177,7 +177,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, static inline void ast_open_key(struct ast_private *ast) { - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xA1, 0xFF, 0x04); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); } #define AST_VIDMEM_SIZE_8M 0x00800000 diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e7e92429d10..8759d699bd8 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2501,10 +2501,22 @@ int drm_mode_getfb(struct drm_device *dev, r->depth = fb->depth; r->bpp = fb->bits_per_pixel; r->pitch = fb->pitches[0]; - if (fb->funcs->create_handle) - ret = fb->funcs->create_handle(fb, file_priv, &r->handle); - else + if (fb->funcs->create_handle) { + if (file_priv->is_master || capable(CAP_SYS_ADMIN)) { + ret = fb->funcs->create_handle(fb, file_priv, + &r->handle); + } else { + /* GET_FB() is an unprivileged ioctl so we must not + * return a buffer-handle to non-master processes! For + * backwards-compatibility reasons, we cannot make + * GET_FB() privileged, so just return an invalid handle + * for non-masters. */ + r->handle = 0; + ret = 0; + } + } else { ret = -ENODEV; + } drm_framebuffer_unreference(fb); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e5e328691e3..c8d16a622f3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1009,6 +1009,34 @@ done: return ret; } +static void i915_error_wake_up(struct drm_i915_private *dev_priv, + bool reset_completed) +{ + struct intel_ring_buffer *ring; + int i; + + /* + * Notify all waiters for GPU completion events that reset state has + * been changed, and that they need to restart their wait after + * checking for potential errors (and bail out to drop locks if there is + * a gpu reset pending so that i915_error_work_func can acquire them). + */ + + /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */ + for_each_ring(ring, dev_priv, i) + wake_up_all(&ring->irq_queue); + + /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */ + wake_up_all(&dev_priv->pending_flip_queue); + + /* + * Signal tasks blocked in i915_gem_wait_for_error that the pending + * reset state is cleared. + */ + if (reset_completed) + wake_up_all(&dev_priv->gpu_error.reset_queue); +} + /** * i915_error_work_func - do process context error handling work * @work: work struct @@ -1023,11 +1051,10 @@ static void i915_error_work_func(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t, gpu_error); struct drm_device *dev = dev_priv->dev; - struct intel_ring_buffer *ring; char *error_event[] = { "ERROR=1", NULL }; char *reset_event[] = { "RESET=1", NULL }; char *reset_done_event[] = { "ERROR=0", NULL }; - int i, ret; + int ret; kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); @@ -1046,8 +1073,16 @@ static void i915_error_work_func(struct work_struct *work) kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); + /* + * All state reset _must_ be completed before we update the + * reset counter, for otherwise waiters might miss the reset + * pending state and not properly drop locks, resulting in + * deadlocks with the reset work. + */ ret = i915_reset(dev); + intel_display_handle_reset(dev); + if (ret == 0) { /* * After all the gem state is reset, increment the reset @@ -1068,12 +1103,11 @@ static void i915_error_work_func(struct work_struct *work) atomic_set(&error->reset_counter, I915_WEDGED); } - for_each_ring(ring, dev_priv, i) - wake_up_all(&ring->irq_queue); - - intel_display_handle_reset(dev); - - wake_up_all(&dev_priv->gpu_error.reset_queue); + /* + * Note: The wake_up also serves as a memory barrier so that + * waiters see the update value of the reset counter atomic_t. + */ + i915_error_wake_up(dev_priv, true); } } @@ -1709,8 +1743,6 @@ static void i915_report_and_clear_eir(struct drm_device *dev) void i915_handle_error(struct drm_device *dev, bool wedged) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - int i; i915_capture_error_state(dev); i915_report_and_clear_eir(dev); @@ -1720,14 +1752,28 @@ void i915_handle_error(struct drm_device *dev, bool wedged) &dev_priv->gpu_error.reset_counter); /* - * Wakeup waiting processes so that the reset work item - * doesn't deadlock trying to grab various locks. + * Wakeup waiting processes so that the reset work function + * i915_error_work_func doesn't deadlock trying to grab various + * locks. By bumping the reset counter first, the woken + * processes will see a reset in progress and back off, + * releasing their locks and then wait for the reset completion. + * We must do this for _all_ gpu waiters that might hold locks + * that the reset work needs to acquire. + * + * Note: The wake_up serves as the required memory barrier to + * ensure that the waiters see the updated value of the reset + * counter atomic_t. */ - for_each_ring(ring, dev_priv, i) - wake_up_all(&ring->irq_queue); + i915_error_wake_up(dev_priv, false); } - queue_work(dev_priv->wq, &dev_priv->gpu_error.work); + /* + * Our reset work can grab modeset locks (since it needs to reset the + * state of outstanding pagelips). Hence it must not be run on our own + * dev-priv->wq work queue for otherwise the flush_work in the pageflip + * code will deadlock. + */ + schedule_work(&dev_priv->gpu_error.work); } static void __always_unused i915_pageflip_stall_check(struct drm_device *dev, int pipe) diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c index f02fd9f443f..a66b27c0fca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c @@ -49,18 +49,23 @@ int nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) { const u32 doff = (or * 0x800); - int load = -EINVAL; + nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); + nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); mdelay(9); udelay(500); - nv_wr32(priv, 0x61a00c + doff, 0x80000000); - load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27; - nv_wr32(priv, 0x61a00c + doff, 0x00000000); + loadval = nv_mask(priv, 0x61a00c + doff, 0xffffffff, 0x00000000); + nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); - return load; + + nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval); + if (!(loadval & 0x80000000)) + return -ETIMEDOUT; + + return (loadval & 0x38000000) >> 27; } int diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 32501f6ec99..16023986d30 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -50,7 +50,7 @@ static char *pre_emph_names[] = { * or from atom. Note that atom operates on * dw units. */ -static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) +void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) { #ifdef __BIG_ENDIAN u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ @@ -100,7 +100,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); - radeon_copy_swap(base, send, send_bytes, true); + radeon_atom_copy_swap(base, send, send_bytes, true); args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); @@ -137,7 +137,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, recv_bytes = recv_size; if (recv && recv_size) - radeon_copy_swap(recv, base + 16, recv_bytes, false); + radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); return recv_bytes; } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 4120d355cad..c272d883260 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1636,8 +1636,12 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) + /* some dce3.x boards have a bug in their transmitter control table. + * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE + * does the same thing and more. + */ + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && + (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index 082338df708..2ca389d1925 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -27,6 +27,8 @@ #include "radeon.h" #include "atom.h" +extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); + #define TARGET_HW_I2C_CLOCK 50 /* these are a limitation of ProcessI2cChannelTransaction not the hw */ @@ -77,7 +79,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, } if (!(flags & HW_I2C_WRITE)) - memcpy(buf, base, num); + radeon_atom_copy_swap(buf, base, num, false); return 0; } diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 687b421f75c..2068df1bf75 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1718,7 +1718,8 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -1741,18 +1742,34 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + } /* second controller of the pair uses second half of the lb */ if (radeon_crtc->crtc_id % 2) tmp += 4; WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 75c05631146..9490972c021 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -810,6 +810,10 @@ # define LATENCY_LOW_WATERMARK(x) ((x) << 0) # define LATENCY_HIGH_WATERMARK(x) ((x) << 16) +#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define IH_RB_CNTL 0x3e00 # define IH_RB_ENABLE (1 << 0) # define IH_IB_SIZE(x) ((x) << 1) /* log2 */ diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index dea6f63c972..239a4074f12 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -715,13 +715,16 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) (ctx->bios + data_offset + le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); + u8 *num_dst_objs = (u8 *) + ((u8 *)router_src_dst_table + 1 + + (router_src_dst_table->ucNumberOfSrc * 2)); + u16 *dst_objs = (u16 *)(num_dst_objs + 1); int enum_id; router.router_id = router_obj_id; - for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; - enum_id++) { + for (enum_id = 0; enum_id < (*num_dst_objs); enum_id++) { if (le16_to_cpu(path->usConnObjectId) == - le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) + le16_to_cpu(dst_objs[enum_id])) break; } @@ -1651,7 +1654,9 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct kfree(edid); } } - record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); + record += fake_edid_record->ucFakeEDIDLength ? + fake_edid_record->ucFakeEDIDLength + 2 : + sizeof(ATOM_FAKE_EDID_PATCH_RECORD); break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2399f25ec03..5a87c9fc78d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1489,6 +1489,24 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { .force = radeon_dvi_force, }; +static const struct drm_connector_funcs radeon_edp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_lvds_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + +static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_lvds_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + void radeon_add_atom_connector(struct drm_device *dev, uint32_t connector_id, @@ -1580,8 +1598,6 @@ radeon_add_atom_connector(struct drm_device *dev, goto failed; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { /* add DP i2c bus */ if (connector_type == DRM_MODE_CONNECTOR_eDP) @@ -1598,6 +1614,10 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_DVIA: default: + drm_connector_init(dev, &radeon_connector->base, + &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); connector->interlace_allowed = true; connector->doublescan_allowed = true; radeon_connector->dac_load_detect = true; @@ -1610,6 +1630,10 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: case DRM_MODE_CONNECTOR_DisplayPort: + drm_connector_init(dev, &radeon_connector->base, + &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); drm_object_attach_property(&radeon_connector->base.base, rdev->mode_info.underscan_property, UNDERSCAN_OFF); @@ -1634,6 +1658,10 @@ radeon_add_atom_connector(struct drm_device *dev, break; case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_eDP: + drm_connector_init(dev, &radeon_connector->base, + &radeon_lvds_bridge_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); drm_object_attach_property(&radeon_connector->base.base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); @@ -1797,7 +1825,7 @@ radeon_add_atom_connector(struct drm_device *dev, goto failed; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { /* add DP i2c bus */ diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 7e265a58141..6337f67637f 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -80,9 +80,11 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) p->relocs[i].lobj.bo = p->relocs[i].robj; p->relocs[i].lobj.written = !!r->write_domain; - /* the first reloc of an UVD job is the - msg and that must be in VRAM */ - if (p->ring == R600_RING_TYPE_UVD_INDEX && i == 0) { + /* the first reloc of an UVD job is the msg and that must be in + VRAM, also but everything into VRAM on AGP cards to avoid + image corruptions */ + if (p->ring == R600_RING_TYPE_UVD_INDEX && + (i == 0 || p->rdev->flags & RADEON_IS_AGP)) { /* TODO: is this still needed for NI+ ? */ p->relocs[i].lobj.domain = RADEON_GEM_DOMAIN_VRAM; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 4f2d4f4c1da..7e292d89920 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -414,6 +414,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) value = rdev->config.si.tile_mode_array; value_size = sizeof(uint32_t)*32; break; + case RADEON_INFO_SI_CP_DMA_COMPUTE: + *value = 1; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 233a9b9fa1f..b8074a8ec75 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -174,10 +174,13 @@ int rs400_gart_enable(struct radeon_device *rdev) /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0, * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */ if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { - WREG32_MC(RS480_MC_MISC_CNTL, - (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN)); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } else { - WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } /* Enable gart */ WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 1a96a16b999..f054a3b6c4b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1467,7 +1467,8 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -1482,16 +1483,30 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + } WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, DC_LB_MEMORY_CONFIG(tmp)); + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: @@ -3796,13 +3811,64 @@ static int si_vm_packet3_ce_check(struct radeon_device *rdev, return 0; } +static int si_vm_packet3_cp_dma_check(u32 *ib, u32 idx) +{ + u32 start_reg, reg, i; + u32 command = ib[idx + 4]; + u32 info = ib[idx + 1]; + u32 idx_value = ib[idx]; + if (command & PACKET3_CP_DMA_CMD_SAS) { + /* src address space is register */ + if (((info & 0x60000000) >> 29) == 0) { + start_reg = idx_value << 2; + if (command & PACKET3_CP_DMA_CMD_SAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad SRC register\n"); + return -EINVAL; + } + } + } + } + } + if (command & PACKET3_CP_DMA_CMD_DAS) { + /* dst address space is register */ + if (((info & 0x00300000) >> 20) == 0) { + start_reg = ib[idx + 2]; + if (command & PACKET3_CP_DMA_CMD_DAIC) { + reg = start_reg; + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } else { + for (i = 0; i < (command & 0x1fffff); i++) { + reg = start_reg + (4 * i); + if (!si_vm_reg_valid(reg)) { + DRM_ERROR("CP DMA Bad DST register\n"); + return -EINVAL; + } + } + } + } + } + return 0; +} + static int si_vm_packet3_gfx_check(struct radeon_device *rdev, u32 *ib, struct radeon_cs_packet *pkt) { + int r; u32 idx = pkt->idx + 1; u32 idx_value = ib[idx]; u32 start_reg, end_reg, reg, i; - u32 command, info; switch (pkt->opcode) { case PACKET3_NOP: @@ -3903,50 +3969,9 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev, } break; case PACKET3_CP_DMA: - command = ib[idx + 4]; - info = ib[idx + 1]; - if (command & PACKET3_CP_DMA_CMD_SAS) { - /* src address space is register */ - if (((info & 0x60000000) >> 29) == 0) { - start_reg = idx_value << 2; - if (command & PACKET3_CP_DMA_CMD_SAIC) { - reg = start_reg; - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad SRC register\n"); - return -EINVAL; - } - } else { - for (i = 0; i < (command & 0x1fffff); i++) { - reg = start_reg + (4 * i); - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad SRC register\n"); - return -EINVAL; - } - } - } - } - } - if (command & PACKET3_CP_DMA_CMD_DAS) { - /* dst address space is register */ - if (((info & 0x00300000) >> 20) == 0) { - start_reg = ib[idx + 2]; - if (command & PACKET3_CP_DMA_CMD_DAIC) { - reg = start_reg; - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad DST register\n"); - return -EINVAL; - } - } else { - for (i = 0; i < (command & 0x1fffff); i++) { - reg = start_reg + (4 * i); - if (!si_vm_reg_valid(reg)) { - DRM_ERROR("CP DMA Bad DST register\n"); - return -EINVAL; - } - } - } - } - } + r = si_vm_packet3_cp_dma_check(ib, idx); + if (r) + return r; break; default: DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode); @@ -3958,6 +3983,7 @@ static int si_vm_packet3_gfx_check(struct radeon_device *rdev, static int si_vm_packet3_compute_check(struct radeon_device *rdev, u32 *ib, struct radeon_cs_packet *pkt) { + int r; u32 idx = pkt->idx + 1; u32 idx_value = ib[idx]; u32 start_reg, reg, i; @@ -4030,6 +4056,11 @@ static int si_vm_packet3_compute_check(struct radeon_device *rdev, return -EINVAL; } break; + case PACKET3_CP_DMA: + r = si_vm_packet3_cp_dma_check(ib, idx); + if (r) + return r; + break; default: DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode); return -EINVAL; diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 8f2d7d4f9b2..8c68e67c784 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -97,6 +97,10 @@ #define DMIF_ADDR_CALC 0xC00 +#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define SRBM_STATUS 0xE50 #define GRBM_RQ_PENDING (1 << 5) #define VMC_BUSY (1 << 8) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 5e93a52d4f2..210d5036516 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -170,7 +170,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) ttm_tt_unbind(ttm); } - if (likely(ttm->pages != NULL)) { + if (ttm->state == tt_unbound) { ttm->bdev->driver->ttm_tt_unpopulate(ttm); } |