Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4aac0473 authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie
Browse files

drm/radeon/kms: clear confusion in GART init/deinit path



GART static one time initialization was mixed up with GART
enabling/disabling which could happen several time for instance
during suspend/resume cycles. This patch splits all GART
handling into 4 differents function. gart_init is for one
time initialization, gart_deinit is called upon module unload
to free resources allocated by gart_init, gart_enable enable
the GART and is intented to be call after first initialization
and at each resume cycle or reset cycle. Finaly gart_disable
stop the GART and is intended to be call at suspend time or
when unloading the module.

Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 21f9a437
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -84,23 +84,28 @@ void r100_pci_gart_tlb_flush(struct radeon_device *rdev)
	 * could end up in wrong address. */
}

int r100_pci_gart_enable(struct radeon_device *rdev)
int r100_pci_gart_init(struct radeon_device *rdev)
{
	uint32_t tmp;
	int r;

	if (rdev->gart.table.ram.ptr) {
		WARN(1, "R100 PCI GART already initialized.\n");
		return 0;
	}
	/* Initialize common gart structure */
	r = radeon_gart_init(rdev);
	if (r) {
	if (r)
		return r;
	}
	if (rdev->gart.table.ram.ptr == NULL) {
	rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
		r = radeon_gart_table_ram_alloc(rdev);
		if (r) {
			return r;
		}
	rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
	rdev->asic->gart_set_page = &r100_pci_gart_set_page;
	return radeon_gart_table_ram_alloc(rdev);
}

int r100_pci_gart_enable(struct radeon_device *rdev)
{
	uint32_t tmp;

	/* discard memory request outside of configured range */
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
	WREG32(RADEON_AIC_CNTL, tmp);
@@ -140,13 +145,11 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
	return 0;
}

int r100_gart_enable(struct radeon_device *rdev)
void r100_pci_gart_fini(struct radeon_device *rdev)
{
	if (rdev->flags & RADEON_IS_AGP) {
	r100_pci_gart_disable(rdev);
		return 0;
	}
	return r100_pci_gart_enable(rdev);
	radeon_gart_table_ram_free(rdev);
	radeon_gart_fini(rdev);
}


@@ -273,9 +276,6 @@ int r100_mc_init(struct radeon_device *rdev)

void r100_mc_fini(struct radeon_device *rdev)
{
	r100_pci_gart_disable(rdev);
	radeon_gart_table_ram_free(rdev);
	radeon_gart_fini(rdev);
}


+45 −63
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ int r100_cp_reset(struct radeon_device *rdev);
int r100_rb2d_reset(struct radeon_device *rdev);
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
int r100_pci_gart_enable(struct radeon_device *rdev);
void r100_pci_gart_disable(struct radeon_device *rdev);
void r100_mc_setup(struct radeon_device *rdev);
void r100_mc_disable_clients(struct radeon_device *rdev);
int r100_gui_wait_for_idle(struct radeon_device *rdev);
@@ -86,26 +85,57 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
	mb();
}

int rv370_pcie_gart_enable(struct radeon_device *rdev)
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;

	if (i < 0 || i > rdev->gart.num_gpu_pages) {
		return -EINVAL;
	}
	addr = (lower_32_bits(addr) >> 8) |
	       ((upper_32_bits(addr) & 0xff) << 24) |
	       0xc;
	/* on x86 we want this to be CPU endian, on powerpc
	 * on powerpc without HW swappers, it'll get swapped on way
	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
	writel(addr, ((void __iomem *)ptr) + (i * 4));
	return 0;
}

int rv370_pcie_gart_init(struct radeon_device *rdev)
{
	uint32_t table_addr;
	uint32_t tmp;
	int r;

	if (rdev->gart.table.vram.robj) {
		WARN(1, "RV370 PCIE GART already initialized.\n");
		return 0;
	}
	/* Initialize common gart structure */
	r = radeon_gart_init(rdev);
	if (r) {
	if (r)
		return r;
	}
	r = rv370_debugfs_pcie_gart_info_init(rdev);
	if (r) {
	if (r)
		DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
	}
	rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
	r = radeon_gart_table_vram_alloc(rdev);
	if (r) {
		return r;
	rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
	rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
	return radeon_gart_table_vram_alloc(rdev);
}

int rv370_pcie_gart_enable(struct radeon_device *rdev)
{
	uint32_t table_addr;
	uint32_t tmp;
	int r;

	if (rdev->gart.table.vram.robj == NULL) {
		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
		return -EINVAL;
	}
	r = radeon_gart_table_vram_pin(rdev);
	if (r)
		return r;
	/* discard memory request outside of configured range */
	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
@@ -145,51 +175,13 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
	}
}

int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
void rv370_pcie_gart_fini(struct radeon_device *rdev)
{
	void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;

	if (i < 0 || i > rdev->gart.num_gpu_pages) {
		return -EINVAL;
	}
	addr = (lower_32_bits(addr) >> 8) |
	       ((upper_32_bits(addr) & 0xff) << 24) |
	       0xc;
	/* on x86 we want this to be CPU endian, on powerpc
	 * on powerpc without HW swappers, it'll get swapped on way
	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
	writel(addr, ((void __iomem *)ptr) + (i * 4));
	return 0;
}

int r300_gart_enable(struct radeon_device *rdev)
{
#if __OS_HAS_AGP
	if (rdev->flags & RADEON_IS_AGP) {
		if (rdev->family > CHIP_RV350) {
	rv370_pcie_gart_disable(rdev);
		} else {
			r100_pci_gart_disable(rdev);
		}
		return 0;
	}
#endif
	if (rdev->flags & RADEON_IS_PCIE) {
		rdev->asic->gart_disable = &rv370_pcie_gart_disable;
		rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
		rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
		return rv370_pcie_gart_enable(rdev);
	}
	if (rdev->flags & RADEON_IS_PCI) {
		rdev->asic->gart_disable = &r100_pci_gart_disable;
		rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
		rdev->asic->gart_set_page = &r100_pci_gart_set_page;
		return r100_pci_gart_enable(rdev);
	}
	return r100_pci_gart_enable(rdev);
	radeon_gart_table_vram_free(rdev);
	radeon_gart_fini(rdev);
}


/*
 * MC
 */
@@ -237,14 +229,6 @@ int r300_mc_init(struct radeon_device *rdev)

void r300_mc_fini(struct radeon_device *rdev)
{
	if (rdev->flags & RADEON_IS_PCIE) {
		rv370_pcie_gart_disable(rdev);
		radeon_gart_table_vram_free(rdev);
	} else {
		r100_pci_gart_disable(rdev);
		radeon_gart_table_ram_free(rdev);
	}
	radeon_gart_fini(rdev);
}


@@ -1299,8 +1283,6 @@ void r300_mc_program(struct radeon_device *rdev)

	/* Stops all mc clients */
	r100_mc_stop(rdev, &save);
	/* Shutdown PCI/PCIE GART */
	radeon_gart_disable(rdev);
	if (rdev->flags & RADEON_IS_AGP) {
		WREG32(R_00014C_MC_AGP_LOCATION,
			S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
+36 −21
Original line number Diff line number Diff line
@@ -161,6 +161,11 @@ int r420_resume(struct radeon_device *rdev)
{
	int r;

	/* Make sur GART are not working */
	if (rdev->flags & RADEON_IS_PCIE)
		rv370_pcie_gart_disable(rdev);
	if (rdev->flags & RADEON_IS_PCI)
		r100_pci_gart_disable(rdev);
	/* Resume clock before doing reset */
	r420_clock_resume(rdev);
	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
@@ -180,9 +185,14 @@ int r420_resume(struct radeon_device *rdev)
	r300_mc_program(rdev);
	/* Initialize GART (initialize after TTM so we can allocate
	 * memory through TTM but finalize after TTM) */
	r = radeon_gart_enable(rdev);
	if (r) {
		dev_err(rdev->dev, "failled initializing GART (%d).\n", r);
	if (rdev->flags & RADEON_IS_PCIE) {
		r = rv370_pcie_gart_enable(rdev);
		if (r)
			return r;
	}
	if (rdev->flags & RADEON_IS_PCI) {
		r = r100_pci_gart_enable(rdev);
		if (r)
			return r;
	}
	r420_pipes_init(rdev);
@@ -212,7 +222,10 @@ int r420_suspend(struct radeon_device *rdev)
	r100_cp_disable(rdev);
	r100_wb_disable(rdev);
	r100_irq_disable(rdev);
	radeon_gart_disable(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
		rv370_pcie_gart_disable(rdev);
	if (rdev->flags & RADEON_IS_PCI)
		r100_pci_gart_disable(rdev);
	return 0;
}

@@ -222,14 +235,10 @@ void r420_fini(struct radeon_device *rdev)
	r100_wb_fini(rdev);
	r100_ib_fini(rdev);
	radeon_gem_fini(rdev);
	if (rdev->flags & RADEON_IS_PCIE) {
		rv370_pcie_gart_disable(rdev);
		radeon_gart_table_vram_free(rdev);
	} else {
		r100_pci_gart_disable(rdev);
		radeon_gart_table_ram_free(rdev);
	}
	radeon_gart_fini(rdev);
	if (rdev->flags & RADEON_IS_PCIE)
		rv370_pcie_gart_fini(rdev);
	if (rdev->flags & RADEON_IS_PCI)
		r100_pci_gart_fini(rdev);
	radeon_agp_fini(rdev);
	radeon_irq_kms_fini(rdev);
	radeon_fence_driver_fini(rdev);
@@ -309,6 +318,16 @@ int r420_init(struct radeon_device *rdev)
	if (r) {
		return r;
	}
	if (rdev->flags & RADEON_IS_PCIE) {
		r = rv370_pcie_gart_init(rdev);
		if (r)
			return r;
	}
	if (rdev->flags & RADEON_IS_PCI) {
		r = r100_pci_gart_init(rdev);
		if (r)
			return r;
	}
	r300_set_reg_safe(rdev);
	r = r420_resume(rdev);
	if (r) {
@@ -318,14 +337,10 @@ int r420_init(struct radeon_device *rdev)
		r100_cp_fini(rdev);
		r100_wb_fini(rdev);
		r100_ib_fini(rdev);
		if (rdev->flags & RADEON_IS_PCIE) {
			rv370_pcie_gart_disable(rdev);
			radeon_gart_table_vram_free(rdev);
		} else {
			r100_pci_gart_disable(rdev);
			radeon_gart_table_ram_free(rdev);
		}
		radeon_gart_fini(rdev);
		if (rdev->flags & RADEON_IS_PCIE)
			rv370_pcie_gart_fini(rdev);
		if (rdev->flags & RADEON_IS_PCI)
			r100_pci_gart_fini(rdev);
		radeon_agp_fini(rdev);
		radeon_irq_kms_fini(rdev);
	}
+0 −5
Original line number Diff line number Diff line
@@ -31,8 +31,6 @@

/* r520,rv530,rv560,rv570,r580 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
int rv370_pcie_gart_enable(struct radeon_device *rdev);
void rv370_pcie_gart_disable(struct radeon_device *rdev);
void r420_pipes_init(struct radeon_device *rdev);
void rs600_mc_disable_clients(struct radeon_device *rdev);
void rs600_disable_vga(struct radeon_device *rdev);
@@ -118,9 +116,6 @@ int r520_mc_init(struct radeon_device *rdev)

void r520_mc_fini(struct radeon_device *rdev)
{
	rv370_pcie_gart_disable(rdev);
	radeon_gart_table_vram_free(rdev);
	radeon_gart_fini(rdev);
}


+38 −15
Original line number Diff line number Diff line
@@ -113,21 +113,34 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
	}
}

int r600_pcie_gart_enable(struct radeon_device *rdev)
int r600_pcie_gart_init(struct radeon_device *rdev)
{
	u32 tmp;
	int r, i;
	int r;

	if (rdev->gart.table.vram.robj) {
		WARN(1, "R600 PCIE GART already initialized.\n");
		return 0;
	}
	/* Initialize common gart structure */
	r = radeon_gart_init(rdev);
	if (r) {
	if (r)
		return r;
	}
	rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
	r = radeon_gart_table_vram_alloc(rdev);
	if (r) {
		return r;
	return radeon_gart_table_vram_alloc(rdev);
}

int r600_pcie_gart_enable(struct radeon_device *rdev)
{
	u32 tmp;
	int r, i;

	if (rdev->gart.table.vram.robj == NULL) {
		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
		return -EINVAL;
	}
	r = radeon_gart_table_vram_pin(rdev);
	if (r)
		return r;
	for (i = 0; i < rdev->gart.num_gpu_pages; i++)
		r600_gart_clear_page(rdev, i);
	/* Setup L2 cache */
@@ -175,10 +188,6 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
	u32 tmp;
	int i;

	/* Clear ptes*/
	for (i = 0; i < rdev->gart.num_gpu_pages; i++)
		r600_gart_clear_page(rdev, i);
	r600_pcie_gart_tlb_flush(rdev);
	/* Disable all tables */
	for (i = 0; i < 7; i++)
		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
@@ -204,6 +213,17 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
	WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
	WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
	WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
	if (rdev->gart.table.vram.robj) {
		radeon_object_kunmap(rdev->gart.table.vram.robj);
		radeon_object_unpin(rdev->gart.table.vram.robj);
	}
}

void r600_pcie_gart_fini(struct radeon_device *rdev)
{
	r600_pcie_gart_disable(rdev);
	radeon_gart_table_vram_free(rdev);
	radeon_gart_fini(rdev);
}

int r600_mc_wait_for_idle(struct radeon_device *rdev)
@@ -1472,6 +1492,7 @@ int r600_suspend(struct radeon_device *rdev)
{
	/* FIXME: we should wait for ring to be empty */
	r600_cp_stop(rdev);
	r600_pcie_gart_disable(rdev);
	return 0;
}

@@ -1548,6 +1569,10 @@ int r600_init(struct radeon_device *rdev)
		}
	}

	r = r600_pcie_gart_init(rdev);
	if (r)
		return r;

	r = r600_resume(rdev);
	if (r) {
		if (rdev->flags & RADEON_IS_AGP) {
@@ -1583,9 +1608,7 @@ void r600_fini(struct radeon_device *rdev)

	r600_blit_fini(rdev);
	radeon_ring_fini(rdev);
	r600_pcie_gart_disable(rdev);
	radeon_gart_table_vram_free(rdev);
	radeon_gart_fini(rdev);
	r600_pcie_gart_fini(rdev);
	radeon_gem_fini(rdev);
	radeon_fence_driver_fini(rdev);
	radeon_clocks_fini(rdev);
Loading