misc: rockchip: pcie-rkep: Support continuous buffer

1.Add continuous buffer support:
    alloc continuous buffer by ioctl PCIE_EP_CONTINUOUS_BUFFER_ALLOC
    free continuous buffer by ioctl PCIE_EP_CONTINUOUS_BUFFER_FREE
    mmap continuous buffer virtual addr by ioctl PCIE_EP_SET_MMAP_RESOURCE_CONTINUOUS_BUFFER
2.Change to record mmap resource index under each task file.

Change-Id: Ib820086dd67b3f0bd2f820232491860b8e170ae3
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2025-08-24 14:33:58 +08:00
committed by Tao Huang
parent 8421327494
commit 8633bf3947
2 changed files with 140 additions and 30 deletions

View File

@@ -34,7 +34,7 @@
#endif #endif
#define DRV_NAME "pcie-rkep" #define DRV_NAME "pcie-rkep"
#define DRV_VERSION 0x00030000 #define DRV_VERSION 0x00030200
#ifndef PCI_VENDOR_ID_ROCKCHIP #ifndef PCI_VENDOR_ID_ROCKCHIP
#define PCI_VENDOR_ID_ROCKCHIP 0x1d87 #define PCI_VENDOR_ID_ROCKCHIP 0x1d87
@@ -115,7 +115,6 @@ struct pcie_rkep {
void __iomem *bar0; void __iomem *bar0;
void __iomem *bar2; void __iomem *bar2;
void __iomem *bar4; void __iomem *bar4;
int cur_mmap_res;
struct pcie_rkep_irq_context irq_ctx[RKEP_NUM_IRQ_VECTORS]; struct pcie_rkep_irq_context irq_ctx[RKEP_NUM_IRQ_VECTORS];
int irq_valid; int irq_valid;
@@ -129,10 +128,22 @@ struct pcie_rkep {
wait_queue_head_t wq_head; wait_queue_head_t wq_head;
}; };
struct pcie_ep_continuous_buffer_req {
struct list_head cont_buffer_list;
uint64_t dma_addr;
void *vir_addr;
u32 size;
};
struct pcie_file { struct pcie_file {
struct mutex file_lock_mutex; struct mutex file_lock_mutex;
struct pcie_rkep *pcie_rkep; struct pcie_rkep *pcie_rkep;
DECLARE_BITMAP(child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX); /* The virtual IDs applied for each task */ DECLARE_BITMAP(child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX); /* The virtual IDs applied for each task */
int cur_mmap_res;
u64 cur_mmap_addr;
/* memory manager */
struct list_head cont_buffer_list;
}; };
static bool pcie_rkep_wait_for_link_up(struct pci_dev *pdev) static bool pcie_rkep_wait_for_link_up(struct pci_dev *pdev)
@@ -325,6 +336,66 @@ static int rkep_ep_poll_irq_user(struct pcie_file *pcie_file, struct pcie_ep_obj
return 0; return 0;
} }
static int rkep_mem_continuous_buffer_alloc(struct pcie_file *pcie_file,
struct pcie_ep_continuous_buffer_param *param)
{
struct pcie_ep_continuous_buffer_req *buffer_req;
struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep;
dma_addr_t dma_addr;
void *vir_addr;
int ret = 0;
mutex_lock(&pcie_file->file_lock_mutex);
vir_addr = dma_alloc_coherent(&pcie_rkep->pdev->dev, param->size,
&dma_addr, GFP_KERNEL);
if (!vir_addr) {
ret = -ENOMEM;
goto unlock;
}
buffer_req = kzalloc(sizeof(*buffer_req), GFP_KERNEL);
if (!buffer_req) {
dma_free_coherent(&pcie_rkep->pdev->dev, param->size, vir_addr, dma_addr);
ret = -ENOMEM;
goto unlock;
}
buffer_req->dma_addr = dma_addr;
param->dma_addr = dma_addr;
list_add(&buffer_req->cont_buffer_list, &pcie_file->cont_buffer_list);
unlock:
mutex_unlock(&pcie_file->file_lock_mutex);
return ret;
}
static int rkep_mem_continuous_buffer_free(struct pcie_file *pcie_file,
struct pcie_ep_continuous_buffer_param *param)
{
struct pcie_ep_continuous_buffer_req *buffer_req, *tmp;
struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep;
int ret = -ENOENT;
mutex_lock(&pcie_file->file_lock_mutex);
list_for_each_entry_safe(buffer_req, tmp, &pcie_file->cont_buffer_list, cont_buffer_list) {
if (buffer_req->dma_addr == param->dma_addr && buffer_req->size == param->size) {
dma_free_coherent(&pcie_rkep->pdev->dev, buffer_req->size,
buffer_req->vir_addr, buffer_req->dma_addr);
list_del(&buffer_req->cont_buffer_list);
kfree(buffer_req);
ret = 0;
break;
}
}
mutex_unlock(&pcie_file->file_lock_mutex);
return ret;
}
static int pcie_rkep_open(struct inode *inode, struct file *file) static int pcie_rkep_open(struct inode *inode, struct file *file)
{ {
struct miscdevice *miscdev = file->private_data; struct miscdevice *miscdev = file->private_data;
@@ -338,6 +409,7 @@ static int pcie_rkep_open(struct inode *inode, struct file *file)
pcie_file->pcie_rkep = pcie_rkep; pcie_file->pcie_rkep = pcie_rkep;
mutex_init(&pcie_file->file_lock_mutex); mutex_init(&pcie_file->file_lock_mutex);
INIT_LIST_HEAD(&pcie_file->cont_buffer_list);
file->private_data = pcie_file; file->private_data = pcie_file;
@@ -348,6 +420,7 @@ static int pcie_rkep_release(struct inode *inode, struct file *file)
{ {
struct pcie_file *pcie_file = file->private_data; struct pcie_file *pcie_file = file->private_data;
struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep;
struct pcie_ep_continuous_buffer_req *buffer_req, *tmp;
int index; int index;
while (1) { while (1) {
@@ -369,7 +442,14 @@ static int pcie_rkep_release(struct inode *inode, struct file *file)
dev_dbg(&pcie_rkep->pdev->dev, "release virtual id %d\n", index); dev_dbg(&pcie_rkep->pdev->dev, "release virtual id %d\n", index);
} }
devm_kfree(&pcie_rkep->pdev->dev, pcie_file); mutex_lock(&pcie_file->file_lock_mutex);
list_for_each_entry_safe(buffer_req, tmp, &pcie_file->cont_buffer_list, cont_buffer_list) {
dma_free_coherent(&pcie_rkep->pdev->dev, buffer_req->size,
buffer_req->vir_addr, buffer_req->dma_addr);
list_del(&buffer_req->cont_buffer_list);
kfree(buffer_req);
}
mutex_unlock(&pcie_file->file_lock_mutex);
return 0; return 0;
} }
@@ -541,7 +621,7 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
resource_size_t bar_size; resource_size_t bar_size;
int err; int err;
switch (pcie_rkep->cur_mmap_res) { switch (pcie_file->cur_mmap_res) {
case PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI: case PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI:
if (size > PCIE_DBI_SIZE) { if (size > PCIE_DBI_SIZE) {
dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n"); dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n");
@@ -608,12 +688,16 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
} }
addr = page_to_phys(pcie_rkep->user_pages); addr = page_to_phys(pcie_rkep->user_pages);
break; break;
case PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER:
addr = pcie_file->cur_mmap_addr;
break;
default: default:
dev_err(&pcie_rkep->pdev->dev, "cur mmap_res %d is unsurreport\n", pcie_rkep->cur_mmap_res); dev_err(&pcie_rkep->pdev->dev, "cur mmap_res %d is unsurreport\n", pcie_file->cur_mmap_res);
return -EINVAL; return -EINVAL;
} }
if (pcie_rkep->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM) if (pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM ||
pcie_file->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
else else
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -629,21 +713,19 @@ static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma)
static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long args) static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{ {
void __user *argp;
struct pcie_file *pcie_file = file->private_data; struct pcie_file *pcie_file = file->private_data;
struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep;
struct pcie_ep_dma_cache_cfg cfg; struct pcie_ep_dma_cache_cfg cfg;
struct pcie_ep_dma_block_req dma; struct pcie_ep_dma_block_req dma;
void __user *uarg = (void __user *)args; void __user *uarg = (void __user *)args;
struct pcie_ep_obj_poll_virtual_id_cfg poll_cfg; struct pcie_ep_obj_poll_virtual_id_cfg poll_cfg;
struct pcie_ep_continuous_buffer_param cont_buf_pram;
int mmap_res; int mmap_res;
int ret; int ret;
int index; int index;
u64 addr; u64 addr;
u32 val; u32 val;
argp = (void __user *)args;
switch (cmd) { switch (cmd) {
case 0x4: case 0x4:
/* get mapped physical address */ /* get mapped physical address */
@@ -652,7 +734,7 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
return -EINVAL; return -EINVAL;
} }
addr = page_to_phys(pcie_rkep->user_pages); addr = page_to_phys(pcie_rkep->user_pages);
if (copy_to_user(argp, &addr, sizeof(addr))) if (copy_to_user(uarg, &addr, sizeof(addr)))
return -EFAULT; return -EFAULT;
break; break;
case PCIE_DMA_CACHE_INVALIDE: case PCIE_DMA_CACHE_INVALIDE:
@@ -695,7 +777,7 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
return -EFAULT; return -EFAULT;
} }
if (copy_to_user(argp, &index, sizeof(index))) if (copy_to_user(uarg, &index, sizeof(index)))
return -EFAULT; return -EFAULT;
break; break;
case PCIE_EP_RELEASE_VIRTUAL_ID: case PCIE_EP_RELEASE_VIRTUAL_ID:
@@ -738,7 +820,7 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
if (ret < 0) if (ret < 0)
return -EFAULT; return -EFAULT;
if (copy_to_user(argp, &poll_cfg, sizeof(poll_cfg))) if (copy_to_user(uarg, &poll_cfg, sizeof(poll_cfg)))
return -EFAULT; return -EFAULT;
break; break;
case PCIE_EP_RAISE_ELBI: case PCIE_EP_RAISE_ELBI:
@@ -768,14 +850,13 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
return -EINVAL; return -EINVAL;
} }
pcie_rkep->cur_mmap_res = mmap_res; pcie_file->cur_mmap_res = mmap_res;
break; break;
case PCIE_EP_GET_FUNC_DRV_VERSION: case PCIE_EP_GET_FUNC_DRV_VERSION:
val = DRV_VERSION; val = DRV_VERSION;
if (copy_to_user(argp, &val, sizeof(val))) if (copy_to_user(uarg, &val, sizeof(val)))
return -EFAULT; return -EFAULT;
break; break;
case PCIE_EP_RESET_CTRL:
#ifdef CONFIG_PCIEASPM_EXT #ifdef CONFIG_PCIEASPM_EXT
dev_info(&pcie_rkep->pdev->dev, "reset controller\n"); dev_info(&pcie_rkep->pdev->dev, "reset controller\n");
return rockchip_dw_pcie_pm_ctrl_for_user(pcie_rkep->pdev, ROCKCHIP_PCIE_PM_CTRL_RESET); return rockchip_dw_pcie_pm_ctrl_for_user(pcie_rkep->pdev, ROCKCHIP_PCIE_PM_CTRL_RESET);
@@ -783,6 +864,27 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
dev_warn(&pcie_rkep->pdev->dev, "reset controller not support\n"); dev_warn(&pcie_rkep->pdev->dev, "reset controller not support\n");
return -EINVAL; return -EINVAL;
#endif #endif
case PCIE_EP_CONTINUOUS_BUFFER_ALLOC:
if (copy_from_user(&cont_buf_pram, uarg, sizeof(cont_buf_pram)))
return -EFAULT;
ret = rkep_mem_continuous_buffer_alloc(pcie_file, &cont_buf_pram);
if (ret) {
dev_err(&pcie_rkep->pdev->dev, "buffer alloc failed, ret=%d\n", ret);
return ret;
}
if (copy_to_user(uarg, &cont_buf_pram, sizeof(cont_buf_pram)))
return -EFAULT;
break;
case PCIE_EP_CONTINUOUS_BUFFER_FREE:
if (copy_from_user(&cont_buf_pram, uarg, sizeof(cont_buf_pram)))
return -EFAULT;
return rkep_mem_continuous_buffer_free(pcie_file, &cont_buf_pram);
case PCIE_EP_SET_MMAP_RESOURCE_CONTINUOUS_BUFFER:
if (copy_from_user(&cont_buf_pram, uarg, sizeof(cont_buf_pram)))
return -EFAULT;
pcie_file->cur_mmap_res = PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER;
pcie_file->cur_mmap_addr = cont_buf_pram.dma_addr;
break;
default: default:
break; break;
} }
@@ -1232,7 +1334,6 @@ static ssize_t rkep_store(struct device *dev, struct device_attribute *attr,
else if (val == 3) else if (val == 3)
writel(RKEP_CMD_LOADER_RUN, pcie_rkep->bar0 + 0x400); writel(RKEP_CMD_LOADER_RUN, pcie_rkep->bar0 + 0x400);
dev_info(dev, "%s done\n", __func__);
return count; return count;
} }
@@ -1348,7 +1449,6 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pcie_dw_dmatest_unregister(pcie_rkep->dma_obj); pcie_dw_dmatest_unregister(pcie_rkep->dma_obj);
goto err_register_obj; goto err_register_obj;
} }
pcie_rkep->cur_mmap_res = PCIE_EP_MMAP_RESOURCE_USER_MEM;
dev_info(&pdev->dev, "successfully allocate continuouse buffer for userspace\n"); dev_info(&pdev->dev, "successfully allocate continuouse buffer for userspace\n");
pci_read_config_word(pcie_rkep->pdev, PCI_VENDOR_ID, &val); pci_read_config_word(pcie_rkep->pdev, PCI_VENDOR_ID, &val);

View File

@@ -71,6 +71,7 @@ enum pcie_ep_mmap_resource {
PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI, PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI,
PCIE_EP_MMAP_RESOURCE_BAR1, PCIE_EP_MMAP_RESOURCE_BAR1,
PCIE_EP_MMAP_RESOURCE_BAR5, PCIE_EP_MMAP_RESOURCE_BAR5,
PCIE_EP_MMAP_RESOURCE_CONTINUOUS_BUFFER,
PCIE_EP_MMAP_RESOURCE_MAX, PCIE_EP_MMAP_RESOURCE_MAX,
}; };
@@ -109,19 +110,28 @@ struct pcie_ep_obj_poll_virtual_id_cfg {
__u32 poll_status; __u32 poll_status;
}; };
struct pcie_ep_continuous_buffer_param {
__u64 dma_addr;
__u32 size;
};
#define PCIE_BASE 'P' #define PCIE_BASE 'P'
#define PCIE_EP_GET_FUNC_DRV_VERSION _IOR(PCIE_BASE, 0, unsigned int) #define PCIE_EP_GET_FUNC_DRV_VERSION _IOR(PCIE_BASE, 0x00, unsigned int)
#define PCIE_DMA_CACHE_INVALIDE _IOW(PCIE_BASE, 1, struct pcie_ep_dma_cache_cfg) #define PCIE_DMA_CACHE_INVALIDE _IOW(PCIE_BASE, 0x01, struct pcie_ep_dma_cache_cfg)
#define PCIE_DMA_CACHE_FLUSH _IOW(PCIE_BASE, 2, struct pcie_ep_dma_cache_cfg) #define PCIE_DMA_CACHE_FLUSH _IOW(PCIE_BASE, 0x02, struct pcie_ep_dma_cache_cfg)
#define PCIE_DMA_IRQ_MASK_ALL _IOW(PCIE_BASE, 3, int) #define PCIE_DMA_IRQ_MASK_ALL _IOW(PCIE_BASE, 0x03, int)
#define PCIE_EP_RAISE_MSI _IOW(PCIE_BASE, 4, int) #define PCIE_EP_RAISE_MSI _IOW(PCIE_BASE, 0x04, int)
#define PCIE_EP_SET_MMAP_RESOURCE _IOW(PCIE_BASE, 6, int) #define PCIE_EP_SET_MMAP_RESOURCE _IOW(PCIE_BASE, 0x06, int)
#define PCIE_EP_RAISE_ELBI _IOW(PCIE_BASE, 7, int) #define PCIE_EP_RAISE_ELBI _IOW(PCIE_BASE, 0x07, int)
#define PCIE_EP_RESET_CTRL _IOW(PCIE_BASE, 8, int) #define PCIE_EP_RESET_CTRL _IOW(PCIE_BASE, 0x08, int)
#define PCIE_EP_REQUEST_VIRTUAL_ID _IOR(PCIE_BASE, 16, int) #define PCIE_EP_REQUEST_VIRTUAL_ID _IOR(PCIE_BASE, 0x10, int)
#define PCIE_EP_RELEASE_VIRTUAL_ID _IOW(PCIE_BASE, 17, int) #define PCIE_EP_RELEASE_VIRTUAL_ID _IOW(PCIE_BASE, 0x11, int)
#define PCIE_EP_RAISE_IRQ_USER _IOW(PCIE_BASE, 18, int) #define PCIE_EP_RAISE_IRQ_USER _IOW(PCIE_BASE, 0x12, int)
#define PCIE_EP_POLL_IRQ_USER _IOW(PCIE_BASE, 19, struct pcie_ep_obj_poll_virtual_id_cfg) #define PCIE_EP_POLL_IRQ_USER _IOW(PCIE_BASE, 0x13, struct pcie_ep_obj_poll_virtual_id_cfg)
#define PCIE_EP_DMA_XFER_BLOCK _IOW(PCIE_BASE, 32, struct pcie_ep_dma_block_req) #define PCIE_EP_DMA_XFER_BLOCK _IOW(PCIE_BASE, 0x20, struct pcie_ep_dma_block_req)
#define PCIE_EP_CONTINUOUS_BUFFER_ALLOC _IOWR(PCIE_BASE, 0x30, struct pcie_ep_continuous_buffer_param)
#define PCIE_EP_CONTINUOUS_BUFFER_FREE _IOW(PCIE_BASE, 0x31, struct pcie_ep_continuous_buffer_param)
#define PCIE_EP_SET_MMAP_RESOURCE_CONTINUOUS_BUFFER _IOW(PCIE_BASE, 0x32, struct pcie_ep_continuous_buffer_param)
#endif #endif