diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 1191 | 
1 files changed, 647 insertions, 544 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index fb44e7e4908..8acb34fd3fd 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -65,6 +65,19 @@ MODULE_FIRMWARE(FIRMWARE_R520);  #include "r100_track.h" +/* This files gather functions specifics to: + * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 + * and others in some cases. + */ + +/** + * r100_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 (r1xx-r4xx). + */  void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; @@ -99,128 +112,49 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)  	}  } -/* This files gather functions specifics to: - * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 +/** + * r100_pre_page_flip - pre-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to prepare for pageflip on + * + * Pre-pageflip callback (r1xx-r4xx). + * Enables the pageflip irq (vblank irq).   */ - -int r100_reloc_pitch_offset(struct radeon_cs_parser *p, -			    struct radeon_cs_packet *pkt, -			    unsigned idx, -			    unsigned reg) -{ -	int r; -	u32 tile_flags = 0; -	u32 tmp; -	struct radeon_cs_reloc *reloc; -	u32 value; - -	r = r100_cs_packet_next_reloc(p, &reloc); -	if (r) { -		DRM_ERROR("No reloc for ib[%d]=0x%04X\n", -			  idx, reg); -		r100_cs_dump_packet(p, pkt); -		return r; -	} - -	value = radeon_get_ib_value(p, idx); -	tmp = value & 0x003fffff; -	tmp += (((u32)reloc->lobj.gpu_offset) >> 10); - -	if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) -			tile_flags |= RADEON_DST_TILE_MACRO; -		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { -			if (reg == RADEON_SRC_PITCH_OFFSET) { -				DRM_ERROR("Cannot src blit from microtiled surface\n"); -				r100_cs_dump_packet(p, pkt); -				return -EINVAL; -			} -			tile_flags |= RADEON_DST_TILE_MICRO; -		} - -		tmp |= tile_flags; -		p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; -	} else -		p->ib.ptr[idx] = (value & 0xffc00000) | tmp; -	return 0; -} - -int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, -			     struct radeon_cs_packet *pkt, -			     int idx) -{ -	unsigned c, i; -	struct radeon_cs_reloc *reloc; -	struct r100_cs_track *track; -	int r = 0; -	volatile uint32_t *ib; -	u32 idx_value; - -	ib = p->ib.ptr; -	track = (struct r100_cs_track *)p->track; -	c = radeon_get_ib_value(p, idx++) & 0x1F; -	if (c > 16) { -	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n", -		      pkt->opcode); -	    r100_cs_dump_packet(p, pkt); -	    return -EINVAL; -	} -	track->num_arrays = c; -	for (i = 0; i < (c - 1); i+=2, idx+=3) { -		r = r100_cs_packet_next_reloc(p, &reloc); -		if (r) { -			DRM_ERROR("No reloc for packet3 %d\n", -				  pkt->opcode); -			r100_cs_dump_packet(p, pkt); -			return r; -		} -		idx_value = radeon_get_ib_value(p, idx); -		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); - -		track->arrays[i + 0].esize = idx_value >> 8; -		track->arrays[i + 0].robj = reloc->robj; -		track->arrays[i + 0].esize &= 0x7F; -		r = r100_cs_packet_next_reloc(p, &reloc); -		if (r) { -			DRM_ERROR("No reloc for packet3 %d\n", -				  pkt->opcode); -			r100_cs_dump_packet(p, pkt); -			return r; -		} -		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); -		track->arrays[i + 1].robj = reloc->robj; -		track->arrays[i + 1].esize = idx_value >> 24; -		track->arrays[i + 1].esize &= 0x7F; -	} -	if (c & 1) { -		r = r100_cs_packet_next_reloc(p, &reloc); -		if (r) { -			DRM_ERROR("No reloc for packet3 %d\n", -					  pkt->opcode); -			r100_cs_dump_packet(p, pkt); -			return r; -		} -		idx_value = radeon_get_ib_value(p, idx); -		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); -		track->arrays[i + 0].robj = reloc->robj; -		track->arrays[i + 0].esize = idx_value >> 8; -		track->arrays[i + 0].esize &= 0x7F; -	} -	return r; -} -  void r100_pre_page_flip(struct radeon_device *rdev, int crtc)  {  	/* enable the pflip int */  	radeon_irq_kms_pflip_irq_get(rdev, crtc);  } +/** + * r100_post_page_flip - pos-pageflip callback. + * + * @rdev: radeon_device pointer + * @crtc: crtc to cleanup pageflip on + * + * Post-pageflip callback (r1xx-r4xx). + * Disables the pageflip irq (vblank irq). + */  void r100_post_page_flip(struct radeon_device *rdev, int crtc)  {  	/* disable the pflip int */  	radeon_irq_kms_pflip_irq_put(rdev, crtc);  } +/** + * r100_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 (r1xx-r4xx). + * 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 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; @@ -247,6 +181,15 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  	return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;  } +/** + * r100_pm_get_dynpm_state - look up dynpm power state callback. + * + * @rdev: radeon_device pointer + * + * Look up the optimal power state based on the + * current state of the GPU (r1xx-r5xx). + * Used for dynpm only. + */  void r100_pm_get_dynpm_state(struct radeon_device *rdev)  {  	int i; @@ -329,6 +272,15 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev)  		  pcie_lanes);  } +/** + * r100_pm_init_profile - Initialize power profiles callback. + * + * @rdev: radeon_device pointer + * + * Initialize the power states used in profile mode + * (r1xx-r3xx). + * Used for profile mode only. + */  void r100_pm_init_profile(struct radeon_device *rdev)  {  	/* default */ @@ -368,6 +320,14 @@ void r100_pm_init_profile(struct radeon_device *rdev)  	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;  } +/** + * r100_pm_misc - set additional pm hw parameters callback. + * + * @rdev: radeon_device pointer + * + * Set non-clock parameters associated with a power state + * (voltage, pcie lanes, etc.) (r1xx-r4xx). + */  void r100_pm_misc(struct radeon_device *rdev)  {  	int requested_index = rdev->pm.requested_power_state_index; @@ -459,6 +419,13 @@ void r100_pm_misc(struct radeon_device *rdev)  	}  } +/** + * r100_pm_prepare - pre-power state change callback. + * + * @rdev: radeon_device pointer + * + * Prepare for a power state change (r1xx-r4xx). + */  void r100_pm_prepare(struct radeon_device *rdev)  {  	struct drm_device *ddev = rdev->ddev; @@ -483,6 +450,13 @@ void r100_pm_prepare(struct radeon_device *rdev)  	}  } +/** + * r100_pm_finish - post-power state change callback. + * + * @rdev: radeon_device pointer + * + * Clean up after a power state change (r1xx-r4xx). + */  void r100_pm_finish(struct radeon_device *rdev)  {  	struct drm_device *ddev = rdev->ddev; @@ -507,6 +481,14 @@ void r100_pm_finish(struct radeon_device *rdev)  	}  } +/** + * r100_gui_idle - gui idle callback. + * + * @rdev: radeon_device pointer + * + * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). + * Returns true if idle, false if not. + */  bool r100_gui_idle(struct radeon_device *rdev)  {  	if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) @@ -516,6 +498,15 @@ bool r100_gui_idle(struct radeon_device *rdev)  }  /* hpd for digital panel detect/disconnect */ +/** + * r100_hpd_sense - hpd sense callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Checks if a digital monitor is connected (r1xx-r4xx). + * Returns true if connected, false if not connected. + */  bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)  {  	bool connected = false; @@ -535,6 +526,14 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)  	return connected;  } +/** + * r100_hpd_set_polarity - hpd set polarity callback. + * + * @rdev: radeon_device pointer + * @hpd: hpd (hotplug detect) pin + * + * Set the polarity of the hpd pin (r1xx-r4xx). + */  void r100_hpd_set_polarity(struct radeon_device *rdev,  			   enum radeon_hpd_id hpd)  { @@ -563,47 +562,47 @@ void r100_hpd_set_polarity(struct radeon_device *rdev,  	}  } +/** + * r100_hpd_init - hpd setup callback. + * + * @rdev: radeon_device pointer + * + * Setup the hpd pins used by the card (r1xx-r4xx). + * Set the polarity, and enable the hpd interrupts. + */  void r100_hpd_init(struct radeon_device *rdev)  {  	struct drm_device *dev = rdev->ddev;  	struct drm_connector *connector; +	unsigned enable = 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: -			rdev->irq.hpd[0] = true; -			break; -		case RADEON_HPD_2: -			rdev->irq.hpd[1] = true; -			break; -		default: -			break; -		} +		enable |= 1 << radeon_connector->hpd.hpd;  		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);  	} -	if (rdev->irq.installed) -		r100_irq_set(rdev); +	radeon_irq_kms_enable_hpd(rdev, enable);  } +/** + * r100_hpd_fini - hpd tear down callback. + * + * @rdev: radeon_device pointer + * + * Tear down the hpd pins used by the card (r1xx-r4xx). + * Disable the hpd interrupts. + */  void r100_hpd_fini(struct radeon_device *rdev)  {  	struct drm_device *dev = rdev->ddev;  	struct drm_connector *connector; +	unsigned disable = 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: -			rdev->irq.hpd[0] = false; -			break; -		case RADEON_HPD_2: -			rdev->irq.hpd[1] = false; -			break; -		default: -			break; -		} +		disable |= 1 << radeon_connector->hpd.hpd;  	} +	radeon_irq_kms_disable_hpd(rdev, disable);  }  /* @@ -635,15 +634,6 @@ int r100_pci_gart_init(struct radeon_device *rdev)  	return radeon_gart_table_ram_alloc(rdev);  } -/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ -void r100_enable_bm(struct radeon_device *rdev) -{ -	uint32_t tmp; -	/* Enable bus mastering */ -	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; -	WREG32(RADEON_BUS_CNTL, tmp); -} -  int r100_pci_gart_enable(struct radeon_device *rdev)  {  	uint32_t tmp; @@ -705,18 +695,18 @@ int r100_irq_set(struct radeon_device *rdev)  		WREG32(R_000040_GEN_INT_CNTL, 0);  		return -EINVAL;  	} -	if (rdev->irq.sw_int[RADEON_RING_TYPE_GFX_INDEX]) { +	if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) {  		tmp |= RADEON_SW_INT_ENABLE;  	}  	if (rdev->irq.gui_idle) {  		tmp |= RADEON_GUI_IDLE_MASK;  	}  	if (rdev->irq.crtc_vblank_int[0] || -	    rdev->irq.pflip[0]) { +	    atomic_read(&rdev->irq.pflip[0])) {  		tmp |= RADEON_CRTC_VBLANK_MASK;  	}  	if (rdev->irq.crtc_vblank_int[1] || -	    rdev->irq.pflip[1]) { +	    atomic_read(&rdev->irq.pflip[1])) {  		tmp |= RADEON_CRTC2_VBLANK_MASK;  	}  	if (rdev->irq.hpd[0]) { @@ -782,7 +772,6 @@ int r100_irq_process(struct radeon_device *rdev)  		/* gui idle interrupt */  		if (status & RADEON_GUI_IDLE_STAT) {  			rdev->irq.gui_idle_acked = true; -			rdev->pm.gui_idle = true;  			wake_up(&rdev->irq.idle_queue);  		}  		/* Vertical blank interrupts */ @@ -792,7 +781,7 @@ int r100_irq_process(struct radeon_device *rdev)  				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);  		}  		if (status & RADEON_CRTC2_VBLANK_STAT) { @@ -801,7 +790,7 @@ int r100_irq_process(struct radeon_device *rdev)  				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);  		}  		if (status & RADEON_FP_DETECT_STAT) { @@ -883,7 +872,7 @@ int r100_copy_blit(struct radeon_device *rdev,  		   uint64_t src_offset,  		   uint64_t dst_offset,  		   unsigned num_gpu_pages, -		   struct radeon_fence *fence) +		   struct radeon_fence **fence)  {  	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];  	uint32_t cur_pages; @@ -947,7 +936,7 @@ int r100_copy_blit(struct radeon_device *rdev,  			  RADEON_WAIT_HOST_IDLECLEAN |  			  RADEON_WAIT_DMA_GUI_IDLE);  	if (fence) { -		r = radeon_fence_emit(rdev, fence); +		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);  	}  	radeon_ring_unlock_commit(rdev, ring);  	return r; @@ -1192,6 +1181,14 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)  	}  	ring->ready = true;  	radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + +	if (radeon_ring_supports_scratch_reg(rdev, ring)) { +		r = radeon_scratch_get(rdev, &ring->rptr_save_reg); +		if (r) { +			DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); +			ring->rptr_save_reg = 0; +		} +	}  	return 0;  } @@ -1202,6 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev)  	}  	/* Disable ring */  	r100_cp_disable(rdev); +	radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg);  	radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);  	DRM_INFO("radeon: cp finalized\n");  } @@ -1223,6 +1221,112 @@ void r100_cp_disable(struct radeon_device *rdev)  /*   * CS functions   */ +int r100_reloc_pitch_offset(struct radeon_cs_parser *p, +			    struct radeon_cs_packet *pkt, +			    unsigned idx, +			    unsigned reg) +{ +	int r; +	u32 tile_flags = 0; +	u32 tmp; +	struct radeon_cs_reloc *reloc; +	u32 value; + +	r = r100_cs_packet_next_reloc(p, &reloc); +	if (r) { +		DRM_ERROR("No reloc for ib[%d]=0x%04X\n", +			  idx, reg); +		r100_cs_dump_packet(p, pkt); +		return r; +	} + +	value = radeon_get_ib_value(p, idx); +	tmp = value & 0x003fffff; +	tmp += (((u32)reloc->lobj.gpu_offset) >> 10); + +	if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { +		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +			tile_flags |= RADEON_DST_TILE_MACRO; +		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { +			if (reg == RADEON_SRC_PITCH_OFFSET) { +				DRM_ERROR("Cannot src blit from microtiled surface\n"); +				r100_cs_dump_packet(p, pkt); +				return -EINVAL; +			} +			tile_flags |= RADEON_DST_TILE_MICRO; +		} + +		tmp |= tile_flags; +		p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; +	} else +		p->ib.ptr[idx] = (value & 0xffc00000) | tmp; +	return 0; +} + +int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, +			     struct radeon_cs_packet *pkt, +			     int idx) +{ +	unsigned c, i; +	struct radeon_cs_reloc *reloc; +	struct r100_cs_track *track; +	int r = 0; +	volatile uint32_t *ib; +	u32 idx_value; + +	ib = p->ib.ptr; +	track = (struct r100_cs_track *)p->track; +	c = radeon_get_ib_value(p, idx++) & 0x1F; +	if (c > 16) { +	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n", +		      pkt->opcode); +	    r100_cs_dump_packet(p, pkt); +	    return -EINVAL; +	} +	track->num_arrays = c; +	for (i = 0; i < (c - 1); i+=2, idx+=3) { +		r = r100_cs_packet_next_reloc(p, &reloc); +		if (r) { +			DRM_ERROR("No reloc for packet3 %d\n", +				  pkt->opcode); +			r100_cs_dump_packet(p, pkt); +			return r; +		} +		idx_value = radeon_get_ib_value(p, idx); +		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); + +		track->arrays[i + 0].esize = idx_value >> 8; +		track->arrays[i + 0].robj = reloc->robj; +		track->arrays[i + 0].esize &= 0x7F; +		r = r100_cs_packet_next_reloc(p, &reloc); +		if (r) { +			DRM_ERROR("No reloc for packet3 %d\n", +				  pkt->opcode); +			r100_cs_dump_packet(p, pkt); +			return r; +		} +		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); +		track->arrays[i + 1].robj = reloc->robj; +		track->arrays[i + 1].esize = idx_value >> 24; +		track->arrays[i + 1].esize &= 0x7F; +	} +	if (c & 1) { +		r = r100_cs_packet_next_reloc(p, &reloc); +		if (r) { +			DRM_ERROR("No reloc for packet3 %d\n", +					  pkt->opcode); +			r100_cs_dump_packet(p, pkt); +			return r; +		} +		idx_value = radeon_get_ib_value(p, idx); +		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); +		track->arrays[i + 0].robj = reloc->robj; +		track->arrays[i + 0].esize = idx_value >> 8; +		track->arrays[i + 0].esize &= 0x7F; +	} +	return r; +} +  int r100_cs_parse_packet0(struct radeon_cs_parser *p,  			  struct radeon_cs_packet *pkt,  			  const unsigned *auth, unsigned n, @@ -2048,6 +2152,379 @@ int r100_cs_parse(struct radeon_cs_parser *p)  	return 0;  } +static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) +{ +	DRM_ERROR("pitch                      %d\n", t->pitch); +	DRM_ERROR("use_pitch                  %d\n", t->use_pitch); +	DRM_ERROR("width                      %d\n", t->width); +	DRM_ERROR("width_11                   %d\n", t->width_11); +	DRM_ERROR("height                     %d\n", t->height); +	DRM_ERROR("height_11                  %d\n", t->height_11); +	DRM_ERROR("num levels                 %d\n", t->num_levels); +	DRM_ERROR("depth                      %d\n", t->txdepth); +	DRM_ERROR("bpp                        %d\n", t->cpp); +	DRM_ERROR("coordinate type            %d\n", t->tex_coord_type); +	DRM_ERROR("width round to power of 2  %d\n", t->roundup_w); +	DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); +	DRM_ERROR("compress format            %d\n", t->compress_format); +} + +static int r100_track_compress_size(int compress_format, int w, int h) +{ +	int block_width, block_height, block_bytes; +	int wblocks, hblocks; +	int min_wblocks; +	int sz; + +	block_width = 4; +	block_height = 4; + +	switch (compress_format) { +	case R100_TRACK_COMP_DXT1: +		block_bytes = 8; +		min_wblocks = 4; +		break; +	default: +	case R100_TRACK_COMP_DXT35: +		block_bytes = 16; +		min_wblocks = 2; +		break; +	} + +	hblocks = (h + block_height - 1) / block_height; +	wblocks = (w + block_width - 1) / block_width; +	if (wblocks < min_wblocks) +		wblocks = min_wblocks; +	sz = wblocks * hblocks * block_bytes; +	return sz; +} + +static int r100_cs_track_cube(struct radeon_device *rdev, +			      struct r100_cs_track *track, unsigned idx) +{ +	unsigned face, w, h; +	struct radeon_bo *cube_robj; +	unsigned long size; +	unsigned compress_format = track->textures[idx].compress_format; + +	for (face = 0; face < 5; face++) { +		cube_robj = track->textures[idx].cube_info[face].robj; +		w = track->textures[idx].cube_info[face].width; +		h = track->textures[idx].cube_info[face].height; + +		if (compress_format) { +			size = r100_track_compress_size(compress_format, w, h); +		} else +			size = w * h; +		size *= track->textures[idx].cpp; + +		size += track->textures[idx].cube_info[face].offset; + +		if (size > radeon_bo_size(cube_robj)) { +			DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", +				  size, radeon_bo_size(cube_robj)); +			r100_cs_track_texture_print(&track->textures[idx]); +			return -1; +		} +	} +	return 0; +} + +static int r100_cs_track_texture_check(struct radeon_device *rdev, +				       struct r100_cs_track *track) +{ +	struct radeon_bo *robj; +	unsigned long size; +	unsigned u, i, w, h, d; +	int ret; + +	for (u = 0; u < track->num_texture; u++) { +		if (!track->textures[u].enabled) +			continue; +		if (track->textures[u].lookup_disable) +			continue; +		robj = track->textures[u].robj; +		if (robj == NULL) { +			DRM_ERROR("No texture bound to unit %u\n", u); +			return -EINVAL; +		} +		size = 0; +		for (i = 0; i <= track->textures[u].num_levels; i++) { +			if (track->textures[u].use_pitch) { +				if (rdev->family < CHIP_R300) +					w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); +				else +					w = track->textures[u].pitch / (1 << i); +			} else { +				w = track->textures[u].width; +				if (rdev->family >= CHIP_RV515) +					w |= track->textures[u].width_11; +				w = w / (1 << i); +				if (track->textures[u].roundup_w) +					w = roundup_pow_of_two(w); +			} +			h = track->textures[u].height; +			if (rdev->family >= CHIP_RV515) +				h |= track->textures[u].height_11; +			h = h / (1 << i); +			if (track->textures[u].roundup_h) +				h = roundup_pow_of_two(h); +			if (track->textures[u].tex_coord_type == 1) { +				d = (1 << track->textures[u].txdepth) / (1 << i); +				if (!d) +					d = 1; +			} else { +				d = 1; +			} +			if (track->textures[u].compress_format) { + +				size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; +				/* compressed textures are block based */ +			} else +				size += w * h * d; +		} +		size *= track->textures[u].cpp; + +		switch (track->textures[u].tex_coord_type) { +		case 0: +		case 1: +			break; +		case 2: +			if (track->separate_cube) { +				ret = r100_cs_track_cube(rdev, track, u); +				if (ret) +					return ret; +			} else +				size *= 6; +			break; +		default: +			DRM_ERROR("Invalid texture coordinate type %u for unit " +				  "%u\n", track->textures[u].tex_coord_type, u); +			return -EINVAL; +		} +		if (size > radeon_bo_size(robj)) { +			DRM_ERROR("Texture of unit %u needs %lu bytes but is " +				  "%lu\n", u, size, radeon_bo_size(robj)); +			r100_cs_track_texture_print(&track->textures[u]); +			return -EINVAL; +		} +	} +	return 0; +} + +int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) +{ +	unsigned i; +	unsigned long size; +	unsigned prim_walk; +	unsigned nverts; +	unsigned num_cb = track->cb_dirty ? track->num_cb : 0; + +	if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && +	    !track->blend_read_enable) +		num_cb = 0; + +	for (i = 0; i < num_cb; i++) { +		if (track->cb[i].robj == NULL) { +			DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); +			return -EINVAL; +		} +		size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; +		size += track->cb[i].offset; +		if (size > radeon_bo_size(track->cb[i].robj)) { +			DRM_ERROR("[drm] Buffer too small for color buffer %d " +				  "(need %lu have %lu) !\n", i, size, +				  radeon_bo_size(track->cb[i].robj)); +			DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", +				  i, track->cb[i].pitch, track->cb[i].cpp, +				  track->cb[i].offset, track->maxy); +			return -EINVAL; +		} +	} +	track->cb_dirty = false; + +	if (track->zb_dirty && track->z_enabled) { +		if (track->zb.robj == NULL) { +			DRM_ERROR("[drm] No buffer for z buffer !\n"); +			return -EINVAL; +		} +		size = track->zb.pitch * track->zb.cpp * track->maxy; +		size += track->zb.offset; +		if (size > radeon_bo_size(track->zb.robj)) { +			DRM_ERROR("[drm] Buffer too small for z buffer " +				  "(need %lu have %lu) !\n", size, +				  radeon_bo_size(track->zb.robj)); +			DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", +				  track->zb.pitch, track->zb.cpp, +				  track->zb.offset, track->maxy); +			return -EINVAL; +		} +	} +	track->zb_dirty = false; + +	if (track->aa_dirty && track->aaresolve) { +		if (track->aa.robj == NULL) { +			DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); +			return -EINVAL; +		} +		/* I believe the format comes from colorbuffer0. */ +		size = track->aa.pitch * track->cb[0].cpp * track->maxy; +		size += track->aa.offset; +		if (size > radeon_bo_size(track->aa.robj)) { +			DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " +				  "(need %lu have %lu) !\n", i, size, +				  radeon_bo_size(track->aa.robj)); +			DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", +				  i, track->aa.pitch, track->cb[0].cpp, +				  track->aa.offset, track->maxy); +			return -EINVAL; +		} +	} +	track->aa_dirty = false; + +	prim_walk = (track->vap_vf_cntl >> 4) & 0x3; +	if (track->vap_vf_cntl & (1 << 14)) { +		nverts = track->vap_alt_nverts; +	} else { +		nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; +	} +	switch (prim_walk) { +	case 1: +		for (i = 0; i < track->num_arrays; i++) { +			size = track->arrays[i].esize * track->max_indx * 4; +			if (track->arrays[i].robj == NULL) { +				DRM_ERROR("(PW %u) Vertex array %u no buffer " +					  "bound\n", prim_walk, i); +				return -EINVAL; +			} +			if (size > radeon_bo_size(track->arrays[i].robj)) { +				dev_err(rdev->dev, "(PW %u) Vertex array %u " +					"need %lu dwords have %lu dwords\n", +					prim_walk, i, size >> 2, +					radeon_bo_size(track->arrays[i].robj) +					>> 2); +				DRM_ERROR("Max indices %u\n", track->max_indx); +				return -EINVAL; +			} +		} +		break; +	case 2: +		for (i = 0; i < track->num_arrays; i++) { +			size = track->arrays[i].esize * (nverts - 1) * 4; +			if (track->arrays[i].robj == NULL) { +				DRM_ERROR("(PW %u) Vertex array %u no buffer " +					  "bound\n", prim_walk, i); +				return -EINVAL; +			} +			if (size > radeon_bo_size(track->arrays[i].robj)) { +				dev_err(rdev->dev, "(PW %u) Vertex array %u " +					"need %lu dwords have %lu dwords\n", +					prim_walk, i, size >> 2, +					radeon_bo_size(track->arrays[i].robj) +					>> 2); +				return -EINVAL; +			} +		} +		break; +	case 3: +		size = track->vtx_size * nverts; +		if (size != track->immd_dwords) { +			DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", +				  track->immd_dwords, size); +			DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", +				  nverts, track->vtx_size); +			return -EINVAL; +		} +		break; +	default: +		DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", +			  prim_walk); +		return -EINVAL; +	} + +	if (track->tex_dirty) { +		track->tex_dirty = false; +		return r100_cs_track_texture_check(rdev, track); +	} +	return 0; +} + +void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) +{ +	unsigned i, face; + +	track->cb_dirty = true; +	track->zb_dirty = true; +	track->tex_dirty = true; +	track->aa_dirty = true; + +	if (rdev->family < CHIP_R300) { +		track->num_cb = 1; +		if (rdev->family <= CHIP_RS200) +			track->num_texture = 3; +		else +			track->num_texture = 6; +		track->maxy = 2048; +		track->separate_cube = 1; +	} else { +		track->num_cb = 4; +		track->num_texture = 16; +		track->maxy = 4096; +		track->separate_cube = 0; +		track->aaresolve = false; +		track->aa.robj = NULL; +	} + +	for (i = 0; i < track->num_cb; i++) { +		track->cb[i].robj = NULL; +		track->cb[i].pitch = 8192; +		track->cb[i].cpp = 16; +		track->cb[i].offset = 0; +	} +	track->z_enabled = true; +	track->zb.robj = NULL; +	track->zb.pitch = 8192; +	track->zb.cpp = 4; +	track->zb.offset = 0; +	track->vtx_size = 0x7F; +	track->immd_dwords = 0xFFFFFFFFUL; +	track->num_arrays = 11; +	track->max_indx = 0x00FFFFFFUL; +	for (i = 0; i < track->num_arrays; i++) { +		track->arrays[i].robj = NULL; +		track->arrays[i].esize = 0x7F; +	} +	for (i = 0; i < track->num_texture; i++) { +		track->textures[i].compress_format = R100_TRACK_COMP_NONE; +		track->textures[i].pitch = 16536; +		track->textures[i].width = 16536; +		track->textures[i].height = 16536; +		track->textures[i].width_11 = 1 << 11; +		track->textures[i].height_11 = 1 << 11; +		track->textures[i].num_levels = 12; +		if (rdev->family <= CHIP_RS200) { +			track->textures[i].tex_coord_type = 0; +			track->textures[i].txdepth = 0; +		} else { +			track->textures[i].txdepth = 16; +			track->textures[i].tex_coord_type = 1; +		} +		track->textures[i].cpp = 64; +		track->textures[i].robj = NULL; +		/* CS IB emission code makes sure texture unit are disabled */ +		track->textures[i].enabled = false; +		track->textures[i].lookup_disable = false; +		track->textures[i].roundup_w = true; +		track->textures[i].roundup_h = true; +		if (track->separate_cube) +			for (face = 0; face < 5; face++) { +				track->textures[i].cube_info[face].robj = NULL; +				track->textures[i].cube_info[face].width = 16536; +				track->textures[i].cube_info[face].height = 16536; +				track->textures[i].cube_info[face].offset = 0; +			} +	} +}  /*   * Global GPU functions @@ -2175,6 +2652,15 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)  	return radeon_ring_test_lockup(rdev, ring);  } +/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +void r100_enable_bm(struct radeon_device *rdev) +{ +	uint32_t tmp; +	/* Enable bus mastering */ +	tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; +	WREG32(RADEON_BUS_CNTL, tmp); +} +  void r100_bm_disable(struct radeon_device *rdev)  {  	u32 tmp; @@ -3261,380 +3747,6 @@ void r100_bandwidth_update(struct radeon_device *rdev)  	}  } -static void r100_cs_track_texture_print(struct r100_cs_track_texture *t) -{ -	DRM_ERROR("pitch                      %d\n", t->pitch); -	DRM_ERROR("use_pitch                  %d\n", t->use_pitch); -	DRM_ERROR("width                      %d\n", t->width); -	DRM_ERROR("width_11                   %d\n", t->width_11); -	DRM_ERROR("height                     %d\n", t->height); -	DRM_ERROR("height_11                  %d\n", t->height_11); -	DRM_ERROR("num levels                 %d\n", t->num_levels); -	DRM_ERROR("depth                      %d\n", t->txdepth); -	DRM_ERROR("bpp                        %d\n", t->cpp); -	DRM_ERROR("coordinate type            %d\n", t->tex_coord_type); -	DRM_ERROR("width round to power of 2  %d\n", t->roundup_w); -	DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); -	DRM_ERROR("compress format            %d\n", t->compress_format); -} - -static int r100_track_compress_size(int compress_format, int w, int h) -{ -	int block_width, block_height, block_bytes; -	int wblocks, hblocks; -	int min_wblocks; -	int sz; - -	block_width = 4; -	block_height = 4; - -	switch (compress_format) { -	case R100_TRACK_COMP_DXT1: -		block_bytes = 8; -		min_wblocks = 4; -		break; -	default: -	case R100_TRACK_COMP_DXT35: -		block_bytes = 16; -		min_wblocks = 2; -		break; -	} - -	hblocks = (h + block_height - 1) / block_height; -	wblocks = (w + block_width - 1) / block_width; -	if (wblocks < min_wblocks) -		wblocks = min_wblocks; -	sz = wblocks * hblocks * block_bytes; -	return sz; -} - -static int r100_cs_track_cube(struct radeon_device *rdev, -			      struct r100_cs_track *track, unsigned idx) -{ -	unsigned face, w, h; -	struct radeon_bo *cube_robj; -	unsigned long size; -	unsigned compress_format = track->textures[idx].compress_format; - -	for (face = 0; face < 5; face++) { -		cube_robj = track->textures[idx].cube_info[face].robj; -		w = track->textures[idx].cube_info[face].width; -		h = track->textures[idx].cube_info[face].height; - -		if (compress_format) { -			size = r100_track_compress_size(compress_format, w, h); -		} else -			size = w * h; -		size *= track->textures[idx].cpp; - -		size += track->textures[idx].cube_info[face].offset; - -		if (size > radeon_bo_size(cube_robj)) { -			DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", -				  size, radeon_bo_size(cube_robj)); -			r100_cs_track_texture_print(&track->textures[idx]); -			return -1; -		} -	} -	return 0; -} - -static int r100_cs_track_texture_check(struct radeon_device *rdev, -				       struct r100_cs_track *track) -{ -	struct radeon_bo *robj; -	unsigned long size; -	unsigned u, i, w, h, d; -	int ret; - -	for (u = 0; u < track->num_texture; u++) { -		if (!track->textures[u].enabled) -			continue; -		if (track->textures[u].lookup_disable) -			continue; -		robj = track->textures[u].robj; -		if (robj == NULL) { -			DRM_ERROR("No texture bound to unit %u\n", u); -			return -EINVAL; -		} -		size = 0; -		for (i = 0; i <= track->textures[u].num_levels; i++) { -			if (track->textures[u].use_pitch) { -				if (rdev->family < CHIP_R300) -					w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); -				else -					w = track->textures[u].pitch / (1 << i); -			} else { -				w = track->textures[u].width; -				if (rdev->family >= CHIP_RV515) -					w |= track->textures[u].width_11; -				w = w / (1 << i); -				if (track->textures[u].roundup_w) -					w = roundup_pow_of_two(w); -			} -			h = track->textures[u].height; -			if (rdev->family >= CHIP_RV515) -				h |= track->textures[u].height_11; -			h = h / (1 << i); -			if (track->textures[u].roundup_h) -				h = roundup_pow_of_two(h); -			if (track->textures[u].tex_coord_type == 1) { -				d = (1 << track->textures[u].txdepth) / (1 << i); -				if (!d) -					d = 1; -			} else { -				d = 1; -			} -			if (track->textures[u].compress_format) { - -				size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; -				/* compressed textures are block based */ -			} else -				size += w * h * d; -		} -		size *= track->textures[u].cpp; - -		switch (track->textures[u].tex_coord_type) { -		case 0: -		case 1: -			break; -		case 2: -			if (track->separate_cube) { -				ret = r100_cs_track_cube(rdev, track, u); -				if (ret) -					return ret; -			} else -				size *= 6; -			break; -		default: -			DRM_ERROR("Invalid texture coordinate type %u for unit " -				  "%u\n", track->textures[u].tex_coord_type, u); -			return -EINVAL; -		} -		if (size > radeon_bo_size(robj)) { -			DRM_ERROR("Texture of unit %u needs %lu bytes but is " -				  "%lu\n", u, size, radeon_bo_size(robj)); -			r100_cs_track_texture_print(&track->textures[u]); -			return -EINVAL; -		} -	} -	return 0; -} - -int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) -{ -	unsigned i; -	unsigned long size; -	unsigned prim_walk; -	unsigned nverts; -	unsigned num_cb = track->cb_dirty ? track->num_cb : 0; - -	if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && -	    !track->blend_read_enable) -		num_cb = 0; - -	for (i = 0; i < num_cb; i++) { -		if (track->cb[i].robj == NULL) { -			DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); -			return -EINVAL; -		} -		size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; -		size += track->cb[i].offset; -		if (size > radeon_bo_size(track->cb[i].robj)) { -			DRM_ERROR("[drm] Buffer too small for color buffer %d " -				  "(need %lu have %lu) !\n", i, size, -				  radeon_bo_size(track->cb[i].robj)); -			DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", -				  i, track->cb[i].pitch, track->cb[i].cpp, -				  track->cb[i].offset, track->maxy); -			return -EINVAL; -		} -	} -	track->cb_dirty = false; - -	if (track->zb_dirty && track->z_enabled) { -		if (track->zb.robj == NULL) { -			DRM_ERROR("[drm] No buffer for z buffer !\n"); -			return -EINVAL; -		} -		size = track->zb.pitch * track->zb.cpp * track->maxy; -		size += track->zb.offset; -		if (size > radeon_bo_size(track->zb.robj)) { -			DRM_ERROR("[drm] Buffer too small for z buffer " -				  "(need %lu have %lu) !\n", size, -				  radeon_bo_size(track->zb.robj)); -			DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", -				  track->zb.pitch, track->zb.cpp, -				  track->zb.offset, track->maxy); -			return -EINVAL; -		} -	} -	track->zb_dirty = false; - -	if (track->aa_dirty && track->aaresolve) { -		if (track->aa.robj == NULL) { -			DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); -			return -EINVAL; -		} -		/* I believe the format comes from colorbuffer0. */ -		size = track->aa.pitch * track->cb[0].cpp * track->maxy; -		size += track->aa.offset; -		if (size > radeon_bo_size(track->aa.robj)) { -			DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " -				  "(need %lu have %lu) !\n", i, size, -				  radeon_bo_size(track->aa.robj)); -			DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", -				  i, track->aa.pitch, track->cb[0].cpp, -				  track->aa.offset, track->maxy); -			return -EINVAL; -		} -	} -	track->aa_dirty = false; - -	prim_walk = (track->vap_vf_cntl >> 4) & 0x3; -	if (track->vap_vf_cntl & (1 << 14)) { -		nverts = track->vap_alt_nverts; -	} else { -		nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; -	} -	switch (prim_walk) { -	case 1: -		for (i = 0; i < track->num_arrays; i++) { -			size = track->arrays[i].esize * track->max_indx * 4; -			if (track->arrays[i].robj == NULL) { -				DRM_ERROR("(PW %u) Vertex array %u no buffer " -					  "bound\n", prim_walk, i); -				return -EINVAL; -			} -			if (size > radeon_bo_size(track->arrays[i].robj)) { -				dev_err(rdev->dev, "(PW %u) Vertex array %u " -					"need %lu dwords have %lu dwords\n", -					prim_walk, i, size >> 2, -					radeon_bo_size(track->arrays[i].robj) -					>> 2); -				DRM_ERROR("Max indices %u\n", track->max_indx); -				return -EINVAL; -			} -		} -		break; -	case 2: -		for (i = 0; i < track->num_arrays; i++) { -			size = track->arrays[i].esize * (nverts - 1) * 4; -			if (track->arrays[i].robj == NULL) { -				DRM_ERROR("(PW %u) Vertex array %u no buffer " -					  "bound\n", prim_walk, i); -				return -EINVAL; -			} -			if (size > radeon_bo_size(track->arrays[i].robj)) { -				dev_err(rdev->dev, "(PW %u) Vertex array %u " -					"need %lu dwords have %lu dwords\n", -					prim_walk, i, size >> 2, -					radeon_bo_size(track->arrays[i].robj) -					>> 2); -				return -EINVAL; -			} -		} -		break; -	case 3: -		size = track->vtx_size * nverts; -		if (size != track->immd_dwords) { -			DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", -				  track->immd_dwords, size); -			DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", -				  nverts, track->vtx_size); -			return -EINVAL; -		} -		break; -	default: -		DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", -			  prim_walk); -		return -EINVAL; -	} - -	if (track->tex_dirty) { -		track->tex_dirty = false; -		return r100_cs_track_texture_check(rdev, track); -	} -	return 0; -} - -void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) -{ -	unsigned i, face; - -	track->cb_dirty = true; -	track->zb_dirty = true; -	track->tex_dirty = true; -	track->aa_dirty = true; - -	if (rdev->family < CHIP_R300) { -		track->num_cb = 1; -		if (rdev->family <= CHIP_RS200) -			track->num_texture = 3; -		else -			track->num_texture = 6; -		track->maxy = 2048; -		track->separate_cube = 1; -	} else { -		track->num_cb = 4; -		track->num_texture = 16; -		track->maxy = 4096; -		track->separate_cube = 0; -		track->aaresolve = false; -		track->aa.robj = NULL; -	} - -	for (i = 0; i < track->num_cb; i++) { -		track->cb[i].robj = NULL; -		track->cb[i].pitch = 8192; -		track->cb[i].cpp = 16; -		track->cb[i].offset = 0; -	} -	track->z_enabled = true; -	track->zb.robj = NULL; -	track->zb.pitch = 8192; -	track->zb.cpp = 4; -	track->zb.offset = 0; -	track->vtx_size = 0x7F; -	track->immd_dwords = 0xFFFFFFFFUL; -	track->num_arrays = 11; -	track->max_indx = 0x00FFFFFFUL; -	for (i = 0; i < track->num_arrays; i++) { -		track->arrays[i].robj = NULL; -		track->arrays[i].esize = 0x7F; -	} -	for (i = 0; i < track->num_texture; i++) { -		track->textures[i].compress_format = R100_TRACK_COMP_NONE; -		track->textures[i].pitch = 16536; -		track->textures[i].width = 16536; -		track->textures[i].height = 16536; -		track->textures[i].width_11 = 1 << 11; -		track->textures[i].height_11 = 1 << 11; -		track->textures[i].num_levels = 12; -		if (rdev->family <= CHIP_RS200) { -			track->textures[i].tex_coord_type = 0; -			track->textures[i].txdepth = 0; -		} else { -			track->textures[i].txdepth = 16; -			track->textures[i].tex_coord_type = 1; -		} -		track->textures[i].cpp = 64; -		track->textures[i].robj = NULL; -		/* CS IB emission code makes sure texture unit are disabled */ -		track->textures[i].enabled = false; -		track->textures[i].lookup_disable = false; -		track->textures[i].roundup_w = true; -		track->textures[i].roundup_h = true; -		if (track->separate_cube) -			for (face = 0; face < 5; face++) { -				track->textures[i].cube_info[face].robj = NULL; -				track->textures[i].cube_info[face].width = 16536; -				track->textures[i].cube_info[face].height = 16536; -				track->textures[i].cube_info[face].offset = 0; -			} -	} -} -  int r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)  {  	uint32_t scratch; @@ -3679,6 +3791,12 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)  {  	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; +	if (ring->rptr_save_reg) { +		u32 next_rptr = ring->wptr + 2 + 3; +		radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); +		radeon_ring_write(ring, next_rptr); +	} +  	radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1));  	radeon_ring_write(ring, ib->gpu_addr);  	radeon_ring_write(ring, ib->length_dw); @@ -3711,7 +3829,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)  	ib.ptr[6] = PACKET2(0);  	ib.ptr[7] = PACKET2(0);  	ib.length_dw = 8; -	r = radeon_ib_schedule(rdev, &ib); +	r = radeon_ib_schedule(rdev, &ib, NULL);  	if (r) {  		radeon_scratch_free(rdev, scratch);  		radeon_ib_free(rdev, &ib); @@ -3740,12 +3858,6 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)  	return r;  } -void r100_ib_fini(struct radeon_device *rdev) -{ -	radeon_ib_pool_suspend(rdev); -	radeon_ib_pool_fini(rdev); -} -  void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)  {  	/* Shutdown CP we shouldn't need to do that but better be safe than @@ -3905,13 +4017,11 @@ static int r100_startup(struct radeon_device *rdev)  		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; +	}  	return 0;  } @@ -3948,7 +4058,6 @@ int r100_resume(struct radeon_device *rdev)  int r100_suspend(struct radeon_device *rdev)  { -	radeon_ib_pool_suspend(rdev);  	r100_cp_disable(rdev);  	radeon_wb_disable(rdev);  	r100_irq_disable(rdev); @@ -3961,7 +4070,7 @@ void r100_fini(struct radeon_device *rdev)  {  	r100_cp_fini(rdev);  	radeon_wb_fini(rdev); -	r100_ib_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_gem_fini(rdev);  	if (rdev->flags & RADEON_IS_PCI)  		r100_pci_gart_fini(rdev); @@ -4068,20 +4177,14 @@ int r100_init(struct radeon_device *rdev)  	}  	r100_set_safe_registers(rdev); -	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 = r100_startup(rdev);  	if (r) {  		/* Somethings want wront with the accel init stop accel */  		dev_err(rdev->dev, "Disabling GPU acceleration\n");  		r100_cp_fini(rdev);  		radeon_wb_fini(rdev); -		r100_ib_fini(rdev); +		radeon_ib_pool_fini(rdev);  		radeon_irq_kms_fini(rdev);  		if (rdev->flags & RADEON_IS_PCI)  			r100_pci_gart_fini(rdev);  |