misc: rockchip: pcie-rkep: Support adding virtual id by ioctl

Change-Id: I020ca781ac684caa5fe1c066c1e4b2a65d4891a5
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
This commit is contained in:
Jon Lin
2023-09-19 11:41:55 +08:00
committed by Tao Huang
parent 62e3d6fad9
commit 60c4612d62
2 changed files with 78 additions and 8 deletions

View File

@@ -87,6 +87,8 @@ static DEFINE_MUTEX(rkep_mutex);
#define PCIE_CFG_ELBI_APP_OFFSET 0xe00
#define PCIE_ELBI_REG_NUM 0x2
#define RKEP_EP_VIRTUAL_ID_MAX (8 * 4096)
struct pcie_rkep_msix_context {
struct pci_dev *dev;
u16 msg_id;
@@ -109,6 +111,8 @@ struct pcie_rkep {
struct pcie_ep_obj_info *obj_info;
struct page *user_pages; /* Allocated physical memory for user space */
struct fasync_struct *async;
struct mutex dev_lock_mutex;
DECLARE_BITMAP(virtual_id_bitmap, RKEP_EP_VIRTUAL_ID_MAX);
};
static int rkep_ep_dma_xfer(struct pcie_rkep *pcie_rkep, struct pcie_ep_dma_block_req *dma)
@@ -123,6 +127,43 @@ static int rkep_ep_dma_xfer(struct pcie_rkep *pcie_rkep, struct pcie_ep_dma_bloc
return ret;
}
static int rkep_ep_request_virtual_id(struct pcie_rkep *pcie_rkep)
{
int index;
mutex_lock(&pcie_rkep->dev_lock_mutex);
index = find_first_zero_bit(pcie_rkep->virtual_id_bitmap, RKEP_EP_VIRTUAL_ID_MAX);
if (index > RKEP_EP_VIRTUAL_ID_MAX) {
dev_err(&pcie_rkep->pdev->dev, "request virtual id %d is invalid\n", index);
mutex_unlock(&pcie_rkep->dev_lock_mutex);
return -EINVAL;
}
__set_bit(index, pcie_rkep->virtual_id_bitmap);
mutex_unlock(&pcie_rkep->dev_lock_mutex);
dev_dbg(&pcie_rkep->pdev->dev, "request virtual id %d\n", index);
return index;
}
static int rkep_ep_release_virtual_id(struct pcie_rkep *pcie_rkep, int index)
{
if (index > RKEP_EP_VIRTUAL_ID_MAX) {
dev_err(&pcie_rkep->pdev->dev, "release virtual id %d out of range\n", index);
return -EINVAL;
}
if (!test_bit(index, pcie_rkep->virtual_id_bitmap))
dev_err(&pcie_rkep->pdev->dev, "release virtual id %d is already free\n", index);
mutex_lock(&pcie_rkep->dev_lock_mutex);
__clear_bit(index, pcie_rkep->virtual_id_bitmap);
mutex_unlock(&pcie_rkep->dev_lock_mutex);
return 0;
}
static int pcie_rkep_fasync(int fd, struct file *file, int mode)
{
struct miscdevice *miscdev = file->private_data;
@@ -267,7 +308,7 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
struct pcie_ep_dma_cache_cfg cfg;
struct pcie_ep_dma_block_req dma;
void __user *uarg = (void __user *)args;
int ret;
int ret, index;
u64 addr;
argp = (void __user *)args;
@@ -313,6 +354,32 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long a
dev_err(&pcie_rkep->pdev->dev, "failed to transfer dma, ret=%d\n", ret);
return -EFAULT;
}
break;
case PCIE_EP_REQUEST_VIRTUAL_ID:
index = rkep_ep_request_virtual_id(pcie_rkep);
if (index < 0) {
dev_err(&pcie_rkep->pdev->dev,
"request virtual id failed, ret=%d\n", index);
return -EFAULT;
}
if (copy_to_user(argp, &index, sizeof(index)))
return -EFAULT;
break;
case PCIE_EP_RELEASE_VIRTUAL_ID:
ret = copy_from_user(&index, uarg, sizeof(index));
if (ret) {
dev_err(&pcie_rkep->pdev->dev, "failed to get dma_data copy from userspace\n");
return -EFAULT;
}
ret = rkep_ep_release_virtual_id(pcie_rkep, index);
if (ret < 0) {
dev_err(&pcie_rkep->pdev->dev,
"release virtual id %d failed, ret=%d\n", index, ret);
return -EFAULT;
}
break;
default:
break;
}
@@ -758,6 +825,12 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!pcie_rkep)
return -ENOMEM;
name = devm_kzalloc(&pdev->dev, MISC_DEV_NAME_MAX_LENGTH, GFP_KERNEL);
if (!name)
return -ENOMEM;
__set_bit(0, pcie_rkep->virtual_id_bitmap);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_enable_device failed %d\n", ret);
@@ -796,17 +869,14 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev_dbg(&pdev->dev, "get bar4 address is %p\n", pcie_rkep->bar4);
name = devm_kzalloc(&pdev->dev, MISC_DEV_NAME_MAX_LENGTH, GFP_KERNEL);
if (!name) {
ret = -ENOMEM;
goto err_pci_iomap;
}
sprintf(name, "%s-%s", DRV_NAME, dev_name(&pdev->dev));
pcie_rkep->dev.minor = MISC_DYNAMIC_MINOR;
pcie_rkep->dev.name = name;
pcie_rkep->dev.fops = &pcie_rkep_fops;
pcie_rkep->dev.parent = NULL;
mutex_init(&pcie_rkep->dev_lock_mutex);
ret = misc_register(&pcie_rkep->dev);
if (ret) {
dev_err(&pdev->dev, "failed to register misc device.\n");
@@ -839,8 +909,6 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
}
#if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES)
pcie_rkep->user_pages =
alloc_contig_pages(RKEP_USER_MEM_SIZE >> PAGE_SHIFT, GFP_KERNEL, 0, NULL);

View File

@@ -104,6 +104,8 @@ struct pcie_ep_obj_info {
#define PCIE_DMA_RAISE_MSI_OBJ_IRQ_USER _IOW(PCIE_BASE, 4, int)
#define PCIE_EP_GET_USER_INFO _IOR(PCIE_BASE, 5, struct pcie_ep_user_data)
#define PCIE_EP_SET_MMAP_RESOURCE _IOW(PCIE_BASE, 6, enum pcie_ep_mmap_resource)
#define PCIE_EP_REQUEST_VIRTUAL_ID _IOR(PCIE_BASE, 16, int)
#define PCIE_EP_RELEASE_VIRTUAL_ID _IOW(PCIE_BASE, 17, int)
#define PCIE_EP_DMA_XFER_BLOCK _IOW(PCIE_BASE, 32, struct pcie_ep_dma_block_req)
#endif