Commit b5620901 authored by Jiakun Shuai's avatar Jiakun Shuai
Browse files

drm/phytium: Bugfix Xorg startup for ps23xx when using pe2201 bmc card

phytium inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9NGXP


CVE: NA

--------------------------------------------------------------

When the pe2201 bmc card is detected on ps23xx SoCs, map the card's
graphics memory to device attributes to avoid unnecessary trouble.

Fixes: b2a83bcd ("DRM: Phytium display DRM driver")
Signed-off-by: default avatarWangHao <wanghao1851@phytium.com.cn>
Signed-off-by: default avatarJiakun Shuai <shuaijiakun1288@phytium.com.cn>
parent e38654e6
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ static int phytium_display_load(struct drm_device *dev, unsigned long flags)
		goto failed_modeset_init;
	}

	if (priv->support_memory_type & MEMORY_TYPE_VRAM)
	if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE))
		priv->vram_hw_init(priv);

	ret = drm_irq_install(dev, priv->irq);
@@ -281,8 +281,25 @@ static void phytium_display_unload(struct drm_device *dev)
	drm_mode_config_cleanup(dev);
}

/* phytium display specific ioctls
 * The device specific ioctl range is 0x40 to 0x79.
 */
#define DRM_PHYTIUM_VRAM_TYPE_DEVICE	0x0
#define DRM_IOCTL_PHYTIUM_VRAM_TYPE_DEVICE	DRM_IO(DRM_COMMAND_BASE\
	+ DRM_PHYTIUM_VRAM_TYPE_DEVICE)

static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data,
				struct drm_file *file_priv)
{
	struct phytium_display_private *priv = dev->dev_private;

	return ((priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE) ? 1 : 0);
}

static const struct drm_ioctl_desc phytium_ioctls[] = {
	/* for test, none so far */
	DRM_IOCTL_DEF_DRV(PHYTIUM_VRAM_TYPE_DEVICE, phytium_ioctl_check_vram_device,
						DRM_AUTH|DRM_UNLOCKED),
};

static const struct file_operations phytium_drm_driver_fops = {
@@ -382,7 +399,7 @@ static int phytium_display_pm_resume(struct drm_device *dev)
	phytium_crtc_resume(dev);
	phytium_gem_resume(dev);

	if (priv->support_memory_type & MEMORY_TYPE_VRAM)
	if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE))
		priv->vram_hw_init(priv);

	ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state);
+2 −1
Original line number Diff line number Diff line
@@ -49,9 +49,10 @@ enum phytium_mem_state_type {
	PHYTIUM_MEM_STATE_TYPE_COUNT,
};

#define MEMORY_TYPE_VRAM		0x1
#define MEMORY_TYPE_VRAM_WC		0x1
#define MEMORY_TYPE_SYSTEM_CARVEOUT	0x2
#define MEMORY_TYPE_SYSTEM_UNIFIED	0x4
#define MEMORY_TYPE_VRAM_DEVICE		0x8

#define IS_PLATFORM(priv, p) ((priv)->info.platform_mask & BIT(p))

+17 −8
Original line number Diff line number Diff line
@@ -86,7 +86,8 @@ phytium_gem_prime_get_sg_table(struct drm_gem_object *obj)
		return ERR_PTR(-ENOMEM);
	}

	if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) ||
	if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) ||
	    (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) ||
	    (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT)) {
		ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
		if (ret) {
@@ -280,7 +281,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev)
	int ret = 0;

	list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
		if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
		if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) &&
			(phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE))
			continue;

		phytium_gem_obj->vaddr_save = vmalloc(phytium_gem_obj->size);
@@ -299,7 +301,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev)
	return 0;
malloc_failed:
	list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
		if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
		if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) &&
			(phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE))
			continue;

		if (phytium_gem_obj->vaddr_save) {
@@ -316,7 +319,8 @@ void phytium_gem_resume(struct drm_device *drm_dev)
	struct phytium_gem_object *phytium_gem_obj = NULL;

	list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) {
		if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM)
		if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) &&
			(phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE))
			continue;

		memcpy(phytium_gem_obj->vaddr, phytium_gem_obj->vaddr_save, phytium_gem_obj->size);
@@ -335,7 +339,8 @@ void phytium_gem_free_object(struct drm_gem_object *obj)
	DRM_DEBUG_KMS("free phytium_gem_obj iova:0x%pa size:0x%lx\n",
		      &phytium_gem_obj->iova, phytium_gem_obj->size);
	if (phytium_gem_obj->vaddr) {
		if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) {
		if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) ||
			(phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE)) {
			phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size);
			priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] -= size;
		} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) {
@@ -368,10 +373,14 @@ int phytium_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma)
	vma->vm_pgoff = 0;
	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);

	if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) {
	if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) {
		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
		ret = remap_pfn_range(vma, vma->vm_start, pfn,
			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
	} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) {
		vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
		ret = remap_pfn_range(vma, vma->vm_start, pfn,
			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
	} else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) {
		ret = remap_pfn_range(vma, vma->vm_start, pfn,
				      vma->vm_end - vma->vm_start, vma->vm_page_prot);
@@ -434,7 +443,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns
		goto failed_object_init;
	}

	if (priv->support_memory_type & MEMORY_TYPE_VRAM) {
	if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) {
		ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr,
						&phytium_gem_obj->phys_addr, size);
		if (ret) {
@@ -442,7 +451,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns
			goto failed_dma_alloc;
		}
		phytium_gem_obj->iova = phytium_gem_obj->phys_addr;
		phytium_gem_obj->memory_type = MEMORY_TYPE_VRAM;
		phytium_gem_obj->memory_type = priv->support_memory_type;
		priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] += size;
	} else if (priv->support_memory_type & MEMORY_TYPE_SYSTEM_CARVEOUT) {
		ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr,
+29 −4
Original line number Diff line number Diff line
@@ -27,6 +27,24 @@ void phytium_pci_vram_hw_init(struct phytium_display_private *priv)
	pci_priv->dc_hw_vram_init(priv, priv->pool_phys_addr, priv->pool_size);
}

static bool phytium_pci_host_is_5c01(struct pci_bus *bus)
{
	struct pci_bus *child = bus;
	struct pci_dev *root = NULL;

	while (child) {
		if (child->parent->parent)
			child = child->parent;
		else
			break;
	}

	root = child->self;
	if ((root->vendor == 0x1db7) && (root->device == 0x5c01))
		return true;
	return false;
}

int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *priv)
{
	int ret = 0;
@@ -34,8 +52,15 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *
	priv->pool_phys_addr = pci_resource_start(pdev, 2);
	priv->pool_size = pci_resource_len(pdev, 2);
	if ((priv->pool_phys_addr != 0) && (priv->pool_size != 0)) {
		if ((pdev->device == 0xdc3e) && phytium_pci_host_is_5c01(pdev->bus)) {
			priv->pool_virt_addr = devm_ioremap(&pdev->dev, priv->pool_phys_addr,
					       priv->pool_size);
			priv->support_memory_type = MEMORY_TYPE_VRAM_DEVICE;
		} else {
			priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr,
					       priv->pool_size);
			priv->support_memory_type = MEMORY_TYPE_VRAM_WC;
		}
		if (priv->pool_virt_addr == NULL) {
			DRM_ERROR("pci vram ioremap fail, addr:0x%llx, size:0x%llx\n",
				   priv->pool_phys_addr, priv->pool_size);
@@ -47,7 +72,6 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *
			goto failed_init_memory_pool;

		priv->mem_state[PHYTIUM_MEM_VRAM_TOTAL] = priv->pool_size;
		priv->support_memory_type = MEMORY_TYPE_VRAM;
		priv->vram_hw_init = phytium_pci_vram_hw_init;
	} else {
		DRM_DEBUG_KMS("not support vram\n");
@@ -67,7 +91,8 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *

void phytium_pci_vram_fini(struct pci_dev *pdev, struct phytium_display_private *priv)
{
	if (priv->support_memory_type == MEMORY_TYPE_VRAM) {
	if ((priv->support_memory_type == MEMORY_TYPE_VRAM_WC) ||
		(priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE)) {
		phytium_memory_pool_fini(&pdev->dev, priv);
		devm_iounmap(&pdev->dev, priv->pool_virt_addr);
	}