[FreeBSD] IGP gart needs to be un-cached.
Airlied inadvertently discovered that the IGP gart needs to be un-cached for radeon rs485 and rs690 to work. Initial tests by placing a wbinvd() after allocating the gart were successful. This is an attempt at a more appropriate method of achieving success.main
parent
be5fad45ee
commit
740f09bffd
|
@ -39,31 +39,86 @@
|
||||||
#define ATI_PCIE_WRITE 0x4
|
#define ATI_PCIE_WRITE 0x4
|
||||||
#define ATI_PCIE_READ 0x8
|
#define ATI_PCIE_READ 0x8
|
||||||
|
|
||||||
static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
|
static void
|
||||||
struct drm_ati_pcigart_info *gart_info)
|
drm_ati_alloc_pcigart_table_cb(void *arg, bus_dma_segment_t *segs,
|
||||||
|
int nsegs, int error)
|
||||||
{
|
{
|
||||||
drm_dma_handle_t *dmah;
|
struct drm_dma_handle *dmah = arg;
|
||||||
|
|
||||||
DRM_UNLOCK();
|
if (error != 0)
|
||||||
dmah = drm_pci_alloc(dev, gart_info->table_size, PAGE_SIZE,
|
return;
|
||||||
gart_info->table_mask);
|
|
||||||
DRM_LOCK();
|
KASSERT(nsegs == 1,
|
||||||
|
("drm_ati_alloc_pcigart_table_cb: bad dma segment count"));
|
||||||
|
|
||||||
|
dmah->busaddr = segs[0].ds_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_ati_alloc_pcigart_table(struct drm_device *dev,
|
||||||
|
struct drm_ati_pcigart_info *gart_info)
|
||||||
|
{
|
||||||
|
struct drm_dma_handle *dmah;
|
||||||
|
int flags, ret;
|
||||||
|
|
||||||
|
dmah = malloc(sizeof(struct drm_dma_handle), M_DRM, M_ZERO | M_NOWAIT);
|
||||||
if (dmah == NULL)
|
if (dmah == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
DRM_UNLOCK();
|
||||||
|
ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
|
||||||
|
gart_info->table_mask, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
|
||||||
|
NULL, NULL, /* filtfunc, filtfuncargs */
|
||||||
|
gart_info->table_size, 1, /* maxsize, nsegs */
|
||||||
|
gart_info->table_size, /* maxsegsize */
|
||||||
|
BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
|
||||||
|
&dmah->tag);
|
||||||
|
if (ret != 0) {
|
||||||
|
free(dmah, M_DRM);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = BUS_DMA_NOWAIT | BUS_DMA_ZERO;
|
||||||
|
if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
|
||||||
|
flags |= BUS_DMA_NOCACHE;
|
||||||
|
|
||||||
|
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, flags, &dmah->map);
|
||||||
|
if (ret != 0) {
|
||||||
|
bus_dma_tag_destroy(dmah->tag);
|
||||||
|
free(dmah, M_DRM);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
DRM_LOCK();
|
||||||
|
|
||||||
|
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
|
||||||
|
gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||||
|
bus_dma_tag_destroy(dmah->tag);
|
||||||
|
free(dmah, M_DRM);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
dev->sg->dmah = dmah;
|
dev->sg->dmah = dmah;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drm_ati_free_pcigart_table(struct drm_device *dev,
|
static void
|
||||||
struct drm_ati_pcigart_info *gart_info)
|
drm_ati_free_pcigart_table(struct drm_device *dev,
|
||||||
|
struct drm_ati_pcigart_info *gart_info)
|
||||||
{
|
{
|
||||||
drm_pci_free(dev, dev->sg->dmah);
|
struct drm_dma_handle *dmah = dev->sg->dmah;
|
||||||
|
|
||||||
|
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
|
||||||
|
bus_dma_tag_destroy(dmah->tag);
|
||||||
|
free(dmah, M_DRM);
|
||||||
dev->sg->dmah = NULL;
|
dev->sg->dmah = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
|
int
|
||||||
|
drm_ati_pcigart_cleanup(struct drm_device *dev,
|
||||||
|
struct drm_ati_pcigart_info *gart_info)
|
||||||
{
|
{
|
||||||
/* we need to support large memory configurations */
|
/* we need to support large memory configurations */
|
||||||
if (dev->sg == NULL) {
|
if (dev->sg == NULL) {
|
||||||
|
@ -82,17 +137,17 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int drm_ati_pcigart_init(struct drm_device *dev,
|
int
|
||||||
struct drm_ati_pcigart_info *gart_info)
|
drm_ati_pcigart_init(struct drm_device *dev,
|
||||||
|
struct drm_ati_pcigart_info *gart_info)
|
||||||
{
|
{
|
||||||
|
|
||||||
void *address = NULL;
|
void *address = NULL;
|
||||||
unsigned long pages;
|
unsigned long pages;
|
||||||
u32 *pci_gart, page_base;
|
u32 *pci_gart, page_base;
|
||||||
dma_addr_t bus_address = 0;
|
dma_addr_t bus_address = 0;
|
||||||
|
dma_addr_t entry_addr;
|
||||||
int i, j, ret = 0;
|
int i, j, ret = 0;
|
||||||
int max_pages;
|
int max_pages;
|
||||||
dma_addr_t entry_addr;
|
|
||||||
|
|
||||||
/* we need to support large memory configurations */
|
/* we need to support large memory configurations */
|
||||||
if (dev->sg == NULL) {
|
if (dev->sg == NULL) {
|
||||||
|
@ -134,12 +189,14 @@ int drm_ati_pcigart_init(struct drm_device *dev,
|
||||||
page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
|
page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
|
||||||
switch(gart_info->gart_reg_if) {
|
switch(gart_info->gart_reg_if) {
|
||||||
case DRM_ATI_GART_IGP:
|
case DRM_ATI_GART_IGP:
|
||||||
page_base |= (upper_32_bits(entry_addr) & 0xff) << 4;
|
page_base |=
|
||||||
|
(upper_32_bits(entry_addr) & 0xff) << 4;
|
||||||
page_base |= 0xc;
|
page_base |= 0xc;
|
||||||
break;
|
break;
|
||||||
case DRM_ATI_GART_PCIE:
|
case DRM_ATI_GART_PCIE:
|
||||||
page_base >>= 8;
|
page_base >>= 8;
|
||||||
page_base |= (upper_32_bits(entry_addr) & 0xff) << 24;
|
page_base |=
|
||||||
|
(upper_32_bits(entry_addr) & 0xff) << 24;
|
||||||
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
|
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -152,8 +209,6 @@ int drm_ati_pcigart_init(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_MEMORYBARRIER();
|
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
Loading…
Reference in New Issue