From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/misc/rockchip/pcie-rkep.c | 1032 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 764 insertions(+), 268 deletions(-) diff --git a/kernel/drivers/misc/rockchip/pcie-rkep.c b/kernel/drivers/misc/rockchip/pcie-rkep.c index 12caa41..7f5ba5a 100644 --- a/kernel/drivers/misc/rockchip/pcie-rkep.c +++ b/kernel/drivers/misc/rockchip/pcie-rkep.c @@ -19,10 +19,16 @@ #include <linux/mutex.h> #include <linux/ctype.h> #include <linux/of.h> +#include <linux/interrupt.h> +#include <linux/iopoll.h> + #include <uapi/linux/rk-pcie-ep.h> #include "../../pci/controller/rockchip-pcie-dma.h" #include "../../pci/controller/dwc/pcie-dw-dmatest.h" +#if IS_MODULE(CONFIG_PCIE_FUNC_RKEP) && IS_ENABLED(CONFIG_PCIE_DW_DMATEST) +#include "../../pci/controller/dwc/pcie-dw-dmatest.c" +#endif #define DRV_NAME "pcie-rkep" @@ -34,8 +40,7 @@ static DEFINE_MUTEX(rkep_mutex); #define BAR_0_SZ SZ_4M -#define RKEP_NUM_MSI_VECTORS 4 -#define RKEP_NUM_MSIX_VECTORS 8 +#define RKEP_NUM_IRQ_VECTORS 4 #define PCIe_CLIENT_MSI_IRQ_OBJ 0 /* rockchip ep object special irq */ @@ -50,12 +55,16 @@ #define PCIE_DMA_WR_SAR_PTR_HI 0x210 #define PCIE_DMA_WR_DAR_PTR_LO 0x214 #define PCIE_DMA_WR_DAR_PTR_HI 0x218 +#define PCIE_DMA_WR_LL_PTR_LO 0x21c +#define PCIE_DMA_WR_LL_PTR_HI 0x220 #define PCIE_DMA_WR_WEILO 0x18 #define PCIE_DMA_WR_WEIHI 0x1c #define PCIE_DMA_WR_DOORBELL 0x10 #define PCIE_DMA_WR_INT_STATUS 0x4c #define PCIE_DMA_WR_INT_MASK 0x54 #define PCIE_DMA_WR_INT_CLEAR 0x58 +#define PCIE_DMA_WR_ERR_STATUS 0x5c +#define PCIE_DMA_WR_LL_ERR_EN 0x90 #define PCIE_DMA_RD_ENB 0x2c #define PCIE_DMA_RD_CTRL_LO 0x300 @@ -65,24 +74,36 @@ #define PCIE_DMA_RD_SAR_PTR_HI 0x310 #define PCIE_DMA_RD_DAR_PTR_LO 0x314 #define PCIE_DMA_RD_DAR_PTR_HI 0x318 +#define PCIE_DMA_RD_LL_PTR_LO 0x31c +#define PCIE_DMA_RD_LL_PTR_HI 0x320 #define PCIE_DMA_RD_WEILO 0x38 #define PCIE_DMA_RD_WEIHI 0x3c #define PCIE_DMA_RD_DOORBELL 0x30 #define PCIE_DMA_RD_INT_STATUS 0xa0 #define PCIE_DMA_RD_INT_MASK 0xa8 #define PCIE_DMA_RD_INT_CLEAR 0xac +#define PCIE_DMA_RD_ERR_STATUS_LOW 0xb8 +#define PCIE_DMA_RD_ERR_STATUS_HIGH 0xbc +#define PCIE_DMA_RD_LL_ERR_EN 0xc4 #define PCIE_DMA_CHANEL_MAX_NUM 2 #define RKEP_USER_MEM_SIZE SZ_64M #define PCIE_CFG_ELBI_APP_OFFSET 0xe00 +#define PCIE_CFG_ELBI_USER_DATA_OFF 0x10 + #define PCIE_ELBI_REG_NUM 0x2 -struct pcie_rkep_msix_context { +#define RKEP_EP_ELBI_TIEMOUT_US 100000 + +#define PCIE_RK3568_RC_DBI_BASE 0xf6000000 +#define PCIE_RK3588_RC_DBI_BASE 0xf5000000 +#define PCIE_DBI_SIZE 0x400000 + +struct pcie_rkep_irq_context { struct pci_dev *dev; u16 msg_id; - u8 *name; }; struct pcie_rkep { @@ -90,54 +111,212 @@ void __iomem *bar0; void __iomem *bar2; void __iomem *bar4; - bool in_used; + int cur_mmap_res; + struct pcie_rkep_irq_context irq_ctx[RKEP_NUM_IRQ_VECTORS]; + int irq_valid; + struct miscdevice dev; - struct msix_entry msix_entries[RKEP_NUM_MSIX_VECTORS]; - struct pcie_rkep_msix_context msix_ctx[RKEP_NUM_MSIX_VECTORS]; - struct pcie_rkep_msix_context msi_ctx[RKEP_NUM_MSI_VECTORS]; - bool msi_enable; - bool msix_enable; struct dma_trx_obj *dma_obj; 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; /* Sync resources in multi-process, such as vid and ELBI0 */ + DECLARE_BITMAP(virtual_id_bitmap, RKEP_EP_VIRTUAL_ID_MAX); + DECLARE_BITMAP(virtual_id_irq_bitmap, RKEP_EP_VIRTUAL_ID_MAX); + wait_queue_head_t wq_head; }; -static int pcie_rkep_fasync(int fd, struct file *file, int mode) -{ - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); +struct pcie_file { + struct mutex file_lock_mutex; + struct pcie_rkep *pcie_rkep; + DECLARE_BITMAP(child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX); /* The virtual IDs applied for each task */ +}; - return fasync_helper(fd, file, mode, &pcie_rkep->async); +static int rkep_ep_dma_xfer(struct pcie_rkep *pcie_rkep, struct pcie_ep_dma_block_req *dma) +{ + int ret; + + if (dma->wr) + ret = pcie_dw_wired_dma_tobus_block(pcie_rkep->dma_obj, dma->chn, dma->block.bus_paddr, dma->block.local_paddr, dma->block.size); + else + ret = pcie_dw_wired_dma_frombus_block(pcie_rkep->dma_obj, dma->chn, dma->block.local_paddr, dma->block.bus_paddr, dma->block.size); + + return ret; +} + +static int rkep_ep_request_virtual_id(struct pcie_file *pcie_file) +{ + struct pcie_rkep *pcie_rkep = pcie_file->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); + + mutex_lock(&pcie_file->file_lock_mutex); + set_bit(index, pcie_file->child_vid_bitmap); + mutex_unlock(&pcie_file->file_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_file *pcie_file, int index) +{ + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + + 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_file->file_lock_mutex); + __clear_bit(index, pcie_file->child_vid_bitmap); + mutex_unlock(&pcie_file->file_lock_mutex); + + mutex_lock(&pcie_rkep->dev_lock_mutex); + __clear_bit(index, pcie_rkep->virtual_id_bitmap); + mutex_unlock(&pcie_rkep->dev_lock_mutex); + + dev_dbg(&pcie_rkep->pdev->dev, "release virtual id %d\n", index); + + return 0; +} + +static int rkep_ep_raise_elbi_irq(struct pcie_file *pcie_file, u32 interrupt_num) +{ + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + u32 index, off; + int i, gap_us = 100; + u32 val; + int ret; + + if (interrupt_num >= (PCIE_ELBI_REG_NUM * 16)) { + dev_err(&pcie_rkep->pdev->dev, "elbi int num out of max count\n"); + return -EINVAL; + } + + index = interrupt_num / 16; + off = interrupt_num % 16; + + for (i = 0; i < RKEP_EP_ELBI_TIEMOUT_US; i += gap_us) { + pci_read_config_dword(pcie_rkep->pdev, PCIE_CFG_ELBI_APP_OFFSET + 4 * index, &val); + if (val & BIT(off)) + usleep_range(gap_us, gap_us + 10); + else + break; + } + + if (i >= gap_us) + dev_err(&pcie_rkep->pdev->dev, "elbi int is not clear, status=%x\n", val); + + ret = pci_write_config_dword(pcie_rkep->pdev, PCIE_CFG_ELBI_APP_OFFSET + 4 * index, + (1 << (off + 16)) | (1 << off)); + + return ret; +} + +static int rkep_ep_raise_irq_user_obj(struct pcie_file *pcie_file, u32 index) +{ + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + int ret; + + if (index >= RKEP_EP_VIRTUAL_ID_MAX) { + dev_err(&pcie_rkep->pdev->dev, "raise irq_user, virtual id %d out of range\n", index); + + return -EINVAL; + } + + pcie_rkep->obj_info->irq_type_ep = OBJ_IRQ_USER; + pcie_rkep->obj_info->irq_user_data_ep = index; + mutex_lock(&pcie_rkep->dev_lock_mutex); + ret = rkep_ep_raise_elbi_irq(pcie_file, 0); + mutex_unlock(&pcie_rkep->dev_lock_mutex); + + return ret; +} + +static int rkep_ep_poll_irq_user(struct pcie_file *pcie_file, struct pcie_ep_obj_poll_virtual_id_cfg *cfg) +{ + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + u32 index = cfg->virtual_id; + + if (index >= RKEP_EP_VIRTUAL_ID_MAX) { + dev_err(&pcie_rkep->pdev->dev, "poll irq_user, virtual id %d out of range\n", index); + + return -EINVAL; + } + + cfg->poll_status = NSIGPOLL; + if (cfg->sync) { + wait_event_interruptible(pcie_rkep->wq_head, + test_bit(index, pcie_rkep->virtual_id_irq_bitmap)); + } else { + wait_event_interruptible_timeout(pcie_rkep->wq_head, + test_bit(index, pcie_rkep->virtual_id_irq_bitmap), + cfg->timeout_ms); + } + if (test_and_clear_bit(index, pcie_rkep->virtual_id_irq_bitmap)) + cfg->poll_status = POLL_IN; + + dev_dbg(&pcie_rkep->pdev->dev, "poll virtual id %d, ret=%d\n", index, cfg->poll_status); + + return 0; } static int pcie_rkep_open(struct inode *inode, struct file *file) { struct miscdevice *miscdev = file->private_data; struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); - int ret = 0; + struct pcie_file *pcie_file = NULL; - mutex_lock(&rkep_mutex); + pcie_file = devm_kzalloc(&pcie_rkep->pdev->dev, sizeof(struct pcie_file), GFP_KERNEL); + if (!pcie_file) + return -ENOMEM; - if (pcie_rkep->in_used) - ret = -EINVAL; - else - pcie_rkep->in_used = true; + pcie_file->pcie_rkep = pcie_rkep; - mutex_unlock(&rkep_mutex); + mutex_init(&pcie_file->file_lock_mutex); - return ret; + file->private_data = pcie_file; + + return 0; } static int pcie_rkep_release(struct inode *inode, struct file *file) { - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); + struct pcie_file *pcie_file = file->private_data; + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + int index; - mutex_lock(&rkep_mutex); - pcie_rkep->in_used = false; - pcie_rkep_fasync(-1, file, 0); - mutex_unlock(&rkep_mutex); + while (1) { + mutex_lock(&pcie_file->file_lock_mutex); + index = find_first_bit(pcie_file->child_vid_bitmap, RKEP_EP_VIRTUAL_ID_MAX); + + if (index >= RKEP_EP_VIRTUAL_ID_MAX) + break; + + __clear_bit(index, pcie_file->child_vid_bitmap); + mutex_unlock(&pcie_file->file_lock_mutex); + + mutex_lock(&pcie_rkep->dev_lock_mutex); + __clear_bit(index, pcie_rkep->virtual_id_bitmap); + mutex_unlock(&pcie_rkep->dev_lock_mutex); + + dev_dbg(&pcie_rkep->pdev->dev, "release virtual id %d\n", index); + } + + devm_kfree(&pcie_rkep->pdev->dev, pcie_file); return 0; } @@ -145,96 +324,240 @@ static ssize_t pcie_rkep_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); - u32 *bar0_buf; - int loop, i = 0; - size_t raw_count = count; + struct pcie_file *pcie_file = file->private_data; + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + struct pci_dev *dev = pcie_rkep->pdev; + unsigned int size = count; + loff_t init_off = *ppos, off = *ppos; + u8 *data; - count = (count % 4) ? (count - count % 4) : count; - - if (count > BAR_0_SZ) - return -EINVAL; - - bar0_buf = kzalloc(count, GFP_KERNEL); - if (!bar0_buf) + data = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); + if (!data) return -ENOMEM; - if (copy_from_user(bar0_buf, buf, count)) { - raw_count = -EFAULT; - goto exit; + if (off > dev->cfg_size) { + kfree(data); + return 0; + } + if (off + count > dev->cfg_size) { + size = dev->cfg_size - off; + count = size; } - for (loop = 0; loop < count / 4; loop++) { - iowrite32(bar0_buf[i], pcie_rkep->bar0 + loop * 4); - i++; + if (copy_from_user(data, buf, count)) { + kfree(data); + return -EFAULT; } -exit: - kfree(bar0_buf); + if ((off & 1) && size) { + pci_write_config_byte(dev, off, data[off - init_off]); + off++; + size--; + } - return raw_count; + if ((off & 3) && size > 2) { + u16 val = data[off - init_off]; + + val |= (u16) data[off - init_off + 1] << 8; + pci_write_config_word(dev, off, val); + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val = data[off - init_off]; + + val |= (u32) data[off - init_off + 1] << 8; + val |= (u32) data[off - init_off + 2] << 16; + val |= (u32) data[off - init_off + 3] << 24; + pci_write_config_dword(dev, off, val); + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val = data[off - init_off]; + + val |= (u16) data[off - init_off + 1] << 8; + pci_write_config_word(dev, off, val); + off += 2; + size -= 2; + } + + if (size) { + pci_write_config_byte(dev, off, data[off - init_off]); + off++; + --size; + } + + kfree(data); + + return count; } static ssize_t pcie_rkep_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); - u32 *bar0_buf; - int loop, i = 0; - size_t raw_count = count; + struct pcie_file *pcie_file = file->private_data; + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + struct pci_dev *dev = pcie_rkep->pdev; + unsigned int size = count; + loff_t init_off = *ppos, off = *ppos; + u8 *data; - count = (count % 4) ? (count - count % 4) : count; - - if (count > BAR_0_SZ) - return -EINVAL; - - bar0_buf = kzalloc(count, GFP_ATOMIC); - if (!bar0_buf) + data = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); + if (!data) return -ENOMEM; - for (loop = 0; loop < count / 4; loop++) { - bar0_buf[i] = ioread32(pcie_rkep->bar0 + loop * 4); - i++; + if (off > dev->cfg_size) { + kfree(data); + return 0; + } + if (off + count > dev->cfg_size) { + size = dev->cfg_size - off; + count = size; } - if (copy_to_user(buf, bar0_buf, count)) { - raw_count = -EFAULT; - goto exit; + if ((off & 1) && size) { + u8 val; + + pci_read_config_byte(dev, off, &val); + data[off - init_off] = val; + off++; + size--; } -exit: - kfree(bar0_buf); + if ((off & 3) && size > 2) { + u16 val; - return raw_count; + pci_read_config_word(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + off += 2; + size -= 2; + } + + while (size > 3) { + u32 val; + + pci_read_config_dword(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + data[off - init_off + 2] = (val >> 16) & 0xff; + data[off - init_off + 3] = (val >> 24) & 0xff; + off += 4; + size -= 4; + } + + if (size >= 2) { + u16 val; + + pci_read_config_word(dev, off, &val); + data[off - init_off] = val & 0xff; + data[off - init_off + 1] = (val >> 8) & 0xff; + off += 2; + size -= 2; + } + + if (size > 0) { + u8 val; + + pci_read_config_byte(dev, off, &val); + data[off - init_off] = val; + off++; + --size; + } + + if (copy_to_user(buf, data, count)) { + kfree(data); + return -EFAULT; + } + + kfree(data); + + return count; } static int pcie_rkep_mmap(struct file *file, struct vm_area_struct *vma) { u64 addr; - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); + struct pcie_file *pcie_file = file->private_data; + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; + struct pci_dev *dev = pcie_rkep->pdev; size_t size = vma->vm_end - vma->vm_start; + resource_size_t bar_size; + int err; - if (size > RKEP_USER_MEM_SIZE) { - dev_warn(&pcie_rkep->pdev->dev, "mmap size is out of limitation\n"); + switch (pcie_rkep->cur_mmap_res) { + case PCIE_EP_MMAP_RESOURCE_RK3568_RC_DBI: + if (size > PCIE_DBI_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n"); + return -EINVAL; + } + addr = PCIE_RK3568_RC_DBI_BASE; + break; + case PCIE_EP_MMAP_RESOURCE_RK3588_RC_DBI: + if (size > PCIE_DBI_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "dbi mmap size is out of limitation\n"); + return -EINVAL; + } + addr = PCIE_RK3588_RC_DBI_BASE; + break; + case PCIE_EP_MMAP_RESOURCE_BAR0: + bar_size = pci_resource_len(dev, 0); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar0 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 0); + break; + case PCIE_EP_MMAP_RESOURCE_BAR2: + bar_size = pci_resource_len(dev, 2); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar2 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 2); + break; + case PCIE_EP_MMAP_RESOURCE_BAR4: + bar_size = pci_resource_len(dev, 4); + if (size > bar_size) { + dev_warn(&pcie_rkep->pdev->dev, "bar4 mmap size is out of limitation\n"); + return -EINVAL; + } + addr = pci_resource_start(dev, 4); + break; + case PCIE_EP_MMAP_RESOURCE_USER_MEM: + if (size > RKEP_USER_MEM_SIZE) { + dev_warn(&pcie_rkep->pdev->dev, "mmap size is out of limitation\n"); + return -EINVAL; + } + + if (!pcie_rkep->user_pages) { + dev_warn(&pcie_rkep->pdev->dev, "user_pages has not been allocated yet\n"); + return -EINVAL; + } + addr = page_to_phys(pcie_rkep->user_pages); + break; + default: + dev_err(&pcie_rkep->pdev->dev, "cur mmap_res %d is unsurreport\n", pcie_rkep->cur_mmap_res); return -EINVAL; } - if (!pcie_rkep->user_pages) { - dev_warn(&pcie_rkep->pdev->dev, "user_pages has not been allocated yet\n"); - return -EINVAL; - } - - addr = page_to_phys(pcie_rkep->user_pages); vma->vm_flags |= VM_IO; - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); - if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, size, vma->vm_page_prot)) { - dev_err(&pcie_rkep->pdev->dev, "io_remap_pfn_range failed\n"); + if (pcie_rkep->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_BAR2 || + pcie_rkep->cur_mmap_res == PCIE_EP_MMAP_RESOURCE_USER_MEM) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + else + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + err = remap_pfn_range(vma, vma->vm_start, + __phys_to_pfn(addr), + size, vma->vm_page_prot); + if (err) return -EAGAIN; - } return 0; } @@ -242,11 +565,15 @@ static long pcie_rkep_ioctl(struct file *file, unsigned int cmd, unsigned long args) { void __user *argp; - struct miscdevice *miscdev = file->private_data; - struct pcie_rkep *pcie_rkep = container_of(miscdev, struct pcie_rkep, dev); + struct pcie_file *pcie_file = file->private_data; + struct pcie_rkep *pcie_rkep = pcie_file->pcie_rkep; struct pcie_ep_dma_cache_cfg cfg; + struct pcie_ep_dma_block_req dma; void __user *uarg = (void __user *)args; + struct pcie_ep_obj_poll_virtual_id_cfg poll_cfg; + int mmap_res; int ret; + int index; u64 addr; argp = (void __user *)args; @@ -265,7 +592,8 @@ case PCIE_DMA_CACHE_INVALIDE: ret = copy_from_user(&cfg, uarg, sizeof(cfg)); if (ret) { - dev_err(&pcie_rkep->pdev->dev, "failed to get copy from\n"); + dev_err(&pcie_rkep->pdev->dev, + "failed to get invalid cfg copy from userspace\n"); return -EFAULT; } dma_sync_single_for_cpu(&pcie_rkep->pdev->dev, cfg.addr, cfg.size, DMA_FROM_DEVICE); @@ -273,11 +601,108 @@ case PCIE_DMA_CACHE_FLUSH: ret = copy_from_user(&cfg, uarg, sizeof(cfg)); if (ret) { - dev_err(&pcie_rkep->pdev->dev, "failed to get copy from\n"); + dev_err(&pcie_rkep->pdev->dev, + "failed to get flush cfg copy from userspace\n"); return -EFAULT; } dma_sync_single_for_device(&pcie_rkep->pdev->dev, cfg.addr, cfg.size, DMA_TO_DEVICE); + break; + case PCIE_EP_DMA_XFER_BLOCK: + ret = copy_from_user(&dma, uarg, sizeof(dma)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, + "failed to get dma_data copy from userspace\n"); + return -EFAULT; + } + ret = rkep_ep_dma_xfer(pcie_rkep, &dma); + if (ret) { + 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_file); + 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 release data copy from userspace\n"); + return -EFAULT; + } + ret = rkep_ep_release_virtual_id(pcie_file, index); + if (ret < 0) { + dev_err(&pcie_rkep->pdev->dev, + "release virtual id %d failed, ret=%d\n", index, ret); + + return -EFAULT; + } + break; + case PCIE_EP_RAISE_IRQ_USER: + ret = copy_from_user(&index, uarg, sizeof(index)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, + "failed to get raise irq data copy from userspace\n"); + return -EFAULT; + } + + ret = rkep_ep_raise_irq_user_obj(pcie_file, index); + if (ret < 0) + return -EFAULT; + break; + case PCIE_EP_POLL_IRQ_USER: + ret = copy_from_user(&poll_cfg, uarg, sizeof(poll_cfg)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, + "failed to get poll irq data copy from userspace\n"); + + return -EFAULT; + } + + ret = rkep_ep_poll_irq_user(pcie_file, &poll_cfg); + if (ret < 0) + return -EFAULT; + + if (copy_to_user(argp, &poll_cfg, sizeof(poll_cfg))) + return -EFAULT; + break; + case PCIE_EP_RAISE_ELBI: + ret = copy_from_user(&index, uarg, sizeof(index)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, + "failed to get raise elbi data copy from userspace\n"); + return -EFAULT; + } + ret = rkep_ep_raise_elbi_irq(pcie_file, index); + if (ret < 0) { + dev_err(&pcie_rkep->pdev->dev, + "raise elbi %d failed, ret=%d\n", index, ret); + + return -EFAULT; + } + break; + case PCIE_EP_SET_MMAP_RESOURCE: + ret = copy_from_user(&mmap_res, uarg, sizeof(mmap_res)); + if (ret) { + dev_err(&pcie_rkep->pdev->dev, "failed to get copy from\n"); + return -EFAULT; + } + + if (mmap_res >= PCIE_EP_MMAP_RESOURCE_MAX || mmap_res < 0) { + dev_err(&pcie_rkep->pdev->dev, "mmap index %d is out of number\n", mmap_res); + return -EINVAL; + } + + pcie_rkep->cur_mmap_res = mmap_res; break; default: break; @@ -293,9 +718,8 @@ .read = pcie_rkep_read, .unlocked_ioctl = pcie_rkep_ioctl, .mmap = pcie_rkep_mmap, - .fasync = pcie_rkep_fasync, .release = pcie_rkep_release, - .llseek = no_llseek, + .llseek = default_llseek, }; static inline void pcie_rkep_writel_dbi(struct pcie_rkep *pcie_rkep, u32 reg, u32 val) @@ -308,29 +732,115 @@ return readl(pcie_rkep->bar4 + reg); } +static void pcie_rkep_dma_debug(struct dma_trx_obj *obj, struct dma_table *table) +{ + struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); + struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); + unsigned int ctr_off = PCIE_DMA_OFFSET + table->chn * 0x200; + + dev_err(&pdev->dev, "chnl=%x\n", table->start.chnl); + dev_err(&pdev->dev, "%s\n", table->dir == DMA_FROM_BUS ? "udma read" : "udma write"); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "src=0x%x %x\n", table->ctx_reg.sarptrhi, table->ctx_reg.sarptrlo); + dev_err(&pdev->dev, "dst=0x%x %x\n", table->ctx_reg.darptrhi, table->ctx_reg.darptrlo); + } else { + dev_err(&pdev->dev, "phys_descs=0x%llx\n", table->phys_descs); + } + dev_err(&pdev->dev, "xfersize=%x\n", table->ctx_reg.xfersize); + + if (table->dir == DMA_FROM_BUS) { + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_MASK = %x\n", PCIE_DMA_RD_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ENB = %x\n", PCIE_DMA_RD_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_LO = %x\n", ctr_off + PCIE_DMA_RD_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_HI = %x\n", ctr_off + PCIE_DMA_RD_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_XFERSIZE = %x\n", ctr_off + PCIE_DMA_RD_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DOORBELL = %x\n", PCIE_DMA_RD_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_STATUS = %x\n", PCIE_DMA_RD_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_LOW = %x\n", PCIE_DMA_RD_ERR_STATUS_LOW, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_LOW)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_HIGH = %x\n", PCIE_DMA_RD_ERR_STATUS_HIGH, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_HIGH)); + } else { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_INT_MASK = %x\n", PCIE_DMA_RD_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ENB = %x\n", PCIE_DMA_RD_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_LO = %x\n", ctr_off + PCIE_DMA_RD_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_CTRL_HI = %x\n", ctr_off + PCIE_DMA_RD_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_LL_PTR_LO = %x\n", ctr_off + PCIE_DMA_RD_LL_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_LL_PTR_HI = %x\n", ctr_off + PCIE_DMA_RD_LL_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_DOORBELL = %x\n", PCIE_DMA_RD_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_LOW = %x\n", PCIE_DMA_RD_ERR_STATUS_LOW, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_LOW)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_RD_ERR_STATUS_HIGH = %x\n", PCIE_DMA_RD_ERR_STATUS_HIGH, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ERR_STATUS_HIGH)); + } + } else { + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_MASK = %x\n", PCIE_DMA_WR_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ENB = %x\n", PCIE_DMA_WR_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_LO = %x\n", ctr_off + PCIE_DMA_WR_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_HI = %x\n", ctr_off + PCIE_DMA_WR_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_XFERSIZE = %x\n", ctr_off + PCIE_DMA_WR_XFERSIZE, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_SAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_SAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DAR_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_DAR_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DOORBELL = %x\n", PCIE_DMA_WR_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_STATUS = %x\n", PCIE_DMA_WR_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ERR_STATUS = %x\n", PCIE_DMA_WR_ERR_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ERR_STATUS)); + } else { + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_MASK = %x\n", PCIE_DMA_WR_INT_MASK, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ENB = %x\n", PCIE_DMA_WR_ENB, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_LO = %x\n", ctr_off + PCIE_DMA_WR_CTRL_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_CTRL_HI = %x\n", ctr_off + PCIE_DMA_WR_CTRL_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_LL_PTR_LO = %x\n", ctr_off + PCIE_DMA_WR_LL_PTR_LO, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_LO)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_LL_PTR_HI = %x\n", ctr_off + PCIE_DMA_WR_LL_PTR_HI, pcie_rkep_readl_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_HI)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_DOORBELL = %x\n", PCIE_DMA_WR_DOORBELL, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_INT_STATUS = %x\n", PCIE_DMA_WR_INT_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_STATUS)); + dev_err(&pdev->dev, "reg[0x%x] PCIE_DMA_WR_ERR_STATUS = %x\n", PCIE_DMA_WR_ERR_STATUS, pcie_rkep_readl_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ERR_STATUS)); + } + } +} + static void pcie_rkep_start_dma_rd(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) { struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, - cur->enb.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, - cur->ctx_reg.ctrllo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, - cur->ctx_reg.ctrlhi.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE, - cur->ctx_reg.xfersize); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO, - cur->ctx_reg.sarptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI, - cur->ctx_reg.sarptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO, - cur->ctx_reg.darptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI, - cur->ctx_reg.darptrhi); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, - cur->start.asdword); + if (cur->dma_mode == RK_PCIE_DMA_BLOCK) { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_XFERSIZE, + cur->ctx_reg.xfersize); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_LO, + cur->ctx_reg.sarptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_SAR_PTR_HI, + cur->ctx_reg.sarptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_LO, + cur->ctx_reg.darptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_DAR_PTR_HI, + cur->ctx_reg.darptrhi); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, + cur->start.asdword); + } else { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_LO, + lower_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_RD_LL_PTR_HI, + upper_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL, + cur->start.asdword); + } + /* pcie_rkep_dma_debug(obj, cur); */ } static void pcie_rkep_start_dma_wr(struct dma_trx_obj *obj, struct dma_table *cur, int ctr_off) @@ -338,26 +848,42 @@ struct pci_dev *pdev = container_of(obj->dev, struct pci_dev, dev); struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, - cur->enb.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, - cur->ctx_reg.ctrllo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, - cur->ctx_reg.ctrlhi.asdword); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE, - cur->ctx_reg.xfersize); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO, - cur->ctx_reg.sarptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI, - cur->ctx_reg.sarptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO, - cur->ctx_reg.darptrlo); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI, - cur->ctx_reg.darptrhi); - pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_WEILO, - cur->weilo.asdword); - pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, - cur->start.asdword); + if (cur->dma_mode == RK_PCIE_DMA_BLOCK) { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_XFERSIZE, + cur->ctx_reg.xfersize); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_LO, + cur->ctx_reg.sarptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_SAR_PTR_HI, + cur->ctx_reg.sarptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_LO, + cur->ctx_reg.darptrlo); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_DAR_PTR_HI, + cur->ctx_reg.darptrhi); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_WEILO, + cur->weilo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, + cur->start.asdword); + } else { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB, + cur->enb.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_LO, + cur->ctx_reg.ctrllo.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_CTRL_HI, + cur->ctx_reg.ctrlhi.asdword); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_LO, + lower_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, ctr_off + PCIE_DMA_WR_LL_PTR_HI, + upper_32_bits(cur->phys_descs)); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL, + cur->start.asdword); + } + /* pcie_rkep_dma_debug(obj, cur); */ } static void pcie_rkep_start_dma_dwc(struct dma_trx_obj *obj, struct dma_table *table) @@ -375,26 +901,36 @@ static void pcie_rkep_config_dma_dwc(struct dma_table *table) { - table->enb.enb = 0x1; - table->ctx_reg.ctrllo.lie = 0x1; - table->ctx_reg.ctrllo.rie = 0x0; - table->ctx_reg.ctrllo.td = 0x1; - table->ctx_reg.ctrlhi.asdword = 0x0; - table->ctx_reg.xfersize = table->buf_size; - if (table->dir == DMA_FROM_BUS) { - table->ctx_reg.sarptrlo = (u32)(table->bus & 0xffffffff); - table->ctx_reg.sarptrhi = (u32)(table->bus >> 32); - table->ctx_reg.darptrlo = (u32)(table->local & 0xffffffff); - table->ctx_reg.darptrhi = (u32)(table->local >> 32); - } else if (table->dir == DMA_TO_BUS) { - table->ctx_reg.sarptrlo = (u32)(table->local & 0xffffffff); - table->ctx_reg.sarptrhi = (u32)(table->local >> 32); - table->ctx_reg.darptrlo = (u32)(table->bus & 0xffffffff); - table->ctx_reg.darptrhi = (u32)(table->bus >> 32); + if (table->dma_mode == RK_PCIE_DMA_BLOCK) { + table->enb.enb = 0x1; + table->ctx_reg.ctrllo.lie = 0x1; + table->ctx_reg.ctrllo.rie = 0x0; + table->ctx_reg.ctrllo.td = 0x1; + table->ctx_reg.ctrlhi.asdword = 0x0; + table->ctx_reg.xfersize = table->buf_size; + if (table->dir == DMA_FROM_BUS) { + table->ctx_reg.sarptrlo = (u32)(table->bus & 0xffffffff); + table->ctx_reg.sarptrhi = (u32)(table->bus >> 32); + table->ctx_reg.darptrlo = (u32)(table->local & 0xffffffff); + table->ctx_reg.darptrhi = (u32)(table->local >> 32); + } else if (table->dir == DMA_TO_BUS) { + table->ctx_reg.sarptrlo = (u32)(table->local & 0xffffffff); + table->ctx_reg.sarptrhi = (u32)(table->local >> 32); + table->ctx_reg.darptrlo = (u32)(table->bus & 0xffffffff); + table->ctx_reg.darptrhi = (u32)(table->bus >> 32); + } + table->weilo.weight0 = 0x0; + table->start.stop = 0x0; + table->start.chnl = table->chn; + } else { + table->enb.enb = 0x1; + table->ctx_reg.ctrllo.lie = 0x1; + table->ctx_reg.ctrllo.rie = 0x0; + table->ctx_reg.ctrllo.ccs = 1; + table->ctx_reg.ctrllo.llen = 1; + table->ctx_reg.ctrlhi.asdword = 0x0; + table->start.chnl = table->chn; } - table->weilo.weight0 = 0x0; - table->start.stop = 0x0; - table->start.chnl = table->chn; } static int pcie_rkep_get_dma_status(struct dma_trx_obj *obj, u8 chn, enum dma_dir dir) @@ -420,7 +956,7 @@ } if (status.abortsta & BIT(chn)) { - dev_err(&pdev->dev, "%s, write abort\n", __func__); + dev_err(&pdev->dev, "%s, write abort %x\n", __func__, status.asdword); clears.abortclr = BIT(chn); pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_CLEAR, clears.asdword); @@ -455,8 +991,8 @@ u32 irq_type; u32 chn; union int_clear clears; + u32 reg; - kill_fasync(&pcie_rkep->async, SIGIO, POLL_IN); irq_type = pcie_rkep->obj_info->irq_type_rc; if (irq_type == OBJ_IRQ_DMA) { /* DMA helper */ @@ -499,122 +1035,77 @@ } } } + } else if (irq_type == OBJ_IRQ_USER) { + reg = pcie_rkep->obj_info->irq_user_data_rc; + if (reg < RKEP_EP_VIRTUAL_ID_MAX) { + set_bit(reg, pcie_rkep->virtual_id_irq_bitmap); + wake_up_interruptible(&pcie_rkep->wq_head); + } } return 0; } -static int __maybe_unused rockchip_pcie_raise_elbi_irq(struct pcie_rkep *pcie_rkep, - u8 interrupt_num) -{ - u32 index, off; - - if (interrupt_num >= (PCIE_ELBI_REG_NUM * 16)) { - dev_err(&pcie_rkep->pdev->dev, "elbi int num out of max count\n"); - return -EINVAL; - } - - index = interrupt_num / 16; - off = interrupt_num % 16; - return pci_write_config_dword(pcie_rkep->pdev, PCIE_CFG_ELBI_APP_OFFSET + 4 * index, - (1 << (off + 16)) | (1 << off)); -} - static irqreturn_t pcie_rkep_pcie_interrupt(int irq, void *context) { - struct pcie_rkep_msix_context *ctx = context; + struct pcie_rkep_irq_context *ctx = context; struct pci_dev *pdev = ctx->dev; struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); if (!pcie_rkep) return IRQ_HANDLED; - if (pcie_rkep->msix_enable) - dev_info(&pdev->dev, "MSI-X is triggered for 0x%x\n", ctx->msg_id); - - else /* pcie_rkep->msi_enable */ { - /* - * The msi 0 is the dedicated interrupt for obj to issue remote rc device. - */ - if (irq == pci_irq_vector(pcie_rkep->pdev, PCIe_CLIENT_MSI_IRQ_OBJ)) - pcie_rkep_obj_handler(pcie_rkep, pdev); - } + /* + * The irq 0 is the dedicated interrupt for obj to issue remote rc device. + */ + if (irq == pci_irq_vector(pcie_rkep->pdev, PCIe_CLIENT_MSI_IRQ_OBJ)) + pcie_rkep_obj_handler(pcie_rkep, pdev); return IRQ_HANDLED; } -static int __maybe_unused pcie_rkep_request_msi_irq(struct pcie_rkep *pcie_rkep) +static void pcie_rkep_release_irq(struct pcie_rkep *pcie_rkep) { - int nvec, ret = -EINVAL, i, j; + int i; + + if (pcie_rkep->irq_valid) { + for (i = 0; i < pcie_rkep->irq_valid; i++) + pci_free_irq(pcie_rkep->pdev, i, &pcie_rkep->irq_ctx[i]); + + pci_free_irq_vectors(pcie_rkep->pdev); + } + pcie_rkep->irq_valid = 0; +} + +static int pcie_rkep_request_irq(struct pcie_rkep *pcie_rkep, u32 irq_type) +{ + int nvec, ret = -EINVAL, i; /* Using msi as default */ - nvec = pci_alloc_irq_vectors(pcie_rkep->pdev, 1, RKEP_NUM_MSI_VECTORS, PCI_IRQ_MSI); + nvec = pci_alloc_irq_vectors(pcie_rkep->pdev, 1, RKEP_NUM_IRQ_VECTORS, irq_type); if (nvec < 0) return nvec; - if (nvec != RKEP_NUM_MSI_VECTORS) - dev_err(&pcie_rkep->pdev->dev, "only allocate %d msi interrupt\n", nvec); + if (nvec != RKEP_NUM_IRQ_VECTORS) + dev_err(&pcie_rkep->pdev->dev, "only allocate %d irq interrupt, irq_type=%d\n", nvec, irq_type); + pcie_rkep->irq_valid = 0; for (i = 0; i < nvec; i++) { - pcie_rkep->msi_ctx[i].dev = pcie_rkep->pdev; - pcie_rkep->msi_ctx[i].msg_id = i; - pcie_rkep->msi_ctx[i].name = - devm_kzalloc(&pcie_rkep->pdev->dev, RKEP_NUM_MSIX_VECTORS, GFP_KERNEL); - sprintf(pcie_rkep->msi_ctx[i].name, "%s-%d\n", pcie_rkep->dev.name, i); - ret = request_irq(pci_irq_vector(pcie_rkep->pdev, i), - pcie_rkep_pcie_interrupt, IRQF_SHARED, - pcie_rkep->msi_ctx[i].name, &pcie_rkep->msi_ctx[i]); + pcie_rkep->irq_ctx[i].dev = pcie_rkep->pdev; + pcie_rkep->irq_ctx[i].msg_id = i; + ret = pci_request_irq(pcie_rkep->pdev, i, + pcie_rkep_pcie_interrupt, NULL, + &pcie_rkep->irq_ctx[i], "%s-%d", pcie_rkep->dev.name, i); if (ret) break; + pcie_rkep->irq_valid++; } if (ret) { - for (j = 0; j < i; j++) - free_irq(pci_irq_vector(pcie_rkep->pdev, j), &pcie_rkep->msi_ctx[j]); - pci_disable_msi(pcie_rkep->pdev); + pcie_rkep_release_irq(pcie_rkep); dev_err(&pcie_rkep->pdev->dev, "fail to allocate msi interrupt\n"); } else { - pcie_rkep->msi_enable = true; dev_err(&pcie_rkep->pdev->dev, "success to request msi irq\n"); - } - - return ret; -} - -static int __maybe_unused pcie_rkep_request_msix_irq(struct pcie_rkep *pcie_rkep) -{ - int ret, i, j; - - for (i = 0; i < RKEP_NUM_MSIX_VECTORS; i++) - pcie_rkep->msix_entries[i].entry = i; - - ret = pci_enable_msix_exact(pcie_rkep->pdev, pcie_rkep->msix_entries, - RKEP_NUM_MSIX_VECTORS); - if (ret) - return ret; - - for (i = 0; i < RKEP_NUM_MSIX_VECTORS; i++) { - pcie_rkep->msix_ctx[i].dev = pcie_rkep->pdev; - pcie_rkep->msix_ctx[i].msg_id = i; - pcie_rkep->msix_ctx[i].name = - devm_kzalloc(&pcie_rkep->pdev->dev, RKEP_NUM_MSIX_VECTORS, GFP_KERNEL); - sprintf(pcie_rkep->msix_ctx[i].name, "%s-%d\n", pcie_rkep->dev.name, i); - ret = request_irq(pcie_rkep->msix_entries[i].vector, - pcie_rkep_pcie_interrupt, 0, pcie_rkep->msix_ctx[i].name, - &pcie_rkep->msix_ctx[i]); - - if (ret) - break; - } - - if (ret) { - for (j = 0; j < i; j++) - free_irq(pcie_rkep->msix_entries[j].vector, &pcie_rkep->msix_ctx[j]); - pci_disable_msix(pcie_rkep->pdev); - dev_err(&pcie_rkep->pdev->dev, "fail to allocate msi-x interrupt\n"); - } else { - pcie_rkep->msix_enable = true; - dev_err(&pcie_rkep->pdev->dev, "success to request msi-x irq\n"); } return ret; @@ -637,7 +1128,7 @@ dev_info(dev, "%s file %s size %lld to %p\n", __func__, path, size, bar + pos); offset = 0; - kernel_read(p_file, bar + pos, size, &offset); + kernel_read(p_file, (void *)bar + pos, (size_t)size, (loff_t *)&offset); dev_info(dev, "kernel_read size %lld from %s to %p\n", size, path, bar + pos); @@ -670,14 +1161,21 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret, i; + int ret; struct pcie_rkep *pcie_rkep; u8 *name; u16 val; + bool dmatest_irq = false; pcie_rkep = devm_kzalloc(&pdev->dev, sizeof(*pcie_rkep), GFP_KERNEL); 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) { @@ -717,16 +1215,13 @@ 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) { @@ -738,11 +1233,12 @@ pci_set_drvdata(pdev, pcie_rkep); - ret = pcie_rkep_request_msi_irq(pcie_rkep); + init_waitqueue_head(&pcie_rkep->wq_head); + ret = pcie_rkep_request_irq(pcie_rkep, PCI_IRQ_MSI); if (ret) goto err_register_irq; - pcie_rkep->dma_obj = pcie_dw_dmatest_register(&pdev->dev, true); + pcie_rkep->dma_obj = pcie_dw_dmatest_register(&pdev->dev, dmatest_irq); if (IS_ERR(pcie_rkep->dma_obj)) { dev_err(&pcie_rkep->pdev->dev, "failed to prepare dmatest\n"); ret = -EINVAL; @@ -750,9 +1246,19 @@ } if (pcie_rkep->dma_obj) { + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); pcie_rkep->dma_obj->start_dma_func = pcie_rkep_start_dma_dwc; pcie_rkep->dma_obj->config_dma_func = pcie_rkep_config_dma_dwc; pcie_rkep->dma_obj->get_dma_status = pcie_rkep_get_dma_status; + pcie_rkep->dma_obj->dma_debug = pcie_rkep_dma_debug; + if (!dmatest_irq) { + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK, 0xffffffff); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK, 0xffffffff); + + /* Enable linked list err en */ + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_WR_LL_ERR_EN, 0xffffffff); + pcie_rkep_writel_dbi(pcie_rkep, PCIE_DMA_OFFSET + PCIE_DMA_RD_LL_ERR_EN, 0xffffffff); + } } #if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES) @@ -761,8 +1267,11 @@ if (!pcie_rkep->user_pages) { dev_err(&pcie_rkep->pdev->dev, "failed to allocate contiguous pages\n"); ret = -EINVAL; + if (pcie_rkep->dma_obj) + pcie_dw_dmatest_unregister(pcie_rkep->dma_obj); goto err_register_obj; } + pcie_rkep->cur_mmap_res = PCIE_EP_MMAP_RESOURCE_USER_MEM; dev_err(&pdev->dev, "successfully allocate continuouse buffer for userspace\n"); #endif @@ -777,18 +1286,7 @@ return 0; err_register_obj: - if (pcie_rkep->msix_enable) { - for (i = 0; i < RKEP_NUM_MSIX_VECTORS; i++) - free_irq(pcie_rkep->msix_entries[i].vector, &pcie_rkep->msix_ctx[i]); - pci_disable_msix(pdev); - } else if (pcie_rkep->msi_enable) { - for (i = 0; i < RKEP_NUM_MSI_VECTORS; i++) { - if (pcie_rkep->msi_ctx[i].dev) - free_irq(pci_irq_vector(pdev, i), &pcie_rkep->msi_ctx[i]); - } - - pci_disable_msi(pcie_rkep->pdev); - } + pcie_rkep_release_irq(pcie_rkep); err_register_irq: misc_deregister(&pcie_rkep->dev); err_pci_iomap: @@ -809,27 +1307,25 @@ static void pcie_rkep_remove(struct pci_dev *pdev) { struct pcie_rkep *pcie_rkep = pci_get_drvdata(pdev); - int i; + + if (pcie_rkep->dma_obj) + pcie_dw_dmatest_unregister(pcie_rkep->dma_obj); device_remove_file(&pdev->dev, &dev_attr_rkep); #if IS_ENABLED(CONFIG_PCIE_FUNC_RKEP_USERPAGES) free_contig_range(page_to_pfn(pcie_rkep->user_pages), RKEP_USER_MEM_SIZE >> PAGE_SHIFT); #endif - pci_iounmap(pdev, pcie_rkep->bar0); + pcie_rkep_release_irq(pcie_rkep); + + if (pcie_rkep->bar0) + pci_iounmap(pdev, pcie_rkep->bar0); + if (pcie_rkep->bar2) + pci_iounmap(pdev, pcie_rkep->bar2); + if (pcie_rkep->bar4) + pci_iounmap(pdev, pcie_rkep->bar4); pci_release_regions(pdev); pci_disable_device(pdev); misc_deregister(&pcie_rkep->dev); - - if (pcie_rkep->msix_enable) { - for (i = 0; i < RKEP_NUM_MSIX_VECTORS; i++) - free_irq(pcie_rkep->msix_entries[i].vector, &pcie_rkep->msix_ctx[i]); - pci_disable_msix(pdev); - } else if (pcie_rkep->msi_enable) { - for (i = 0; i < RKEP_NUM_MSI_VECTORS; i++) - if (pcie_rkep->msi_ctx[i].dev) - free_irq(pci_irq_vector(pdev, i), &pcie_rkep->msi_ctx[i]); - pci_disable_msi(pcie_rkep->pdev); - } } static const struct pci_device_id pcie_rkep_pcidev_id[] = { -- Gitblit v1.6.2